From df9ce84c5e7c57528c48c39e6142e6143729aa4f Mon Sep 17 00:00:00 2001 From: iamEvan <47493765+iamEvanYT@users.noreply.github.com> Date: Fri, 9 May 2025 00:24:57 +0100 Subject: [PATCH 01/27] feat: initial translation implementation (browser-ui) --- bun.lock | 12 ++++++++ package.json | 4 +++ src/main/ipc/app/app.ts | 3 +- src/preload/index.ts | 4 ++- .../components/browser-ui/browser-action.tsx | 8 ++++-- .../sidebar/content/new-tab-button.tsx | 4 ++- .../sidebar/content/space-sidebar.tsx | 4 ++- .../header/address-bar/address-bar.tsx | 4 ++- src/renderer/src/lib/i18n.ts | 28 +++++++++++++++++++ src/renderer/src/locales/en/browser-ui.json | 8 ++++++ src/renderer/src/main.tsx | 1 + src/shared/flow/interfaces/app/app.ts | 1 + 12 files changed, 73 insertions(+), 8 deletions(-) create mode 100644 src/renderer/src/lib/i18n.ts create mode 100644 src/renderer/src/locales/en/browser-ui.json diff --git a/bun.lock b/bun.lock index 22a874a5..2d69c4ee 100644 --- a/bun.lock +++ b/bun.lock @@ -11,9 +11,13 @@ "electron-chrome-web-store": "npm:@iamevan/electron-chrome-web-store@0.11.2", "electron-context-menu": "^4.0.5", "electron-updater": "^6.6.2", + "i18next": "^25.1.2", + "i18next-resources-to-backend": "^1.2.1", + "ico-to-png": "^0.2.2", "knex": "^3.1.0", "mime-types": "^3.0.1", "posthog-node": "^4.17.1", + "react-i18next": "^15.5.1", "sharp": "^0.34.1", "sharp-ico": "^0.1.5", "zod": "^3.24.4", @@ -1174,6 +1178,10 @@ "hyphenate-style-name": ["hyphenate-style-name@1.1.0", "", {}, "sha512-WDC/ui2VVRrz3jOVi+XtjqkDjiVjTtFaAGiW37k6b+ohyQ5wYDOGkvCZa8+H0nx3gyvv0+BST9xuOgIyGQ00gw=="], + "i18next": ["i18next@25.1.2", "", { "dependencies": { "@babel/runtime": "^7.26.10" }, "peerDependencies": { "typescript": "^5" }, "optionalPeers": ["typescript"] }, "sha512-SP63m8LzdjkrAjruH7SCI3ndPSgjt4/wX7ouUUOzCW/eY+HzlIo19IQSfYA9X3qRiRP1SYtaTsg/Oz/PGsfD8w=="], + + "i18next-resources-to-backend": ["i18next-resources-to-backend@1.2.1", "", { "dependencies": { "@babel/runtime": "^7.23.2" } }, "sha512-okHbVA+HZ7n1/76MsfhPqDou0fptl2dAlhRDu2ideXloRRduzHsqDOznJBef+R3DFZnbvWoBW+KxJ7fnFjd6Yw=="], + "ico-endec": ["ico-endec@0.1.6", "", {}, "sha512-ZdLU38ZoED3g1j3iEyzcQj+wAkY2xfWNkymszfJPoxucIUhK7NayQ+/C4Kv0nDFMIsbtbEHldv3V8PU494/ueQ=="], "iconv-corefoundation": ["iconv-corefoundation@1.1.7", "", { "dependencies": { "cli-truncate": "^2.1.0", "node-addon-api": "^1.6.3" }, "os": "darwin" }, "sha512-T10qvkw0zz4wnm560lOEg0PovVqUXuOFhhHAkixw8/sycy7TJt7v/RrkEKEQnAw2viPSJu6iAkErxnzR0g8PpQ=="], @@ -1574,6 +1582,8 @@ "react-dom": ["react-dom@19.1.0", "", { "dependencies": { "scheduler": "^0.26.0" }, "peerDependencies": { "react": "^19.1.0" } }, "sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g=="], + "react-i18next": ["react-i18next@15.5.1", "", { "dependencies": { "@babel/runtime": "^7.25.0", "html-parse-stringify": "^3.0.1" }, "peerDependencies": { "i18next": ">= 23.2.3", "react": ">= 16.8.0", "typescript": "^5" }, "optionalPeers": ["typescript"] }, "sha512-C8RZ7N7H0L+flitiX6ASjq9p5puVJU1Z8VyL3OgM/QOMRf40BMZX+5TkpxzZVcTmOLPX5zlti4InEX5pFyiVeA=="], + "react-is": ["react-is@16.13.1", "", {}, "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="], "react-refresh": ["react-refresh@0.17.0", "", {}, "sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ=="], @@ -1884,6 +1894,8 @@ "vite": ["vite@6.3.5", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.4", "picomatch": "^4.0.2", "postcss": "^8.5.3", "rollup": "^4.34.9", "tinyglobby": "^0.2.13" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "jiti": ">=1.21.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ=="], + "void-elements": ["void-elements@3.1.0", "", {}, "sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w=="], + "wcwidth": ["wcwidth@1.0.1", "", { "dependencies": { "defaults": "^1.0.3" } }, "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg=="], "which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="], diff --git a/package.json b/package.json index e2d96d75..3f71a1ce 100644 --- a/package.json +++ b/package.json @@ -37,9 +37,13 @@ "electron-chrome-web-store": "npm:@iamevan/electron-chrome-web-store@0.11.2", "electron-context-menu": "^4.0.5", "electron-updater": "^6.6.2", + "i18next": "^25.1.2", + "i18next-resources-to-backend": "^1.2.1", + "ico-to-png": "^0.2.2", "knex": "^3.1.0", "mime-types": "^3.0.1", "posthog-node": "^4.17.1", + "react-i18next": "^15.5.1", "sharp": "^0.34.1", "sharp-ico": "^0.1.5", "zod": "^3.24.4" diff --git a/src/main/ipc/app/app.ts b/src/main/ipc/app/app.ts index 77847904..f2dc8336 100644 --- a/src/main/ipc/app/app.ts +++ b/src/main/ipc/app/app.ts @@ -5,7 +5,8 @@ import { ipcMain } from "electron"; ipcMain.handle("app:get-info", async () => { return { version: app.getVersion(), - packaged: app.isPackaged + packaged: app.isPackaged, + locale: app.getLocale() }; }); diff --git a/src/preload/index.ts b/src/preload/index.ts index fc1aa834..3746957f 100644 --- a/src/preload/index.ts +++ b/src/preload/index.ts @@ -404,6 +404,7 @@ const appAPI: FlowAppAPI = { const appInfo: { version: string; packaged: boolean; + locale: string; } = await ipcRenderer.invoke("app:get-info"); const appVersion = appInfo.version; const updateChannel: "Stable" | "Beta" | "Alpha" | "Development" = appInfo.packaged ? "Stable" : "Development"; @@ -416,7 +417,8 @@ const appAPI: FlowAppAPI = { chrome_version: process.versions.chrome, electron_version: process.versions.electron, os: os, - update_channel: updateChannel + update_channel: updateChannel, + locale: appInfo.locale }; }, writeTextToClipboard: (text: string) => { diff --git a/src/renderer/src/components/browser-ui/browser-action.tsx b/src/renderer/src/components/browser-ui/browser-action.tsx index a8b51135..854699dd 100644 --- a/src/renderer/src/components/browser-ui/browser-action.tsx +++ b/src/renderer/src/components/browser-ui/browser-action.tsx @@ -10,6 +10,7 @@ import { cn } from "@/lib/utils"; import { CogIcon, LayersIcon, PackageXIcon, PinIcon, PinOffIcon, PuzzleIcon } from "lucide-react"; import { MouseEvent, useCallback, useMemo, useRef, useState } from "react"; import { PortalPopover } from "@/components/portal/popover"; +import { useTranslation } from "react-i18next"; interface BrowserActionListProps { partition?: string; @@ -144,6 +145,7 @@ function BrowserAction({ action, alignment, partition, activeTabId }: BrowserAct } export function BrowserActionList({ alignmentX = "left", alignmentY = "bottom" }: BrowserActionListProps) { + const { t } = useTranslation(); const { isCurrentSpaceLight } = useSpaces(); const { actions, activeTabId, partition } = useBrowserAction(); const [open, setOpen] = useState(false); @@ -184,19 +186,19 @@ export function BrowserActionList({ alignmentX = "left", alignmentY = "bottom" } {noActiveTab && ( - No Active Tab + {t("No Active Tab")} )} {!noActiveTab && noActions && ( - No Extensions Available + {t("No Extensions Available")} )} - Manage Extensions + {t("Manage Extensions")} diff --git a/src/renderer/src/components/browser-ui/sidebar/content/new-tab-button.tsx b/src/renderer/src/components/browser-ui/sidebar/content/new-tab-button.tsx index 1fc7cef9..c33bfa12 100644 --- a/src/renderer/src/components/browser-ui/sidebar/content/new-tab-button.tsx +++ b/src/renderer/src/components/browser-ui/sidebar/content/new-tab-button.tsx @@ -4,10 +4,12 @@ import { SidebarMenuButton } from "@/components/ui/resizable-sidebar"; import { PlusIcon } from "lucide-react"; import { SIDEBAR_HOVER_COLOR } from "@/components/browser-ui/browser-sidebar"; import { cn } from "@/lib/utils"; +import { useTranslation } from "react-i18next"; const MotionSidebarMenuButton = motion(SidebarMenuButton); export function NewTabButton() { + const { t } = useTranslation(); const [isPressed, setIsPressed] = useState(false); const handleMouseDown = () => { @@ -32,7 +34,7 @@ export function NewTabButton() { className={cn(SIDEBAR_HOVER_COLOR, "text-black/50 dark:text-muted-foreground")} > - New Tab + {t("New Tab")} ); } diff --git a/src/renderer/src/components/browser-ui/sidebar/content/space-sidebar.tsx b/src/renderer/src/components/browser-ui/sidebar/content/space-sidebar.tsx index faacf7ae..1d8c0636 100644 --- a/src/renderer/src/components/browser-ui/sidebar/content/space-sidebar.tsx +++ b/src/renderer/src/components/browser-ui/sidebar/content/space-sidebar.tsx @@ -6,6 +6,7 @@ import { Button } from "@/components/ui/button"; import { SidebarGroup, SidebarMenu, useSidebar } from "@/components/ui/resizable-sidebar"; import { Space } from "~/flow/interfaces/sessions/spaces"; import { cn, hex_is_light } from "@/lib/utils"; +import { useTranslation } from "react-i18next"; import { AnimatePresence, motion } from "motion/react"; import { useCallback, useMemo, useRef } from "react"; import { DropIndicator as BaseDropIndicator } from "@atlaskit/pragmatic-drag-and-drop-react-drop-indicator/list-item"; @@ -38,6 +39,7 @@ export function DropIndicator({ isSpaceLight }: { isSpaceLight: boolean }) { function SidebarSectionDivider({ hasTabs, handleCloseAllTabs }: { hasTabs: boolean; handleCloseAllTabs: () => void }) { const { open } = useSidebar(); + const { t } = useTranslation(); if (!hasTabs) return null; @@ -62,7 +64,7 @@ function SidebarSectionDivider({ hasTabs, handleCloseAllTabs }: { hasTabs: boole size="sm" onClick={handleCloseAllTabs} > - Clear + {t("Clear")} )} diff --git a/src/renderer/src/components/browser-ui/sidebar/header/address-bar/address-bar.tsx b/src/renderer/src/components/browser-ui/sidebar/header/address-bar/address-bar.tsx index d7b7bdde..6e70e6e7 100644 --- a/src/renderer/src/components/browser-ui/sidebar/header/address-bar/address-bar.tsx +++ b/src/renderer/src/components/browser-ui/sidebar/header/address-bar/address-bar.tsx @@ -6,8 +6,10 @@ import { simplifyUrl } from "@/lib/url"; import { cn } from "@/lib/utils"; import { SearchIcon } from "lucide-react"; import { useRef } from "react"; +import { useTranslation } from "react-i18next"; function FakeAddressBar({ className }: { className?: string }) { + const { t } = useTranslation(); const inputRef = useRef(null); const { addressUrl, focusedTab } = useTabs(); @@ -34,7 +36,7 @@ function FakeAddressBar({ className }: { className?: string }) { const simplifiedUrl = simplifyUrl(addressUrl); const isPlaceholder = !simplifiedUrl; - const value = isPlaceholder ? "Search or type URL" : simplifiedUrl; + const value = isPlaceholder ? t("Search or type URL") : simplifiedUrl; return (
import(`@/locales/${language}/${namespace}.json`))) + .use(initReactI18next) // passes i18n down to react-i18next + .init({ + lng: "en", // default language + fallbackLng: "en", + + ns: ["browser-ui"], + + interpolation: { + escapeValue: false // react already safes from xss + } + }); + +// Set the language to the user's locale +flow.app.getAppInfo().then((appInfo) => { + i18n.changeLanguage(appInfo.locale); +}); + +export default i18n; diff --git a/src/renderer/src/locales/en/browser-ui.json b/src/renderer/src/locales/en/browser-ui.json new file mode 100644 index 00000000..326184d0 --- /dev/null +++ b/src/renderer/src/locales/en/browser-ui.json @@ -0,0 +1,8 @@ +{ + "Clear": "Clear", + "New Tab": "New Tab", + "Search or type URL": "Search or type URL", + "No Active Tab": "No Active Tab", + "No Extensions Available": "No Extensions Available", + "Manage Extensions": "Manage Extensions" +} diff --git a/src/renderer/src/main.tsx b/src/renderer/src/main.tsx index 327304ff..04da8c28 100644 --- a/src/renderer/src/main.tsx +++ b/src/renderer/src/main.tsx @@ -2,6 +2,7 @@ import { Fragment, StrictMode as ReactStrictMode } from "react"; import { createRoot } from "react-dom/client"; import "./index.css"; import App from "./App"; +import "@/lib/i18n"; const STRICT_MODE_ENABLED = true; diff --git a/src/shared/flow/interfaces/app/app.ts b/src/shared/flow/interfaces/app/app.ts index 70f0d492..3f431911 100644 --- a/src/shared/flow/interfaces/app/app.ts +++ b/src/shared/flow/interfaces/app/app.ts @@ -11,6 +11,7 @@ export interface FlowAppAPI { electron_version: string; os: string; update_channel: "Stable" | "Beta" | "Alpha" | "Development"; + locale: string; }>; /** From b69e9f5e33a77a56148e5072d94b268ddfccb8b6 Mon Sep 17 00:00:00 2001 From: iamEvan <47493765+iamEvanYT@users.noreply.github.com> Date: Fri, 9 May 2025 00:32:35 +0100 Subject: [PATCH 02/27] feat: settings topbar translation --- .../src/components/settings/settings-layout.tsx | 17 ++++++++++------- .../components/settings/settings-titlebar.tsx | 6 +++++- src/renderer/src/lib/i18n.ts | 2 +- src/renderer/src/locales/en/settings.json | 9 +++++++++ 4 files changed, 25 insertions(+), 9 deletions(-) create mode 100644 src/renderer/src/locales/en/settings.json diff --git a/src/renderer/src/components/settings/settings-layout.tsx b/src/renderer/src/components/settings/settings-layout.tsx index 1829285c..a82fbee5 100644 --- a/src/renderer/src/components/settings/settings-layout.tsx +++ b/src/renderer/src/components/settings/settings-layout.tsx @@ -12,20 +12,23 @@ import { SettingsProvider } from "@/components/providers/settings-provider"; import { AppUpdatesProvider } from "@/components/providers/app-updates-provider"; import { Globe, DockIcon, UsersIcon, OrbitIcon, BlocksIcon, Info, KeyboardIcon } from "lucide-react"; import { ShortcutsProvider } from "@/components/providers/shortcuts-provider"; +import { useTranslation } from "react-i18next"; export function SettingsLayout() { + const { t } = useTranslation("settings"); + const [activeSection, setActiveSection] = useState("general"); const [selectedProfileId, setSelectedProfileId] = useState(null); const [selectedSpaceId, setSelectedSpaceId] = useState(null); const sections = [ - { id: "general", label: "General", icon: }, - { id: "icons", label: "Icon", icon: }, - { id: "profiles", label: "Profiles", icon: }, - { id: "spaces", label: "Spaces", icon: }, - { id: "external-apps", label: "External Apps", icon: }, - { id: "shortcuts", label: "Shortcuts", icon: }, - { id: "about", label: "About", icon: } + { id: "general", label: t("General"), icon: }, + { id: "icons", label: t("Icon"), icon: }, + { id: "profiles", label: t("Profiles"), icon: }, + { id: "spaces", label: t("Spaces"), icon: }, + { id: "external-apps", label: t("External Apps"), icon: }, + { id: "shortcuts", label: t("Shortcuts"), icon: }, + { id: "about", label: t("About"), icon: } ]; const navigateToSpaces = (profileId: string) => { diff --git a/src/renderer/src/components/settings/settings-titlebar.tsx b/src/renderer/src/components/settings/settings-titlebar.tsx index 7564bc14..1f794d9d 100644 --- a/src/renderer/src/components/settings/settings-titlebar.tsx +++ b/src/renderer/src/components/settings/settings-titlebar.tsx @@ -1,9 +1,13 @@ "use client"; +import { useTranslation } from "react-i18next"; + export function SettingsTitlebar() { + const { t } = useTranslation("settings"); + return (
- Flow Settings + {t("Flow Settings")}
); } diff --git a/src/renderer/src/lib/i18n.ts b/src/renderer/src/lib/i18n.ts index f7da5e2a..e70ac43d 100644 --- a/src/renderer/src/lib/i18n.ts +++ b/src/renderer/src/lib/i18n.ts @@ -13,7 +13,7 @@ i18n lng: "en", // default language fallbackLng: "en", - ns: ["browser-ui"], + ns: ["browser-ui", "settings"], interpolation: { escapeValue: false // react already safes from xss diff --git a/src/renderer/src/locales/en/settings.json b/src/renderer/src/locales/en/settings.json new file mode 100644 index 00000000..ecb13b6c --- /dev/null +++ b/src/renderer/src/locales/en/settings.json @@ -0,0 +1,9 @@ +{ + "Flow Settings": "Flow Settings", + "General": "General", + "Icon": "Icon", + "Profiles": "Profiles", + "Spaces": "Spaces", + "External Apps": "External Apps", + "About": "About" +} From 5fd1f5dc4e4527ecd277c83fb72123b20fd9940b Mon Sep 17 00:00:00 2001 From: iamEvan <47493765+iamEvanYT@users.noreply.github.com> Date: Fri, 9 May 2025 00:35:05 +0100 Subject: [PATCH 03/27] fix: translation namespaces --- .../src/components/browser-ui/browser-action.tsx | 4 ++-- .../browser-ui/sidebar/content/new-tab-button.tsx | 4 ++-- .../browser-ui/sidebar/content/space-sidebar.tsx | 4 ++-- .../sidebar/header/address-bar/address-bar.tsx | 4 ++-- .../src/components/settings/settings-layout.tsx | 4 ++-- .../src/components/settings/settings-titlebar.tsx | 4 ++-- src/renderer/src/lib/i18n.ts | 10 +++++++++- 7 files changed, 21 insertions(+), 13 deletions(-) diff --git a/src/renderer/src/components/browser-ui/browser-action.tsx b/src/renderer/src/components/browser-ui/browser-action.tsx index 854699dd..9f0bb5ee 100644 --- a/src/renderer/src/components/browser-ui/browser-action.tsx +++ b/src/renderer/src/components/browser-ui/browser-action.tsx @@ -10,7 +10,7 @@ import { cn } from "@/lib/utils"; import { CogIcon, LayersIcon, PackageXIcon, PinIcon, PinOffIcon, PuzzleIcon } from "lucide-react"; import { MouseEvent, useCallback, useMemo, useRef, useState } from "react"; import { PortalPopover } from "@/components/portal/popover"; -import { useTranslation } from "react-i18next"; +import { useBrowserUITranslations } from "@/lib/i18n"; interface BrowserActionListProps { partition?: string; @@ -145,7 +145,7 @@ function BrowserAction({ action, alignment, partition, activeTabId }: BrowserAct } export function BrowserActionList({ alignmentX = "left", alignmentY = "bottom" }: BrowserActionListProps) { - const { t } = useTranslation(); + const { t } = useBrowserUITranslations(); const { isCurrentSpaceLight } = useSpaces(); const { actions, activeTabId, partition } = useBrowserAction(); const [open, setOpen] = useState(false); diff --git a/src/renderer/src/components/browser-ui/sidebar/content/new-tab-button.tsx b/src/renderer/src/components/browser-ui/sidebar/content/new-tab-button.tsx index c33bfa12..c5227722 100644 --- a/src/renderer/src/components/browser-ui/sidebar/content/new-tab-button.tsx +++ b/src/renderer/src/components/browser-ui/sidebar/content/new-tab-button.tsx @@ -4,12 +4,12 @@ import { SidebarMenuButton } from "@/components/ui/resizable-sidebar"; import { PlusIcon } from "lucide-react"; import { SIDEBAR_HOVER_COLOR } from "@/components/browser-ui/browser-sidebar"; import { cn } from "@/lib/utils"; -import { useTranslation } from "react-i18next"; +import { useBrowserUITranslations } from "@/lib/i18n"; const MotionSidebarMenuButton = motion(SidebarMenuButton); export function NewTabButton() { - const { t } = useTranslation(); + const { t } = useBrowserUITranslations(); const [isPressed, setIsPressed] = useState(false); const handleMouseDown = () => { diff --git a/src/renderer/src/components/browser-ui/sidebar/content/space-sidebar.tsx b/src/renderer/src/components/browser-ui/sidebar/content/space-sidebar.tsx index 1d8c0636..82e9a179 100644 --- a/src/renderer/src/components/browser-ui/sidebar/content/space-sidebar.tsx +++ b/src/renderer/src/components/browser-ui/sidebar/content/space-sidebar.tsx @@ -6,7 +6,7 @@ import { Button } from "@/components/ui/button"; import { SidebarGroup, SidebarMenu, useSidebar } from "@/components/ui/resizable-sidebar"; import { Space } from "~/flow/interfaces/sessions/spaces"; import { cn, hex_is_light } from "@/lib/utils"; -import { useTranslation } from "react-i18next"; +import { useBrowserUITranslations } from "@/lib/i18n"; import { AnimatePresence, motion } from "motion/react"; import { useCallback, useMemo, useRef } from "react"; import { DropIndicator as BaseDropIndicator } from "@atlaskit/pragmatic-drag-and-drop-react-drop-indicator/list-item"; @@ -39,7 +39,7 @@ export function DropIndicator({ isSpaceLight }: { isSpaceLight: boolean }) { function SidebarSectionDivider({ hasTabs, handleCloseAllTabs }: { hasTabs: boolean; handleCloseAllTabs: () => void }) { const { open } = useSidebar(); - const { t } = useTranslation(); + const { t } = useBrowserUITranslations(); if (!hasTabs) return null; diff --git a/src/renderer/src/components/browser-ui/sidebar/header/address-bar/address-bar.tsx b/src/renderer/src/components/browser-ui/sidebar/header/address-bar/address-bar.tsx index 6e70e6e7..95db5d52 100644 --- a/src/renderer/src/components/browser-ui/sidebar/header/address-bar/address-bar.tsx +++ b/src/renderer/src/components/browser-ui/sidebar/header/address-bar/address-bar.tsx @@ -2,14 +2,14 @@ import { AddressBarCopyLinkButton } from "@/components/browser-ui/sidebar/header import { PinnedBrowserActions } from "@/components/browser-ui/sidebar/header/address-bar/pinned-browser-actions"; import { useTabs } from "@/components/providers/tabs-provider"; import { SidebarGroup, useSidebar } from "@/components/ui/resizable-sidebar"; +import { useBrowserUITranslations } from "@/lib/i18n"; import { simplifyUrl } from "@/lib/url"; import { cn } from "@/lib/utils"; import { SearchIcon } from "lucide-react"; import { useRef } from "react"; -import { useTranslation } from "react-i18next"; function FakeAddressBar({ className }: { className?: string }) { - const { t } = useTranslation(); + const { t } = useBrowserUITranslations(); const inputRef = useRef(null); const { addressUrl, focusedTab } = useTabs(); diff --git a/src/renderer/src/components/settings/settings-layout.tsx b/src/renderer/src/components/settings/settings-layout.tsx index a82fbee5..76e325c1 100644 --- a/src/renderer/src/components/settings/settings-layout.tsx +++ b/src/renderer/src/components/settings/settings-layout.tsx @@ -12,10 +12,10 @@ import { SettingsProvider } from "@/components/providers/settings-provider"; import { AppUpdatesProvider } from "@/components/providers/app-updates-provider"; import { Globe, DockIcon, UsersIcon, OrbitIcon, BlocksIcon, Info, KeyboardIcon } from "lucide-react"; import { ShortcutsProvider } from "@/components/providers/shortcuts-provider"; -import { useTranslation } from "react-i18next"; +import { useSettingsTranslations } from "@/lib/i18n"; export function SettingsLayout() { - const { t } = useTranslation("settings"); + const { t } = useSettingsTranslations(); const [activeSection, setActiveSection] = useState("general"); const [selectedProfileId, setSelectedProfileId] = useState(null); diff --git a/src/renderer/src/components/settings/settings-titlebar.tsx b/src/renderer/src/components/settings/settings-titlebar.tsx index 1f794d9d..d619b79b 100644 --- a/src/renderer/src/components/settings/settings-titlebar.tsx +++ b/src/renderer/src/components/settings/settings-titlebar.tsx @@ -1,9 +1,9 @@ "use client"; -import { useTranslation } from "react-i18next"; +import { useSettingsTranslations } from "@/lib/i18n"; export function SettingsTitlebar() { - const { t } = useTranslation("settings"); + const { t } = useSettingsTranslations(); return (
diff --git a/src/renderer/src/lib/i18n.ts b/src/renderer/src/lib/i18n.ts index e70ac43d..8df2e8f2 100644 --- a/src/renderer/src/lib/i18n.ts +++ b/src/renderer/src/lib/i18n.ts @@ -1,5 +1,5 @@ import i18n from "i18next"; -import { initReactI18next } from "react-i18next"; +import { initReactI18next, useTranslation } from "react-i18next"; import resourcesToBackend from "i18next-resources-to-backend"; // Tell vite to load all locale files @@ -25,4 +25,12 @@ flow.app.getAppInfo().then((appInfo) => { i18n.changeLanguage(appInfo.locale); }); +export function useBrowserUITranslations() { + return useTranslation("browser-ui"); +} + +export function useSettingsTranslations() { + return useTranslation("settings"); +} + export default i18n; From 0a41d54127a61d8176f8586a795b4109183adeb8 Mon Sep 17 00:00:00 2001 From: iamEvan <47493765+iamEvanYT@users.noreply.github.com> Date: Fri, 9 May 2025 00:46:14 +0100 Subject: [PATCH 04/27] add: workflow --- .github/workflows/crowdin.yml | 37 +++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 .github/workflows/crowdin.yml diff --git a/.github/workflows/crowdin.yml b/.github/workflows/crowdin.yml new file mode 100644 index 00000000..52249fcf --- /dev/null +++ b/.github/workflows/crowdin.yml @@ -0,0 +1,37 @@ +name: Crowdin Action + +permissions: + contents: write + +on: + push: + branches: [main, evan/translations] + +jobs: + synchronize-with-crowdin: + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: crowdin action + uses: crowdin/github-action@v2 + with: + upload_sources: true + upload_translations: false + download_translations: true + localization_branch_name: l10n_crowdin_translations + create_pull_request: true + pull_request_title: "New Crowdin Translations" + pull_request_body: "New Crowdin translations by [Crowdin GH Action](https://github.com/crowdin/github-action)" + pull_request_base_branch_name: "main" + env: + # A classic GitHub Personal Access Token with the 'repo' scope selected (the user should have write access to the repository). + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + # A numeric ID, found at https://crowdin.com/project//tools/api + CROWDIN_PROJECT_ID: ${{ secrets.CROWDIN_PROJECT_ID }} + + # Visit https://crowdin.com/settings#api-key to create this token + CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }} From 38f691e0a3842400d3cb62040f7d0c902d4c5cbe Mon Sep 17 00:00:00 2001 From: iamEvan <47493765+iamEvanYT@users.noreply.github.com> Date: Fri, 9 May 2025 00:48:02 +0100 Subject: [PATCH 05/27] fix: add crowdin.yml --- crowdin.yml | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 crowdin.yml diff --git a/crowdin.yml b/crowdin.yml new file mode 100644 index 00000000..657fcc4c --- /dev/null +++ b/crowdin.yml @@ -0,0 +1,13 @@ +"project_id_env": "CROWDIN_PROJECT_ID" +"api_token_env": "CROWDIN_PERSONAL_TOKEN" +"base_path": "." + +"preserve_hierarchy": true + +"files": + [ + { + "source": "src/renderer/src/locales/en/*.json", + "translation": "src/renderer/src/locales/%two_letters_code%/*.json" + } + ] From 0f258666b0ab85aee042316b6459908de6de34e1 Mon Sep 17 00:00:00 2001 From: iamEvan <47493765+iamEvanYT@users.noreply.github.com> Date: Fri, 9 May 2025 00:49:15 +0100 Subject: [PATCH 06/27] fix: crowdin config --- crowdin.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crowdin.yml b/crowdin.yml index 657fcc4c..bd5bf172 100644 --- a/crowdin.yml +++ b/crowdin.yml @@ -8,6 +8,6 @@ [ { "source": "src/renderer/src/locales/en/*.json", - "translation": "src/renderer/src/locales/%two_letters_code%/*.json" + "translation": "src/renderer/src/locales/%two_letters_code%/%original_file_name%" } ] From cc108988a3a498def0c1b7d48f572b9993ee4076 Mon Sep 17 00:00:00 2001 From: iamEvan <47493765+iamEvanYT@users.noreply.github.com> Date: Fri, 9 May 2025 00:51:19 +0100 Subject: [PATCH 07/27] fix: crowdin permissions --- .github/workflows/crowdin.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/crowdin.yml b/.github/workflows/crowdin.yml index 52249fcf..7647b5d6 100644 --- a/.github/workflows/crowdin.yml +++ b/.github/workflows/crowdin.yml @@ -2,6 +2,7 @@ name: Crowdin Action permissions: contents: write + pull-requests: write on: push: From 7e63fb37ee9982061f2819e62ad46fac401486aa Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 9 May 2025 00:55:19 +0100 Subject: [PATCH 08/27] New Crowdin translations by GitHub Action (#38) Co-authored-by: Crowdin Bot --- src/renderer/src/locales/pl/browser-ui.json | 8 ++++++++ src/renderer/src/locales/pl/settings.json | 9 +++++++++ src/renderer/src/locales/zh/browser-ui.json | 8 ++++++++ src/renderer/src/locales/zh/settings.json | 9 +++++++++ 4 files changed, 34 insertions(+) create mode 100644 src/renderer/src/locales/pl/browser-ui.json create mode 100644 src/renderer/src/locales/pl/settings.json create mode 100644 src/renderer/src/locales/zh/browser-ui.json create mode 100644 src/renderer/src/locales/zh/settings.json diff --git a/src/renderer/src/locales/pl/browser-ui.json b/src/renderer/src/locales/pl/browser-ui.json new file mode 100644 index 00000000..3e52b127 --- /dev/null +++ b/src/renderer/src/locales/pl/browser-ui.json @@ -0,0 +1,8 @@ +{ + "Tabs": "Tabs", + "New Tab": "New Tab", + "Search or type URL": "Search or type URL", + "No Active Tab": "No Active Tab", + "No Extensions Available": "No Extensions Available", + "Manage Extensions": "Manage Extensions" +} diff --git a/src/renderer/src/locales/pl/settings.json b/src/renderer/src/locales/pl/settings.json new file mode 100644 index 00000000..ecb13b6c --- /dev/null +++ b/src/renderer/src/locales/pl/settings.json @@ -0,0 +1,9 @@ +{ + "Flow Settings": "Flow Settings", + "General": "General", + "Icon": "Icon", + "Profiles": "Profiles", + "Spaces": "Spaces", + "External Apps": "External Apps", + "About": "About" +} diff --git a/src/renderer/src/locales/zh/browser-ui.json b/src/renderer/src/locales/zh/browser-ui.json new file mode 100644 index 00000000..3e52b127 --- /dev/null +++ b/src/renderer/src/locales/zh/browser-ui.json @@ -0,0 +1,8 @@ +{ + "Tabs": "Tabs", + "New Tab": "New Tab", + "Search or type URL": "Search or type URL", + "No Active Tab": "No Active Tab", + "No Extensions Available": "No Extensions Available", + "Manage Extensions": "Manage Extensions" +} diff --git a/src/renderer/src/locales/zh/settings.json b/src/renderer/src/locales/zh/settings.json new file mode 100644 index 00000000..ecb13b6c --- /dev/null +++ b/src/renderer/src/locales/zh/settings.json @@ -0,0 +1,9 @@ +{ + "Flow Settings": "Flow Settings", + "General": "General", + "Icon": "Icon", + "Profiles": "Profiles", + "Spaces": "Spaces", + "External Apps": "External Apps", + "About": "About" +} From ad68dad1f96fac2c92992927f8a2f4c1a3a67836 Mon Sep 17 00:00:00 2001 From: iamEvan <47493765+iamEvanYT@users.noreply.github.com> Date: Fri, 9 May 2025 00:55:38 +0100 Subject: [PATCH 09/27] chore: remove test branch --- .github/workflows/crowdin.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/crowdin.yml b/.github/workflows/crowdin.yml index 7647b5d6..69e6d430 100644 --- a/.github/workflows/crowdin.yml +++ b/.github/workflows/crowdin.yml @@ -6,7 +6,7 @@ permissions: on: push: - branches: [main, evan/translations] + branches: [main] jobs: synchronize-with-crowdin: From b2c99bc8cdd8dde15e4429f0352b76b4e3e90464 Mon Sep 17 00:00:00 2001 From: iamEvan <47493765+iamEvanYT@users.noreply.github.com> Date: Fri, 9 May 2025 08:03:17 +0100 Subject: [PATCH 10/27] move: locales to shared folder --- crowdin.yml | 4 ++-- src/renderer/src/lib/i18n.ts | 4 ++-- src/{renderer/src => shared}/locales/en/browser-ui.json | 0 src/{renderer/src => shared}/locales/en/settings.json | 0 src/{renderer/src => shared}/locales/pl/browser-ui.json | 0 src/{renderer/src => shared}/locales/pl/settings.json | 0 src/{renderer/src => shared}/locales/zh/browser-ui.json | 0 src/{renderer/src => shared}/locales/zh/settings.json | 0 8 files changed, 4 insertions(+), 4 deletions(-) rename src/{renderer/src => shared}/locales/en/browser-ui.json (100%) rename src/{renderer/src => shared}/locales/en/settings.json (100%) rename src/{renderer/src => shared}/locales/pl/browser-ui.json (100%) rename src/{renderer/src => shared}/locales/pl/settings.json (100%) rename src/{renderer/src => shared}/locales/zh/browser-ui.json (100%) rename src/{renderer/src => shared}/locales/zh/settings.json (100%) diff --git a/crowdin.yml b/crowdin.yml index bd5bf172..faeee832 100644 --- a/crowdin.yml +++ b/crowdin.yml @@ -7,7 +7,7 @@ "files": [ { - "source": "src/renderer/src/locales/en/*.json", - "translation": "src/renderer/src/locales/%two_letters_code%/%original_file_name%" + "source": "src/shared/locales/en/*.json", + "translation": "src/shared/locales/%two_letters_code%/%original_file_name%" } ] diff --git a/src/renderer/src/lib/i18n.ts b/src/renderer/src/lib/i18n.ts index 8df2e8f2..d336e9ce 100644 --- a/src/renderer/src/lib/i18n.ts +++ b/src/renderer/src/lib/i18n.ts @@ -3,11 +3,11 @@ import { initReactI18next, useTranslation } from "react-i18next"; import resourcesToBackend from "i18next-resources-to-backend"; // Tell vite to load all locale files -import.meta.glob("@/locales/*/*.json"); +import.meta.glob("~/locales/*/*.json"); // Initialize i18n as quickly as possible i18n - .use(resourcesToBackend((language: string, namespace: string) => import(`@/locales/${language}/${namespace}.json`))) + .use(resourcesToBackend((language: string, namespace: string) => import(`~/locales/${language}/${namespace}.json`))) .use(initReactI18next) // passes i18n down to react-i18next .init({ lng: "en", // default language diff --git a/src/renderer/src/locales/en/browser-ui.json b/src/shared/locales/en/browser-ui.json similarity index 100% rename from src/renderer/src/locales/en/browser-ui.json rename to src/shared/locales/en/browser-ui.json diff --git a/src/renderer/src/locales/en/settings.json b/src/shared/locales/en/settings.json similarity index 100% rename from src/renderer/src/locales/en/settings.json rename to src/shared/locales/en/settings.json diff --git a/src/renderer/src/locales/pl/browser-ui.json b/src/shared/locales/pl/browser-ui.json similarity index 100% rename from src/renderer/src/locales/pl/browser-ui.json rename to src/shared/locales/pl/browser-ui.json diff --git a/src/renderer/src/locales/pl/settings.json b/src/shared/locales/pl/settings.json similarity index 100% rename from src/renderer/src/locales/pl/settings.json rename to src/shared/locales/pl/settings.json diff --git a/src/renderer/src/locales/zh/browser-ui.json b/src/shared/locales/zh/browser-ui.json similarity index 100% rename from src/renderer/src/locales/zh/browser-ui.json rename to src/shared/locales/zh/browser-ui.json diff --git a/src/renderer/src/locales/zh/settings.json b/src/shared/locales/zh/settings.json similarity index 100% rename from src/renderer/src/locales/zh/settings.json rename to src/shared/locales/zh/settings.json From 4450eccd3bf9b571f5cdc9b3cbb7261dfa4be224 Mon Sep 17 00:00:00 2001 From: iamEvan <47493765+iamEvanYT@users.noreply.github.com> Date: Fri, 9 May 2025 08:04:02 +0100 Subject: [PATCH 11/27] test: gh action --- .github/workflows/crowdin.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/crowdin.yml b/.github/workflows/crowdin.yml index 69e6d430..7647b5d6 100644 --- a/.github/workflows/crowdin.yml +++ b/.github/workflows/crowdin.yml @@ -6,7 +6,7 @@ permissions: on: push: - branches: [main] + branches: [main, evan/translations] jobs: synchronize-with-crowdin: From 95dbf449d14fc5558e0da487872ed7a49562dbf9 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 9 May 2025 08:14:22 +0100 Subject: [PATCH 12/27] New Crowdin translations by GitHub Action (#39) Co-authored-by: Crowdin Bot --- src/shared/locales/pl/browser-ui.json | 12 ++++++------ src/shared/locales/pl/settings.json | 14 +++++++------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/shared/locales/pl/browser-ui.json b/src/shared/locales/pl/browser-ui.json index 3e52b127..15a690c9 100644 --- a/src/shared/locales/pl/browser-ui.json +++ b/src/shared/locales/pl/browser-ui.json @@ -1,8 +1,8 @@ { - "Tabs": "Tabs", - "New Tab": "New Tab", - "Search or type URL": "Search or type URL", - "No Active Tab": "No Active Tab", - "No Extensions Available": "No Extensions Available", - "Manage Extensions": "Manage Extensions" + "Tabs": "Karty", + "New Tab": "Nowa karta", + "Search or type URL": "Wyszukaj lub wpisz URL", + "No Active Tab": "Brak aktywnej karty", + "No Extensions Available": "Brak dostępnych rozszerzeń", + "Manage Extensions": "Zarządzaj rozszerzeniami" } diff --git a/src/shared/locales/pl/settings.json b/src/shared/locales/pl/settings.json index ecb13b6c..f32ffc6b 100644 --- a/src/shared/locales/pl/settings.json +++ b/src/shared/locales/pl/settings.json @@ -1,9 +1,9 @@ { - "Flow Settings": "Flow Settings", - "General": "General", - "Icon": "Icon", - "Profiles": "Profiles", - "Spaces": "Spaces", - "External Apps": "External Apps", - "About": "About" + "Flow Settings": "Ustawienia Flow", + "General": "Ogólne", + "Icon": "Ikona", + "Profiles": "Profile", + "Spaces": "Obszary", + "External Apps": "Aplikacje zewnętrzne", + "About": "O Flow" } From a9426baefc91759dce91ac3c98a3b27e22ef3900 Mon Sep 17 00:00:00 2001 From: iamEvan <47493765+iamEvanYT@users.noreply.github.com> Date: Fri, 9 May 2025 08:15:18 +0100 Subject: [PATCH 13/27] chore: disable gh action on branch --- .github/workflows/crowdin.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/crowdin.yml b/.github/workflows/crowdin.yml index 7647b5d6..71732157 100644 --- a/.github/workflows/crowdin.yml +++ b/.github/workflows/crowdin.yml @@ -6,7 +6,7 @@ permissions: on: push: - branches: [main, evan/translations] + branches: [main] jobs: synchronize-with-crowdin: @@ -16,7 +16,7 @@ jobs: - name: Checkout uses: actions/checkout@v4 - - name: crowdin action + - name: Crowdin Action uses: crowdin/github-action@v2 with: upload_sources: true From d4feaa633e0f6db2a2f87b070ecd8fd15d3465d0 Mon Sep 17 00:00:00 2001 From: iamEvan <47493765+iamEvanYT@users.noreply.github.com> Date: Fri, 9 May 2025 08:24:00 +0100 Subject: [PATCH 14/27] enhancement: add locale to posthog analytics --- src/main/modules/posthog.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/modules/posthog.ts b/src/main/modules/posthog.ts index bf10c740..a7c9d35e 100644 --- a/src/main/modules/posthog.ts +++ b/src/main/modules/posthog.ts @@ -46,7 +46,8 @@ function getAppInfoForPosthog() { return { version: app.getVersion(), platform: process.platform, - environment: process.env.NODE_ENV + environment: process.env.NODE_ENV, + locale: app.getLocale() }; } From 421b3c9d7b842936bffd8751e12879a3f198b93a Mon Sep 17 00:00:00 2001 From: iamEvan <47493765+iamEvanYT@users.noreply.github.com> Date: Fri, 9 May 2025 09:13:29 +0100 Subject: [PATCH 15/27] feat: add general and icons --- .github/workflows/crowdin.yml | 2 +- crowdin.yml | 7 +------ .../components/settings/sections/general/section.tsx | 7 +++++-- .../src/components/settings/sections/icon/section.tsx | 10 +++++++--- src/renderer/src/lib/i18n.ts | 6 +++++- src/shared/locales/en/icons.json | 10 ++++++++++ src/shared/locales/en/settings.json | 5 ++++- 7 files changed, 33 insertions(+), 14 deletions(-) create mode 100644 src/shared/locales/en/icons.json diff --git a/.github/workflows/crowdin.yml b/.github/workflows/crowdin.yml index 71732157..a777e7d6 100644 --- a/.github/workflows/crowdin.yml +++ b/.github/workflows/crowdin.yml @@ -6,7 +6,7 @@ permissions: on: push: - branches: [main] + branches: [main, evan/translations] jobs: synchronize-with-crowdin: diff --git a/crowdin.yml b/crowdin.yml index faeee832..68bf99ee 100644 --- a/crowdin.yml +++ b/crowdin.yml @@ -5,9 +5,4 @@ "preserve_hierarchy": true "files": - [ - { - "source": "src/shared/locales/en/*.json", - "translation": "src/shared/locales/%two_letters_code%/%original_file_name%" - } - ] + [{ "source": "src/shared/locales/en/*.json", "translation": "src/shared/locales/%locale%/%original_file_name%" }] diff --git a/src/renderer/src/components/settings/sections/general/section.tsx b/src/renderer/src/components/settings/sections/general/section.tsx index b9b9e8bf..9fe59cbc 100644 --- a/src/renderer/src/components/settings/sections/general/section.tsx +++ b/src/renderer/src/components/settings/sections/general/section.tsx @@ -1,11 +1,14 @@ import { BasicSettingsCards } from "@/components/settings/sections/general/basic-settings-cards"; +import { useSettingsTranslations } from "@/lib/i18n"; export function GeneralSettings() { + const { t } = useSettingsTranslations(); + return (
-

General

-

{"Manage your browser's general settings"}

+

{t("General")}

+

{t("Manage your browser's general settings")}

diff --git a/src/renderer/src/components/settings/sections/icon/section.tsx b/src/renderer/src/components/settings/sections/icon/section.tsx index 7449aff1..e04a1545 100644 --- a/src/renderer/src/components/settings/sections/icon/section.tsx +++ b/src/renderer/src/components/settings/sections/icon/section.tsx @@ -3,6 +3,7 @@ import { Check, Loader2 } from "lucide-react"; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; import { motion } from "motion/react"; import { toast } from "sonner"; +import { useIconsTranslations, useSettingsTranslations } from "@/lib/i18n"; interface IconOption { id: string; @@ -13,6 +14,9 @@ interface IconOption { } export function IconSettings() { + const { t } = useSettingsTranslations(); + const { t: tIcons } = useIconsTranslations(); + const [selectedIcon, setSelectedIcon] = useState(""); const [iconOptions, setIconOptions] = useState([]); const [isUpdating, setIsUpdating] = useState(false); @@ -89,8 +93,8 @@ export function IconSettings() {
- Browser Icon - Select an icon for your browser application + {t("Browser Icon")} + {t("Select an icon for your browser application")} {!isSupported ? ( @@ -131,7 +135,7 @@ export function IconSettings() {
-

{icon.name}

+

{tIcons(icon.name)}

{icon.author &&

by {icon.author}

}
diff --git a/src/renderer/src/lib/i18n.ts b/src/renderer/src/lib/i18n.ts index d336e9ce..612c1023 100644 --- a/src/renderer/src/lib/i18n.ts +++ b/src/renderer/src/lib/i18n.ts @@ -13,7 +13,7 @@ i18n lng: "en", // default language fallbackLng: "en", - ns: ["browser-ui", "settings"], + ns: ["browser-ui", "settings", "icons"], interpolation: { escapeValue: false // react already safes from xss @@ -33,4 +33,8 @@ export function useSettingsTranslations() { return useTranslation("settings"); } +export function useIconsTranslations() { + return useTranslation("icons"); +} + export default i18n; diff --git a/src/shared/locales/en/icons.json b/src/shared/locales/en/icons.json new file mode 100644 index 00000000..5eca8bee --- /dev/null +++ b/src/shared/locales/en/icons.json @@ -0,0 +1,10 @@ +{ + "Default": "Default", + "Nature": "Nature", + "3D": "3D", + "Darkness": "Darkness", + "Glowy": "Glowy", + "Minimal Flat": "Minimal Flat", + "Retro": "Retro", + "Summer": "Summer" +} diff --git a/src/shared/locales/en/settings.json b/src/shared/locales/en/settings.json index ecb13b6c..db1a9c97 100644 --- a/src/shared/locales/en/settings.json +++ b/src/shared/locales/en/settings.json @@ -5,5 +5,8 @@ "Profiles": "Profiles", "Spaces": "Spaces", "External Apps": "External Apps", - "About": "About" + "About": "About", + "Manage your browser's general settings": "Manage your browser's general settings", + "Browser Icon": "Browser Icon", + "Select an icon for your browser application": "Select an icon for your browser application" } From 5f3503d4954316f2947aa6f28308d245f97c39c3 Mon Sep 17 00:00:00 2001 From: iamEvan <47493765+iamEvanYT@users.noreply.github.com> Date: Fri, 9 May 2025 09:16:02 +0100 Subject: [PATCH 16/27] renamed: en -> en-US --- crowdin.yml | 2 +- src/shared/locales/{en => en-US}/browser-ui.json | 0 src/shared/locales/{en => en-US}/icons.json | 0 src/shared/locales/{en => en-US}/settings.json | 0 4 files changed, 1 insertion(+), 1 deletion(-) rename src/shared/locales/{en => en-US}/browser-ui.json (100%) rename src/shared/locales/{en => en-US}/icons.json (100%) rename src/shared/locales/{en => en-US}/settings.json (100%) diff --git a/crowdin.yml b/crowdin.yml index 68bf99ee..d7c5ce0e 100644 --- a/crowdin.yml +++ b/crowdin.yml @@ -5,4 +5,4 @@ "preserve_hierarchy": true "files": - [{ "source": "src/shared/locales/en/*.json", "translation": "src/shared/locales/%locale%/%original_file_name%" }] + [{ "source": "src/shared/locales/en-US/*.json", "translation": "src/shared/locales/%locale%/%original_file_name%" }] diff --git a/src/shared/locales/en/browser-ui.json b/src/shared/locales/en-US/browser-ui.json similarity index 100% rename from src/shared/locales/en/browser-ui.json rename to src/shared/locales/en-US/browser-ui.json diff --git a/src/shared/locales/en/icons.json b/src/shared/locales/en-US/icons.json similarity index 100% rename from src/shared/locales/en/icons.json rename to src/shared/locales/en-US/icons.json diff --git a/src/shared/locales/en/settings.json b/src/shared/locales/en-US/settings.json similarity index 100% rename from src/shared/locales/en/settings.json rename to src/shared/locales/en-US/settings.json From 5e2264599944cb9c22fbefee49e568971ebee1c3 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 9 May 2025 09:17:18 +0100 Subject: [PATCH 17/27] New Crowdin translations by GitHub Action (#40) Co-authored-by: Crowdin Bot --- src/shared/locales/pl-PL/browser-ui.json | 8 ++++++++ src/shared/locales/pl-PL/icons.json | 10 ++++++++++ src/shared/locales/pl-PL/settings.json | 12 ++++++++++++ src/shared/locales/zh-CN/browser-ui.json | 8 ++++++++ src/shared/locales/zh-CN/icons.json | 10 ++++++++++ src/shared/locales/zh-CN/settings.json | 12 ++++++++++++ src/shared/locales/zh-TW/browser-ui.json | 8 ++++++++ src/shared/locales/zh-TW/icons.json | 10 ++++++++++ src/shared/locales/zh-TW/settings.json | 12 ++++++++++++ 9 files changed, 90 insertions(+) create mode 100644 src/shared/locales/pl-PL/browser-ui.json create mode 100644 src/shared/locales/pl-PL/icons.json create mode 100644 src/shared/locales/pl-PL/settings.json create mode 100644 src/shared/locales/zh-CN/browser-ui.json create mode 100644 src/shared/locales/zh-CN/icons.json create mode 100644 src/shared/locales/zh-CN/settings.json create mode 100644 src/shared/locales/zh-TW/browser-ui.json create mode 100644 src/shared/locales/zh-TW/icons.json create mode 100644 src/shared/locales/zh-TW/settings.json diff --git a/src/shared/locales/pl-PL/browser-ui.json b/src/shared/locales/pl-PL/browser-ui.json new file mode 100644 index 00000000..15a690c9 --- /dev/null +++ b/src/shared/locales/pl-PL/browser-ui.json @@ -0,0 +1,8 @@ +{ + "Tabs": "Karty", + "New Tab": "Nowa karta", + "Search or type URL": "Wyszukaj lub wpisz URL", + "No Active Tab": "Brak aktywnej karty", + "No Extensions Available": "Brak dostępnych rozszerzeń", + "Manage Extensions": "Zarządzaj rozszerzeniami" +} diff --git a/src/shared/locales/pl-PL/icons.json b/src/shared/locales/pl-PL/icons.json new file mode 100644 index 00000000..5eca8bee --- /dev/null +++ b/src/shared/locales/pl-PL/icons.json @@ -0,0 +1,10 @@ +{ + "Default": "Default", + "Nature": "Nature", + "3D": "3D", + "Darkness": "Darkness", + "Glowy": "Glowy", + "Minimal Flat": "Minimal Flat", + "Retro": "Retro", + "Summer": "Summer" +} diff --git a/src/shared/locales/pl-PL/settings.json b/src/shared/locales/pl-PL/settings.json new file mode 100644 index 00000000..6517755f --- /dev/null +++ b/src/shared/locales/pl-PL/settings.json @@ -0,0 +1,12 @@ +{ + "Flow Settings": "Ustawienia Flow", + "General": "Ogólne", + "Icon": "Ikona", + "Profiles": "Profile", + "Spaces": "Obszary", + "External Apps": "Aplikacje zewnętrzne", + "About": "O Flow", + "Manage your browser's general settings": "Manage your browser's general settings", + "Browser Icon": "Browser Icon", + "Select an icon for your browser application": "Select an icon for your browser application" +} diff --git a/src/shared/locales/zh-CN/browser-ui.json b/src/shared/locales/zh-CN/browser-ui.json new file mode 100644 index 00000000..a44396fd --- /dev/null +++ b/src/shared/locales/zh-CN/browser-ui.json @@ -0,0 +1,8 @@ +{ + "Tabs": "标签页", + "New Tab": "新标签页", + "Search or type URL": "搜索或输入网址", + "No Active Tab": "没有活动的标签页", + "No Extensions Available": "没有可用的扩展程序", + "Manage Extensions": "管理扩展程序" +} diff --git a/src/shared/locales/zh-CN/icons.json b/src/shared/locales/zh-CN/icons.json new file mode 100644 index 00000000..5eca8bee --- /dev/null +++ b/src/shared/locales/zh-CN/icons.json @@ -0,0 +1,10 @@ +{ + "Default": "Default", + "Nature": "Nature", + "3D": "3D", + "Darkness": "Darkness", + "Glowy": "Glowy", + "Minimal Flat": "Minimal Flat", + "Retro": "Retro", + "Summer": "Summer" +} diff --git a/src/shared/locales/zh-CN/settings.json b/src/shared/locales/zh-CN/settings.json new file mode 100644 index 00000000..a5caf141 --- /dev/null +++ b/src/shared/locales/zh-CN/settings.json @@ -0,0 +1,12 @@ +{ + "Flow Settings": "Flow 设置", + "General": "一般", + "Icon": "图标", + "Profiles": "設定檔配置文件", + "Spaces": "空间", + "External Apps": "外部应用程序", + "About": "关于", + "Manage your browser's general settings": "Manage your browser's general settings", + "Browser Icon": "Browser Icon", + "Select an icon for your browser application": "Select an icon for your browser application" +} diff --git a/src/shared/locales/zh-TW/browser-ui.json b/src/shared/locales/zh-TW/browser-ui.json new file mode 100644 index 00000000..d86f31bc --- /dev/null +++ b/src/shared/locales/zh-TW/browser-ui.json @@ -0,0 +1,8 @@ +{ + "Tabs": "分頁", + "New Tab": "新分頁", + "Search or type URL": "搜尋或輸入網址", + "No Active Tab": "沒有使用中的分頁", + "No Extensions Available": "沒有可用的擴充功能", + "Manage Extensions": "管理擴充功能" +} diff --git a/src/shared/locales/zh-TW/icons.json b/src/shared/locales/zh-TW/icons.json new file mode 100644 index 00000000..5eca8bee --- /dev/null +++ b/src/shared/locales/zh-TW/icons.json @@ -0,0 +1,10 @@ +{ + "Default": "Default", + "Nature": "Nature", + "3D": "3D", + "Darkness": "Darkness", + "Glowy": "Glowy", + "Minimal Flat": "Minimal Flat", + "Retro": "Retro", + "Summer": "Summer" +} diff --git a/src/shared/locales/zh-TW/settings.json b/src/shared/locales/zh-TW/settings.json new file mode 100644 index 00000000..7467afa4 --- /dev/null +++ b/src/shared/locales/zh-TW/settings.json @@ -0,0 +1,12 @@ +{ + "Flow Settings": "Flow 設定", + "General": "一般", + "Icon": "圖示", + "Profiles": "設定檔", + "Spaces": "空間", + "External Apps": "外部應用程式", + "About": "關於", + "Manage your browser's general settings": "Manage your browser's general settings", + "Browser Icon": "Browser Icon", + "Select an icon for your browser application": "Select an icon for your browser application" +} From 5df3b266e92ef6e0d5f9fa4bc80f7c60e84e685c Mon Sep 17 00:00:00 2001 From: iamEvan <47493765+iamEvanYT@users.noreply.github.com> Date: Fri, 9 May 2025 09:19:20 +0100 Subject: [PATCH 18/27] remove: old languages --- src/shared/locales/pl/browser-ui.json | 8 -------- src/shared/locales/pl/settings.json | 9 --------- src/shared/locales/zh/browser-ui.json | 8 -------- src/shared/locales/zh/settings.json | 9 --------- 4 files changed, 34 deletions(-) delete mode 100644 src/shared/locales/pl/browser-ui.json delete mode 100644 src/shared/locales/pl/settings.json delete mode 100644 src/shared/locales/zh/browser-ui.json delete mode 100644 src/shared/locales/zh/settings.json diff --git a/src/shared/locales/pl/browser-ui.json b/src/shared/locales/pl/browser-ui.json deleted file mode 100644 index 15a690c9..00000000 --- a/src/shared/locales/pl/browser-ui.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "Tabs": "Karty", - "New Tab": "Nowa karta", - "Search or type URL": "Wyszukaj lub wpisz URL", - "No Active Tab": "Brak aktywnej karty", - "No Extensions Available": "Brak dostępnych rozszerzeń", - "Manage Extensions": "Zarządzaj rozszerzeniami" -} diff --git a/src/shared/locales/pl/settings.json b/src/shared/locales/pl/settings.json deleted file mode 100644 index f32ffc6b..00000000 --- a/src/shared/locales/pl/settings.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "Flow Settings": "Ustawienia Flow", - "General": "Ogólne", - "Icon": "Ikona", - "Profiles": "Profile", - "Spaces": "Obszary", - "External Apps": "Aplikacje zewnętrzne", - "About": "O Flow" -} diff --git a/src/shared/locales/zh/browser-ui.json b/src/shared/locales/zh/browser-ui.json deleted file mode 100644 index 3e52b127..00000000 --- a/src/shared/locales/zh/browser-ui.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "Tabs": "Tabs", - "New Tab": "New Tab", - "Search or type URL": "Search or type URL", - "No Active Tab": "No Active Tab", - "No Extensions Available": "No Extensions Available", - "Manage Extensions": "Manage Extensions" -} diff --git a/src/shared/locales/zh/settings.json b/src/shared/locales/zh/settings.json deleted file mode 100644 index ecb13b6c..00000000 --- a/src/shared/locales/zh/settings.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "Flow Settings": "Flow Settings", - "General": "General", - "Icon": "Icon", - "Profiles": "Profiles", - "Spaces": "Spaces", - "External Apps": "External Apps", - "About": "About" -} From 1d325b3d6d0a80285639b5f139b3c1d74c435f63 Mon Sep 17 00:00:00 2001 From: iamEvan <47493765+iamEvanYT@users.noreply.github.com> Date: Fri, 9 May 2025 09:23:58 +0100 Subject: [PATCH 19/27] chore: disable gh action on branch --- .github/workflows/crowdin.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/crowdin.yml b/.github/workflows/crowdin.yml index a777e7d6..71732157 100644 --- a/.github/workflows/crowdin.yml +++ b/.github/workflows/crowdin.yml @@ -6,7 +6,7 @@ permissions: on: push: - branches: [main, evan/translations] + branches: [main] jobs: synchronize-with-crowdin: From dc15ec239cf1766a12aee7301a821360870511f2 Mon Sep 17 00:00:00 2001 From: iamEvan <47493765+iamEvanYT@users.noreply.github.com> Date: Fri, 9 May 2025 18:30:17 +0100 Subject: [PATCH 20/27] chore: update use variables --- .../src/components/browser-ui/browser-action.tsx | 8 ++++---- .../sidebar/content/new-tab-button.tsx | 4 ++-- .../browser-ui/sidebar/content/space-sidebar.tsx | 4 ++-- .../sidebar/header/address-bar/address-bar.tsx | 4 ++-- .../settings/sections/general/section.tsx | 6 +++--- .../settings/sections/icon/section.tsx | 8 +++++--- .../src/components/settings/settings-layout.tsx | 16 ++++++++-------- .../components/settings/settings-titlebar.tsx | 4 ++-- 8 files changed, 28 insertions(+), 26 deletions(-) diff --git a/src/renderer/src/components/browser-ui/browser-action.tsx b/src/renderer/src/components/browser-ui/browser-action.tsx index 9f0bb5ee..f96d3339 100644 --- a/src/renderer/src/components/browser-ui/browser-action.tsx +++ b/src/renderer/src/components/browser-ui/browser-action.tsx @@ -145,7 +145,7 @@ function BrowserAction({ action, alignment, partition, activeTabId }: BrowserAct } export function BrowserActionList({ alignmentX = "left", alignmentY = "bottom" }: BrowserActionListProps) { - const { t } = useBrowserUITranslations(); + const { t: tBrowserUI } = useBrowserUITranslations(); const { isCurrentSpaceLight } = useSpaces(); const { actions, activeTabId, partition } = useBrowserAction(); const [open, setOpen] = useState(false); @@ -186,19 +186,19 @@ export function BrowserActionList({ alignmentX = "left", alignmentY = "bottom" } {noActiveTab && ( - {t("No Active Tab")} + {tBrowserUI("No Active Tab")} )} {!noActiveTab && noActions && ( - {t("No Extensions Available")} + {tBrowserUI("No Extensions Available")} )} - {t("Manage Extensions")} + {tBrowserUI("Manage Extensions")} diff --git a/src/renderer/src/components/browser-ui/sidebar/content/new-tab-button.tsx b/src/renderer/src/components/browser-ui/sidebar/content/new-tab-button.tsx index c5227722..642a91cd 100644 --- a/src/renderer/src/components/browser-ui/sidebar/content/new-tab-button.tsx +++ b/src/renderer/src/components/browser-ui/sidebar/content/new-tab-button.tsx @@ -9,7 +9,7 @@ import { useBrowserUITranslations } from "@/lib/i18n"; const MotionSidebarMenuButton = motion(SidebarMenuButton); export function NewTabButton() { - const { t } = useBrowserUITranslations(); + const { t: tBrowserUI } = useBrowserUITranslations(); const [isPressed, setIsPressed] = useState(false); const handleMouseDown = () => { @@ -34,7 +34,7 @@ export function NewTabButton() { className={cn(SIDEBAR_HOVER_COLOR, "text-black/50 dark:text-muted-foreground")} > - {t("New Tab")} + {tBrowserUI("New Tab")} ); } diff --git a/src/renderer/src/components/browser-ui/sidebar/content/space-sidebar.tsx b/src/renderer/src/components/browser-ui/sidebar/content/space-sidebar.tsx index 82e9a179..6057b7ad 100644 --- a/src/renderer/src/components/browser-ui/sidebar/content/space-sidebar.tsx +++ b/src/renderer/src/components/browser-ui/sidebar/content/space-sidebar.tsx @@ -39,7 +39,7 @@ export function DropIndicator({ isSpaceLight }: { isSpaceLight: boolean }) { function SidebarSectionDivider({ hasTabs, handleCloseAllTabs }: { hasTabs: boolean; handleCloseAllTabs: () => void }) { const { open } = useSidebar(); - const { t } = useBrowserUITranslations(); + const { t: tBrowserUI } = useBrowserUITranslations(); if (!hasTabs) return null; @@ -64,7 +64,7 @@ function SidebarSectionDivider({ hasTabs, handleCloseAllTabs }: { hasTabs: boole size="sm" onClick={handleCloseAllTabs} > - {t("Clear")} + {tBrowserUI("Clear")} )} diff --git a/src/renderer/src/components/browser-ui/sidebar/header/address-bar/address-bar.tsx b/src/renderer/src/components/browser-ui/sidebar/header/address-bar/address-bar.tsx index 95db5d52..bc03e109 100644 --- a/src/renderer/src/components/browser-ui/sidebar/header/address-bar/address-bar.tsx +++ b/src/renderer/src/components/browser-ui/sidebar/header/address-bar/address-bar.tsx @@ -9,7 +9,7 @@ import { SearchIcon } from "lucide-react"; import { useRef } from "react"; function FakeAddressBar({ className }: { className?: string }) { - const { t } = useBrowserUITranslations(); + const { t: tBrowserUI } = useBrowserUITranslations(); const inputRef = useRef(null); const { addressUrl, focusedTab } = useTabs(); @@ -36,7 +36,7 @@ function FakeAddressBar({ className }: { className?: string }) { const simplifiedUrl = simplifyUrl(addressUrl); const isPlaceholder = !simplifiedUrl; - const value = isPlaceholder ? t("Search or type URL") : simplifiedUrl; + const value = isPlaceholder ? tBrowserUI("Search or type URL") : simplifiedUrl; return (
-

{t("General")}

-

{t("Manage your browser's general settings")}

+

{tSettings("General")}

+

{tSettings("Manage your browser's general settings")}

diff --git a/src/renderer/src/components/settings/sections/icon/section.tsx b/src/renderer/src/components/settings/sections/icon/section.tsx index e04a1545..aeeca8f3 100644 --- a/src/renderer/src/components/settings/sections/icon/section.tsx +++ b/src/renderer/src/components/settings/sections/icon/section.tsx @@ -14,7 +14,7 @@ interface IconOption { } export function IconSettings() { - const { t } = useSettingsTranslations(); + const { t: tSettings } = useSettingsTranslations(); const { t: tIcons } = useIconsTranslations(); const [selectedIcon, setSelectedIcon] = useState(""); @@ -93,8 +93,10 @@ export function IconSettings() {
- {t("Browser Icon")} - {t("Select an icon for your browser application")} + {tSettings("Browser Icon")} + + {tSettings("Select an icon for your browser application")} + {!isSupported ? ( diff --git a/src/renderer/src/components/settings/settings-layout.tsx b/src/renderer/src/components/settings/settings-layout.tsx index 76e325c1..465954d8 100644 --- a/src/renderer/src/components/settings/settings-layout.tsx +++ b/src/renderer/src/components/settings/settings-layout.tsx @@ -15,20 +15,20 @@ import { ShortcutsProvider } from "@/components/providers/shortcuts-provider"; import { useSettingsTranslations } from "@/lib/i18n"; export function SettingsLayout() { - const { t } = useSettingsTranslations(); + const { t: tSettings } = useSettingsTranslations(); const [activeSection, setActiveSection] = useState("general"); const [selectedProfileId, setSelectedProfileId] = useState(null); const [selectedSpaceId, setSelectedSpaceId] = useState(null); const sections = [ - { id: "general", label: t("General"), icon: }, - { id: "icons", label: t("Icon"), icon: }, - { id: "profiles", label: t("Profiles"), icon: }, - { id: "spaces", label: t("Spaces"), icon: }, - { id: "external-apps", label: t("External Apps"), icon: }, - { id: "shortcuts", label: t("Shortcuts"), icon: }, - { id: "about", label: t("About"), icon: } + { id: "general", label: tSettings("General"), icon: }, + { id: "icons", label: tSettings("Icon"), icon: }, + { id: "profiles", label: tSettings("Profiles"), icon: }, + { id: "spaces", label: tSettings("Spaces"), icon: }, + { id: "external-apps", label: tSettings("External Apps"), icon: }, + { id: "shortcuts", label: tSettings("Shortcuts"), icon: }, + { id: "about", label: tSettings("About"), icon: } ]; const navigateToSpaces = (profileId: string) => { diff --git a/src/renderer/src/components/settings/settings-titlebar.tsx b/src/renderer/src/components/settings/settings-titlebar.tsx index d619b79b..7182acf1 100644 --- a/src/renderer/src/components/settings/settings-titlebar.tsx +++ b/src/renderer/src/components/settings/settings-titlebar.tsx @@ -3,11 +3,11 @@ import { useSettingsTranslations } from "@/lib/i18n"; export function SettingsTitlebar() { - const { t } = useSettingsTranslations(); + const { t: tSettings } = useSettingsTranslations(); return (
- {t("Flow Settings")} + {tSettings("Flow Settings")}
); } From b320d3ef28fbdd877ce6fb2f955e51536bb52e73 Mon Sep 17 00:00:00 2001 From: iamEvan <47493765+iamEvanYT@users.noreply.github.com> Date: Fri, 9 May 2025 18:38:22 +0100 Subject: [PATCH 21/27] feat: external apps section translation --- .../sections/external-apps/section.tsx | 59 +++++++++++-------- src/shared/locales/en-US/settings.json | 23 +++++++- 2 files changed, 57 insertions(+), 25 deletions(-) diff --git a/src/renderer/src/components/settings/sections/external-apps/section.tsx b/src/renderer/src/components/settings/sections/external-apps/section.tsx index b2796c48..b2b251a8 100644 --- a/src/renderer/src/components/settings/sections/external-apps/section.tsx +++ b/src/renderer/src/components/settings/sections/external-apps/section.tsx @@ -15,6 +15,8 @@ import { WebsiteFavicon } from "@/components/main/website-favicon"; import { ExternalAppPermission } from "~/flow/interfaces/settings/openExternal"; import { toast } from "sonner"; import { cn } from "@/lib/utils"; +import { useSettingsTranslations } from "@/lib/i18n"; +import { Trans } from "react-i18next"; function PermissionItem({ websiteUrl, @@ -25,6 +27,7 @@ function PermissionItem({ protocols: string[]; onRevoke: (url: string, protocol: string) => void; }) { + const { t: tSettings } = useSettingsTranslations(); const [expanded, setExpanded] = useState(false); const [confirmDialog, setConfirmDialog] = useState<{ isOpen: boolean; protocol: string }>({ isOpen: false, @@ -55,7 +58,7 @@ function PermissionItem({
- {protocols.length} protocol{protocols.length > 1 ? "s" : ""} + {protocols.length} {protocols.length > 1 ? tSettings("protocols") : tSettings("protocol")}
@@ -91,7 +94,7 @@ function PermissionItem({ setConfirmDialog({ isOpen: true, protocol }); }} > - Revoke + {tSettings("Revoke")} ))} @@ -106,16 +109,22 @@ function PermissionItem({ > - Confirm Revocation + {tSettings("Confirm Revocation")} - Revoke permission for {websiteUrl} to open{" "} - {confirmDialog.protocol}{" "} - links? + , + code: + }} + /> @@ -134,6 +143,7 @@ function PermissionItem({ } export function ExternalAppsSettings() { + const { t: tSettings } = useSettingsTranslations(); const [searchQuery, setSearchQuery] = useState(""); const [permissions, setPermissions] = useState([]); const [isLoading, setIsLoading] = useState(true); @@ -145,29 +155,29 @@ export function ExternalAppsSettings() { setPermissions(fetchedPermissions); } catch (error) { console.error("Failed to fetch permissions:", error); - toast.error("Could not load permissions."); + toast.error(tSettings("Could not load permissions.")); setPermissions([]); } finally { setIsLoading(false); } - }, []); + }, [tSettings]); const revokePermission = useCallback( async (url: string, protocol: string) => { try { const success = await flow.openExternal.unsetAlwaysOpenExternal(url, protocol); if (success) { - toast.success("Permission revoked!"); + toast.success(tSettings("Permission revoked!")); revalidatePermissions(); } else { - toast.error("Failed to revoke permission."); + toast.error(tSettings("Failed to revoke permission.")); } } catch (error) { console.error("Failed to revoke permission:", error); - toast.error("An error occurred while revoking permission."); + toast.error(tSettings("An error occurred while revoking permission.")); } }, - [revalidatePermissions] + [revalidatePermissions, tSettings] ); useEffect(() => { @@ -191,17 +201,17 @@ export function ExternalAppsSettings() { return (
-

External Applications

+

{tSettings("External Applications")}

- Manage websites and the protocols they are allowed to open automatically. + {tSettings("Manage websites and the protocols they are allowed to open automatically.")}

-

Protocol Permissions

+

{tSettings("Protocol Permissions")}

- Websites you have allowed to open external applications via specific protocols. + {tSettings("Websites you have allowed to open external applications via specific protocols.")}

@@ -209,7 +219,7 @@ export function ExternalAppsSettings() { setSearchQuery(e.target.value)} @@ -219,17 +229,17 @@ export function ExternalAppsSettings() { {isLoading ? (
-

Loading permissions...

+

{tSettings("Loading permissions...")}

) : filteredWebsites.length === 0 ? (

- {searchQuery ? "No matching permissions found" : "No permissions configured"} + {searchQuery ? tSettings("No matching permissions found") : tSettings("No permissions configured")}

{!searchQuery && (

- Websites will ask for permission to open external links. + {tSettings("Websites will ask for permission to open external links.")}

)}
@@ -248,8 +258,9 @@ export function ExternalAppsSettings() {

- Note: When you revoke a permission, the website will need to ask for permission again the next time it tries - to open that protocol. + {tSettings( + "Note: When you revoke a permission, the website will need to ask for permission again the next time it tries to open that protocol." + )}

diff --git a/src/shared/locales/en-US/settings.json b/src/shared/locales/en-US/settings.json index db1a9c97..20378ca3 100644 --- a/src/shared/locales/en-US/settings.json +++ b/src/shared/locales/en-US/settings.json @@ -8,5 +8,26 @@ "About": "About", "Manage your browser's general settings": "Manage your browser's general settings", "Browser Icon": "Browser Icon", - "Select an icon for your browser application": "Select an icon for your browser application" + "protocol": "protocol", + "protocols": "protocols", + "Select an icon for your browser application": "Select an icon for your browser application", + "External Applications": "External Applications", + "Manage websites and the protocols they are allowed to open automatically.": "Manage websites and the protocols they are allowed to open automatically.", + "Websites you have allowed to open external applications via specific protocols.": "Websites you have allowed to open external applications via specific protocols.", + "Protocol Permissions": "Protocol Permissions", + "Search by website or protocol...": "Search by website or protocol...", + "No matching permissions found": "No matching permissions found", + "No permissions configured": "No permissions configured", + "Websites will ask for permission to open external links.": "Websites will ask for permission to open external links.", + "Loading permissions...": "Loading permissions...", + "Note: When you revoke a permission, the website will need to ask for permission again the next time it tries to open that protocol.": "Note: When you revoke a permission, the website will need to ask for permission again the next time it tries to open that protocol.", + "Confirm Revocation": "Confirm Revocation", + "Revoke permission for {{websiteUrl}} to open {{protocol}} links?": "Revoke permission for {{websiteUrl}} to open {{protocol}} links?", + "Cancel": "Cancel", + "Revoke Permission": "Revoke Permission", + "Permission revoked!": "Permission revoked!", + "Failed to revoke permission.": "Failed to revoke permission.", + "An error occurred while revoking permission.": "An error occurred while revoking permission.", + "Could not load permissions.": "Could not load permissions.", + "Revoke": "Revoke" } From 4b5eb87bd601851cfc1b8ebfdf524517e43971ce Mon Sep 17 00:00:00 2001 From: iamEvan <47493765+iamEvanYT@users.noreply.github.com> Date: Fri, 9 May 2025 18:50:28 +0100 Subject: [PATCH 22/27] feat: about section translation --- .../sections/about/browser-info-card.tsx | 20 ++++++++++--------- .../settings/sections/about/section.tsx | 7 +++++-- src/renderer/src/lib/i18n.ts | 3 +++ src/shared/locales/en-US/settings.json | 12 ++++++++++- 4 files changed, 30 insertions(+), 12 deletions(-) diff --git a/src/renderer/src/components/settings/sections/about/browser-info-card.tsx b/src/renderer/src/components/settings/sections/about/browser-info-card.tsx index 1f525cc9..26f5b267 100644 --- a/src/renderer/src/components/settings/sections/about/browser-info-card.tsx +++ b/src/renderer/src/components/settings/sections/about/browser-info-card.tsx @@ -1,3 +1,4 @@ +import { useSettingsTranslations } from "@/lib/i18n"; import { useEffect, useState } from "react"; import { Loader2 } from "lucide-react"; // For loading state @@ -18,6 +19,7 @@ function InfoRow({ label, value }: InfoRowProps) { } export function BrowserInfoCard() { + const { t: tSettings } = useSettingsTranslations(); const [appInfo, setAppInfo] = useState> | null>(null); const [isLoading, setIsLoading] = useState(true); @@ -40,8 +42,8 @@ export function BrowserInfoCard() { // Replaced Card with styled div
-

Browser Information

-

Details about your Flow Browser installation.

+

{tSettings("Browser Information")}

+

{tSettings("Details about your browser")}

{isLoading ? ( @@ -52,16 +54,16 @@ export function BrowserInfoCard() { ) : appInfo ? ( // Using a 3-column grid for label & value to better control alignment and wrapping
- - - - - - + + + + + +
) : (
- Could not load browser information. + {tSettings("Could not load browser information.")}
)}
diff --git a/src/renderer/src/components/settings/sections/about/section.tsx b/src/renderer/src/components/settings/sections/about/section.tsx index b60e50da..916612a8 100644 --- a/src/renderer/src/components/settings/sections/about/section.tsx +++ b/src/renderer/src/components/settings/sections/about/section.tsx @@ -1,13 +1,16 @@ import { BrowserInfoCard } from "./browser-info-card"; import { Button } from "@/components/ui/button"; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; +import { useSettingsTranslations } from "@/lib/i18n"; export function AboutSettings() { + const { t: tSettings } = useSettingsTranslations(); + return (
-

About

-

Information about your browser

+

{tSettings("About")}

+

{tSettings("Information about your browser")}

diff --git a/src/renderer/src/lib/i18n.ts b/src/renderer/src/lib/i18n.ts index 612c1023..7036b9b4 100644 --- a/src/renderer/src/lib/i18n.ts +++ b/src/renderer/src/lib/i18n.ts @@ -15,6 +15,9 @@ i18n ns: ["browser-ui", "settings", "icons"], + keySeparator: false, // turn off nested key splitting + nsSeparator: false, // turn off namespace splitting + interpolation: { escapeValue: false // react already safes from xss } diff --git a/src/shared/locales/en-US/settings.json b/src/shared/locales/en-US/settings.json index 20378ca3..0d586501 100644 --- a/src/shared/locales/en-US/settings.json +++ b/src/shared/locales/en-US/settings.json @@ -29,5 +29,15 @@ "Failed to revoke permission.": "Failed to revoke permission.", "An error occurred while revoking permission.": "An error occurred while revoking permission.", "Could not load permissions.": "Could not load permissions.", - "Revoke": "Revoke" + "Revoke": "Revoke", + "Information about your browser": "Information about your browser", + "Browser Information": "Browser Information", + "Details about your browser": "Details about your browser", + "Browser Name": "Browser Name", + "Version": "Version", + "Build": "Build", + "Engine": "Engine", + "OS": "OS", + "Update Channel": "Update Channel", + "Could not load browser information.": "Could not load browser information." } From 729b274d85e746cc6d18d20d842dbe614e451696 Mon Sep 17 00:00:00 2001 From: iamEvan <47493765+iamEvanYT@users.noreply.github.com> Date: Tue, 13 May 2025 16:07:01 +0100 Subject: [PATCH 23/27] update settings strings --- .../components/settings/sections/about/section.tsx | 2 +- .../settings/sections/general/section.tsx | 2 +- .../src/components/settings/settings-layout.tsx | 14 +++++++------- src/shared/locales/en-US/settings.json | 13 +++++++------ 4 files changed, 16 insertions(+), 15 deletions(-) diff --git a/src/renderer/src/components/settings/sections/about/section.tsx b/src/renderer/src/components/settings/sections/about/section.tsx index 916612a8..a536b8e3 100644 --- a/src/renderer/src/components/settings/sections/about/section.tsx +++ b/src/renderer/src/components/settings/sections/about/section.tsx @@ -9,7 +9,7 @@ export function AboutSettings() { return (
-

{tSettings("About")}

+

{tSettings("sections.about")}

{tSettings("Information about your browser")}

diff --git a/src/renderer/src/components/settings/sections/general/section.tsx b/src/renderer/src/components/settings/sections/general/section.tsx index 75fbce12..3e8a751d 100644 --- a/src/renderer/src/components/settings/sections/general/section.tsx +++ b/src/renderer/src/components/settings/sections/general/section.tsx @@ -7,7 +7,7 @@ export function GeneralSettings() { return (
-

{tSettings("General")}

+

{tSettings("sections.general")}

{tSettings("Manage your browser's general settings")}

diff --git a/src/renderer/src/components/settings/settings-layout.tsx b/src/renderer/src/components/settings/settings-layout.tsx index 465954d8..26676913 100644 --- a/src/renderer/src/components/settings/settings-layout.tsx +++ b/src/renderer/src/components/settings/settings-layout.tsx @@ -22,13 +22,13 @@ export function SettingsLayout() { const [selectedSpaceId, setSelectedSpaceId] = useState(null); const sections = [ - { id: "general", label: tSettings("General"), icon: }, - { id: "icons", label: tSettings("Icon"), icon: }, - { id: "profiles", label: tSettings("Profiles"), icon: }, - { id: "spaces", label: tSettings("Spaces"), icon: }, - { id: "external-apps", label: tSettings("External Apps"), icon: }, - { id: "shortcuts", label: tSettings("Shortcuts"), icon: }, - { id: "about", label: tSettings("About"), icon: } + { id: "general", label: tSettings("sections.general"), icon: }, + { id: "icons", label: tSettings("sections.icon"), icon: }, + { id: "profiles", label: tSettings("sections.profiles"), icon: }, + { id: "spaces", label: tSettings("sections.spaces"), icon: }, + { id: "external-apps", label: tSettings("sections.external-apps"), icon: }, + { id: "shortcuts", label: tSettings("sections.shortcuts"), icon: }, + { id: "about", label: tSettings("sections.about"), icon: } ]; const navigateToSpaces = (profileId: string) => { diff --git a/src/shared/locales/en-US/settings.json b/src/shared/locales/en-US/settings.json index 0d586501..6de21444 100644 --- a/src/shared/locales/en-US/settings.json +++ b/src/shared/locales/en-US/settings.json @@ -1,11 +1,12 @@ { "Flow Settings": "Flow Settings", - "General": "General", - "Icon": "Icon", - "Profiles": "Profiles", - "Spaces": "Spaces", - "External Apps": "External Apps", - "About": "About", + "sections.general": "General", + "sections.icon": "Icon", + "sections.profiles": "Profiles", + "sections.spaces": "Spaces", + "sections.external-apps": "External Apps", + "sections.shortcuts": "Shortcuts", + "sections.about": "About", "Manage your browser's general settings": "Manage your browser's general settings", "Browser Icon": "Browser Icon", "protocol": "protocol", From 7b406df2938e46c4a9b95d598cea6cf6079a371e Mon Sep 17 00:00:00 2001 From: iamEvan <47493765+iamEvanYT@users.noreply.github.com> Date: Wed, 14 May 2025 13:19:13 +0100 Subject: [PATCH 24/27] fix: lock file --- bun.lock | 2 ++ 1 file changed, 2 insertions(+) diff --git a/bun.lock b/bun.lock index 2d69c4ee..b9c7922c 100644 --- a/bun.lock +++ b/bun.lock @@ -1164,6 +1164,8 @@ "hosted-git-info": ["hosted-git-info@4.1.0", "", { "dependencies": { "lru-cache": "^6.0.0" } }, "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA=="], + "html-parse-stringify": ["html-parse-stringify@3.0.1", "", { "dependencies": { "void-elements": "3.1.0" } }, "sha512-KknJ50kTInJ7qIScF3jeaFRpMpE8/lfiTdzf/twXyPBLAGrLRTmkz3AdTnKeh40X8k9L2fdYwEp/42WGXIRGcg=="], + "http-cache-semantics": ["http-cache-semantics@4.2.0", "", {}, "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ=="], "http-errors": ["http-errors@2.0.0", "", { "dependencies": { "depd": "2.0.0", "inherits": "2.0.4", "setprototypeof": "1.2.0", "statuses": "2.0.1", "toidentifier": "1.0.1" } }, "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ=="], From 05eceec532de09d54bf97e1547aa03bbee64a981 Mon Sep 17 00:00:00 2001 From: iamEvan <47493765+iamEvanYT@users.noreply.github.com> Date: Thu, 15 May 2025 12:32:17 +0100 Subject: [PATCH 25/27] feat: settings --- .../sections/about/browser-info-card.tsx | 20 +++--- .../settings/sections/about/section.tsx | 2 +- .../sections/external-apps/section.tsx | 51 ++++++------- .../settings/sections/general/section.tsx | 2 +- .../settings/sections/icon/section.tsx | 12 ++-- .../components/settings/settings-titlebar.tsx | 2 +- src/renderer/src/lib/i18n.ts | 22 +++++- src/shared/locales/en-US/settings.json | 72 ++++++++++--------- 8 files changed, 96 insertions(+), 87 deletions(-) diff --git a/src/renderer/src/components/settings/sections/about/browser-info-card.tsx b/src/renderer/src/components/settings/sections/about/browser-info-card.tsx index 26f5b267..a46c7251 100644 --- a/src/renderer/src/components/settings/sections/about/browser-info-card.tsx +++ b/src/renderer/src/components/settings/sections/about/browser-info-card.tsx @@ -42,28 +42,28 @@ export function BrowserInfoCard() { // Replaced Card with styled div
-

{tSettings("Browser Information")}

-

{tSettings("Details about your browser")}

+

{tSettings("sections.about.info.title")}

+

{tSettings("sections.about.info.description")}

{isLoading ? (
- Loading browser details... + {tSettings("sections.about.info.loading")}
) : appInfo ? ( // Using a 3-column grid for label & value to better control alignment and wrapping
- - - - - - + + + + + +
) : (
- {tSettings("Could not load browser information.")} + {tSettings("sections.about.info.loading.failed")}
)}
diff --git a/src/renderer/src/components/settings/sections/about/section.tsx b/src/renderer/src/components/settings/sections/about/section.tsx index a536b8e3..a98db2ed 100644 --- a/src/renderer/src/components/settings/sections/about/section.tsx +++ b/src/renderer/src/components/settings/sections/about/section.tsx @@ -10,7 +10,7 @@ export function AboutSettings() {

{tSettings("sections.about")}

-

{tSettings("Information about your browser")}

+

{tSettings("sections.about.description")}

diff --git a/src/renderer/src/components/settings/sections/external-apps/section.tsx b/src/renderer/src/components/settings/sections/external-apps/section.tsx index b2b251a8..ad90acc3 100644 --- a/src/renderer/src/components/settings/sections/external-apps/section.tsx +++ b/src/renderer/src/components/settings/sections/external-apps/section.tsx @@ -51,14 +51,14 @@ function PermissionItem({ expanded && "rotate-90" )} /> - +

{websiteUrl}

- {protocols.length} {protocols.length > 1 ? tSettings("protocols") : tSettings("protocol")} + {tSettings("settings.external-apps.protocol", { count: protocols.length })}
@@ -94,7 +94,7 @@ function PermissionItem({ setConfirmDialog({ isOpen: true, protocol }); }} > - {tSettings("Revoke")} + {tSettings("settings.external-apps.revoke")} ))} @@ -109,11 +109,11 @@ function PermissionItem({ > - {tSettings("Confirm Revocation")} + {tSettings("settings.external-apps.confirm-card.title")} , @@ -124,7 +124,7 @@ function PermissionItem({ @@ -155,7 +155,7 @@ export function ExternalAppsSettings() { setPermissions(fetchedPermissions); } catch (error) { console.error("Failed to fetch permissions:", error); - toast.error(tSettings("Could not load permissions.")); + toast.error(tSettings("settings.external-apps.loading.failed")); setPermissions([]); } finally { setIsLoading(false); @@ -167,14 +167,14 @@ export function ExternalAppsSettings() { try { const success = await flow.openExternal.unsetAlwaysOpenExternal(url, protocol); if (success) { - toast.success(tSettings("Permission revoked!")); + toast.success(tSettings("settings.external-apps.revoke-permission.success")); revalidatePermissions(); } else { - toast.error(tSettings("Failed to revoke permission.")); + toast.error(tSettings("settings.external-apps.revoke-permission.failed")); } } catch (error) { console.error("Failed to revoke permission:", error); - toast.error(tSettings("An error occurred while revoking permission.")); + toast.error(tSettings("settings.external-apps.revoke-permission.error")); } }, [revalidatePermissions, tSettings] @@ -201,25 +201,16 @@ export function ExternalAppsSettings() { return (
-

{tSettings("External Applications")}

-

- {tSettings("Manage websites and the protocols they are allowed to open automatically.")} -

+

{tSettings("settings.external-apps.title")}

+

{tSettings("settings.external-apps.description")}

-
-

{tSettings("Protocol Permissions")}

-

- {tSettings("Websites you have allowed to open external applications via specific protocols.")} -

-
-
setSearchQuery(e.target.value)} @@ -229,17 +220,19 @@ export function ExternalAppsSettings() { {isLoading ? (
-

{tSettings("Loading permissions...")}

+

{tSettings("settings.external-apps.loading")}

) : filteredWebsites.length === 0 ? (

- {searchQuery ? tSettings("No matching permissions found") : tSettings("No permissions configured")} + {searchQuery + ? tSettings("settings.external-apps.no-matching-permissions") + : tSettings("settings.external-apps.no-permissions-configured")}

{!searchQuery && (

- {tSettings("Websites will ask for permission to open external links.")} + {tSettings("settings.external-apps.no-permissions-found.description")}

)}
@@ -257,11 +250,7 @@ export function ExternalAppsSettings() { )}
-

- {tSettings( - "Note: When you revoke a permission, the website will need to ask for permission again the next time it tries to open that protocol." - )} -

+

{tSettings("settings.external-apps.note")}

diff --git a/src/renderer/src/components/settings/sections/general/section.tsx b/src/renderer/src/components/settings/sections/general/section.tsx index 3e8a751d..49590a88 100644 --- a/src/renderer/src/components/settings/sections/general/section.tsx +++ b/src/renderer/src/components/settings/sections/general/section.tsx @@ -8,7 +8,7 @@ export function GeneralSettings() {

{tSettings("sections.general")}

-

{tSettings("Manage your browser's general settings")}

+

{tSettings("sections.general.description")}

diff --git a/src/renderer/src/components/settings/sections/icon/section.tsx b/src/renderer/src/components/settings/sections/icon/section.tsx index aeeca8f3..f23af1a7 100644 --- a/src/renderer/src/components/settings/sections/icon/section.tsx +++ b/src/renderer/src/components/settings/sections/icon/section.tsx @@ -93,19 +93,17 @@ export function IconSettings() {
- {tSettings("Browser Icon")} - - {tSettings("Select an icon for your browser application")} - + {tSettings("settings.icon.title")} + {tSettings("settings.icon.description")} {!isSupported ? (
-
Icon customization is not supported on this platform.
+
{tSettings("settings.icon.unsupported")}
) : isLoading ? (
-
Loading icons...
+
{tSettings("settings.icon.loading")}
) : (
@@ -165,7 +163,7 @@ export function IconSettings() { {icon.current && selectedIcon !== icon.id && !isUpdating && (
- CURRENT + {tSettings("settings.icon.current")}
)} diff --git a/src/renderer/src/components/settings/settings-titlebar.tsx b/src/renderer/src/components/settings/settings-titlebar.tsx index 7182acf1..560a48e4 100644 --- a/src/renderer/src/components/settings/settings-titlebar.tsx +++ b/src/renderer/src/components/settings/settings-titlebar.tsx @@ -7,7 +7,7 @@ export function SettingsTitlebar() { return (
- {tSettings("Flow Settings")} + {tSettings("title")}
); } diff --git a/src/renderer/src/lib/i18n.ts b/src/renderer/src/lib/i18n.ts index 7036b9b4..b107c8f8 100644 --- a/src/renderer/src/lib/i18n.ts +++ b/src/renderer/src/lib/i18n.ts @@ -2,6 +2,9 @@ import i18n from "i18next"; import { initReactI18next, useTranslation } from "react-i18next"; import resourcesToBackend from "i18next-resources-to-backend"; +// Config +const I18N_DEBUG_ENABLED = false; + // Tell vite to load all locale files import.meta.glob("~/locales/*/*.json"); @@ -20,9 +23,26 @@ i18n interpolation: { escapeValue: false // react already safes from xss - } + }, + postProcess: I18N_DEBUG_ENABLED ? ["debugger"] : [], + debug: I18N_DEBUG_ENABLED }); +// Custom post processor for debugging +const debugProcessor = { + type: "postProcessor" as const, // Add type assertion + name: "debugger", + // eslint-disable-next-line @typescript-eslint/no-unused-vars + process(value: string, _key: string, _options: unknown, _translator: unknown) { + if (I18N_DEBUG_ENABLED) { + return "a"; + } + return value; + } +}; + +i18n.use(debugProcessor); // Register the post processor + // Set the language to the user's locale flow.app.getAppInfo().then((appInfo) => { i18n.changeLanguage(appInfo.locale); diff --git a/src/shared/locales/en-US/settings.json b/src/shared/locales/en-US/settings.json index 6de21444..a2a894fc 100644 --- a/src/shared/locales/en-US/settings.json +++ b/src/shared/locales/en-US/settings.json @@ -1,5 +1,6 @@ { - "Flow Settings": "Flow Settings", + "title": "Flow Settings", + "cancel": "Cancel", "sections.general": "General", "sections.icon": "Icon", "sections.profiles": "Profiles", @@ -7,38 +8,39 @@ "sections.external-apps": "External Apps", "sections.shortcuts": "Shortcuts", "sections.about": "About", - "Manage your browser's general settings": "Manage your browser's general settings", - "Browser Icon": "Browser Icon", - "protocol": "protocol", - "protocols": "protocols", - "Select an icon for your browser application": "Select an icon for your browser application", - "External Applications": "External Applications", - "Manage websites and the protocols they are allowed to open automatically.": "Manage websites and the protocols they are allowed to open automatically.", - "Websites you have allowed to open external applications via specific protocols.": "Websites you have allowed to open external applications via specific protocols.", - "Protocol Permissions": "Protocol Permissions", - "Search by website or protocol...": "Search by website or protocol...", - "No matching permissions found": "No matching permissions found", - "No permissions configured": "No permissions configured", - "Websites will ask for permission to open external links.": "Websites will ask for permission to open external links.", - "Loading permissions...": "Loading permissions...", - "Note: When you revoke a permission, the website will need to ask for permission again the next time it tries to open that protocol.": "Note: When you revoke a permission, the website will need to ask for permission again the next time it tries to open that protocol.", - "Confirm Revocation": "Confirm Revocation", - "Revoke permission for {{websiteUrl}} to open {{protocol}} links?": "Revoke permission for {{websiteUrl}} to open {{protocol}} links?", - "Cancel": "Cancel", - "Revoke Permission": "Revoke Permission", - "Permission revoked!": "Permission revoked!", - "Failed to revoke permission.": "Failed to revoke permission.", - "An error occurred while revoking permission.": "An error occurred while revoking permission.", - "Could not load permissions.": "Could not load permissions.", - "Revoke": "Revoke", - "Information about your browser": "Information about your browser", - "Browser Information": "Browser Information", - "Details about your browser": "Details about your browser", - "Browser Name": "Browser Name", - "Version": "Version", - "Build": "Build", - "Engine": "Engine", - "OS": "OS", - "Update Channel": "Update Channel", - "Could not load browser information.": "Could not load browser information." + "sections.general.description": "Manage your browser's general settings", + "settings.icon.title": "Browser Icon", + "settings.icon.description": "Select an icon for your browser application", + "settings.icon.unsupported": "Icon customization is not supported on this platform.", + "settings.icon.loading": "Loading icons...", + "settings.icon.current": "CURRENT", + "settings.external-apps.title": "External Applications", + "settings.external-apps.description": "Manage websites and the protocols they are allowed to open automatically.", + "settings.external-apps.note": "Note: When you revoke a permission, the website will need to ask for permission again the next time it tries to open that protocol.", + "settings.external-apps.confirm-card.title": "Confirm Revocation", + "settings.external-apps.confirm-card.description": "Revoke permission for {{websiteUrl}} to open {{protocol}} links?", + "settings.external-apps.search-placeholder": "Search by website or protocol...", + "settings.external-apps.revoke-permission.confirm": "Revoke Permission", + "settings.external-apps.revoke-permission.success": "Permission revoked!", + "settings.external-apps.revoke-permission.failed": "Failed to revoke permission.", + "settings.external-apps.revoke-permission.error": "An error occurred while revoking permission.", + "settings.external-apps.protocol_one": "{{count}} protocol", + "settings.external-apps.protocol_other": "{{count}} protocols", + "settings.external-apps.no-matching-permissions": "No matching permissions found", + "settings.external-apps.no-permissions-configured": "No permissions configured", + "settings.external-apps.no-permissions-found.description": "We couldn't find any matching permissions.", + "settings.external-apps.loading": "Loading permissions...", + "settings.external-apps.loading.failed": "Could not load permissions.", + "settings.external-apps.revoke": "Revoke", + "sections.about.description": "Information about your browser", + "sections.about.info.title": "Browser Information", + "sections.about.info.description": "Details about your browser", + "sections.about.info.browser-name": "Browser Name", + "sections.about.info.version": "Version", + "sections.about.info.build": "Build", + "sections.about.info.engine": "Engine", + "sections.about.info.os": "OS", + "sections.about.info.update-channel": "Update Channel", + "sections.about.info.loading": "Loading browser details...", + "sections.about.info.loading.failed": "Could not load browser information." } From 503ad388828a8e28b771ebca76514080f474aadd Mon Sep 17 00:00:00 2001 From: iamEvan <47493765+iamEvanYT@users.noreply.github.com> Date: Thu, 15 May 2025 12:35:38 +0100 Subject: [PATCH 26/27] feat: about page --- src/renderer/src/lib/i18n.ts | 4 ++++ src/renderer/src/routes/about/page.tsx | 7 +++++-- src/shared/locales/en-US/pages.json | 4 ++++ 3 files changed, 13 insertions(+), 2 deletions(-) create mode 100644 src/shared/locales/en-US/pages.json diff --git a/src/renderer/src/lib/i18n.ts b/src/renderer/src/lib/i18n.ts index b107c8f8..f421706c 100644 --- a/src/renderer/src/lib/i18n.ts +++ b/src/renderer/src/lib/i18n.ts @@ -60,4 +60,8 @@ export function useIconsTranslations() { return useTranslation("icons"); } +export function usePagesTranslations() { + return useTranslation("pages"); +} + export default i18n; diff --git a/src/renderer/src/routes/about/page.tsx b/src/renderer/src/routes/about/page.tsx index 1feee2c1..6c4443bf 100644 --- a/src/renderer/src/routes/about/page.tsx +++ b/src/renderer/src/routes/about/page.tsx @@ -2,8 +2,11 @@ import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/com import { Button } from "@/components/ui/button"; import { motion } from "motion/react"; import { copyTextToClipboard } from "@/lib/utils"; +import { usePagesTranslations } from "@/lib/i18n"; function Page() { + const { t: tPages } = usePagesTranslations(); + const hostnames = ["about", "new-tab", "games", "omnibox", "error", "extensions"]; return ( @@ -16,8 +19,8 @@ function Page() { > - Flow URLs - A list of available Flow browser URLs + {tPages("about.title")} + {tPages("about.description")}
diff --git a/src/shared/locales/en-US/pages.json b/src/shared/locales/en-US/pages.json new file mode 100644 index 00000000..be3c2178 --- /dev/null +++ b/src/shared/locales/en-US/pages.json @@ -0,0 +1,4 @@ +{ + "about.title": "Flow URLs", + "about.description": "A list of available Flow browser URLs" +} From 752b7161771a4262aaf46b02b5d7b63bbb6e8420 Mon Sep 17 00:00:00 2001 From: iamEvan <47493765+iamEvanYT@users.noreply.github.com> Date: Wed, 11 Jun 2025 14:59:41 +0100 Subject: [PATCH 27/27] remove: ico-to-png --- bun.lock | 1 - package.json | 1 - 2 files changed, 2 deletions(-) diff --git a/bun.lock b/bun.lock index b9c7922c..a75bca01 100644 --- a/bun.lock +++ b/bun.lock @@ -13,7 +13,6 @@ "electron-updater": "^6.6.2", "i18next": "^25.1.2", "i18next-resources-to-backend": "^1.2.1", - "ico-to-png": "^0.2.2", "knex": "^3.1.0", "mime-types": "^3.0.1", "posthog-node": "^4.17.1", diff --git a/package.json b/package.json index 3f71a1ce..d72c8cbc 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,6 @@ "electron-updater": "^6.6.2", "i18next": "^25.1.2", "i18next-resources-to-backend": "^1.2.1", - "ico-to-png": "^0.2.2", "knex": "^3.1.0", "mime-types": "^3.0.1", "posthog-node": "^4.17.1",