diff --git a/windows/tauri/package.json b/windows/tauri/package.json index dceed09f3..93ac9b31f 100644 --- a/windows/tauri/package.json +++ b/windows/tauri/package.json @@ -4,7 +4,7 @@ "private": true, "type": "module", "scripts": { - "dev": "bunx vp dev", + "dev": "bun ./node_modules/vite-plus/bin/vp dev", "build": "bunx vp build", "preview": "bunx vp preview", "tauri": "tauri", diff --git a/windows/tauri/src-tauri/Cargo.lock b/windows/tauri/src-tauri/Cargo.lock index 268a1486f..8fc75becd 100644 --- a/windows/tauri/src-tauri/Cargo.lock +++ b/windows/tauri/src-tauri/Cargo.lock @@ -267,6 +267,12 @@ version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" +[[package]] +name = "base64ct" +version = "1.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06" + [[package]] name = "bit-set" version = "0.8.0" @@ -530,7 +536,7 @@ checksum = "d524456ba66e72eb8b115ff89e01e497f8e6d11d78b70b1aa13c0fbd97540a81" dependencies = [ "cfg-if", "cpufeatures 0.3.0", - "rand_core", + "rand_core 0.10.1", ] [[package]] @@ -591,6 +597,12 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "const-oid" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + [[package]] name = "const-random" version = "0.1.18" @@ -880,6 +892,17 @@ dependencies = [ "thiserror 2.0.20", ] +[[package]] +name = "der" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" +dependencies = [ + "const-oid", + "pem-rfc7468", + "zeroize", +] + [[package]] name = "deranged" version = "0.5.8" @@ -928,6 +951,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer", + "const-oid", "crypto-common", ] @@ -1383,6 +1407,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1f9e3d69d39e4862ffed03ed071a76f9a13ba1d9109d355b0f0aa6b15e393c4" dependencies = [ "futures-core", + "futures-sink", ] [[package]] @@ -1614,7 +1639,7 @@ dependencies = [ "js-sys", "libc", "r-efi 6.0.0", - "rand_core", + "rand_core 0.10.1", "wasm-bindgen", ] @@ -2452,6 +2477,9 @@ name = "lazy_static" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +dependencies = [ + "spin", +] [[package]] name = "libappindicator" @@ -2502,6 +2530,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "libm" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" + [[package]] name = "libredox" version = "0.1.19" @@ -2528,14 +2562,21 @@ name = "lithe-core" version = "0.1.0" dependencies = [ "ammonia", + "base64 0.22.1", "comrak", "quick-xml 0.37.5", + "rand 0.8.7", "regex", + "reqwest 0.12.28", + "rsa", "serde", "serde_json", "serde_yaml_ng", + "sha1", "sha2", "toml 1.1.4+spec-1.1.0", + "url", + "zip 2.4.2", ] [[package]] @@ -2828,12 +2869,47 @@ dependencies = [ "bitflags 2.13.1", ] +[[package]] +name = "num-bigint-dig" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e661dda6640fad38e827a6d4a310ff4763082116fe217f279885c97f511bb0b7" +dependencies = [ + "lazy_static", + "libm", + "num-integer", + "num-iter", + "num-traits", + "rand 0.8.7", + "smallvec", + "zeroize", +] + [[package]] name = "num-conv" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "521739c6d2bac4aa25192232afe6841231376b2b26d4d9fae5ecf8ca5772e441" +[[package]] +name = "num-integer" +version = "0.1.47" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ce2d95d4b3734dc35aa2f45e1aa22cd416814592a4f9d9205e11affd5b8e10b" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-iter" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c92800bd69a1eac91786bcfe9da64a897eb72911b8dc3095decbd07429e8048b" +dependencies = [ + "num-integer", + "num-traits", +] + [[package]] name = "num-traits" version = "0.2.19" @@ -2841,6 +2917,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", + "libm", ] [[package]] @@ -3217,6 +3294,15 @@ dependencies = [ "windows-link 0.2.1", ] +[[package]] +name = "pem-rfc7468" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412" +dependencies = [ + "base64ct", +] + [[package]] name = "percent-encoding" version = "2.3.2" @@ -3304,6 +3390,27 @@ dependencies = [ "futures-io", ] +[[package]] +name = "pkcs1" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f" +dependencies = [ + "der", + "pkcs8", + "spki", +] + +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der", + "spki", +] + [[package]] name = "pkg-config" version = "0.3.34" @@ -3414,6 +3521,15 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" +[[package]] +name = "ppv-lite86" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + [[package]] name = "precomputed-hash" version = "0.1.1" @@ -3557,7 +3673,7 @@ dependencies = [ "bytes", "getrandom 0.4.3", "lru-slab", - "rand", + "rand 0.10.2", "rand_pcg", "ring", "rustc-hash", @@ -3605,6 +3721,17 @@ version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" +[[package]] +name = "rand" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22f6172bdec972074665ed81ed53b71da00bfc44b65a753cfde883ec4c702a1a" +dependencies = [ + "libc", + "rand_chacha", + "rand_core 0.6.4", +] + [[package]] name = "rand" version = "0.10.2" @@ -3613,7 +3740,26 @@ checksum = "c7f5fa3a058cd35567ef9bfa5e75732bee0f9e4c55fa90477bef2dfcdbc4be80" dependencies = [ "chacha20", "getrandom 0.4.3", - "rand_core", + "rand_core 0.10.1", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom 0.2.17", ] [[package]] @@ -3628,7 +3774,7 @@ version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "caa0f4137e1c0a72f4c651489402276c8e8e1cf081f3b0ba156d2cbeef09e86a" dependencies = [ - "rand_core", + "rand_core 0.10.1", ] [[package]] @@ -3728,7 +3874,9 @@ dependencies = [ "cookie", "cookie_store", "encoding_rs", + "futures-channel", "futures-core", + "futures-util", "h2", "http", "http-body", @@ -3837,6 +3985,26 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "rsa" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8573f03f5883dcaebdfcf4725caa1ecb9c15b2ef50c43a07b816e06799bb12d" +dependencies = [ + "const-oid", + "digest", + "num-bigint-dig", + "num-integer", + "num-traits", + "pkcs1", + "pkcs8", + "rand_core 0.6.4", + "signature", + "spki", + "subtle", + "zeroize", +] + [[package]] name = "rust-ini" version = "0.21.3" @@ -4283,6 +4451,17 @@ dependencies = [ "stable_deref_trait", ] +[[package]] +name = "sha1" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a978451301f4db1d02937a4ab3ccce137717b81826e79b7d49ffe3244a13c3b8" +dependencies = [ + "cfg-if", + "cpufeatures 0.2.17", + "digest", +] + [[package]] name = "sha2" version = "0.10.9" @@ -4358,6 +4537,16 @@ dependencies = [ "libc", ] +[[package]] +name = "signature" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +dependencies = [ + "digest", + "rand_core 0.6.4", +] + [[package]] name = "simd-adler32" version = "0.3.10" @@ -4456,6 +4645,22 @@ dependencies = [ "system-deps", ] +[[package]] +name = "spin" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3763264f6b73151db08c50ff20d7d8a0b8796e021cdea7ceedad07b80155fa0e" + +[[package]] +name = "spki" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der", +] + [[package]] name = "stable_deref_trait" version = "1.2.1" @@ -5037,7 +5242,7 @@ dependencies = [ "tokio", "url", "windows-sys 0.60.2", - "zip", + "zip 4.6.1", ] [[package]] @@ -6926,6 +7131,23 @@ dependencies = [ "syn 3.0.3", ] +[[package]] +name = "zip" +version = "2.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fabe6324e908f85a1c52063ce7aa26b68dcb7eb6dbc83a2d148403c9bc3eba50" +dependencies = [ + "arbitrary", + "crc32fast", + "crossbeam-utils", + "displaydoc", + "flate2", + "indexmap 2.14.0", + "memchr", + "thiserror 2.0.20", + "zopfli", +] + [[package]] name = "zip" version = "4.6.1" @@ -6944,6 +7166,18 @@ version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b" +[[package]] +name = "zopfli" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f05cd8797d63865425ff89b5c4a48804f35ba0ce8d125800027ad6017d2b5249" +dependencies = [ + "bumpalo", + "crc32fast", + "log", + "simd-adler32", +] + [[package]] name = "zune-core" version = "0.5.3" diff --git a/windows/tauri/src-tauri/icons/icon.ico b/windows/tauri/src-tauri/icons/icon.ico index 26418f0dd..a76d1c206 100644 Binary files a/windows/tauri/src-tauri/icons/icon.ico and b/windows/tauri/src-tauri/icons/icon.ico differ diff --git a/windows/tauri/src-tauri/src/host.rs b/windows/tauri/src-tauri/src/host.rs index 486f776b5..bb1a64f56 100644 --- a/windows/tauri/src-tauri/src/host.rs +++ b/windows/tauri/src-tauri/src/host.rs @@ -9,6 +9,16 @@ use tauri_plugin_opener::OpenerExt; static WINDOW_ID: AtomicU64 = AtomicU64::new(1); +// Windows 11 taskbar downscales a 256-only ICO into an empty pill. Use the 32px +// asset after window creation so frameless windows keep a readable app icon. +const WINDOW_TASKBAR_ICON: tauri::image::Image<'_> = tauri::include_image!("./icons/32x32.png"); + +pub fn apply_window_taskbar_icon(window: &WebviewWindow) { + if let Err(error) = window.set_icon(WINDOW_TASKBAR_ICON.clone()) { + eprintln!("[host] failed to set window icon: {error}"); + } +} + #[derive(Debug, Serialize)] pub struct FontInfo { name: String, @@ -273,13 +283,16 @@ pub fn create_app_window(app: AppHandle, request: Option) -> Result) -> Result= 6); + let count = u16::from_le_bytes(data[4..6].try_into().unwrap()) as usize; + let mut widths = Vec::new(); + let mut offset = 6usize; + for _ in 0..count { + let width = match data[offset] { + 0 => 256, + value => u32::from(value), + }; + widths.push(width); + offset += 16; + } + assert!(widths.contains(&16), "{widths:?}"); + assert!(widths.contains(&32), "{widths:?}"); + assert!(widths.contains(&256), "{widths:?}"); + } } #[tauri::command] diff --git a/windows/tauri/src-tauri/src/main.rs b/windows/tauri/src-tauri/src/main.rs index d2dc1531f..893a8fefa 100644 --- a/windows/tauri/src-tauri/src/main.rs +++ b/windows/tauri/src-tauri/src/main.rs @@ -48,6 +48,9 @@ fn main() { )); app.manage(host::FileClipboard::default()); app.manage(run::RunProcessManager::default()); + if let Some(window) = app.get_webview_window("main") { + host::apply_window_taskbar_icon(&window); + } Ok(()) }) .invoke_handler(tauri::generate_handler![ diff --git a/windows/tauri/src/features/command-palette/constants/git-actions.tsx b/windows/tauri/src/features/command-palette/constants/git-actions.tsx index af519e92c..500b3e79f 100644 --- a/windows/tauri/src/features/command-palette/constants/git-actions.tsx +++ b/windows/tauri/src/features/command-palette/constants/git-actions.tsx @@ -5,6 +5,7 @@ import { FolderOpenIcon as FolderOpen, GitBranchIcon as GitBranch, GitCommitIcon as GitCommit, + GitGraphIcon as GitGraph, HardDrivesIcon as Server, NodesIcon as Nodes, TagIcon as Tag, @@ -163,7 +164,7 @@ export const createGitActions = (params: GitActionsParams): Action[] => { id: "git-open-log", label: "Git: Open Log", description: "Open the full Git Log tool window", - icon: , + icon: , category: "Git", action: () => { setBottomPaneActiveTab("gitLog"); diff --git a/windows/tauri/src/features/diagnostics/components/diagnostics-pane.tsx b/windows/tauri/src/features/diagnostics/components/diagnostics-pane.tsx index f744ca379..5260b13c2 100644 --- a/windows/tauri/src/features/diagnostics/components/diagnostics-pane.tsx +++ b/windows/tauri/src/features/diagnostics/components/diagnostics-pane.tsx @@ -17,6 +17,7 @@ import { XIcon as X, } from "@/ui/icons"; import { type ReactNode, useCallback, useEffect, useMemo, useRef, useState } from "react"; +import { useTranslation } from "@/i18n/locale-provider"; import { LspClient } from "@/features/editor/lsp/lsp-client"; import { useBufferStore } from "@/features/editor/stores/buffer.store"; import { @@ -84,16 +85,16 @@ const DEFAULT_PREFERENCES: PanePreferences = { fileNavigatorViewMode: "flat", }; -const GROUP_OPTIONS: Array<{ value: GroupBy; label: string }> = [ - { value: "file", label: "File" }, - { value: "severity", label: "Severity" }, - { value: "none", label: "None" }, +const GROUP_OPTIONS: Array<{ value: GroupBy; labelKey: string }> = [ + { value: "file", labelKey: "diagnostics.groupByFile" }, + { value: "severity", labelKey: "diagnostics.groupBySeverity" }, + { value: "none", labelKey: "diagnostics.groupByNone" }, ]; -const SORT_OPTIONS: Array<{ value: SortBy; label: string }> = [ - { value: "severity", label: "Severity" }, - { value: "file", label: "File" }, - { value: "position", label: "Position" }, +const SORT_OPTIONS: Array<{ value: SortBy; labelKey: string }> = [ + { value: "severity", labelKey: "diagnostics.sortBySeverity" }, + { value: "file", labelKey: "diagnostics.sortByFile" }, + { value: "position", labelKey: "diagnostics.sortByPosition" }, ]; const SEVERITY_ORDER: Record = { @@ -102,10 +103,10 @@ const SEVERITY_ORDER: Record = { info: 2, }; -const SEVERITY_LABEL: Record = { - error: "Errors", - warning: "Warnings", - info: "Info", +const SEVERITY_LABEL_KEY: Record = { + error: "diagnostics.errors", + warning: "diagnostics.warnings", + info: "diagnostics.info", }; const SEVERITY_TEXT_CLASS: Record = { @@ -216,6 +217,7 @@ const DiagnosticsPane = ({ onFullScreen, isFullScreen = false, }: DiagnosticsPaneProps) => { + const { t } = useTranslation(); const { showToast } = useToast(); const lspClient = useMemo(() => LspClient.getInstance(), []); const widthMode = useTerminalStore((state) => state.widthMode); @@ -371,7 +373,7 @@ const DiagnosticsPane = ({ return [ { id: "all", - label: "All Diagnostics", + label: t("diagnostics.all"), items: filteredDiagnostics, }, ]; @@ -385,7 +387,7 @@ const DiagnosticsPane = ({ ); return { id: `severity-${severity}`, - label: SEVERITY_LABEL[severity as Diagnostic["severity"]], + label: t(SEVERITY_LABEL_KEY[severity as Diagnostic["severity"]]), items, severity: severity as Diagnostic["severity"], }; @@ -407,7 +409,7 @@ const DiagnosticsPane = ({ label: filePath, items, })); - }, [filteredDiagnostics, preferences.groupBy]); + }, [filteredDiagnostics, preferences.groupBy, t]); const totalBySeverity = useMemo(() => { return diagnostics.reduce( @@ -565,18 +567,18 @@ const DiagnosticsPane = ({ const copyDiagnosticMessage = useCallback( async (diagnostic: Diagnostic) => { await copyToClipboard(diagnostic.message); - showToast({ message: "Diagnostic message copied", type: "success" }); + showToast({ message: t("diagnostics.messageCopied"), type: "success" }); }, - [showToast], + [showToast, t], ); const copyDiagnosticLocation = useCallback( async (diagnostic: Diagnostic) => { const text = `${diagnostic.filePath}:${diagnostic.line + 1}:${diagnostic.column + 1}`; await copyToClipboard(text); - showToast({ message: "Diagnostic location copied", type: "success" }); + showToast({ message: t("diagnostics.locationCopied"), type: "success" }); }, - [showToast], + [showToast, t], ); const copyDiagnosticDetails = useCallback( @@ -592,9 +594,9 @@ const DiagnosticsPane = ({ .join(" | "); await copyToClipboard(details); - showToast({ message: "Diagnostic details copied", type: "success" }); + showToast({ message: t("diagnostics.detailsCopied"), type: "success" }); }, - [showToast], + [showToast, t], ); const diagnosticContextMenuItems = useMemo(() => { @@ -610,7 +612,7 @@ const DiagnosticsPane = ({ if (isLoading) { items.push({ id: "loading-actions", - label: "Loading quick fixes...", + label: t("diagnostics.loadingFixes"), icon: , onClick: () => {}, disabled: true, @@ -633,7 +635,7 @@ const DiagnosticsPane = ({ } else { items.push({ id: "no-actions", - label: "No quick fixes available", + label: t("diagnostics.noFixes"), icon: , onClick: () => {}, disabled: true, @@ -645,12 +647,12 @@ const DiagnosticsPane = ({ items.push( { id: "go-to-problem", - label: "Go to Problem", + label: t("diagnostics.goToProblem"), onClick: () => onDiagnosticClick?.(diagnostic), }, { id: "copy-message", - label: "Copy Message", + label: t("diagnostics.copyMessage"), icon: , onClick: () => { void copyDiagnosticMessage(diagnostic); @@ -658,7 +660,7 @@ const DiagnosticsPane = ({ }, { id: "copy-location", - label: "Copy Location", + label: t("diagnostics.copyLocation"), icon: , onClick: () => { void copyDiagnosticLocation(diagnostic); @@ -666,7 +668,7 @@ const DiagnosticsPane = ({ }, { id: "copy-details", - label: "Copy Full Details", + label: t("diagnostics.copyDetails"), icon: , onClick: () => { void copyDiagnosticDetails(diagnostic); @@ -679,14 +681,14 @@ const DiagnosticsPane = ({ if (sourceFilter?.toLowerCase() === source.toLowerCase()) { items.push({ id: "clear-source-filter", - label: "Clear Source Filter", + label: t("diagnostics.clearSourceFilterSimple"), icon: , onClick: () => setSourceFilter(null), }); } else { items.push({ id: "filter-by-source", - label: `Filter by Source: ${source}`, + label: t("diagnostics.filterBySource", { source }), icon: , onClick: () => setSourceFilter(source), }); @@ -697,7 +699,9 @@ const DiagnosticsPane = ({ items.push({ id: "toggle-wrap", - label: preferences.wrapMessages ? "Disable Message Wrap" : "Enable Message Wrap", + label: preferences.wrapMessages + ? t("diagnostics.disableWrap") + : t("diagnostics.enableWrap"), onClick: () => togglePreference("wrapMessages"), }); @@ -714,6 +718,7 @@ const DiagnosticsPane = ({ preferences.wrapMessages, sourceFilter, togglePreference, + t, ]); const hasNonDefaultPreferences = @@ -742,7 +747,10 @@ const DiagnosticsPane = ({ const hasSearch = Boolean(searchQuery.trim()); const visibleProblemCount = filteredDiagnostics.length; const hasDiagnosticFiles = diagnosticFileItems.length > 0; - const problemSummary = `${visibleProblemCount} problem${visibleProblemCount === 1 ? "" : "s"}`; + const problemSummary = + visibleProblemCount === 1 + ? t("diagnostics.problemCountOne", { count: visibleProblemCount }) + : t("diagnostics.problemCount", { count: visibleProblemCount }); const problemSummaryTone = visibleBySeverity.error > 0 ? "text-destructive" @@ -760,7 +768,7 @@ const DiagnosticsPane = ({ items.push( ...GROUP_OPTIONS.map((option) => ({ id: `group-${option.value}`, - label: `Group by: ${option.label}`, + label: t(option.labelKey), icon: preferences.groupBy === option.value ? : undefined, onClick: () => { setPreferences((prev) => ({ @@ -776,7 +784,7 @@ const DiagnosticsPane = ({ items.push( ...SORT_OPTIONS.map((option) => ({ id: `sort-${option.value}`, - label: `Sort by: ${option.label}`, + label: t(option.labelKey), icon: preferences.sortBy === option.value ? : undefined, onClick: () => { setPreferences((prev) => ({ @@ -792,7 +800,11 @@ const DiagnosticsPane = ({ for (const severity of ["error", "warning", "info"] as Diagnostic["severity"][]) { items.push({ id: `severity-${severity}`, - label: `${SEVERITY_LABEL[severity]} (${visibleBySeverity[severity]}/${totalBySeverity[severity]})`, + label: t("diagnostics.severityCount", { + label: t(SEVERITY_LABEL_KEY[severity]), + visible: visibleBySeverity[severity], + total: totalBySeverity[severity], + }), icon: severityFilter[severity] ? : undefined, onClick: () => toggleSeverity(severity), }); @@ -801,7 +813,7 @@ const DiagnosticsPane = ({ if (activeFilePath) { items.push({ id: "only-current-file", - label: "Only Current File", + label: t("diagnostics.onlyCurrentFile"), icon: preferences.onlyCurrentFile ? : undefined, onClick: () => togglePreference("onlyCurrentFile"), }); @@ -810,7 +822,7 @@ const DiagnosticsPane = ({ if (sourceFilter) { items.push({ id: "clear-source-filter", - label: `Clear Source Filter (${sourceFilter})`, + label: t("diagnostics.clearSourceFilter", { source: sourceFilter }), onClick: () => setSourceFilter(null), }); } @@ -819,7 +831,7 @@ const DiagnosticsPane = ({ items.push({ id: "sep-reset", label: "", separator: true, onClick: () => {} }); items.push({ id: "reset-filters", - label: "Reset All Filters", + label: t("diagnostics.resetAllFilters"), onClick: resetFilters, }); } @@ -839,14 +851,15 @@ const DiagnosticsPane = ({ toggleSeverity, totalBySeverity, visibleBySeverity, + t, ]); const headerContextMenuItems = useMemo(() => { if (!headerContextMenu.data) return []; const widthModes: { value: TerminalWidthMode; label: string; icon: ReactNode }[] = [ - { value: "full", label: "Full Width", icon: }, - { value: "editor", label: "Editor Width", icon: }, + { value: "full", label: t("diagnostics.fullWidth"), icon: }, + { value: "editor", label: t("diagnostics.editorWidth"), icon: }, ]; const items: MenuItem[] = widthModes.map((mode) => ({ @@ -862,7 +875,7 @@ const DiagnosticsPane = ({ { id: "sep-fullscreen", label: "", separator: true, onClick: () => {} }, { id: "toggle-fullscreen", - label: isFullScreen ? "Exit Full Screen" : "Full Screen", + label: isFullScreen ? t("diagnostics.exitFullScreen") : t("diagnostics.fullScreen"), icon: isFullScreen ? : , onClick: onFullScreen, }, @@ -870,7 +883,7 @@ const DiagnosticsPane = ({ } return items; - }, [headerContextMenu.data, widthMode, setWidthMode, onFullScreen, isFullScreen]); + }, [headerContextMenu.data, widthMode, setWidthMode, onFullScreen, isFullScreen, t]); if (!isVisible) return null; @@ -894,8 +907,12 @@ const DiagnosticsPane = ({ className={cn( isFileNavigatorVisible && "border-border/70 bg-accent text-foreground", )} - tooltip={isFileNavigatorVisible ? "Hide files" : "Show files"} - aria-label={isFileNavigatorVisible ? "Hide files" : "Show files"} + tooltip={ + isFileNavigatorVisible ? t("diagnostics.hideFiles") : t("diagnostics.showFiles") + } + aria-label={ + isFileNavigatorVisible ? t("diagnostics.hideFiles") : t("diagnostics.showFiles") + } > @@ -914,7 +931,7 @@ const DiagnosticsPane = ({ className={cn( (isSearchVisible || hasSearch) && "border-border/70 bg-accent text-foreground", )} - tooltip="Search problems" + tooltip={t("diagnostics.search")} > @@ -925,7 +942,7 @@ const DiagnosticsPane = ({ filterContextMenu.open(event, "filters"); }} className={cn("relative", hasFilterSettings && "text-primary")} - tooltip="Filter problems" + tooltip={t("diagnostics.filter")} > {activeFilterCount > 0 && ( @@ -943,16 +960,18 @@ const DiagnosticsPane = ({ {isFullScreen ? : } )} {!isEmbedded && ( - + )} @@ -979,7 +998,7 @@ const DiagnosticsPane = ({ } } }} - placeholder="Search problems" + placeholder={t("diagnostics.search")} inputRef={searchInputRef} extraActions={ {activeFilterCount > 0 && ( @@ -1014,7 +1033,7 @@ const DiagnosticsPane = ({ items={diagnosticFileItems} selectedKey={selectedFileNavigatorKey} onSelect={selectDiagnosticFile} - ariaLabel="Diagnostic files" + ariaLabel={t("diagnostics.filesAria")} viewMode={preferences.fileNavigatorViewMode} onViewModeChange={(fileNavigatorViewMode) => setPreferences((prev) => ({ @@ -1027,11 +1046,15 @@ const DiagnosticsPane = ({ {diagnostics.length === 0 ? ( - + ) : filteredDiagnostics.length === 0 ? ( ) : (
diff --git a/windows/tauri/src/features/editor/components/code-editor.tsx b/windows/tauri/src/features/editor/components/code-editor.tsx index 3a4545c88..1cd9c7557 100644 --- a/windows/tauri/src/features/editor/components/code-editor.tsx +++ b/windows/tauri/src/features/editor/components/code-editor.tsx @@ -514,6 +514,7 @@ const CodeEditor = ({ editorViewKey={editorViewKey} bufferId={activeBufferId ?? undefined} filePathOverride={breadcrumbProps?.filePathOverride ?? filePath} + showFilePath={breadcrumbProps?.showFilePath ?? false} /> )} diff --git a/windows/tauri/src/features/editor/components/toolbar/breadcrumb.tsx b/windows/tauri/src/features/editor/components/toolbar/breadcrumb.tsx index 5e76df993..8e44f2cb7 100644 --- a/windows/tauri/src/features/editor/components/toolbar/breadcrumb.tsx +++ b/windows/tauri/src/features/editor/components/toolbar/breadcrumb.tsx @@ -11,6 +11,7 @@ import { useExtensionActions } from "@/extensions/ui/hooks/use-extension-actions import { ExtensionToolbarAction } from "@/extensions/ui/components/extension-toolbar-action"; import { isMarkdownPreviewableFile } from "@/features/editor/markdown/previewable"; import { useSettingsStore } from "@/features/settings/stores/settings.store"; +import { useTranslation } from "@/i18n/locale-provider"; import { Button, type ButtonProps } from "@/ui/button"; import { Dropdown, type MenuItem } from "@/ui/dropdown"; import { cn } from "@/utils/cn"; @@ -26,6 +27,7 @@ export interface BreadcrumbProps { showDefaultActions?: boolean; interactive?: boolean; showPath?: boolean; + showFilePath?: boolean; } type BreadcrumbActionButtonProps = Omit; @@ -50,7 +52,9 @@ export default function Breadcrumb({ showDefaultActions = true, interactive = true, showPath = true, + showFilePath = true, }: BreadcrumbProps = {}) { + const { t } = useTranslation(); const resolvedBufferId = useBufferStore((state) => bufferId ?? state.activeBufferId); const activeBuffer = useBufferStore( useShallow((state) => { @@ -149,19 +153,19 @@ export default function Breadcrumb({ ? [ { id: "preview", - label: "Preview", + label: t("editor.preview"), onClick: handlePreviewClick, }, ] : []), { id: "inline-edit", - label: "AI inline edit", + label: t("editor.aiInlineEdit"), onClick: handleInlineEditClick, }, { id: "find", - label: "Find in file", + label: t("editor.findInFile"), onClick: onSearchClick, }, ]; @@ -177,7 +181,7 @@ export default function Breadcrumb({ ref={actionsButtonRef} onClick={() => setIsActionsMenuOpen((open) => !open)} active={isActionsMenuOpen} - tooltip="Editor actions" + tooltip={t("editor.actions")} tooltipSide="bottom" > @@ -202,10 +206,12 @@ export default function Breadcrumb({
{showPath && showBreadcrumbPath ? ( <> - + {showFilePath ? ( + + ) : null} [number]; -function CursorPositionChip({ editorViewKey }: { editorViewKey?: string | null }) { +export function CursorPositionChip({ editorViewKey }: { editorViewKey?: string | null }) { const activeEditorViewKey = useEditorStateStore.use.activeEditorViewKey(); const cursorPosition = useEditorStateStore.use.cursorPosition(); const [isEditing, setIsEditing] = useState(false); @@ -157,7 +158,8 @@ function CursorPositionChip({ editorViewKey }: { editorViewKey?: string | null } ); } -export function EditorStatusActions({ bufferId, editorViewKey }: EditorStatusActionsProps = {}) { +export function EditorStatusActions({ bufferId }: EditorStatusActionsProps = {}) { + const { t } = useTranslation(); const rootFolderPath = useFileSystemStore((state) => state.rootFolderPath); const resolvedBufferId = useBufferStore((state) => bufferId ?? state.activeBufferId); const breadcrumbsEnabled = useSettingsStore((state) => state.settings.coreFeatures.breadcrumbs); @@ -190,25 +192,25 @@ export function EditorStatusActions({ bufferId, editorViewKey }: EditorStatusAct return { icon: , color: "text-success", - title: "Language Servers Active", + title: t("lsp.active"), }; case "connecting": return { - icon: , + icon: , color: "text-warning", - title: "Connecting to Language Server...", + title: t("lsp.connecting"), }; case "error": return { icon: , color: "text-destructive", - title: "Language server issue", + title: t("lsp.issue"), }; default: return { icon: , color: "text-subtle-foreground opacity-50", - title: "No active language servers", + title: t("lsp.noActive"), }; } }; @@ -216,7 +218,7 @@ export function EditorStatusActions({ bufferId, editorViewKey }: EditorStatusAct const config = getStatusConfig(lspStatus.status); const activeServers = lspStatus.supportedLanguages || []; const hasActiveServers = lspStatus.status === "connected" && activeServers.length > 0; - const projectName = rootFolderPath ? getFilenameFromPath(rootFolderPath) : "No Project"; + const projectName = rootFolderPath ? getFilenameFromPath(rootFolderPath) : t("lsp.noProject"); const activeBuffer = useBufferStore( useShallow((state) => { const buffer = getBufferById(state.buffers, resolvedBufferId); @@ -384,7 +386,7 @@ export function EditorStatusActions({ bufferId, editorViewKey }: EditorStatusAct const displayOptions = [ { id: "breadcrumbs", - label: "Breadcrumbs", + label: t("settings.advanced.feature.breadcrumbs.name"), checked: breadcrumbsEnabled, shortcut: null, onToggle: () => { @@ -397,14 +399,14 @@ export function EditorStatusActions({ bufferId, editorViewKey }: EditorStatusAct }, { id: "minimap", - label: "Minimap", + label: t("editor.minimap"), checked: showMinimap, shortcut: minimapShortcut, onToggle: () => updateSetting("showMinimap", !showMinimap), }, { id: "line-numbers", - label: "Line Numbers", + label: t("settings.editor.lineNumbers"), checked: lineNumbers, shortcut: null, onToggle: () => updateSetting("lineNumbers", !lineNumbers), @@ -412,7 +414,7 @@ export function EditorStatusActions({ bufferId, editorViewKey }: EditorStatusAct }, { id: "relative-line-numbers", - label: "Relative Line Numbers", + label: t("settings.editor.relativeLineNumbers"), checked: vimRelativeLineNumbers, shortcut: null, onToggle: () => updateSetting("vimRelativeLineNumbers", !vimRelativeLineNumbers), @@ -420,7 +422,7 @@ export function EditorStatusActions({ bufferId, editorViewKey }: EditorStatusAct }, { id: "word-wrap", - label: "Word Wrap", + label: t("settings.editor.wordWrap"), checked: wordWrap, shortcut: null, onToggle: () => updateSetting("wordWrap", !wordWrap), @@ -428,7 +430,7 @@ export function EditorStatusActions({ bufferId, editorViewKey }: EditorStatusAct }, { id: "parameter-hints", - label: "Parameter Hints", + label: t("settings.editor.parameterHints"), checked: parameterHints, shortcut: null, onToggle: () => updateSetting("parameterHints", !parameterHints), @@ -436,7 +438,7 @@ export function EditorStatusActions({ bufferId, editorViewKey }: EditorStatusAct }, { id: "auto-completion", - label: "Auto Completion", + label: t("settings.editor.autoCompletion"), checked: autoCompletion, shortcut: null, onToggle: () => updateSetting("autoCompletion", !autoCompletion), @@ -444,7 +446,7 @@ export function EditorStatusActions({ bufferId, editorViewKey }: EditorStatusAct }, { id: "inlay-hints", - label: "Inlay Hints", + label: t("settings.editor.inlayHints"), checked: inlayHints, shortcut: null, onToggle: () => updateSetting("inlayHints", !inlayHints), @@ -452,7 +454,7 @@ export function EditorStatusActions({ bufferId, editorViewKey }: EditorStatusAct }, { id: "code-lens", - label: "Code Lens", + label: t("settings.editor.codeLens"), checked: codeLens, shortcut: null, onToggle: () => updateSetting("codeLens", !codeLens), @@ -460,7 +462,7 @@ export function EditorStatusActions({ bufferId, editorViewKey }: EditorStatusAct }, { id: "semantic-tokens", - label: "Semantic Tokens", + label: t("settings.editor.semanticTokens"), checked: semanticTokens, shortcut: null, onToggle: () => updateSetting("semanticTokens", !semanticTokens), @@ -468,7 +470,7 @@ export function EditorStatusActions({ bufferId, editorViewKey }: EditorStatusAct }, { id: "vim-mode", - label: "Vim Mode", + label: t("settings.keyboard.vimMode"), checked: vimMode, shortcut: null, onToggle: () => updateSetting("vimMode", !vimMode), @@ -476,7 +478,7 @@ export function EditorStatusActions({ bufferId, editorViewKey }: EditorStatusAct }, { id: "inline-git-blame", - label: "Inline Git Blame", + label: t("editor.inlineGitBlame"), checked: enableInlineGitBlame, shortcut: null, onToggle: () => updateSetting("enableInlineGitBlame", !enableInlineGitBlame), @@ -486,8 +488,6 @@ export function EditorStatusActions({ bufferId, editorViewKey }: EditorStatusAct return ( <> - - {activeBuffer?.type === "editor" && (
{lang.displayName} ))} - No languages found + {t("editor.noLanguages")} @@ -554,7 +554,7 @@ export function EditorStatusActions({ bufferId, editorViewKey }: EditorStatusAct config.color, isLspOpen && "bg-accent text-foreground", )} - aria-label="Language server status" + aria-label={t("lsp.status")} tooltip={config.title} tooltipSide="bottom" > @@ -584,7 +584,7 @@ export function EditorStatusActions({ bufferId, editorViewKey }: EditorStatusAct size="xs" className={cn(editorMenuActionButtonClass, "flex-1")} > - {bulkLspAction === "restart" ? "Restarting..." : "Restart all"} + {bulkLspAction === "restart" ? t("lsp.restarting") : t("lsp.restartAll")}
)} @@ -617,7 +617,7 @@ export function EditorStatusActions({ bufferId, editorViewKey }: EditorStatusAct size="xs" className={editorMenuActionButtonClass} > - {isBusy ? "..." : "Restart"} + {isBusy ? "..." : t("lsp.restart")}
@@ -660,7 +660,7 @@ export function EditorStatusActions({ bufferId, editorViewKey }: EditorStatusAct ) : lspStatus.status === "connecting" ? ( - + ) : lspStatus.status === "error" ? ( @@ -672,19 +672,16 @@ export function EditorStatusActions({ bufferId, editorViewKey }: EditorStatusAct - Language server issue + {t("lsp.issue")} - - Check notifications for the latest error. Reinstall the affected language tools - from Extensions if the server binary is missing or failed to launch. - + {t("lsp.issueHint")} ) : ( - No active language servers + {t("lsp.noActive")} )} @@ -703,7 +700,7 @@ export function EditorStatusActions({ bufferId, editorViewKey }: EditorStatusAct "text-subtle-foreground", isViewMenuOpen && "border-border/60 bg-accent/80 text-foreground", )} - tooltip="Editor preferences" + tooltip={t("editor.preferences")} tooltipSide="bottom" > diff --git a/windows/tauri/src/features/editor/components/toolbar/file-path-breadcrumb.tsx b/windows/tauri/src/features/editor/components/toolbar/file-path-breadcrumb.tsx index 6e7b6ed00..84eac6cc5 100644 --- a/windows/tauri/src/features/editor/components/toolbar/file-path-breadcrumb.tsx +++ b/windows/tauri/src/features/editor/components/toolbar/file-path-breadcrumb.tsx @@ -23,12 +23,14 @@ interface DirectoryEntry { interface FilePathBreadcrumbProps { filePath: string; interactive?: boolean; + menuSide?: "top" | "bottom"; className?: string; } export function FilePathBreadcrumb({ filePath, interactive = true, + menuSide = "bottom", className, }: FilePathBreadcrumbProps) { const rootFolderPath = useFileSystemStore((state) => state.rootFolderPath); @@ -162,7 +164,7 @@ export function FilePathBreadcrumb({ setDropdown({ segmentIndex, x: rect.left, - y: rect.bottom + 2, + y: menuSide === "top" ? rect.top : rect.bottom + 2, items, currentPath: dirPath, navigationStack: [], @@ -187,6 +189,13 @@ export function FilePathBreadcrumb({ } : undefined } + lastSegmentLeading={ + + } className={className} /> diff --git a/windows/tauri/src/features/editor/components/toolbar/path-breadcrumb.tsx b/windows/tauri/src/features/editor/components/toolbar/path-breadcrumb.tsx index 2e5d5d89e..85fcf794e 100644 --- a/windows/tauri/src/features/editor/components/toolbar/path-breadcrumb.tsx +++ b/windows/tauri/src/features/editor/components/toolbar/path-breadcrumb.tsx @@ -1,4 +1,4 @@ -import { Fragment, type MouseEvent } from "react"; +import { Fragment, type MouseEvent, type ReactNode } from "react"; import { Button } from "@/ui/button"; import { Breadcrumb, @@ -15,6 +15,7 @@ interface PathBreadcrumbProps { interactive?: boolean; onSegmentClick?: (index: number, event: MouseEvent) => void; setSegmentRef?: (index: number, element: HTMLButtonElement | null) => void; + lastSegmentLeading?: ReactNode; className?: string; } @@ -23,6 +24,7 @@ export function PathBreadcrumb({ interactive = false, onSegmentClick, setSegmentRef, + lastSegmentLeading, className, }: PathBreadcrumbProps) { if (segments.length === 0) return null; @@ -52,16 +54,25 @@ export function PathBreadcrumb({ /> } className={cn( - "min-w-0 whitespace-nowrap", + "min-w-0 items-center gap-1 whitespace-nowrap", isLast ? "font-medium text-foreground hover:text-foreground" : "text-subtle-foreground hover:text-foreground", )} > + {isLast && lastSegmentLeading ? ( + {lastSegmentLeading} + ) : null} {segment} ) : isLast ? ( - + + {lastSegmentLeading ? ( + {lastSegmentLeading} + ) : null} {segment} ) : ( diff --git a/windows/tauri/src/features/editor/context-menu/context-menu.tsx b/windows/tauri/src/features/editor/context-menu/context-menu.tsx index 5448ed9a3..2e9a21ad3 100644 --- a/windows/tauri/src/features/editor/context-menu/context-menu.tsx +++ b/windows/tauri/src/features/editor/context-menu/context-menu.tsx @@ -1,5 +1,6 @@ import { EDITOR_CONSTANTS } from "@/features/editor/config/constants"; import { useEditorStateStore } from "@/features/editor/stores/state.store"; +import { useTranslation } from "@/i18n/locale-provider"; import { Dropdown } from "@/ui/dropdown"; import { IS_MAC } from "@/utils/platform"; import { @@ -14,6 +15,7 @@ interface EditorContextMenuProps extends EditorContextMenuHandlers { } const EditorContextMenu = ({ isOpen, position, onClose, ...handlers }: EditorContextMenuProps) => { + const { t } = useTranslation(); const hasSelection = (() => { if (!isOpen) return false; const selection = useEditorStateStore.getState().selection; @@ -28,6 +30,7 @@ const EditorContextMenu = ({ isOpen, position, onClose, ...handlers }: EditorCon hasSelection, modifierKey, altKey, + t, ...handlers, }); diff --git a/windows/tauri/src/features/editor/context-menu/editor-context-menu-items.tsx b/windows/tauri/src/features/editor/context-menu/editor-context-menu-items.tsx index 8ad20a56b..bb45e9a09 100644 --- a/windows/tauri/src/features/editor/context-menu/editor-context-menu-items.tsx +++ b/windows/tauri/src/features/editor/context-menu/editor-context-menu-items.tsx @@ -53,6 +53,7 @@ export interface EditorContextMenuItemOptions extends EditorContextMenuHandlers hasSelection: boolean; modifierKey: string; altKey: string; + t: (key: string) => string; } const noop = () => {}; @@ -69,6 +70,7 @@ export function buildEditorContextMenuItems({ hasSelection, modifierKey, altKey, + t, onCopy, onCut, onPaste, @@ -99,7 +101,7 @@ export function buildEditorContextMenuItems({ return [ { id: "copy", - label: "Copy", + label: t("files.copy"), icon: , keybinding: , disabled: isDisabled(onCopy, !hasSelection), @@ -107,7 +109,7 @@ export function buildEditorContextMenuItems({ }, { id: "cut", - label: "Cut", + label: t("files.cut"), icon: , keybinding: , disabled: isDisabled(onCut, !hasSelection), @@ -115,7 +117,7 @@ export function buildEditorContextMenuItems({ }, { id: "paste", - label: "Paste", + label: t("files.paste"), icon: , keybinding: , disabled: isDisabled(onPaste), @@ -123,7 +125,7 @@ export function buildEditorContextMenuItems({ }, { id: "delete", - label: "Delete", + label: t("files.delete"), icon: , keybinding: , disabled: isDisabled(onDelete, !hasSelection), @@ -132,7 +134,7 @@ export function buildEditorContextMenuItems({ separator("sep-1"), { id: "select-all", - label: "Select All", + label: t("editor.selectAll"), icon: , keybinding: , disabled: isDisabled(onSelectAll), @@ -140,14 +142,14 @@ export function buildEditorContextMenuItems({ }, { id: "duplicate", - label: "Duplicate Line", + label: t("editor.duplicateLine"), icon: , disabled: isDisabled(onDuplicate), onClick: onDuplicate ?? noop, }, { id: "select-next-occurrence", - label: "Add Selection to Next Match", + label: t("editor.addSelectionToNextMatch"), icon: , keybinding: , disabled: isDisabled(onSelectNextOccurrence), @@ -155,7 +157,7 @@ export function buildEditorContextMenuItems({ }, { id: "select-all-occurrences", - label: "Select All Occurrences", + label: t("editor.selectAllOccurrences"), icon: , keybinding: , disabled: isDisabled(onSelectAllOccurrences), @@ -164,7 +166,7 @@ export function buildEditorContextMenuItems({ separator("sep-2"), { id: "toggle-comment", - label: "Toggle Comment", + label: t("editor.toggleComment"), icon: , keybinding: , disabled: isDisabled(onToggleComment), @@ -172,7 +174,7 @@ export function buildEditorContextMenuItems({ }, { id: "indent", - label: "Indent", + label: t("editor.indent"), icon: , keybinding: , disabled: isDisabled(onIndent), @@ -180,7 +182,7 @@ export function buildEditorContextMenuItems({ }, { id: "outdent", - label: "Outdent", + label: t("editor.outdent"), icon: , keybinding: , disabled: isDisabled(onOutdent), @@ -188,7 +190,7 @@ export function buildEditorContextMenuItems({ }, { id: "format", - label: "Format Document", + label: t("editor.formatDocument"), icon: , keybinding: , disabled: isDisabled(onFormat), @@ -196,7 +198,7 @@ export function buildEditorContextMenuItems({ }, { id: "format-selection", - label: "Format Selection", + label: t("editor.formatSelection"), icon: , keybinding: , disabled: isDisabled(onFormatSelection, !hasSelection), @@ -205,7 +207,7 @@ export function buildEditorContextMenuItems({ separator("sep-3"), { id: "move-up", - label: "Move Line Up", + label: t("editor.moveLineUp"), icon: , keybinding: , disabled: isDisabled(onMoveLineUp), @@ -213,7 +215,7 @@ export function buildEditorContextMenuItems({ }, { id: "move-down", - label: "Move Line Down", + label: t("editor.moveLineDown"), icon: , keybinding: , disabled: isDisabled(onMoveLineDown), @@ -221,7 +223,7 @@ export function buildEditorContextMenuItems({ }, { id: "toggle-case", - label: "Toggle Case", + label: t("editor.toggleCase"), icon: , disabled: isDisabled(onToggleCase, !hasSelection), onClick: onToggleCase ?? noop, @@ -229,7 +231,7 @@ export function buildEditorContextMenuItems({ separator("sep-4"), { id: "go-to-definition", - label: "Go to Definition", + label: t("editor.goToDefinition"), icon: , keybinding: , disabled: isDisabled(onGoToDefinition), @@ -237,7 +239,7 @@ export function buildEditorContextMenuItems({ }, { id: "find-references", - label: "Find All References", + label: t("editor.findAllReferences"), icon: , keybinding: , disabled: isDisabled(onFindReferences), @@ -245,14 +247,14 @@ export function buildEditorContextMenuItems({ }, { id: "go-to-type-definition", - label: "Go to Type Definition", + label: t("editor.goToTypeDefinition"), icon: , disabled: isDisabled(onGoToTypeDefinition), onClick: onGoToTypeDefinition ?? noop, }, { id: "rename-symbol", - label: "Rename Symbol", + label: t("editor.renameSymbol"), icon: , keybinding: , disabled: isDisabled(onRenameSymbol), @@ -260,7 +262,7 @@ export function buildEditorContextMenuItems({ }, { id: "quick-fix", - label: "Quick Fix...", + label: t("editor.quickFix"), icon: , keybinding: , disabled: isDisabled(onQuickFix), @@ -268,7 +270,7 @@ export function buildEditorContextMenuItems({ }, { id: "show-hover", - label: "Show Hover", + label: t("editor.showHover"), icon: , keybinding: , disabled: isDisabled(onShowHover), @@ -276,7 +278,7 @@ export function buildEditorContextMenuItems({ }, { id: "trigger-suggest", - label: "Trigger Suggest", + label: t("editor.triggerSuggest"), icon: , keybinding: , disabled: isDisabled(onTriggerSuggest), @@ -285,7 +287,7 @@ export function buildEditorContextMenuItems({ separator("sep-5"), { id: "find", - label: "Find", + label: t("editor.find"), icon: , keybinding: , disabled: isDisabled(onFind), @@ -293,7 +295,7 @@ export function buildEditorContextMenuItems({ }, { id: "go-to-line", - label: "Go to Line", + label: t("editor.goToLine"), icon: , keybinding: , disabled: isDisabled(onGoToLine), @@ -301,7 +303,7 @@ export function buildEditorContextMenuItems({ }, { id: "bookmark", - label: "Toggle Bookmark", + label: t("editor.toggleBookmark"), icon: , keybinding: , disabled: isDisabled(onToggleBookmark), diff --git a/windows/tauri/src/features/file-explorer/hooks/use-file-explorer-context-menu.tsx b/windows/tauri/src/features/file-explorer/hooks/use-file-explorer-context-menu.tsx index 31ce5e2ba..89ca8b82f 100644 --- a/windows/tauri/src/features/file-explorer/hooks/use-file-explorer-context-menu.tsx +++ b/windows/tauri/src/features/file-explorer/hooks/use-file-explorer-context-menu.tsx @@ -38,6 +38,7 @@ import { Button } from "@/ui/button"; import { Dropdown, type MenuItem } from "@/ui/dropdown"; import Dialog from "@/ui/dialog"; import { toast } from "sonner"; +import { useTranslation } from "@/i18n/locale-provider"; import { getBaseName, getDirName, getRelativePath, joinPath } from "@/utils/path-helpers"; interface UseFileExplorerContextMenuOptions { @@ -77,9 +78,9 @@ interface PropertiesDialogState { const menuIconSpacer =