diff --git a/packages/react/src/components/layout/InlayContainer.tsx b/packages/react/src/components/layout/InlayContainer.tsx
index 787e85a04..b76b51697 100644
--- a/packages/react/src/components/layout/InlayContainer.tsx
+++ b/packages/react/src/components/layout/InlayContainer.tsx
@@ -1,4 +1,4 @@
-import { DetailedHTMLProps, HTMLAttributes, Suspense, useState } from "react";
+import { DetailedHTMLProps, HTMLAttributes, Suspense } from "react";
import { Loading } from "../common/Loading";
import { Link, Outlet, useLocation, useNavigate } from "react-router-dom";
import { Button } from "@/shadcn/ui/button";
diff --git a/packages/react/src/components/settings/SettingsItem.tsx b/packages/react/src/components/settings/SettingsItem.tsx
new file mode 100644
index 000000000..9893f160e
--- /dev/null
+++ b/packages/react/src/components/settings/SettingsItem.tsx
@@ -0,0 +1,15 @@
+import { Children, ReactNode } from "react";
+
+interface SettingsItemProps {
+ label: string;
+ children: ReactNode;
+}
+
+export function SettingsItem({ label, children }: SettingsItemProps) {
+ return (
+
+
{label}
+ {Children.only(children)}
+
+ );
+}
diff --git a/packages/react/src/locales/en/ui.yml b/packages/react/src/locales/en/ui.yml
index 5036b6856..4bb23ae92 100644
--- a/packages/react/src/locales/en/ui.yml
+++ b/packages/react/src/locales/en/ui.yml
@@ -331,6 +331,11 @@ views:
ignoredTopicsMsg: Hide videos with these topics from the Home and Favorites pages
theme: Theme
moreSettings: More Settings
+ user: User & Account
+ homepage: Homepage & Filters
+ blockedChannels: Blocked Channels
+ languageSearch: Search language...
+ languageNotfound: No language found
app:
update_available: An update is available
update_btn: Update
diff --git a/packages/react/src/routes/router.tsx b/packages/react/src/routes/router.tsx
index 615d0ce0a..423e068fc 100644
--- a/packages/react/src/routes/router.tsx
+++ b/packages/react/src/routes/router.tsx
@@ -8,6 +8,7 @@ import React from "react";
const Login = React.lazy(() => import("./login"));
const Settings = React.lazy(() => import("./settings"));
+const SettingsLang = React.lazy(() => import("./settings/lang"));
const About = React.lazy(() => import("./about"));
const AboutGeneral = React.lazy(() => import("./about/general"));
const AboutChangelog = React.lazy(() => import("./about/changelog"));
@@ -82,6 +83,10 @@ const router = createBrowserRouter([
path: "settings",
element: ,
children: [
+ {
+ path: "lang",
+ element: ,
+ },
// Add children routes similar to above pattern
],
},
diff --git a/packages/react/src/routes/settings.tsx b/packages/react/src/routes/settings.tsx
deleted file mode 100644
index 9025eb7e9..000000000
--- a/packages/react/src/routes/settings.tsx
+++ /dev/null
@@ -1,9 +0,0 @@
-import { Outlet } from "react-router-dom";
-
-export default function Settings() {
- return (
-
- Settings
-
- );
-}
diff --git a/packages/react/src/routes/settings/index.tsx b/packages/react/src/routes/settings/index.tsx
new file mode 100644
index 000000000..b927058c0
--- /dev/null
+++ b/packages/react/src/routes/settings/index.tsx
@@ -0,0 +1,43 @@
+import {
+ InlayContainer,
+ InlayContainerRoutes,
+} from "@/components/layout/InlayContainer";
+import { useMemo } from "react";
+import { useTranslation } from "react-i18next";
+
+export default function Settings() {
+ const { t } = useTranslation();
+
+ const routes: InlayContainerRoutes[] = useMemo(
+ () => [
+ {
+ icon: "i-heroicons:language",
+ href: "/settings/lang",
+ label: t("views.settings.languageSettings"),
+ },
+ {
+ icon: "i-heroicons:moon",
+ href: "/settings/themes",
+ label: t("views.settings.theme"),
+ },
+ {
+ icon: "i-heroicons:user",
+ href: "/settings/user",
+ label: t("views.settings.user"),
+ },
+ {
+ icon: "i-heroicons:funnel",
+ href: "/settings/homepage",
+ label: t("views.settings.homepage"),
+ },
+ {
+ icon: "i-heroicons:eye-slash",
+ href: "/settings/blocked",
+ label: t("views.settings.blockedChannels"),
+ },
+ ],
+ [t],
+ );
+
+ return ;
+}
diff --git a/packages/react/src/routes/settings/lang.tsx b/packages/react/src/routes/settings/lang.tsx
new file mode 100644
index 000000000..be4eee6ff
--- /dev/null
+++ b/packages/react/src/routes/settings/lang.tsx
@@ -0,0 +1,124 @@
+import { SettingsItem } from "@/components/settings/SettingsItem";
+import { TL_LANGS } from "@/lib/consts";
+import { langs } from "@/lib/i18n";
+import { cn } from "@/lib/utils";
+import { Button } from "@/shadcn/ui/button";
+import { Checkbox } from "@/shadcn/ui/checkbox";
+import {
+ Command,
+ CommandEmpty,
+ CommandGroup,
+ CommandInput,
+ CommandItem,
+} from "@/shadcn/ui/command";
+import { Label } from "@/shadcn/ui/label";
+import { Popover, PopoverContent, PopoverTrigger } from "@/shadcn/ui/popover";
+import { Switch } from "@/shadcn/ui/switch";
+import { clipLanguageAtom, englishNameAtom } from "@/store/settings";
+import { useAtom } from "jotai";
+import { useState } from "react";
+import { useTranslation } from "react-i18next";
+
+export default function SettingsLang() {
+ const [useENName, setUseENName] = useAtom(englishNameAtom);
+ const [clipLangs, setClipLangs] = useAtom(clipLanguageAtom);
+ const [langOpen, setLangOpen] = useState(false);
+ const { i18n, t } = useTranslation();
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+ {t("views.settings.languageNotfound")}
+
+
+ {langs.map(({ val, display }) => (
+ {
+ i18n.changeLanguage(val);
+ setLangOpen(false);
+ }}
+ >
+
+ {display}
+
+ ))}
+
+
+
+
+
+
+ {langs.find(({ val }) => i18n.language === val)?.credit}
+
+
+
+
+
+
+
+
+
+
+
+
+ {TL_LANGS.map(({ text, value }, index) => (
+
+ ))}
+
+
+
+ );
+}
diff --git a/packages/react/src/store/i18n.ts b/packages/react/src/store/i18n.ts
index a7532b3de..455e2673e 100644
--- a/packages/react/src/store/i18n.ts
+++ b/packages/react/src/store/i18n.ts
@@ -1,7 +1,7 @@
import dayjs from "dayjs";
import { atom, useSetAtom } from "jotai";
import type { i18n } from "i18next";
-import { useCallback, useEffect } from "react";
+import { useEffect } from "react";
import { useTranslation } from "react-i18next";
export const localeAtom = atom({
diff --git a/packages/react/src/store/settings.ts b/packages/react/src/store/settings.ts
index a09fcd548..3f5039ba9 100644
--- a/packages/react/src/store/settings.ts
+++ b/packages/react/src/store/settings.ts
@@ -1,5 +1,7 @@
import { atom } from "jotai";
+export const englishNameAtom = atom(false);
+export const clipLanguageAtom = atom([]);
export const redirectModeAtom = atom(false);
export const hideThumbnailAtom = atom(false);
export const hidePlaceholderAtom = atom(false);