From 804c1263d52945930e5e84ee1c5e6b8a1bc582a1 Mon Sep 17 00:00:00 2001 From: NourEldin Osama <58091991+NourEldin-Osama@users.noreply.github.com> Date: Wed, 4 Feb 2026 11:43:16 +0200 Subject: [PATCH] feat(i18n): Enhance RTL support and update language direction handling (#698) * feat(i18n): Enhance RTL support and update language direction handling * format * minor tweaks --------- Co-authored-by: CJ Pais --- index.html | 2 +- src/App.tsx | 14 ++++- src/components/Sidebar.tsx | 2 +- .../model-selector/ModelDropdown.tsx | 12 ++-- src/components/onboarding/ModelCard.tsx | 6 +- src/components/settings/LanguageSelector.tsx | 6 +- src/components/shared/ProgressBar.tsx | 2 +- src/components/ui/Dropdown.tsx | 6 +- src/components/ui/Input.tsx | 2 +- src/components/ui/Slider.tsx | 2 +- src/components/ui/Textarea.tsx | 2 +- src/i18n/index.ts | 15 +++++ src/i18n/languages.ts | 10 +++- src/lib/utils/rtl.ts | 59 +++++++++++++++++++ src/overlay/RecordingOverlay.tsx | 9 ++- src/overlay/index.html | 2 +- 16 files changed, 124 insertions(+), 27 deletions(-) create mode 100644 src/lib/utils/rtl.ts diff --git a/index.html b/index.html index df00d31..3b77a05 100644 --- a/index.html +++ b/index.html @@ -1,5 +1,5 @@ - + diff --git a/src/App.tsx b/src/App.tsx index 56e4328..454ccd2 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,5 +1,6 @@ import { useEffect, useState, useRef } from "react"; import { Toaster } from "sonner"; +import { useTranslation } from "react-i18next"; import { platform } from "@tauri-apps/plugin-os"; import { checkAccessibilityPermission, @@ -13,6 +14,7 @@ import { Sidebar, SidebarSection, SECTIONS_CONFIG } from "./components/Sidebar"; import { useSettings } from "./hooks/useSettings"; import { useSettingsStore } from "./stores/settingsStore"; import { commands } from "@/bindings"; +import { getLanguageDirection, initializeRTL } from "@/lib/utils/rtl"; type OnboardingStep = "accessibility" | "model" | "done"; @@ -23,6 +25,7 @@ const renderSettingsContent = (section: SidebarSection) => { }; function App() { + const { i18n } = useTranslation(); const [onboardingStep, setOnboardingStep] = useState( null, ); @@ -32,6 +35,7 @@ function App() { const [currentSection, setCurrentSection] = useState("general"); const { settings, updateSetting } = useSettings(); + const direction = getLanguageDirection(i18n.language); const refreshAudioDevices = useSettingsStore( (state) => state.refreshAudioDevices, ); @@ -44,6 +48,11 @@ function App() { checkOnboardingStatus(); }, []); + // Initialize RTL direction when language changes + useEffect(() => { + initializeRTL(i18n.language); + }, [i18n.language]); + // Initialize Enigo, shortcuts, and refresh audio devices when main app loads useEffect(() => { if (onboardingStep === "done" && !hasCompletedPostOnboardingInit.current) { @@ -146,7 +155,10 @@ function App() { } return ( -
+
= ({ .map(([id, config]) => ({ id: id as SidebarSection, ...config })); return ( -
+
{availableSections.map((section) => { diff --git a/src/components/model-selector/ModelDropdown.tsx b/src/components/model-selector/ModelDropdown.tsx index 8f22fe5..4a2003d 100644 --- a/src/components/model-selector/ModelDropdown.tsx +++ b/src/components/model-selector/ModelDropdown.tsx @@ -66,7 +66,7 @@ const ModelDropdown: React.FC = ({ }; return ( -
+
{/* First Run Welcome */} {isFirstRun && (
@@ -97,7 +97,7 @@ const ModelDropdown: React.FC = ({ }} tabIndex={0} role="button" - className={`w-full px-3 py-2 text-left hover:bg-mid-gray/10 transition-colors cursor-pointer focus:outline-none ${ + className={`w-full px-3 py-2 text-start hover:bg-mid-gray/10 transition-colors cursor-pointer focus:outline-none ${ currentModelId === model.id ? "bg-logo-primary/10 text-logo-primary" : "" @@ -108,7 +108,7 @@ const ModelDropdown: React.FC = ({
{getTranslatedModelName(model, t)}
-
+
{getTranslatedModelDescription(model, t)}
@@ -174,7 +174,7 @@ const ModelDropdown: React.FC = ({ tabIndex={0} role="button" aria-disabled={isDownloading} - className={`w-full px-3 py-2 text-left hover:bg-mid-gray/10 transition-colors cursor-pointer focus:outline-none ${ + className={`w-full px-3 py-2 text-start hover:bg-mid-gray/10 transition-colors cursor-pointer focus:outline-none ${ isDownloading ? "opacity-50 cursor-not-allowed hover:bg-transparent" : "" @@ -185,12 +185,12 @@ const ModelDropdown: React.FC = ({
{getTranslatedModelName(model, t)} {model.id === "parakeet-tdt-0.6b-v3" && isFirstRun && ( - + {t("onboarding.recommended")} )}
-
+
{getTranslatedModelDescription(model, t)}
diff --git a/src/components/onboarding/ModelCard.tsx b/src/components/onboarding/ModelCard.tsx index b79a945..5994534 100644 --- a/src/components/onboarding/ModelCard.tsx +++ b/src/components/onboarding/ModelCard.tsx @@ -32,7 +32,7 @@ const ModelCard: React.FC = ({ const displayDescription = getTranslatedModelDescription(model, t); const baseButtonClasses = - "flex justify-between items-center rounded-xl p-3 px-4 text-left transition-all duration-200 disabled:opacity-50 disabled:cursor-not-allowed focus:outline-none focus:ring-2 focus:ring-logo-primary/25 active:scale-[0.98] cursor-pointer group"; + "flex justify-between items-center rounded-xl p-3 px-4 text-start transition-all duration-200 disabled:opacity-50 disabled:cursor-not-allowed focus:outline-none focus:ring-2 focus:ring-logo-primary/25 active:scale-[0.98] cursor-pointer group"; const variantClasses = isFeatured ? "border-2 border-logo-primary/25 bg-logo-primary/5 hover:border-logo-primary/40 hover:bg-logo-primary/8 hover:shadow-lg hover:scale-[1.02] disabled:hover:border-logo-primary/25 disabled:hover:bg-logo-primary/5 disabled:hover:shadow-none disabled:hover:scale-100" @@ -64,7 +64,7 @@ const ModelCard: React.FC = ({
-

+

{t("onboarding.modelCard.accuracy")}

@@ -75,7 +75,7 @@ const ModelCard: React.FC = ({
-

+

{t("onboarding.modelCard.speed")}

diff --git a/src/components/settings/LanguageSelector.tsx b/src/components/settings/LanguageSelector.tsx index c011e4d..893d98f 100644 --- a/src/components/settings/LanguageSelector.tsx +++ b/src/components/settings/LanguageSelector.tsx @@ -98,7 +98,7 @@ export const LanguageSelector: React.FC = ({