From 1c68f5d288f5446ce3a2ed0df5010e9250e068d8 Mon Sep 17 00:00:00 2001 From: MusiCode1 <54508123+MusiCode1@users.noreply.github.com> Date: Tue, 24 Mar 2026 23:09:52 +0200 Subject: [PATCH] feat(i18n): Hebrew locale + full RTL support (#243) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # feat(i18n): Hebrew locale + full RTL support ## Summary This PR adds full Hebrew (he) locale support to the UI, including a complete translation of all user-facing strings and comprehensive RTL layout support across all components. ## What was done ### Hebrew translation - Full translation of all i18n message files for the `he` locale (17 translation files) - Registered the language in the i18n system and the language picker ### RTL support - Automatic direction detection (`dir="rtl"`) when Hebrew is selected - Replaced physical CSS properties (`left`/`right`) with logical equivalents (`inline-start`/`inline-end`) across the project - Fixed resize direction, file path alignment, and textarea padding - Fixed navigation button positioning in textarea for RTL - Fixed scrollbar direction in RTL - Fixed code block direction and selector alignment - Fixed Monaco editor direction in the file viewer - Auto-detect text direction in reasoning block (`dir="auto"` + `unicode-bidi: plaintext`) ### Adapted components - `session-layout` — sidebar and resize handle - `prompt-input` — text direction and buttons - `message-base` — message blocks and reasoning - `message-timeline` — timeline bar - `right-panel` — right side panel - `tool-call` — tool call display - `settings-screen` — settings page - `selector` — selection component - `instance-shell` — main shell ## New files ``` packages/ui/src/lib/i18n/messages/he/ advancedSettings.ts app.ts commands.ts dialogs.ts filesystem.ts folderSelection.ts index.ts instance.ts loadingScreen.ts logs.ts markdown.ts messaging.ts remoteAccess.ts session.ts settings.ts time.ts toolCall.ts ``` ## Suggested testing - Switch language to Hebrew and verify all strings are translated - Verify RTL layout is correct across all screens (session, settings, file viewer) - Verify that English text inside a reasoning block is displayed LTR - Switch back to English and verify everything returns to LTR --------- Co-authored-by: Claude Sonnet 4.6 Co-authored-by: Shantur Rathore --- manifest.json | 6 - .../src/components/folder-selection-view.tsx | 5 +- packages/ui/src/components/instance-info.tsx | 8 +- .../components/instance/instance-shell2.tsx | 17 +- .../instance/shell/right-panel/RightPanel.tsx | 6 +- .../right-panel/components/DiffToolbar.tsx | 8 +- .../right-panel/components/SplitFilePanel.tsx | 4 +- .../shell/right-panel/tabs/FilesTab.tsx | 2 +- .../shell/right-panel/tabs/GitChangesTab.tsx | 2 +- .../instance/shell/useDrawerResize.ts | 4 +- packages/ui/src/components/message-block.tsx | 2 +- packages/ui/src/components/model-selector.tsx | 2 +- .../ui/src/components/worktree-selector.tsx | 7 +- packages/ui/src/lib/i18n/index.tsx | 23 ++- .../ui/src/lib/i18n/messages/en/instance.ts | 10 + .../lib/i18n/messages/he/advancedSettings.ts | 6 + packages/ui/src/lib/i18n/messages/he/app.ts | 42 +++++ .../ui/src/lib/i18n/messages/he/commands.ts | 176 ++++++++++++++++++ .../ui/src/lib/i18n/messages/he/dialogs.ts | 16 ++ .../ui/src/lib/i18n/messages/he/filesystem.ts | 43 +++++ .../lib/i18n/messages/he/folderSelection.ts | 42 +++++ packages/ui/src/lib/i18n/messages/he/index.ts | 36 ++++ .../ui/src/lib/i18n/messages/he/instance.ts | 166 +++++++++++++++++ .../src/lib/i18n/messages/he/loadingScreen.ts | 17 ++ packages/ui/src/lib/i18n/messages/he/logs.ts | 27 +++ .../ui/src/lib/i18n/messages/he/markdown.ts | 7 + .../ui/src/lib/i18n/messages/he/messaging.ts | 141 ++++++++++++++ .../src/lib/i18n/messages/he/remoteAccess.ts | 51 +++++ .../ui/src/lib/i18n/messages/he/session.ts | 90 +++++++++ .../ui/src/lib/i18n/messages/he/settings.ts | 142 ++++++++++++++ packages/ui/src/lib/i18n/messages/he/time.ts | 6 + .../ui/src/lib/i18n/messages/he/toolCall.ts | 132 +++++++++++++ .../styles/components/directory-browser.css | 2 +- .../ui/src/styles/components/selector.css | 4 +- .../src/styles/components/settings-screen.css | 11 +- packages/ui/src/styles/markdown.css | 1 + packages/ui/src/styles/messaging.css | 2 +- .../ui/src/styles/messaging/message-base.css | 20 +- .../src/styles/messaging/message-section.css | 4 +- .../styles/messaging/message-selection.css | 4 +- .../src/styles/messaging/message-timeline.css | 29 ++- .../ui/src/styles/messaging/prompt-input.css | 22 ++- .../ui/src/styles/messaging/tool-call.css | 40 ++-- .../src/styles/messaging/tool-call/task.css | 12 +- .../styles/messaging/virtual-follow-list.css | 2 +- packages/ui/src/styles/panels/modal.css | 2 +- packages/ui/src/styles/panels/panel-shell.css | 2 +- packages/ui/src/styles/panels/right-panel.css | 17 +- .../ui/src/styles/panels/session-layout.css | 37 ++-- 49 files changed, 1334 insertions(+), 123 deletions(-) delete mode 100644 manifest.json create mode 100644 packages/ui/src/lib/i18n/messages/he/advancedSettings.ts create mode 100644 packages/ui/src/lib/i18n/messages/he/app.ts create mode 100644 packages/ui/src/lib/i18n/messages/he/commands.ts create mode 100644 packages/ui/src/lib/i18n/messages/he/dialogs.ts create mode 100644 packages/ui/src/lib/i18n/messages/he/filesystem.ts create mode 100644 packages/ui/src/lib/i18n/messages/he/folderSelection.ts create mode 100644 packages/ui/src/lib/i18n/messages/he/index.ts create mode 100644 packages/ui/src/lib/i18n/messages/he/instance.ts create mode 100644 packages/ui/src/lib/i18n/messages/he/loadingScreen.ts create mode 100644 packages/ui/src/lib/i18n/messages/he/logs.ts create mode 100644 packages/ui/src/lib/i18n/messages/he/markdown.ts create mode 100644 packages/ui/src/lib/i18n/messages/he/messaging.ts create mode 100644 packages/ui/src/lib/i18n/messages/he/remoteAccess.ts create mode 100644 packages/ui/src/lib/i18n/messages/he/session.ts create mode 100644 packages/ui/src/lib/i18n/messages/he/settings.ts create mode 100644 packages/ui/src/lib/i18n/messages/he/time.ts create mode 100644 packages/ui/src/lib/i18n/messages/he/toolCall.ts diff --git a/manifest.json b/manifest.json deleted file mode 100644 index d10e5612..00000000 --- a/manifest.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "minServerVersion": "0.12.3", - "latestUIVersion": "0.12.3-rtl", - "uiPackageURL": "https://github.com/MusiCode1/CodeNomad/releases/download/v0.12.3-rtl/codenomad-ui-rtl.zip", - "sha256": "a2ce1aaa04345a2f9ca9d3c3149567867f3a5e477cf6eb269381e6dc1bec7ca2" -} diff --git a/packages/ui/src/components/folder-selection-view.tsx b/packages/ui/src/components/folder-selection-view.tsx index e7e9cfa2..85c80059 100644 --- a/packages/ui/src/components/folder-selection-view.tsx +++ b/packages/ui/src/components/folder-selection-view.tsx @@ -45,6 +45,7 @@ const FolderSelectionView: Component = (props) => { { value: "ru", label: "Русский" }, { value: "ja", label: "日本語" }, { value: "zh-Hans", label: "简体中文" }, + { value: "he", label: "עברית" }, ] const selectedLanguageOption = () => languageOptions.find((opt) => opt.value === locale()) ?? languageOptions[0] @@ -341,7 +342,7 @@ const FolderSelectionView: Component = (props) => { class="w-full max-w-5xl h-full px-4 sm:px-8 pb-2 flex flex-col overflow-hidden" aria-busy={isLoading() ? "true" : "false"} > -
+
value={selectedLanguageOption()} onChange={(value) => { @@ -385,7 +386,7 @@ const FolderSelectionView: Component = (props) => {
-
+
{props.header} diff --git a/packages/ui/src/components/instance/shell/right-panel/tabs/FilesTab.tsx b/packages/ui/src/components/instance/shell/right-panel/tabs/FilesTab.tsx index 9b7d3c19..976d1431 100644 --- a/packages/ui/src/components/instance/shell/right-panel/tabs/FilesTab.tsx +++ b/packages/ui/src/components/instance/shell/right-panel/tabs/FilesTab.tsx @@ -175,7 +175,7 @@ const FilesTab: Component = (props) => { title={props.t("instanceShell.rightPanel.actions.refresh")} aria-label={props.t("instanceShell.rightPanel.actions.refresh")} disabled={props.browserLoading()} - style={{ "margin-left": "auto" }} + style={{ "margin-inline-start": "auto" }} onClick={() => props.onRefresh()} > diff --git a/packages/ui/src/components/instance/shell/right-panel/tabs/GitChangesTab.tsx b/packages/ui/src/components/instance/shell/right-panel/tabs/GitChangesTab.tsx index 5f83d9e6..019dce1d 100644 --- a/packages/ui/src/components/instance/shell/right-panel/tabs/GitChangesTab.tsx +++ b/packages/ui/src/components/instance/shell/right-panel/tabs/GitChangesTab.tsx @@ -82,7 +82,7 @@ const GitChangesTab: Component = (props) => { }) const emptyViewerMessage = createMemo(() => { - if (!hasSession()) return props.t("instanceShell.sessionChanges.noSessionSelected") + if (!hasSession()) return props.t("instanceShell.gitChanges.noSessionSelected") const currentEntries = entries() if (currentEntries === null) return props.t("instanceShell.gitChanges.loading") if (nonDeleted().length === 0) return props.t("instanceShell.gitChanges.empty") diff --git a/packages/ui/src/components/instance/shell/useDrawerResize.ts b/packages/ui/src/components/instance/shell/useDrawerResize.ts index d3a4f982..c07fc139 100644 --- a/packages/ui/src/components/instance/shell/useDrawerResize.ts +++ b/packages/ui/src/components/instance/shell/useDrawerResize.ts @@ -46,7 +46,9 @@ export function useDrawerResize(options: DrawerResizeOptions): DrawerResizeApi { if (!side) return const startWidth = resizeStartWidth() const clamp = side === "left" ? options.clampLeft : options.clampRight - const delta = side === "left" ? clientX - resizeStartX() : resizeStartX() - clientX + const isRtl = typeof document !== "undefined" && document.documentElement.dir === "rtl" + const rawDelta = side === "left" ? clientX - resizeStartX() : resizeStartX() - clientX + const delta = isRtl ? -rawDelta : rawDelta const nextWidth = clamp(startWidth + delta) applyDrawerWidth(side, nextWidth) } diff --git a/packages/ui/src/components/message-block.tsx b/packages/ui/src/components/message-block.tsx index 7cbf8c96..4157f342 100644 --- a/packages/ui/src/components/message-block.tsx +++ b/packages/ui/src/components/message-block.tsx @@ -1531,7 +1531,7 @@ function ReasoningCard(props: ReasoningCardProps) {
-
{reasoningText() || ""}
+
{reasoningText() || ""}
diff --git a/packages/ui/src/components/model-selector.tsx b/packages/ui/src/components/model-selector.tsx index 005af3ad..6f5c5955 100644 --- a/packages/ui/src/components/model-selector.tsx +++ b/packages/ui/src/components/model-selector.tsx @@ -295,7 +295,7 @@ export default function ModelSelector(props: ModelSelectorProps) { {t("modelSelector.trigger.primary", { model: currentModelValue()?.name ?? t("modelSelector.none") })} {currentModelValue() && ( - + {currentModelValue()!.providerId}/{currentModelValue()!.id} )} diff --git a/packages/ui/src/components/worktree-selector.tsx b/packages/ui/src/components/worktree-selector.tsx index 71773d86..52c7f7d7 100644 --- a/packages/ui/src/components/worktree-selector.tsx +++ b/packages/ui/src/components/worktree-selector.tsx @@ -18,6 +18,7 @@ import { setWorktreeSlugForParentSession, } from "../stores/worktrees" import { sessions } from "../stores/sessions" +import { useI18n } from "../lib/i18n" const log = getLogger("session") @@ -25,8 +26,6 @@ type WorktreeOption = | { kind: "action"; key: "__create__"; label: string } | { kind: "worktree"; key: string; slug: string; directory: string; raw: WorktreeDescriptor } -const CREATE_OPTION: WorktreeOption = { kind: "action", key: "__create__", label: "+ Create worktree" } - function preventSelectPress(event: PointerEvent | MouseEvent) { // Prevent Select.Item from treating this as a selection. // We intentionally prevent default to stop Kobalte's internal press handling. @@ -71,6 +70,7 @@ interface WorktreeSelectorProps { } export default function WorktreeSelector(props: WorktreeSelectorProps) { + const { t } = useI18n() const [isOpen, setIsOpen] = createSignal(false) const [createOpen, setCreateOpen] = createSignal(false) const [createSlug, setCreateSlug] = createSignal("") @@ -99,7 +99,8 @@ export default function WorktreeSelector(props: WorktreeSelectorProps) { directory: wt.directory, raw: wt, })) - return [CREATE_OPTION, ...mapped] + const createOption: WorktreeOption = { kind: "action", key: "__create__", label: t("instanceShell.worktree.create") } + return [createOption, ...mapped] }) const selectedOption = createMemo(() => { diff --git a/packages/ui/src/lib/i18n/index.tsx b/packages/ui/src/lib/i18n/index.tsx index 3a50885c..c65e5bc3 100644 --- a/packages/ui/src/lib/i18n/index.tsx +++ b/packages/ui/src/lib/i18n/index.tsx @@ -7,10 +7,11 @@ type Messages = Record export type TranslateParams = Record -export type Locale = "en" | "es" | "fr" | "ru" | "ja" | "zh-Hans" +export type Locale = "en" | "es" | "fr" | "ru" | "ja" | "zh-Hans" | "he" -const SUPPORTED_LOCALES: readonly Locale[] = ["en", "es", "fr", "ru", "ja", "zh-Hans"] as const +const SUPPORTED_LOCALES: readonly Locale[] = ["en", "es", "fr", "ru", "ja", "zh-Hans", "he"] as const const SUPPORTED_LOCALES_BY_LOWER = new Map(SUPPORTED_LOCALES.map((locale) => [locale.toLowerCase(), locale])) +const RTL_LOCALES = new Set(["he"]) const localeMessagesCache = new Map([["en", enMessages]]) const localeMessagesPromises = new Map>() @@ -22,6 +23,11 @@ const localeLoaders: Record Promise> = { ru: async () => (await import("./messages/ru")).ruMessages, ja: async () => (await import("./messages/ja")).jaMessages, "zh-Hans": async () => (await import("./messages/zh-Hans")).zhHansMessages, + he: async () => (await import("./messages/he")).heMessages, +} + +function getLocaleDirection(locale: Locale): "ltr" | "rtl" { + return RTL_LOCALES.has(locale) ? "rtl" : "ltr" } function normalizeLocaleTag(value: string): string { @@ -149,6 +155,8 @@ export const I18nProvider: ParentComponent = (props) => { const [resolvedLocale, setResolvedLocale] = createSignal(globalLocale) const previousGlobalMessages = globalMessages const previousGlobalLocale = globalLocale + const previousDocumentLanguage = typeof document !== "undefined" ? document.documentElement.lang : "" + const previousDocumentDirection = typeof document !== "undefined" ? document.documentElement.dir : "" onMount(() => { const detected = detectNavigatorLocale() @@ -195,10 +203,21 @@ export const I18nProvider: ParentComponent = (props) => { }) }) + createEffect(() => { + if (typeof document === "undefined") return + const activeLocale = locale() + document.documentElement.dir = getLocaleDirection(activeLocale) + document.documentElement.lang = activeLocale + }) + onCleanup(() => { globalMessages = previousGlobalMessages globalLocale = previousGlobalLocale setGlobalRevision((value) => value + 1) + if (typeof document !== "undefined") { + document.documentElement.lang = previousDocumentLanguage + document.documentElement.dir = previousDocumentDirection + } }) const value: I18nContextValue = { diff --git a/packages/ui/src/lib/i18n/messages/en/instance.ts b/packages/ui/src/lib/i18n/messages/en/instance.ts index 83af3eaf..1ee49f45 100644 --- a/packages/ui/src/lib/i18n/messages/en/instance.ts +++ b/packages/ui/src/lib/i18n/messages/en/instance.ts @@ -114,6 +114,7 @@ export const instanceMessages = { "instanceShell.sessionChanges.filesChanged": "{count} files changed", "instanceShell.sessionChanges.actions.show": "Show changes", + "instanceShell.gitChanges.noSessionSelected": "Select a session to view git changes.", "instanceShell.gitChanges.loading": "Loading git changes...", "instanceShell.gitChanges.empty": "No git changes yet.", "instanceShell.gitChanges.deleted": "Deleted", @@ -124,6 +125,15 @@ export const instanceMessages = { "instanceShell.filesShell.viewerTitle": "Change viewer", "instanceShell.filesShell.viewerPlaceholder": "Detailed change rendering will be added in the next step.", "instanceShell.filesShell.viewerEmpty": "No file selected.", + "instanceShell.filesShell.hideFiles": "Hide files", + "instanceShell.filesShell.showFiles": "Show files", + "instanceShell.diff.hideUnchanged": "Hide unchanged regions", + "instanceShell.diff.showFull": "Show full file", + "instanceShell.diff.switchToSplit": "Switch to split view", + "instanceShell.diff.switchToUnified": "Switch to unified view", + "instanceShell.diff.enableWordWrap": "Enable word wrap", + "instanceShell.diff.disableWordWrap": "Disable word wrap", + "instanceShell.worktree.create": "+ Create worktree", "instanceShell.plan.noSessionSelected": "Select a session to view plan.", "instanceShell.plan.empty": "Nothing planned yet.", diff --git a/packages/ui/src/lib/i18n/messages/he/advancedSettings.ts b/packages/ui/src/lib/i18n/messages/he/advancedSettings.ts new file mode 100644 index 00000000..dd0bada5 --- /dev/null +++ b/packages/ui/src/lib/i18n/messages/he/advancedSettings.ts @@ -0,0 +1,6 @@ +export const advancedSettingsMessages = { + "advancedSettings.title": "הגדרות מתקדמות", + "advancedSettings.environmentVariables.title": "משתני סביבה", + "advancedSettings.environmentVariables.subtitle": "מוחלים בכל פעם שמופע OpenCode חדש מופעל", + "advancedSettings.actions.close": "סגור", +} as const diff --git a/packages/ui/src/lib/i18n/messages/he/app.ts b/packages/ui/src/lib/i18n/messages/he/app.ts new file mode 100644 index 00000000..487f185d --- /dev/null +++ b/packages/ui/src/lib/i18n/messages/he/app.ts @@ -0,0 +1,42 @@ +export const appMessages = { + "app.launchError.title": "לא ניתן להפעיל את OpenCode", + "app.launchError.description": "לא הצלחנו להפעיל את קובץ ה-OpenCode שנבחר. בדוק את פלט השגיאה למטה או בחר קובץ בינארי אחר מהגדרות OpenCode.", + "app.launchError.binaryPathLabel": "נתיב הקובץ הבינארי", + "app.launchError.errorOutputLabel": "פלט שגיאה", + "app.launchError.openAdvancedSettings": "פתח הגדרות OpenCode", + "app.launchError.close": "סגור", + "app.launchError.closeTitle": "סגור (Esc)", + "app.launchError.fallbackMessage": "הפעלת סביבת העבודה נכשלה", + + "app.stopInstance.confirmMessage": "לעצור את מופע OpenCode? פעולה זו תעצור את השרת.", + "app.stopInstance.title": "עצור מופע", + "app.stopInstance.confirmLabel": "עצור", + "app.stopInstance.cancelLabel": "המשך להריץ", + + "emptyState.logoAlt": "לוגו CodeNomad", + "emptyState.brandTitle": "CodeNomad", + "emptyState.tagline": "בחר תיקייה כדי להתחיל לתכנת עם AI", + "emptyState.actions.selectFolder": "בחר תיקייה", + "emptyState.actions.selecting": "בוחר...", + "emptyState.keyboardShortcut": "קיצור מקלדת: {shortcut}", + "emptyState.examples": "דוגמאות: {example}", + "emptyState.multipleInstances": "ניתן לפתוח מספר מופעים של אותה תיקייה", + + "releases.upgradeRequired.title": "נדרש שדרוג", + "releases.upgradeRequired.message.withVersion": "שדרג ל-CodeNomad {version} כדי להשתמש בממשק המעודכן.", + "releases.upgradeRequired.message.noVersion": "שדרג את CodeNomad כדי להשתמש בממשק המעודכן.", + "releases.upgradeRequired.action.getUpdate": "קבל עדכון", + + "releases.uiUpdated.title": "הממשק עודכן", + "releases.uiUpdated.message": "הממשק עודכן לגרסה {version}.", + + "releases.devUpdateAvailable.title": "גרסת פיתוח זמינה", + "releases.devUpdateAvailable.message": "גרסת פיתוח חדשה זמינה: {version}.", + "releases.devUpdateAvailable.action": "צפה בגרסה", + + "theme.mode.system": "מערכת", + "theme.mode.light": "בהיר", + "theme.mode.dark": "כהה", + "theme.toggle.title": "ערכת נושא: {mode}", + "theme.toggle.ariaLabel": "ערכת נושא: {mode}", +} as const diff --git a/packages/ui/src/lib/i18n/messages/he/commands.ts b/packages/ui/src/lib/i18n/messages/he/commands.ts new file mode 100644 index 00000000..09d246ac --- /dev/null +++ b/packages/ui/src/lib/i18n/messages/he/commands.ts @@ -0,0 +1,176 @@ +export const commandMessages = { + "commandPalette.title": "לוח פקודות", + "commandPalette.description": "חיפוש והפעלה של פקודות", + "commandPalette.searchPlaceholder": "הקלד פקודה או חיפוש...", + "commandPalette.empty": "לא נמצאו פקודות עבור \"{query}\"", + "commandPalette.category.customCommands": "פקודות מותאמות אישית", + "commandPalette.category.instance": "מופע", + "commandPalette.category.session": "סשן", + "commandPalette.category.agentModel": "סוכן ומודל", + "commandPalette.category.inputFocus": "קלט ופוקוס", + "commandPalette.category.system": "מערכת", + "commandPalette.category.other": "אחר", + + "commands.newInstance.label": "מופע חדש", + "commands.newInstance.description": "פתח בורר תיקיות ליצירת מופע חדש", + "commands.newInstance.keywords": "תיקייה, פרויקט, סביבת עבודה", + + "commands.closeInstance.label": "סגור מופע", + "commands.closeInstance.description": "עצור את השרת של המופע הנוכחי", + "commands.closeInstance.keywords": "עצור, סגור", + + "commands.nextInstance.label": "מופע הבא", + "commands.nextInstance.description": "עבור למופע הבא", + "commands.nextInstance.keywords": "החלף, נווט", + + "commands.previousInstance.label": "מופע קודם", + "commands.previousInstance.description": "עבור למופע הקודם", + "commands.previousInstance.keywords": "החלף, נווט", + + "commands.newSession.label": "סשן חדש", + "commands.newSession.description": "צור סשן הורה חדש", + "commands.newSession.keywords": "צור, התחל", + + "commands.closeSession.label": "סגור סשן", + "commands.closeSession.description": "סגור את סשן ההורה הנוכחי", + "commands.closeSession.keywords": "סגור, עצור", + + "commands.scrubSessions.label": "נקה סשנים", + "commands.scrubSessions.description": "הסר סשנים ריקים, סשני תת-סוכן שסיימו את משימתם הראשית, וסשני פיצול מיותרים.", + "commands.scrubSessions.keywords": "ניקוי, ריק, סשנים, הסר, מחק", + + "commands.instanceInfo.label": "מידע על מופע", + "commands.instanceInfo.description": "פתח את סקירת המופע ללוגים וסטטוס", + "commands.instanceInfo.keywords": "מידע, לוגים, קונסולה, פלט", + + "commands.nextSession.label": "סשן הבא", + "commands.nextSession.description": "עבור לסשן הבא", + "commands.nextSession.keywords": "החלף, נווט", + + "commands.previousSession.label": "סשן קודם", + "commands.previousSession.description": "עבור לסשן הקודם", + "commands.previousSession.keywords": "החלף, נווט", + + "commands.compactSession.label": "סכם סשן", + "commands.compactSession.description": "סכם ודחוס את הסשן הנוכחי", + "commands.compactSession.keywords": "סיכום, דחיסה", + "commands.compactSession.errorFallback": "סיכום הסשן נכשל", + "commands.compactSession.alert.title": "הסיכום נכשל", + "commands.compactSession.alert.message": "הסיכום נכשל: {message}", + + "commands.undoLastMessage.label": "בטל הודעה אחרונה", + "commands.undoLastMessage.description": "בטל את ההודעה האחרונה", + "commands.undoLastMessage.keywords": "חזרה, ביטול", + "commands.undoLastMessage.none.title": "אין פעולות לביטול", + "commands.undoLastMessage.none.message": "אין מה לבטל", + "commands.undoLastMessage.failed.title": "הביטול נכשל", + "commands.undoLastMessage.failed.message": "ביטול ההודעה נכשל", + + "commands.openModelSelector.label": "פתח בורר מודלים", + "commands.openModelSelector.description": "בחר מודל אחר", + "commands.openModelSelector.keywords": "מודל, llm, ai", + + "commands.selectModelVariant.label": "בחר גרסת מודל", + "commands.selectModelVariant.description": "בחר רמת מאמץ חשיבה למודל הנוכחי", + "commands.selectModelVariant.keywords": "גרסה, חשיבה, מאמץ", + + "commands.openAgentSelector.label": "פתח בורר סוכנים", + "commands.openAgentSelector.description": "בחר סוכן אחר", + "commands.openAgentSelector.keywords": "סוכן, מצב", + + "commands.clearInput.label": "נקה קלט", + "commands.clearInput.description": "נקה את תיבת הטקסט של הפקודה", + "commands.clearInput.keywords": "נקה, אפס", + + "commands.promptSubmitShortcut.label.default": "Enter: שורה חדשה, Cmd/Ctrl+Enter: שלח פקודה", + "commands.promptSubmitShortcut.label.swapped": "Enter: שלח פקודה, Cmd/Ctrl+Enter: שורה חדשה", + "commands.promptSubmitShortcut.description": "החלף את התנהגות Enter ו-Cmd/Ctrl+Enter בקלט הפקודה", + "commands.promptSubmitShortcut.keywords": "enter, cmd, ctrl, שלח, שורה חדשה, קיצור", + + "commands.thinkingBlocks.label.show": "הצג חשיבה", + "commands.thinkingBlocks.label.hide": "הסתר חשיבה", + "commands.thinkingBlocks.description": "הצג או הסתר קטעי חשיבה של ה-AI", + "commands.thinkingBlocks.keywords": "חשיבה, הצג, הסתר", + + "commands.timelineToolCalls.label.show": "הצג קריאות כלי בציר הזמן", + "commands.timelineToolCalls.label.hide": "הסתר קריאות כלי בציר הזמן", + "commands.timelineToolCalls.description": "הצג/הסתר קריאות כלי בציר הודעות", + "commands.timelineToolCalls.keywords": "ציר זמן, כלי, הצג, הסתר", + + "commands.keyboardShortcutHints.label.show": "הצג רמזי קיצורי מקלדת", + "commands.keyboardShortcutHints.label.hide": "הסתר רמזי קיצורי מקלדת", + "commands.keyboardShortcutHints.description": "הצג או הסתר רמזי קיצורי מקלדת בכל הממשק", + "commands.keyboardShortcutHints.description.disabledWeb": "מושבת בממשק Web (רמזי קיצורים תמיד מוסתרים)", + "commands.keyboardShortcutHints.keywords": "קיצור, מקלדת, רמזים", + + "commands.common.expanded": "פרוס", + "commands.common.collapsed": "מכווץ", + "commands.common.visible": "גלוי", + "commands.common.hidden": "מוסתר", + "commands.common.enabled": "מופעל", + "commands.common.disabled": "מושבת", + + "commands.thinkingBlocksDefault.label": "תצוגת חשיבה: {state}", + "commands.thinkingBlocksDefault.description": "כווץ / פרוס קטעי חשיבה של ה-AI", + "commands.thinkingBlocksDefault.keywords": "חשיבה, פרוס, כווץ, ברירת מחדל", + + "commands.diffViewSplit.label": "השתמש בתצוגת diff מפוצלת", + "commands.diffViewSplit.description": "הצג diff של קריאות כלי זה לצד זה", + "commands.diffViewSplit.keywords": "diff, מפוצל, תצוגה", + + "commands.diffViewUnified.label": "השתמש בתצוגת diff מאוחדת", + "commands.diffViewUnified.description": "הצג diff של קריאות כלי בשורה אחת", + "commands.diffViewUnified.keywords": "diff, מאוחד, תצוגה", + + "commands.toolOutputsDefault.label": "ברירת מחדל לפלטי כלים · {state}", + "commands.toolOutputsDefault.description": "החלף ברירת מחדל לפריסת פלטי כלים", + "commands.toolOutputsDefault.keywords": "כלי, פלט, פרוס, כווץ", + + "commands.diagnosticsDefault.label": "ברירת מחדל לאבחון · {state}", + "commands.diagnosticsDefault.description": "החלף ברירת מחדל לפריסת פלט אבחון", + "commands.diagnosticsDefault.keywords": "אבחון, פרוס, כווץ", + + "commands.toolInputsVisibility.label": "נראות קלטי כלים · {state}", + "commands.toolInputsVisibility.description": "הגדר נראות ברירת מחדל לארגומנטים של קריאות כלי", + "commands.toolInputsVisibility.keywords": "כלי, קלטים, ארגומנטים, נראות, הסתר, הצג", + + "commands.tokenUsageDisplay.label": "תצוגת שימוש בטוקנים · {state}", + "commands.tokenUsageDisplay.description": "הצג או הסתר נתוני טוקנים ועלות להודעות הסוכן", + "commands.tokenUsageDisplay.keywords": "טוקן, שימוש, עלות, נתונים", + + "commands.autoCleanupBlankSessions.label": "ניקוי אוטומטי של סשנים ריקים · {state}", + "commands.autoCleanupBlankSessions.description": "נקה אוטומטית סשנים ריקים בעת יצירת סשנים חדשים", + "commands.autoCleanupBlankSessions.keywords": "אוטומטי, ניקוי, ריק, סשנים", + + "commands.showHelp.label": "הצג עזרה", + "commands.showHelp.description": "הצג קיצורי מקלדת ועזרה", + "commands.showHelp.keywords": "קיצורים, עזרה", + + "commands.custom.argumentsPrompt.message": "ארגומנטים עבור /{name}", + "commands.custom.argumentsPrompt.title": "פקודה מותאמת אישית", + "commands.custom.argumentsPrompt.inputLabel": "ארגומנטים", + "commands.custom.argumentsPrompt.inputPlaceholder": "למשל: foo bar", + "commands.custom.argumentsPrompt.confirmLabel": "הפעל", + "commands.custom.argumentsPrompt.cancelLabel": "ביטול", + "commands.custom.argumentsPrompt.openFailed.message": "פתיחת תיבת ארגומנטים נכשלה.", + "commands.custom.argumentsPrompt.openFailed.title": "ארגומנטים לפקודה", + "commands.custom.entries.descriptionFallback": "פקודה מותאמת אישית", + "commands.custom.sessionRequired.message": "בחר סשן לפני הפעלת פקודה מותאמת אישית.", + "commands.custom.sessionRequired.title": "נדרש סשן", + "commands.custom.runFailed.message": "הפעלת הפקודה המותאמת אישית נכשלה. בדוק את הקונסולה לפרטים.", + "commands.custom.runFailed.title": "הפקודה נכשלה", + + "unifiedPicker.loading.searching": "מחפש...", + "unifiedPicker.loading.loadingWorkspace": "טוען סביבת עבודה...", + "unifiedPicker.title.command": "בחר פקודה", + "unifiedPicker.title.mention": "בחר סוכן או קובץ", + "unifiedPicker.empty": "לא נמצאו תוצאות", + "unifiedPicker.sections.commands": "פקודות", + "unifiedPicker.sections.agents": "סוכנים", + "unifiedPicker.sections.files": "קבצים", + "unifiedPicker.sections.workspaceRoot": "שורש סביבת העבודה", + "unifiedPicker.badge.subagent": "תת-סוכן", + "unifiedPicker.footer.navigate": "ניווט", + "unifiedPicker.footer.select": "בחירה", + "unifiedPicker.footer.close": "סגירה", +} as const diff --git a/packages/ui/src/lib/i18n/messages/he/dialogs.ts b/packages/ui/src/lib/i18n/messages/he/dialogs.ts new file mode 100644 index 00000000..d224460f --- /dev/null +++ b/packages/ui/src/lib/i18n/messages/he/dialogs.ts @@ -0,0 +1,16 @@ +export const dialogMessages = { + "alertDialog.fallbackTitle.info": "לתשומת לבך", + "alertDialog.fallbackTitle.warning": "נא לבדוק", + "alertDialog.fallbackTitle.error": "משהו השתבש", + "alertDialog.actions.confirm": "אישור", + "alertDialog.actions.run": "הפעל", + "alertDialog.actions.ok": "אישור", + "alertDialog.actions.cancel": "ביטול", + "alertDialog.prompt.inputLabel": "קלט", + + "backgroundProcessOutputDialog.title": "פלט תהליך רקע", + "backgroundProcessOutputDialog.actions.close": "סגור", + "backgroundProcessOutputDialog.loading": "טוען פלט...", + "backgroundProcessOutputDialog.truncatedNotice": "הפלט קוצר לצורך התצוגה.", + "backgroundProcessOutputDialog.loadErrorFallback": "טעינת הפלט נכשלה.", +} as const diff --git a/packages/ui/src/lib/i18n/messages/he/filesystem.ts b/packages/ui/src/lib/i18n/messages/he/filesystem.ts new file mode 100644 index 00000000..06e80119 --- /dev/null +++ b/packages/ui/src/lib/i18n/messages/he/filesystem.ts @@ -0,0 +1,43 @@ +export const filesystemMessages = { + "directoryBrowser.defaultDescription": "עיון בתיקיות תחת שורש סביבת העבודה המוגדר.", + "directoryBrowser.close": "סגור", + "directoryBrowser.currentFolder": "תיקייה נוכחית", + "directoryBrowser.selectCurrent": "בחר נוכחית", + "directoryBrowser.newFolder": "תיקייה חדשה", + "directoryBrowser.creating": "יוצר…", + "directoryBrowser.loadingFolders": "טוען תיקיות…", + "directoryBrowser.noFolders": "אין תיקיות זמינות.", + "directoryBrowser.upOneLevel": "עלה רמה אחת", + "directoryBrowser.select": "בחר", + "directoryBrowser.load.errorFallback": "לא ניתן לטעון את מערכת הקבצים", + "directoryBrowser.createFolder.promptMessage": "צור תיקייה חדשה בספרייה הנוכחית.", + "directoryBrowser.createFolder.title": "תיקייה חדשה", + "directoryBrowser.createFolder.inputLabel": "שם תיקייה", + "directoryBrowser.createFolder.inputPlaceholder": "למשל: my-new-project", + "directoryBrowser.createFolder.confirmLabel": "צור", + "directoryBrowser.createFolder.cancelLabel": "ביטול", + "directoryBrowser.createFolder.invalidNameMessage": "נא להזין שם תיקייה יחיד.", + "directoryBrowser.createFolder.invalidNameDetail": "שמות תיקיות אינם יכולים לכלול נטויות, '..', או '~'.", + "directoryBrowser.createFolder.errorFallback": "יצירת התיקייה נכשלה", + + "filesystemBrowser.descriptionFallback": "חפש נתיב תחת שורש סביבת העבודה המוגדר.", + "filesystemBrowser.rootLabel": "שורש: {root}", + "filesystemBrowser.actions.close": "סגור", + "filesystemBrowser.actions.retry": "נסה שוב", + "filesystemBrowser.actions.select": "בחר", + "filesystemBrowser.filterLabel": "סינון", + "filesystemBrowser.search.placeholder.directories": "חפש תיקיות", + "filesystemBrowser.search.placeholder.files": "חפש קבצים", + "filesystemBrowser.currentFolder.label": "תיקייה נוכחית", + "filesystemBrowser.currentFolder.selectCurrent": "בחר נוכחית", + "filesystemBrowser.loading.filesystem": "מערכת קבצים", + "filesystemBrowser.loading.workspaceRoot": "שורש סביבת עבודה", + "filesystemBrowser.loading.loadingWithPath": "טוען {path}…", + "filesystemBrowser.empty.noEntries": "לא נמצאו רשומות.", + "filesystemBrowser.navigation.upOneLevel": "עלה רמה אחת", + "filesystemBrowser.hints.navigate": "ניווט", + "filesystemBrowser.hints.select": "בחירה", + "filesystemBrowser.hints.close": "סגירה", + "filesystemBrowser.errors.loadFilesystemFallback": "לא ניתן לטעון את מערכת הקבצים", + "filesystemBrowser.errors.openDirectoryFallback": "לא ניתן לפתוח את הספרייה", +} as const diff --git a/packages/ui/src/lib/i18n/messages/he/folderSelection.ts b/packages/ui/src/lib/i18n/messages/he/folderSelection.ts new file mode 100644 index 00000000..489430a9 --- /dev/null +++ b/packages/ui/src/lib/i18n/messages/he/folderSelection.ts @@ -0,0 +1,42 @@ +export const folderSelectionMessages = { + "folderSelection.language.ariaLabel": "שפה", + + "folderSelection.logoAlt": "לוגו CodeNomad", + "folderSelection.tagline": "בחר תיקייה כדי להתחיל לתכנת עם AI", + + "folderSelection.links.github": "CodeNomad GitHub", + "folderSelection.links.githubStars": "כוכבי CodeNomad ב-GitHub", + "folderSelection.links.discord": "CodeNomad Discord", + + "folderSelection.empty.title": "אין תיקיות אחרונות", + "folderSelection.empty.description": "עיין בתיקייה כדי להתחיל", + + "folderSelection.recent.title": "תיקיות אחרונות", + "folderSelection.recent.subtitle.one": "תיקייה אחת זמינה", + "folderSelection.recent.subtitle.other": "{count} תיקיות זמינות", + "folderSelection.recent.remove": "הסר מהרשימה האחרונה", + + "folderSelection.browse.title": "עיון בתיקייה", + "folderSelection.browse.subtitle": "בחר כל תיקייה במחשב שלך", + "folderSelection.browse.button": "עיון בתיקיות", + "folderSelection.browse.buttonOpening": "פותח...", + + "folderSelection.advancedSettings": "הגדרות מתקדמות", + "folderSelection.opencode": "OpenCode", + + "folderSelection.hints.navigate": "ניווט", + "folderSelection.hints.select": "בחירה", + "folderSelection.hints.remove": "הסרה", + "folderSelection.hints.browse": "עיון", + + "folderSelection.loading.title": "מפעיל מופע...", + "folderSelection.loading.subtitle": "המתן בזמן שאנו מכינים את סביבת העבודה שלך.", + + "folderSelection.drop.title": "שחרר תיקייה כדי לפתוח אותה", + "folderSelection.drop.subtitle": "התחל מופע חדש בתיקייה שנשחררה.", + "folderSelection.drop.invalidTitle": "לא ניתן לפתוח את הפריט שנשחרר", + "folderSelection.drop.invalidMessage": "שחרר תיקייה כדי להתחיל מופע חדש.", + + "folderSelection.dialog.title": "בחר סביבת עבודה", + "folderSelection.dialog.description": "בחר סביבת עבודה כדי להתחיל לתכנת.", +} as const diff --git a/packages/ui/src/lib/i18n/messages/he/index.ts b/packages/ui/src/lib/i18n/messages/he/index.ts new file mode 100644 index 00000000..cee41090 --- /dev/null +++ b/packages/ui/src/lib/i18n/messages/he/index.ts @@ -0,0 +1,36 @@ +import { advancedSettingsMessages } from "./advancedSettings" +import { appMessages } from "./app" +import { commandMessages } from "./commands" +import { dialogMessages } from "./dialogs" +import { filesystemMessages } from "./filesystem" +import { folderSelectionMessages } from "./folderSelection" +import { instanceMessages } from "./instance" +import { loadingScreenMessages } from "./loadingScreen" +import { logMessages } from "./logs" +import { markdownMessages } from "./markdown" +import { messagingMessages } from "./messaging" +import { remoteAccessMessages } from "./remoteAccess" +import { sessionMessages } from "./session" +import { settingsMessages } from "./settings" +import { timeMessages } from "./time" +import { toolCallMessages } from "./toolCall" +import { mergeMessageParts } from "../merge" + +export const heMessages = mergeMessageParts( + folderSelectionMessages, + advancedSettingsMessages, + loadingScreenMessages, + timeMessages, + appMessages, + dialogMessages, + filesystemMessages, + instanceMessages, + logMessages, + sessionMessages, + messagingMessages, + toolCallMessages, + markdownMessages, + settingsMessages, + remoteAccessMessages, + commandMessages, +) diff --git a/packages/ui/src/lib/i18n/messages/he/instance.ts b/packages/ui/src/lib/i18n/messages/he/instance.ts new file mode 100644 index 00000000..6c8345fe --- /dev/null +++ b/packages/ui/src/lib/i18n/messages/he/instance.ts @@ -0,0 +1,166 @@ +export const instanceMessages = { + "instanceTabs.new.title": "מופע חדש (Cmd/Ctrl+N)", + "instanceTabs.new.ariaLabel": "מופע חדש", + "instanceTabs.remote.title": "חיבור מרוחק", + "instanceTabs.remote.ariaLabel": "חיבור מרוחק", + + "instanceInfo.title": "מידע על המופע", + "instanceInfo.labels.folder": "תיקייה", + "instanceInfo.labels.project": "פרויקט", + "instanceInfo.labels.versionControl": "בקרת גרסאות", + "instanceInfo.labels.opencodeVersion": "גרסת OpenCode", + "instanceInfo.labels.binaryPath": "נתיב קובץ בינארי", + "instanceInfo.labels.environmentVariables": "משתני סביבה ({count})", + "instanceInfo.loading": "טוען...", + "instanceInfo.server.title": "שרת", + "instanceInfo.server.port": "פורט:", + "instanceInfo.server.pid": "PID:", + "instanceInfo.server.status": "סטטוס:", + + "instanceTab.status.permission": "ממתין לאישור", + "instanceTab.status.compacting": "מסכם", + "instanceTab.status.working": "עובד", + "instanceTab.status.idle": "מוכן", + "instanceTab.status.ariaLabel": "סטטוס מופע: {status}", + "instanceTab.actions.close.ariaLabel": "סגור מופע", + + "instanceShell.leftPanel.sessionsTitle": "סשנים", + "instanceShell.leftPanel.instanceInfo": "מידע על המופע", + + "instanceShell.leftDrawer.pin": "נעץ מגירה שמאלית", + "instanceShell.leftDrawer.unpin": "שחרר נעיצת מגירה שמאלית", + "instanceShell.leftDrawer.toggle.pinned": "המגירה השמאלית נעוצה", + "instanceShell.leftDrawer.toggle.open": "פתח מגירה שמאלית", + "instanceShell.leftDrawer.toggle.close": "סגור מגירה שמאלית", + + "instanceShell.rightDrawer.pin": "נעץ מגירה ימנית", + "instanceShell.rightDrawer.unpin": "שחרר נעיצת מגירה ימנית", + "instanceShell.rightDrawer.toggle.pinned": "המגירה הימנית נעוצה", + "instanceShell.rightDrawer.toggle.open": "פתח מגירה ימנית", + "instanceShell.rightDrawer.toggle.close": "סגור מגירה ימנית", + + "instanceShell.fullscreen.enter": "מסך מלא", + "instanceShell.fullscreen.exit": "יציאה ממסך מלא", + + "instanceShell.metrics.usedLabel": "בשימוש", + "instanceShell.metrics.availableLabel": "זמין", + + "instanceShell.commandPalette.openAriaLabel": "פתח לוח פקודות", + "instanceShell.commandPalette.button": "לוח פקודות", + + "instanceShell.connection.ariaLabel": "חיבור {status}", + "instanceShell.connection.connected": "מחובר", + "instanceShell.connection.connecting": "מתחבר...", + "instanceShell.connection.disconnected": "מנותק", + "instanceShell.connection.unknown": "לא ידוע", + + "instanceWelcome.shortcuts.newSession": "סשן חדש", + "instanceWelcome.empty.title": "אין סשנים קודמים", + "instanceWelcome.empty.description": "צור סשן חדש למטה כדי להתחיל", + "instanceWelcome.loading.title": "טוען סשנים", + "instanceWelcome.loading.description": "מאחזר את הסשנים הקודמים שלך...", + "instanceWelcome.resume.title": "המשך סשן", + "instanceWelcome.resume.subtitle.one": "סשן אחד זמין", + "instanceWelcome.resume.subtitle.other": "{count} סשנים זמינים", + "instanceWelcome.session.untitled": "סשן ללא שם", + "instanceWelcome.new.title": "התחל סשן חדש", + "instanceWelcome.new.subtitle": "ישתמש אוטומטית בסוכן/מודל האחרון שלך", + "instanceWelcome.new.createButton": "צור סשן", + "instanceWelcome.overlay.close": "סגור", + "instanceWelcome.actions.viewInstanceInfo": "צפה במידע על המופע", + "instanceWelcome.actions.renameTitle": "שנה שם סשן", + "instanceWelcome.actions.deleteTitle": "מחק סשן", + "instanceWelcome.hints.navigate": "ניווט", + "instanceWelcome.hints.jump": "קפיצה", + "instanceWelcome.hints.firstLast": "ראשון/אחרון", + "instanceWelcome.hints.resume": "המשך", + "instanceWelcome.hints.delete": "מחיקה", + "instanceWelcome.toasts.renameError": "לא ניתן לשנות שם הסשן", + + "instanceDisconnected.title": "המופע התנתק", + "instanceDisconnected.folderFallback": "סביבת עבודה זו", + "instanceDisconnected.reasonFallback": "השרת הפסיק להגיב", + "instanceDisconnected.description": "לא ניתן עוד להגיע ל-{folder}. סגור את הלשונית כדי להמשיך לעבוד.", + "instanceDisconnected.details.title": "פרטים", + "instanceDisconnected.details.folderLabel": "תיקייה:", + "instanceDisconnected.actions.closeInstance": "סגור מופע", + + "instanceShell.empty.title": "לא נבחר סשן", + "instanceShell.empty.description": "בחר סשן לצפייה בהודעות", + + "instanceShell.rightPanel.title": "לוח סטטוס", + "instanceShell.rightPanel.tabs.changes": "שינויי סשן", + "instanceShell.rightPanel.tabs.gitChanges": "שינויי Git", + "instanceShell.rightPanel.tabs.files": "קבצים", + "instanceShell.rightPanel.tabs.status": "סטטוס", + "instanceShell.rightPanel.tabs.ariaLabel": "לשוניות לוח ימני", + "instanceShell.rightPanel.actions.refresh": "רענן", + "instanceShell.rightPanel.sections.sessionChanges": "שינויי סשן", + "instanceShell.rightPanel.sections.sessionChanges.tooltip": "קבצים שהשתנו בסשן הנוכחי. מציג הוספות ומחיקות לכל קובץ.", + "instanceShell.rightPanel.sections.plan": "תוכנית", + "instanceShell.rightPanel.sections.plan.tooltip": "מפת הדרכים של הסוכן לסשן זה. עוקב אחר משימות, תת-משימות וסטטוס השלמתן.", + "instanceShell.rightPanel.sections.backgroundProcesses": "מעטפות רקע", + "instanceShell.rightPanel.sections.backgroundProcesses.tooltip": "תהליכים ממושכים שהופעלו על ידי הסוכן. ניתן לעקוב אחר פלטם, לעצור אותם או לסיים אותם.", + "instanceShell.rightPanel.sections.mcp": "שרתי MCP", + "instanceShell.rightPanel.sections.mcp.tooltip": "שרתי Model Context Protocol המרחיבים את יכולות הסוכן עם כלים ושירותים חיצוניים.", + "instanceShell.rightPanel.sections.lsp": "שרתי LSP", + "instanceShell.rightPanel.sections.lsp.tooltip": "שרתי Language Server Protocol המספקים בינת קוד, אבחון ותכונות ספציפיות לשפה.", + "instanceShell.rightPanel.sections.plugins": "תוספים", + "instanceShell.rightPanel.sections.plugins.tooltip": "תוספים המתאימים אישית את הממשק ואת התנהגות השרת, ומוסיפים תכונות מעבר ל-MCP ו-LSP.", + + "instanceShell.sessionChanges.noSessionSelected": "בחר סשן לצפייה בשינויים.", + "instanceShell.sessionChanges.loading": "מאחזר שינויי סשן...", + "instanceShell.sessionChanges.empty": "אין שינויי סשן עדיין.", + "instanceShell.sessionChanges.filesChanged": "{count} קבצים שונו", + "instanceShell.sessionChanges.actions.show": "הצג שינויים", + + "instanceShell.filesShell.fileListTitle": "רשימת קבצים", + "instanceShell.filesShell.mobileSelectorLabel": "בחר קובץ", + "instanceShell.filesShell.mobileSelectorEmpty": "בחר קובץ", + "instanceShell.filesShell.viewerTitle": "מציג שינויים", + "instanceShell.filesShell.viewerPlaceholder": "תצוגת שינויים מפורטת תתווסף בשלב הבא.", + "instanceShell.filesShell.viewerEmpty": "לא נבחר קובץ.", + "instanceShell.filesShell.hideFiles": "הסתר קבצים", + "instanceShell.filesShell.showFiles": "הצג קבצים", + "instanceShell.gitChanges.noSessionSelected": "בחר סשן לצפייה בשינויי Git.", + "instanceShell.gitChanges.loading": "טוען שינויי Git…", + "instanceShell.gitChanges.empty": "אין שינויי Git עדיין.", + "instanceShell.diff.hideUnchanged": "הסתר אזורים ללא שינוי", + "instanceShell.diff.showFull": "הצג קובץ מלא", + "instanceShell.diff.switchToSplit": "עבור לתצוגה מפוצלת", + "instanceShell.diff.switchToUnified": "עבור לתצוגה מאוחדת", + "instanceShell.diff.enableWordWrap": "הפעל גלישת מילים", + "instanceShell.diff.disableWordWrap": "כבה גלישת מילים", + "instanceShell.worktree.create": "+ צור worktree", + + "instanceShell.plan.noSessionSelected": "בחר סשן לצפייה בתוכנית.", + "instanceShell.plan.empty": "עדיין לא תוכנן דבר.", + + "instanceShell.backgroundProcesses.empty": "אין תהליכי רקע.", + "instanceShell.backgroundProcesses.status": "סטטוס: {status}", + "instanceShell.backgroundProcesses.output": "פלט: {sizeKb}KB", + "instanceShell.backgroundProcesses.actions.output": "פלט", + "instanceShell.backgroundProcesses.actions.stop": "עצור", + "instanceShell.backgroundProcesses.actions.terminate": "סיים", + + "versionPill.appWithVersion": "אפליקציה {version}", + "versionPill.ui": "ממשק", + "versionPill.uiWithVersion": "ממשק {version}", + "versionPill.source": " ({source})", + + "opencodeBinarySelector.title": "קובץ בינארי של OpenCode", + "opencodeBinarySelector.subtitle": "בחר איזה קובץ הרצה OpenCode ישתמש", + "opencodeBinarySelector.customPath.placeholder": "הזן נתיב לקובץ בינארי של opencode…", + "opencodeBinarySelector.actions.add": "הוסף", + "opencodeBinarySelector.actions.browse": "עיין אחר קובץ בינארי…", + "opencodeBinarySelector.actions.removeTitle": "הסר קובץ בינארי", + "opencodeBinarySelector.badge.systemPath": "השתמש בקובץ בינארי מנתיב המערכת", + "opencodeBinarySelector.status.checkingVersions": "בודק גרסאות…", + "opencodeBinarySelector.status.checking": "בודק…", + "opencodeBinarySelector.dialog.title": "בחר קובץ בינארי של OpenCode", + "opencodeBinarySelector.dialog.description": "עיין בקבצים החשופים על ידי שרת ה-CLI.", + "opencodeBinarySelector.validation.invalidBinary": "קובץ בינארי לא תקין של OpenCode", + "opencodeBinarySelector.validation.alreadyValidating": "כבר מאמת", + "opencodeBinarySelector.display.systemPath": "{name} (נתיב מערכת)", + "opencodeBinarySelector.versionLabel": "v{version}", +} as const diff --git a/packages/ui/src/lib/i18n/messages/he/loadingScreen.ts b/packages/ui/src/lib/i18n/messages/he/loadingScreen.ts new file mode 100644 index 00000000..daf84040 --- /dev/null +++ b/packages/ui/src/lib/i18n/messages/he/loadingScreen.ts @@ -0,0 +1,17 @@ +export const loadingScreenMessages = { + "loadingScreen.logoAlt": "לוגו CodeNomad", + "loadingScreen.status.issue": "נתקלנו בבעיה", + "loadingScreen.actions.showAnother": "הצג עוד", + "loadingScreen.errors.missingRoot": "אלמנט השורש לטעינה לא נמצא", + + "loadingScreen.phrases.neurons": "מחמם את הנוירונים של ה-AI…", + "loadingScreen.phrases.daydreaming": "משכנע את ה-AI להפסיק לחלום בהקיץ…", + "loadingScreen.phrases.goggles": "מצחצח את משקפי הקוד של ה-AI…", + "loadingScreen.phrases.reorganizingFiles": "מבקש מה-AI להפסיק לארגן מחדש את הקבצים שלך…", + "loadingScreen.phrases.coffee": "מאכיל את ה-AI עוד קפה…", + "loadingScreen.phrases.nodeModules": "מלמד את ה-AI לא למחוק node_modules (שוב)…", + "loadingScreen.phrases.actNatural": "אומר ל-AI להיראות טבעי לפני שתגיע…", + "loadingScreen.phrases.rewritingHistory": "מבקש מה-AI בבקשה להפסיק לשכתב היסטוריה…", + "loadingScreen.phrases.stretch": "מאפשר ל-AI להתמתח לפני ספרינט הקוד שלו…", + "loadingScreen.phrases.keyboardControl": "משכנע את ה-AI לתת לך שליטה על המקלדת…", +} as const diff --git a/packages/ui/src/lib/i18n/messages/he/logs.ts b/packages/ui/src/lib/i18n/messages/he/logs.ts new file mode 100644 index 00000000..37f5f46f --- /dev/null +++ b/packages/ui/src/lib/i18n/messages/he/logs.ts @@ -0,0 +1,27 @@ +export const logMessages = { + "logsView.title": "לוגי שרת", + "logsView.actions.show": "הצג לוגי שרת", + "logsView.actions.hide": "הסתר לוגי שרת", + "logsView.envVars.title": "משתני סביבה ({count})", + "logsView.paused.title": "לוגי השרת מושהים", + "logsView.paused.description": "הפעל זרימה לצפייה בפעילות שרת OpenCode שלך.", + "logsView.empty.waiting": "ממתין לפלט שרת...", + "logsView.scrollToBottom": "גלול למטה", + + "infoView.logs.title": "לוגי שרת", + "infoView.logs.actions.show": "הצג לוגי שרת", + "infoView.logs.actions.hide": "הסתר לוגי שרת", + "infoView.logs.paused.title": "לוגי השרת מושהים", + "infoView.logs.paused.description": "הפעל זרימה לצפייה בפעילות שרת OpenCode שלך.", + "infoView.logs.empty.waiting": "ממתין לפלט שרת...", + "infoView.logs.scrollToBottom": "גלול למטה", + + "infoView.dispose.actions.dispose": "בטל מופע", + "infoView.dispose.actions.disposing": "מבטל...", + "infoView.dispose.confirm.title": "לבטל את המופע?", + "infoView.dispose.confirm.message": "פעולה זו מנקה את המצב השמור לפי פרויקט עבור ספרייה זו ומטעינה מחדש את המופע.", + "infoView.dispose.confirm.confirmLabel": "בטל", + "infoView.dispose.confirm.cancelLabel": "ביטול", + "infoView.dispose.toast.success": "המופע בוטל. מטעין מחדש...", + "infoView.dispose.toast.error": "ביטול המופע נכשל.", +} as const diff --git a/packages/ui/src/lib/i18n/messages/he/markdown.ts b/packages/ui/src/lib/i18n/messages/he/markdown.ts new file mode 100644 index 00000000..5505c65b --- /dev/null +++ b/packages/ui/src/lib/i18n/messages/he/markdown.ts @@ -0,0 +1,7 @@ +export const markdownMessages = { + "markdown.codeBlock.copy.label": "העתק", + "markdown.codeBlock.copy.copied": "הועתק!", + "markdown.codeBlock.copy.failed": "נכשל", + + "markdown.copy": "העתק", +} as const diff --git a/packages/ui/src/lib/i18n/messages/he/messaging.ts b/packages/ui/src/lib/i18n/messages/he/messaging.ts new file mode 100644 index 00000000..15c1cac5 --- /dev/null +++ b/packages/ui/src/lib/i18n/messages/he/messaging.ts @@ -0,0 +1,141 @@ +export const messagingMessages = { + "messageListHeader.sidebar.openSessionListAriaLabel": "פתח רשימת סשנים", + "messageListHeader.metrics.usedLabel": "בשימוש", + "messageListHeader.metrics.availableLabel": "זמין", + "messageListHeader.commandPalette.ariaLabel": "פתח לוח פקודות", + "messageListHeader.commandPalette.button": "לוח פקודות", + "messageListHeader.connection.connected": "מחובר", + "messageListHeader.connection.connecting": "מתחבר...", + "messageListHeader.connection.disconnected": "מנותק", + + "messageSection.empty.logoAlt": "לוגו CodeNomad", + "messageSection.empty.brandTitle": "CodeNomad", + "messageSection.empty.title": "התחל שיחה", + "messageSection.empty.description": "הקלד הודעה למטה או פתח את לוח הפקודות:", + "messageSection.empty.tips.commandPalette": "לוח פקודות", + "messageSection.empty.tips.askAboutCodebase": "שאל על בסיס הקוד שלך", + "messageSection.empty.tips.attachFilesPrefix": "צרף קבצים עם", + "messageSection.loading.messages": "טוען הודעות...", + "messageSection.scroll.toFirstAriaLabel": "גלול להודעה הראשונה", + "messageSection.scroll.toLatestAriaLabel": "גלול להודעה האחרונה", + "messageSection.quote.addAsQuote": "הוסף כציטוט", + "messageSection.quote.addAsCode": "הוסף כקוד", + "messageSection.quote.copy": "העתק", + "messageSection.quote.copied": "הועתק!", + "messageSection.quote.copyFailed": "ההעתקה נכשלה", + "messageTimeline.ariaLabel": "ציר זמן הודעות", + "messageTimeline.segment.user.label": "אתה", + "messageTimeline.segment.assistant.label": "סוכן", + "messageTimeline.segment.compaction.label": "סיכום", + "messageTimeline.tool.fallbackLabel": "קריאת כלי", + "messageTimeline.tooltip.userFallback": "הודעת משתמש", + "messageTimeline.tooltip.assistantFallback": "תגובת הסוכן", + "messageTimeline.tooltip.compaction.auto": "סיכום אוטומטי", + "messageTimeline.tooltip.compaction.manual": "סיכום ידני", + "messageTimeline.text.filePrefix": "[קובץ] {filename}", + "messageTimeline.text.attachment": "קובץ מצורף", + "messageBlock.tool.header": "קריאת כלי", + "messageBlock.tool.unknown": "לא ידוע", + "messageBlock.tool.goToSession.label": "עבור לסשן", + "messageBlock.tool.goToSession.title": "עבור לסשן", + "messageBlock.tool.goToSession.unavailableTitle": "הסשן עדיין אינו זמין", + "messageBlock.tool.deletePart.label": "מחק חלק", + "messageBlock.tool.deletePart.deleting": "מוחק...", + "messageBlock.tool.deletePart.title": "מחק את פלט קריאת הכלי הזו", + "messageBlock.tool.deletePart.failed.title": "המחיקה נכשלה", + "messageBlock.tool.deletePart.failed.message": "מחיקת פלט קריאת הכלי נכשלה", + + "messageBlock.compaction.ariaLabel": "סיכום סשן", + "messageBlock.compaction.autoLabel": "הסשן סוכם אוטומטית", + "messageBlock.compaction.manualLabel": "הסשן סוכם על ידך", + "messageBlock.usage.input": "קלט", + "messageBlock.usage.output": "פלט", + "messageBlock.usage.reasoning": "חשיבה", + "messageBlock.usage.cacheRead": "קריאת מטמון", + "messageBlock.usage.cacheWrite": "כתיבת מטמון", + "messageBlock.usage.cost": "עלות", + "messageBlock.step.agentLabel": "סוכן: {agent}", + "messageBlock.step.modelLabel": "מודל: {model}", + "messageBlock.reasoning.thinkingLabel": "חשיבה", + "messageBlock.reasoning.expandAriaLabel": "פרוס חשיבה", + "messageBlock.reasoning.collapseAriaLabel": "כווץ חשיבה", + "messageBlock.reasoning.indicator.hide": "הסתר", + "messageBlock.reasoning.indicator.view": "צפה", + "messageBlock.reasoning.detailsAriaLabel": "פרטי חשיבה", + + "codeBlockInline.actions.copy": "העתק", + "codeBlockInline.actions.copied": "הועתק!", + + "messageItem.speaker.you": "אתה", + "messageItem.speaker.assistant": "סוכן", + "messageItem.actions.revert": "בטל שינויים", + "messageItem.actions.revertTitle": "בטל שינויים עד כאן (מוחק הודעות)", + "messageItem.actions.fork": "פצל", + "messageItem.actions.forkTitle": "פצל מהודעה זו", + "messageItem.actions.copy": "העתק", + "messageItem.actions.copyTitle": "העתק הודעה", + "messageItem.actions.copied": "הועתק!", + "messageItem.actions.deleteMessage": "מחק הודעה (לא מבטל שינויים)", + "messageItem.actions.deleteMessagesUpTo": "מחק הודעות עד כאן (לא מבטל שינויים)", + "messageItem.actions.deletingMessage": "מוחק...", + "messageItem.actions.deleteMessageFailedTitle": "המחיקה נכשלה", + "messageItem.actions.deleteMessageFailedMessage": "מחיקת ההודעה נכשלה", + + "messageItem.selection.checkboxAriaLabel": "בחר הודעה למחיקה", + + "messageSection.bulkDelete.toolbarAriaLabel": "פריטים נבחרים ({count})", + "messageSection.bulkDelete.deleteSelectedTitle": "מחק פריטים נבחרים", + "messageSection.bulkDelete.selectAllTitle": "בחר את כל ההודעות", + "messageSection.bulkDelete.moreOptionsTitle": "אפשרויות נוספות", + "messageSection.bulkDelete.selectionModeLabel": "בחירה", + "messageSection.bulkDelete.selectionModeAll": "הכל", + "messageSection.bulkDelete.selectionModeTools": "כלים בלבד", + "messageSection.bulkDelete.selectionHint.toggle": "בחר פריט", + "messageSection.bulkDelete.selectionHint.range": "בחר טווח", + "messageSection.bulkDelete.selectionHint.clear": "נקה בחירה", + "messageSection.bulkDelete.cancelTitle": "בטל בחירה", + "messageSection.bulkDelete.failedTitle": "המחיקה נכשלה", + "messageSection.bulkDelete.failedMessage": "מחיקת הפריטים הנבחרים נכשלה", + "messageItem.status.queued": "בתור", + "messageItem.status.generating": "מייצר...", + "messageItem.status.sending": "שולח...", + "messageItem.status.failedToSend": "שליחת ההודעה נכשלה", + "messagePart.actions.delete": "מחק חלק", + "messagePart.actions.deleting": "מוחק...", + "messagePart.actions.deleteTitle": "מחק פריט זה", + "messagePart.actions.deleteFailedTitle": "המחיקה נכשלה", + "messagePart.actions.deleteFailedMessage": "מחיקת הפריט נכשלה", + "messageItem.attachment.defaultName": "קובץ מצורף", + "messageItem.attachment.downloadAriaLabel": "הורד {name}", + "messageItem.agentMeta.agentLabel": "סוכן: {agent}", + "messageItem.agentMeta.modelLabel": "מודל: {model}", + "messageItem.errors.authenticationFallback": "שגיאת אימות", + "messageItem.errors.outputLengthExceeded": "אורך פלט ההודעה חרג מהמגבלה", + "messageItem.errors.requestAborted": "הבקשה בוטלה", + "messageItem.errors.unknownFallback": "אירעה שגיאה לא ידועה", + + "attachmentChip.removeAriaLabel": "הסר קובץ מצורף", + + "expandButton.toggleAriaLabel": "שנה גובה תיבת הקלט", + + "promptInput.placeholder.shell": "הפעל פקודת מעטפת (Esc ליציאה)...", + "promptInput.placeholder.default": "הקלד הודעה, @file, @agent, או הדבק תמונות וטקסט...", + "promptInput.hints.shell.exit": "לצאת ממצב מעטפת", + "promptInput.hints.shell.enable": "מצב מעטפת", + "promptInput.hints.commands": "פקודות", + "promptInput.history.previousAriaLabel": "פקודה קודמת", + "promptInput.history.nextAriaLabel": "פקודה הבאה", + "promptInput.overlay.newLine": "שורה חדשה", + "promptInput.overlay.send": "שלח", + "promptInput.overlay.filesAgents": "קבצים/סוכנים", + "promptInput.overlay.history": "היסטוריה", + "promptInput.overlay.attachments": "• {count} קובץ/ים מצורף/ים", + "promptInput.overlay.shellModeActive": "מצב מעטפת פעיל", + "promptInput.overlay.press": "לחץ", + "promptInput.overlay.againToAbort": "שוב כדי לבטל את הסשן", + "promptInput.stopSession.ariaLabel": "עצור סשן", + "promptInput.stopSession.title": "עצור סשן", + "promptInput.send.ariaLabel": "שלח הודעה", + "promptInput.send.errorFallback": "שליחת ההודעה נכשלה", + "promptInput.send.errorTitle": "השליחה נכשלה", +} as const diff --git a/packages/ui/src/lib/i18n/messages/he/remoteAccess.ts b/packages/ui/src/lib/i18n/messages/he/remoteAccess.ts new file mode 100644 index 00000000..684ff23d --- /dev/null +++ b/packages/ui/src/lib/i18n/messages/he/remoteAccess.ts @@ -0,0 +1,51 @@ +export const remoteAccessMessages = { + "remoteAccess.eyebrow": "גישה מרוחקת", + "remoteAccess.title": "התחבר ל-CodeNomad מרחוק", + "remoteAccess.subtitle": "השתמש בכתובות למטה כדי לפתוח את CodeNomad ממכשיר אחר.", + "remoteAccess.close": "סגור גישה מרוחקת", + "remoteAccess.refresh": "רענן", + + "remoteAccess.sections.listeningMode.label": "מצב האזנה", + "remoteAccess.sections.listeningMode.help": "אפשר או הגבל גישה מרוחקת על ידי קישור לכל הממשקים או רק ל-localhost.", + "remoteAccess.toggle.on": "פועל", + "remoteAccess.toggle.off": "כבוי", + "remoteAccess.toggle.title": "אפשר חיבורים מכתובות IP אחרות", + "remoteAccess.toggle.caption.all": "מקושר ל-0.0.0.0", + "remoteAccess.toggle.caption.local": "מקושר ל-127.0.0.1", + "remoteAccess.toggle.note": "שינוי זה דורש הפעלה מחדש ועוצר זמנית את כל המופעים הפעילים. שתף את הכתובות למטה לאחר שהשרת יופעל מחדש.", + "remoteAccess.listeningMode.restartConfirm.message": "להפעיל מחדש כדי להחיל מצב האזנה? פעולה זו תעצור את כל המופעים הפעילים.", + "remoteAccess.listeningMode.restartConfirm.title.all": "פתוח למכשירים אחרים", + "remoteAccess.listeningMode.restartConfirm.title.local": "מוגבל למכשיר זה", + "remoteAccess.listeningMode.restartConfirm.confirmLabel": "הפעל מחדש עכשיו", + "remoteAccess.listeningMode.restartConfirm.cancelLabel": "ביטול", + "remoteAccess.restart.errorManual": "לא ניתן להפעיל מחדש אוטומטית. אנא הפעל מחדש את האפליקציה כדי להחיל את השינוי.", + + "remoteAccess.sections.serverPassword.label": "סיסמת שרת", + "remoteAccess.sections.serverPassword.help": "גישה מרוחקת דורשת סיסמה. הגדר סיסמה קלה לזכירה כדי לאפשר כניסות ממכשירים אחרים.", + "remoteAccess.authStatus.unavailable": "סטטוס האימות אינו זמין.", + "remoteAccess.username": "שם משתמש: {username}", + "remoteAccess.password.status.set": "סיסמה מוגדרת לגישה מרוחקת.", + "remoteAccess.password.status.unset": "לא הוגדרה סיסמה קלה לזכירה. הגדר סיסמה כדי לאפשר כניסות גישה מרוחקת.", + "remoteAccess.password.actions.cancel": "ביטול", + "remoteAccess.password.actions.change": "שנה סיסמה", + "remoteAccess.password.actions.set": "הגדר סיסמה", + "remoteAccess.password.form.newPassword": "סיסמה חדשה", + "remoteAccess.password.form.confirmPassword": "אשר סיסמה", + "remoteAccess.password.form.placeholder": "לפחות 8 תווים", + "remoteAccess.password.error.tooShort": "הסיסמה חייבת להכיל לפחות 8 תווים.", + "remoteAccess.password.error.mismatch": "הסיסמאות אינן תואמות.", + "remoteAccess.password.save.saving": "שומר…", + "remoteAccess.password.save.label": "שמור סיסמה", + + "remoteAccess.sections.addresses.label": "כתובות נגישות", + "remoteAccess.sections.addresses.help": "הפעל או סרוק ממכונה אחרת להעברת שליטה.", + "remoteAccess.addresses.loading": "טוען כתובות…", + "remoteAccess.addresses.none": "אין כתובות זמינות עדיין.", + "remoteAccess.address.scope.network": "רשת", + "remoteAccess.address.scope.loopback": "לולאה מקומית", + "remoteAccess.address.scope.internal": "פנימי", + "remoteAccess.address.open": "פתח", + "remoteAccess.address.showQr": "הצג QR", + "remoteAccess.address.hideQr": "הסתר QR", + "remoteAccess.address.qrAlt": "QR עבור {url}", +} as const diff --git a/packages/ui/src/lib/i18n/messages/he/session.ts b/packages/ui/src/lib/i18n/messages/he/session.ts new file mode 100644 index 00000000..6ff5035a --- /dev/null +++ b/packages/ui/src/lib/i18n/messages/he/session.ts @@ -0,0 +1,90 @@ +export const sessionMessages = { + "sessionPicker.title": "OpenCode • {folder}", + "sessionPicker.empty.noPrevious": "אין סשנים קודמים", + "sessionPicker.resume.title": "המשך סשן ({count}):", + "sessionPicker.session.untitled": "ללא שם", + "sessionPicker.divider.or": "או", + "sessionPicker.new.title": "התחל סשן חדש:", + "sessionPicker.agents.loading": "טוען סוכנים...", + "sessionPicker.actions.creating": "יוצר...", + "sessionPicker.actions.createSession": "צור סשן", + "sessionPicker.actions.cancel": "ביטול", + + "sessionList.header.title": "סשנים", + "sessionList.session.untitled": "ללא שם", + "sessionList.status.working": "עובד", + "sessionList.status.compacting": "מסכם", + "sessionList.status.idle": "מוכן", + "sessionList.status.needsPermission": "נדרש אישור", + "sessionList.status.needsInput": "נדרש קלט", + "sessionList.expand.collapseAriaLabel": "כווץ סשן", + "sessionList.expand.expandAriaLabel": "פרוס סשן", + "sessionList.expand.collapseTitle": "כווץ", + "sessionList.expand.expandTitle": "פרוס", + "sessionList.actions.newSession.ariaLabel": "סשן חדש", + "sessionList.actions.newSession.title": "סשן חדש", + "sessionList.actions.copyId.ariaLabel": "העתק מזהה סשן", + "sessionList.actions.copyId.title": "העתק מזהה סשן", + "sessionList.actions.rename.ariaLabel": "שנה שם סשן", + "sessionList.actions.rename.title": "שנה שם סשן", + "sessionList.actions.delete.ariaLabel": "מחק סשן", + "sessionList.actions.delete.title": "מחק סשן", + "sessionList.copyId.success": "מזהה סשן הועתק", + "sessionList.copyId.error": "לא ניתן להעתיק מזהה סשן", + "sessionList.delete.error": "לא ניתן למחוק סשן", + "sessionList.delete.title": "מחק סשן", + "sessionList.delete.confirmMessage": "למחוק את \"{label}\"? לא ניתן לבטל פעולה זו.", + "sessionList.delete.confirmLabel": "מחק", + "sessionList.delete.cancelLabel": "ביטול", + "sessionList.rename.error": "לא ניתן לשנות שם הסשן", + + "sessionList.filter.placeholder": "חפש סשנים…", + "sessionList.filter.ariaLabel": "חפש סשנים", + "sessionList.selection.selectAllLabel": "בחר הכל", + "sessionList.selection.selectAllAriaLabel": "בחר את כל הסשנים", + "sessionList.selection.clearLabel": "נקה", + "sessionList.selection.clearAriaLabel": "נקה בחירה", + "sessionList.selection.checkboxAriaLabel": "בחר סשן", + "sessionList.bulkDelete.button": "מחק {count}", + "sessionList.bulkDelete.ariaLabel": "מחק {count} סשנים נבחרים", + "sessionList.bulkDelete.title": "מחק סשנים", + "sessionList.bulkDelete.confirmMessage": "למחוק {count} סשנים נבחרים? לא ניתן לבטל פעולה זו.", + "sessionList.bulkDelete.confirmLabel": "מחק", + "sessionList.bulkDelete.cancelLabel": "ביטול", + "sessionList.bulkDelete.error": "לא ניתן למחוק {count} סשנים", + + "sessionRenameDialog.title": "שנה שם סשן", + "sessionRenameDialog.description.withLabel": "עדכן את הכותרת עבור \"{label}\".", + "sessionRenameDialog.description.default": "הגדר כותרת חדשה לסשן זה.", + "sessionRenameDialog.input.label": "שם סשן", + "sessionRenameDialog.input.placeholder": "הזן שם סשן", + "sessionRenameDialog.actions.cancel": "ביטול", + "sessionRenameDialog.actions.rename": "שנה שם", + "sessionRenameDialog.actions.renaming": "משנה שם…", + + "sessionView.fallback.sessionNotFound": "הסשן לא נמצא", + "sessionView.alerts.abortFailed.message": "עצירת הסשן נכשלה", + "sessionView.alerts.abortFailed.title": "העצירה נכשלה", + "sessionView.alerts.revertFailed.message": "החזרה להודעה נכשלה", + "sessionView.alerts.revertFailed.title": "החזרה נכשלה", + "sessionView.alerts.deleteUpToFailed.message": "מחיקת הודעות נכשלה", + "sessionView.alerts.deleteUpToFailed.title": "המחיקה נכשלה", + "sessionView.alerts.forkFailed.message": "פיצול הסשן נכשל", + "sessionView.alerts.forkFailed.title": "הפיצול נכשל", + "sessionView.attachments.expandPastedTextAriaLabel": "פרוס טקסט שהודבק", + "sessionView.attachments.insertPastedTextTitle": "הכנס טקסט שהודבק", + "sessionView.attachments.removeAriaLabel": "הסר קובץ מצורף", + + "sessionEvents.sessionCompactedToast": "הסשן {label} סוכם", + "sessionEvents.sessionError.unknown": "שגיאה לא ידועה", + "sessionEvents.sessionError.title": "שגיאת סשן", + "sessionEvents.sessionError.message": "שגיאה: {message}", + + "sessionState.cleanup.deepConfirm.message": "ניקוי עמוק זה עשוי להיות איטי, ועלול למחוק סשנים שלא התכוונת למחוק. האם אתה בטוח?", + "sessionState.cleanup.deepConfirm.title": "ניקוי עמוק של סשנים", + "sessionState.cleanup.deepConfirm.detail": "ניקוי עמוק של סשנים ימחק את כל הסשנים ללא הודעות, יסיר סשני תת-סוכן שסיימו, וינקה פיצולים לא בשימוש של סשן.", + "sessionState.cleanup.deepConfirm.confirmLabel": "המשך", + "sessionState.cleanup.deepConfirm.cancelLabel": "ביטול", + "sessionState.cleanup.toast.one": "נוקה {count} סשן ריק", + "sessionState.cleanup.toast.other": "נוקו {count} סשנים ריקים", +} as const diff --git a/packages/ui/src/lib/i18n/messages/he/settings.ts b/packages/ui/src/lib/i18n/messages/he/settings.ts new file mode 100644 index 00000000..6f8d8607 --- /dev/null +++ b/packages/ui/src/lib/i18n/messages/he/settings.ts @@ -0,0 +1,142 @@ +export const settingsMessages = { + "instanceServiceStatus.sections.lsp": "שרתי LSP", + "instanceServiceStatus.sections.mcp": "שרתי MCP", + "instanceServiceStatus.sections.plugins": "תוספים", + "instanceServiceStatus.lsp.loading": "טוען שרתי LSP...", + "instanceServiceStatus.lsp.empty": "לא זוהו שרתי LSP.", + "instanceServiceStatus.lsp.status.connected": "מחובר", + "instanceServiceStatus.lsp.status.error": "שגיאה", + "instanceServiceStatus.mcp.loading": "טוען שרתי MCP...", + "instanceServiceStatus.mcp.empty": "לא זוהו שרתי MCP.", + "instanceServiceStatus.mcp.toggleAriaLabel": "הפעל/כבה שרת MCP {name}", + "instanceServiceStatus.plugins.loading": "טוען תוספים...", + "instanceServiceStatus.plugins.empty": "לא הוגדרו תוספים.", + + "permissionBanner.pendingRequests.one": "בקשה אחת ממתינה", + "permissionBanner.pendingRequests.other": "{count} בקשות ממתינות", + "permissionBanner.detail.permission.one": "אישור אחד", + "permissionBanner.detail.permission.other": "{count} אישורים", + "permissionBanner.detail.question.one": "שאלה אחת", + "permissionBanner.detail.question.other": "{count} שאלות", + "permissionBanner.detail.wrapper": " ({detail})", + + "agentSelector.placeholder": "בחר סוכן...", + "agentSelector.badge.subagent": "תת-סוכן", + "agentSelector.none": "ללא", + "agentSelector.trigger.primary": "סוכן: {agent}", + + "modelSelector.placeholder.search": "חפש מודלים...", + "modelSelector.none": "ללא", + "modelSelector.trigger.primary": "מודל: {model}", + "modelSelector.favoritesOnly.toggle.ariaLabel": "הצג מועדפים בלבד", + "modelSelector.favoritesOnly.showAll": "הצג את כל המודלים", + "modelSelector.favorite.add": "הוסף למועדפים", + "modelSelector.favorite.remove": "הסר ממועדפים", + + "thinkingSelector.variant.default": "ברירת מחדל", + "thinkingSelector.label": "חשיבה: {variant}", + + "envEditor.title": "משתני סביבה", + "envEditor.count.one": "(משתנה אחד)", + "envEditor.count.other": "({count} משתנים)", + "envEditor.fields.name.placeholder": "שם משתנה", + "envEditor.fields.name.readOnlyTitle": "שם משתנה (לקריאה בלבד)", + "envEditor.fields.value.placeholder": "ערך משתנה", + "envEditor.actions.remove.title": "הסר משתנה", + "envEditor.actions.add.title": "הוסף משתנה", + "envEditor.empty": "לא הוגדרו משתני סביבה. הוסף משתנים למעלה להתאמת סביבת OpenCode.", + "envEditor.help": "משתנים אלו יהיו זמינים בסביבת OpenCode בעת הפעלת מופעים.", + + "contextUsagePanel.headings.tokens": "טוקנים", + "contextUsagePanel.headings.context": "הקשר", + "contextUsagePanel.labels.input": "קלט", + "contextUsagePanel.labels.output": "פלט", + "contextUsagePanel.labels.cost": "עלות", + "contextUsagePanel.labels.used": "בשימוש", + "contextUsagePanel.labels.available": "זמין", + "contextUsagePanel.unavailable": "--", + + "settings.title": "הגדרות", + "settings.navigationAriaLabel": "קטגוריות הגדרות", + "settings.close": "סגור הגדרות", + "settings.content.eyebrow": "העדפות סביבת עבודה", + "settings.open.title": "פתח הגדרות", + "settings.open.ariaLabel": "פתח הגדרות", + "settings.nav.appearance": "מראה", + "settings.nav.notifications": "התראות", + "settings.nav.remote": "גישה מרוחקת", + "settings.nav.opencode": "OpenCode", + "settings.scope.device": "מכשיר זה", + "settings.scope.server": "הגדרת שרת", + "settings.common.enabled": "מופעל", + "settings.common.disabled": "מושבת", + "settings.section.appearance.title": "מראה", + "settings.section.appearance.subtitle": "שנה כיצד האפליקציה נראית במכשיר זה.", + "settings.appearance.theme.title": "ערכת נושא", + "settings.appearance.theme.subtitle": "בחר את מצב הצבע שישמש בכל האפליקציה.", + "settings.appearance.theme.option.system": "התאם להגדרת מערכת ההפעלה", + "settings.appearance.theme.option.light": "השתמש במראה בהיר", + "settings.appearance.theme.option.dark": "השתמש במראה כהה", + "settings.section.notifications.title": "התראות", + "settings.section.notifications.subtitle": "שלוט בהתראות ברמת מערכת ההפעלה עבור פעילות סשן.", + "settings.notifications.permission.granted": "ניתן", + "settings.notifications.permission.denied": "נדחה", + "settings.notifications.permission.default": "לא ניתן", + "settings.notifications.permission.unsupported": "לא נתמך", + "settings.notifications.messages.unsupportedEnvironment": "התראות מערכת ההפעלה אינן נתמכות בסביבה זו.", + "settings.notifications.messages.permissionDenied": "הרשאת התראות נדחתה. הפעל התראות בהגדרות המערכת או הדפדפן.", + "settings.notifications.messages.permissionNotGranted": "הרשאת התראות לא ניתנה.", + "settings.notifications.messages.unsupportedGeneral": "התראות אינן נתמכות בסביבה זו.", + "settings.notifications.messages.permissionGranted": "ההרשאה ניתנה. כעת ניתן להפעיל התראות.", + "settings.notifications.messages.permissionRequestDenied": "ההרשאה נדחתה. ייתכן שתצטרך להפעיל התראות בהגדרות המערכת או הדפדפן.", + "settings.notifications.sessionStatus.title": "התראות סטטוס סשן", + "settings.notifications.sessionStatus.subtitle": "קבל התראות כאשר סשנים דורשים את תשומת לבך.", + "settings.notifications.enable.title": "הפעל התראות", + "settings.notifications.enable.permission": "הרשאה: {permission}", + "settings.notifications.requestPermission.title": "בקש הרשאה", + "settings.notifications.requestPermission.subtitle": "אפשר לאפליקציה לשלוח התראות במכשיר זה.", + "settings.notifications.requestPermission.action": "בקש", + "settings.notifications.allowVisible.title": "התרע כאשר האפליקציה ממוקדת", + "settings.notifications.allowVisible.subtitle": "שמור על התראות פעילות גם כאשר חלון זה גלוי.", + "settings.notifications.unsupportedNote": "התראות אינן נתמכות בסביבה זו. פקד ההתראות נשאר מושבת.", + "settings.notifications.events.title": "התרע אותי כאשר", + "settings.notifications.events.subtitle": "בחר אילו אירועי סשן ישלחו התראות.", + "settings.notifications.events.needsInput": "הסשן דורש קלט", + "settings.notifications.events.idle": "הסשן עובר למצב סרלה", + "settings.notifications.status.enabled": "התראות מופעלות", + "settings.notifications.status.disabled": "התראות מושבתות", + "settings.notifications.status.unsupported": "התראות לא נתמכות", + "settings.section.remote.title": "גישה מרוחקת", + "settings.section.remote.subtitle": "בדוק כיצד שרת זה חשוף ברשת שלך ואבטח אישורי גישה.", + "settings.section.opencode.title": "OpenCode", + "settings.section.opencode.subtitle": "בחר את הקובץ הבינארי של OpenCode והסביבה לשימוש במופעים חדשים.", + "settings.opencode.runtime.title": "סביבת ריצה", + "settings.opencode.runtime.subtitle": "הגדר עם איזה קובץ בינארי של OpenCode מופעים חדשים יופעלו.", + + "settings.appearance.behavior.title": "אינטראקציה", + "settings.appearance.behavior.subtitle": "ברירות מחדל להודעות, diff וקלט.", + "settings.behavior.keyboardHints.title": "רמזי קיצורי מקלדת", + "settings.behavior.keyboardHints.subtitle": "הצג רמזי קיצורי מקלדת בכל הממשק.", + "settings.behavior.thinking.title": "קטעי חשיבה", + "settings.behavior.thinking.subtitle": "הצג או הסתר קטעי חשיבה של ה-AI בהודעות.", + "settings.behavior.thinkingDefault.title": "ברירת מחדל לחשיבה", + "settings.behavior.thinkingDefault.subtitle": "בחר האם קטעי חשיבה מתחילים פרוסים או מכווצים.", + "settings.behavior.timelineTools.title": "קריאות כלי בציר הזמן", + "settings.behavior.timelineTools.subtitle": "הצג או הסתר קריאות כלי בציר הודעות.", + "settings.behavior.diffView.title": "תצוגת diff", + "settings.behavior.diffView.subtitle": "בחר כיצד מוצגים diff של קריאות כלי.", + "settings.behavior.diffView.option.split": "מפוצל", + "settings.behavior.diffView.option.unified": "מאוחד", + "settings.behavior.toolOutputsDefault.title": "ברירת מחדל לפלטי כלים", + "settings.behavior.toolOutputsDefault.subtitle": "בחר האם פלטי כלים מתחילים פרוסים או מכווצים.", + "settings.behavior.diagnosticsDefault.title": "ברירת מחדל לאבחון", + "settings.behavior.diagnosticsDefault.subtitle": "בחר האם פלט אבחון מתחיל פרוס או מכווץ.", + "settings.behavior.toolInputsVisibility.title": "נראות קלטי כלים", + "settings.behavior.toolInputsVisibility.subtitle": "הגדר נראות ברירת מחדל לארגומנטים של קריאות כלי.", + "settings.behavior.usageMetrics.title": "מדדי שימוש בטוקנים", + "settings.behavior.usageMetrics.subtitle": "הצג או הסתר נתוני טוקנים ועלות להודעות הסוכן.", + "settings.behavior.autoCleanup.title": "ניקוי אוטומטי של סשנים ריקים", + "settings.behavior.autoCleanup.subtitle": "נקה אוטומטית סשנים ריקים בעת יצירת סשנים חדשים.", + "settings.behavior.promptSubmit.title": "Enter לשליחה", + "settings.behavior.promptSubmit.subtitle": "השתמש ב-Enter לשליחת פקודות; Cmd/Ctrl+Enter מוסיף שורה חדשה.", +} as const diff --git a/packages/ui/src/lib/i18n/messages/he/time.ts b/packages/ui/src/lib/i18n/messages/he/time.ts new file mode 100644 index 00000000..e91210cb --- /dev/null +++ b/packages/ui/src/lib/i18n/messages/he/time.ts @@ -0,0 +1,6 @@ +export const timeMessages = { + "time.relative.justNow": "עכשיו", + "time.relative.daysAgoShort": "לפני {count} ימים", + "time.relative.hoursAgoShort": "לפני {count} שעות", + "time.relative.minutesAgoShort": "לפני {count} דקות", +} as const diff --git a/packages/ui/src/lib/i18n/messages/he/toolCall.ts b/packages/ui/src/lib/i18n/messages/he/toolCall.ts new file mode 100644 index 00000000..cf7e3e74 --- /dev/null +++ b/packages/ui/src/lib/i18n/messages/he/toolCall.ts @@ -0,0 +1,132 @@ +export const toolCallMessages = { + "toolCall.pending.waitingToRun": "ממתין להרצה...", + "toolCall.error.label": "שגיאה:", + + "toolCall.header.copyTitle": "העתק כותרת קריאת כלי", + "toolCall.header.copyAriaLabel": "העתק כותרת קריאת כלי", + + "toolCall.header.showInputTitle": "הצג ארגומנטי כלי", + "toolCall.header.showInputAriaLabel": "הצג ארגומנטי כלי", + "toolCall.header.hideInputTitle": "הסתר ארגומנטי כלי", + "toolCall.header.hideInputAriaLabel": "הסתר ארגומנטי כלי", + + "toolCall.io.input": "קלט כלי", + "toolCall.io.output": "פלט כלי", + + "toolCall.diff.label": "Diff", + "toolCall.diff.label.withPath": "Diff · {path}", + "toolCall.diff.viewMode.ariaLabel": "מצב תצוגת diff", + "toolCall.diff.viewMode.split": "מפוצל", + "toolCall.diff.viewMode.unified": "מאוחד", + + "toolCall.diagnostics.title": "אבחון", + "toolCall.diagnostics.ariaLabel": "אבחון", + "toolCall.diagnostics.ariaLabel.withLabel": "אבחון {label}", + "toolCall.diagnostics.severity.error.short": "שגיאה", + "toolCall.diagnostics.severity.warning.short": "אזהרה", + "toolCall.diagnostics.severity.info.short": "מידע", + + "toolCall.renderer.toolName.shell": "מעטפת", + "toolCall.renderer.toolName.fetch": "Fetch", + "toolCall.renderer.toolName.invalid": "לא תקין", + "toolCall.renderer.toolName.plan": "תוכנית", + "toolCall.renderer.toolName.applyPatch": "החל תיקון", + + "toolCall.renderer.action.working": "עובד...", + "toolCall.renderer.action.writingCommand": "כותב פקודה...", + "toolCall.renderer.action.preparingEdit": "מכין עריכה...", + "toolCall.renderer.action.readingFile": "קורא קובץ...", + "toolCall.renderer.action.preparingWrite": "מכין כתיבה...", + "toolCall.renderer.action.preparingPatch": "מכין תיקון...", + "toolCall.renderer.action.planning": "מתכנן...", + "toolCall.renderer.action.fetchingFromWeb": "מאחזר מהאינטרנט...", + "toolCall.renderer.action.findingFiles": "מחפש קבצים...", + "toolCall.renderer.action.searchingContent": "מחפש תוכן...", + "toolCall.renderer.action.listingDirectory": "מפרט ספרייה...", + + "toolCall.renderer.bash.title.timeout": "פסק זמן: {timeout}", + "toolCall.renderer.read.detail.offset": "היסט: {offset}", + "toolCall.renderer.read.detail.limit": "מגבלה: {limit}", + + "toolCall.renderer.todo.empty": "אין פריטי תוכנית עדיין.", + "toolCall.renderer.todo.status.pending": "ממתין", + "toolCall.renderer.todo.status.inProgress": "בביצוע", + "toolCall.renderer.todo.status.completed": "הושלם", + "toolCall.renderer.todo.status.cancelled": "בוטל", + "toolCall.renderer.todo.title.plan": "תוכנית", + "toolCall.renderer.todo.title.creating": "יוצר תוכנית", + "toolCall.renderer.todo.title.completing": "משלים תוכנית", + "toolCall.renderer.todo.title.updating": "מעדכן תוכנית", + + "toolCall.permission.status.required": "נדרש אישור", + "toolCall.permission.status.queued": "אישור בתור", + "toolCall.permission.requestedDiff.label": "diff מבוקש", + "toolCall.permission.requestedDiff.withPath": "diff מבוקש · {path}", + "toolCall.permission.queuedText": "ממתין לתגובות אישור קודמות.", + "toolCall.permission.actions.allowOnce": "אפשר פעם אחת", + "toolCall.permission.actions.alwaysAllow": "אפשר תמיד", + "toolCall.permission.actions.deny": "דחה", + "toolCall.permission.shortcuts.allowOnce": "אפשר פעם אחת", + "toolCall.permission.shortcuts.alwaysAllow": "אפשר תמיד", + "toolCall.permission.shortcuts.deny": "דחה", + "toolCall.permission.errors.unableToUpdate": "לא ניתן לעדכן אישור", + + "permissionApproval.title": "בקשות", + "permissionApproval.empty": "אין בקשות ממתינות.", + "permissionApproval.kind.permission": "אישור", + "permissionApproval.kind.question": "שאלה", + "permissionApproval.questionCount.one": "שאלה אחת", + "permissionApproval.questionCount.other": "{count} שאלות", + "permissionApproval.status.active": "פעיל", + "permissionApproval.actions.closeAriaLabel": "סגור", + "permissionApproval.actions.goToSession": "עבור לסשן", + "permissionApproval.actions.loadingSession": "טוען…", + "permissionApproval.actions.loadSession": "טען סשן", + "permissionApproval.actions.allowOnce": "אפשר פעם אחת", + "permissionApproval.actions.alwaysAllow": "אפשר תמיד", + "permissionApproval.actions.deny": "דחה", + "permissionApproval.fallbackHint": "טען סשן לקבלת מידע נוסף.", + "permissionApproval.errors.unableToUpdatePermission": "לא ניתן לעדכן אישור", + + "toolCall.question.status.required": "נדרשת תשובה", + "toolCall.question.status.queued": "שאלה בתור", + "toolCall.question.status.questions": "שאלות", + "toolCall.question.action.awaitingAnswers": "ממתין לתשובות...", + "toolCall.question.title.questions": "שאלות", + "toolCall.question.title.askingQuestions": "שואל שאלות", + "toolCall.question.type.one": "שאלה", + "toolCall.question.type.other": "שאלות", + "toolCall.question.number": "ש{number}:", + "toolCall.question.multiple": "מרובות", + "toolCall.question.custom.title": "הקלד תשובה מותאמת אישית", + "toolCall.question.custom.label": "תשובה מותאמת אישית", + "toolCall.question.custom.placeholder": "הקלד תשובה משלך", + "toolCall.question.actions.submit": "שלח", + "toolCall.question.actions.dismiss": "סגור", + "toolCall.question.shortcuts.submit": "שלח", + "toolCall.question.shortcuts.dismiss": "סגור", + "toolCall.question.queuedText": "ממתין לתגובות קודמות.", + "toolCall.question.validation.answerAll": "אנא ענה על כל השאלות לפני השליחה.", + "toolCall.question.errors.unableToReply": "לא ניתן לשלוח תשובה", + "toolCall.question.errors.unableToDismiss": "לא ניתן לסגור", + + "toolCall.task.action.delegating": "מאציל...", + "toolCall.task.sections.prompt": "פקודה", + "toolCall.task.sections.steps": "שלבים", + "toolCall.task.sections.output": "פלט", + "toolCall.task.steps.count": "{count} שלבים", + "toolCall.task.meta.agentModel": "סוכן: {agent} • מודל: {model}", + "toolCall.task.meta.agent": "סוכן: {agent}", + "toolCall.task.meta.model": "מודל: {model}", + + "toolCall.status.pending": "ממתין", + "toolCall.status.running": "רץ", + "toolCall.status.completed": "הושלם", + "toolCall.status.error": "שגיאה", + "toolCall.status.unknown": "לא ידוע", + + "toolCall.applyPatch.action.preparing": "מכין apply_patch...", + "toolCall.applyPatch.title.withFileCount.one": "{tool} (קובץ אחד)", + "toolCall.applyPatch.title.withFileCount.other": "{tool} ({count} קבצים)", + "toolCall.applyPatch.fileFallback": "קובץ {number}", +} as const diff --git a/packages/ui/src/styles/components/directory-browser.css b/packages/ui/src/styles/components/directory-browser.css index bdbccbc0..cc727afa 100644 --- a/packages/ui/src/styles/components/directory-browser.css +++ b/packages/ui/src/styles/components/directory-browser.css @@ -124,7 +124,7 @@ display: flex; align-items: center; gap: var(--space-md); - text-align: left; + text-align: start; background: transparent; border: none; color: var(--text-primary); diff --git a/packages/ui/src/styles/components/selector.css b/packages/ui/src/styles/components/selector.css index bcecda00..414d1213 100644 --- a/packages/ui/src/styles/components/selector.css +++ b/packages/ui/src/styles/components/selector.css @@ -40,11 +40,11 @@ } .selector-trigger-primary--align-left { - @apply text-left w-full; + @apply text-start w-full; } .selector-trigger-secondary { - @apply text-xs text-left truncate; + @apply text-xs text-start truncate w-full; color: var(--text-muted); } diff --git a/packages/ui/src/styles/components/settings-screen.css b/packages/ui/src/styles/components/settings-screen.css index 7f6abe56..31805bb9 100644 --- a/packages/ui/src/styles/components/settings-screen.css +++ b/packages/ui/src/styles/components/settings-screen.css @@ -43,7 +43,7 @@ padding: 1.25rem; background: linear-gradient(180deg, color-mix(in oklab, var(--surface-secondary) 92%, var(--accent-primary) 8%), var(--surface-secondary)); - border-right: 1px solid var(--border-base); + border-inline-end: 1px solid var(--border-base); } .settings-screen-nav-header { @@ -121,6 +121,9 @@ color: var(--text-primary); transform: translateX(2px); } +[dir="rtl"] .settings-nav-button[data-selected="true"] { + transform: translateX(-2px); +} .settings-nav-button-icon { width: 1rem; @@ -360,7 +363,7 @@ border: 1px solid var(--border-base); background: var(--surface-base); color: var(--text-primary); - text-align: left; + text-align: start; transition: border-color 140ms ease, background-color 140ms ease, box-shadow 140ms ease, transform 140ms ease; outline: none; cursor: pointer; @@ -418,7 +421,7 @@ } .settings-choice-check { - margin-left: auto; + margin-inline-start: auto; color: var(--accent-primary); opacity: 0; } @@ -488,7 +491,7 @@ .settings-screen-nav { gap: 0.75rem; padding: 1rem; - border-right: none; + border-inline-end: none; border-bottom: 1px solid var(--border-base); } diff --git a/packages/ui/src/styles/markdown.css b/packages/ui/src/styles/markdown.css index 8cd10e07..bbb4d70f 100644 --- a/packages/ui/src/styles/markdown.css +++ b/packages/ui/src/styles/markdown.css @@ -136,6 +136,7 @@ border-radius: 8px; padding: 0.75rem; margin: 1rem 0; + direction: ltr; } .markdown-body pre:not(.shiki) code, diff --git a/packages/ui/src/styles/messaging.css b/packages/ui/src/styles/messaging.css index 740beffc..10d91f72 100644 --- a/packages/ui/src/styles/messaging.css +++ b/packages/ui/src/styles/messaging.css @@ -28,7 +28,7 @@ /* Message error block */ .message-error-block { - @apply text-sm p-3 rounded border-l-[3px] my-2; + @apply text-sm p-3 rounded border-s-[3px] my-2; color: var(--status-error); background-color: var(--message-error-bg); border-color: var(--status-error); diff --git a/packages/ui/src/styles/messaging/message-base.css b/packages/ui/src/styles/messaging/message-base.css index dc048055..5b290f89 100644 --- a/packages/ui/src/styles/messaging/message-base.css +++ b/packages/ui/src/styles/messaging/message-base.css @@ -141,13 +141,13 @@ .message-step-start { background-color: var(--message-assistant-bg); - border-left: 4px solid var(--message-assistant-border); + border-inline-start: 4px solid var(--message-assistant-border); margin-top: 0; } .message-step-finish { background-color: var(--message-assistant-bg); - border-left: 4px solid var(--message-assistant-border); + border-inline-start: 4px solid var(--message-assistant-border); margin: 0; } @@ -172,7 +172,7 @@ font-size: 9px; color: var(--text-muted); font-weight: var(--font-weight-medium); - margin-right: 0.35rem; + margin-inline-end: 0.35rem; } .message-step-heading { @@ -189,7 +189,7 @@ } .message-error-block { - @apply text-sm p-3 rounded border-l-[3px] my-2; + @apply text-sm p-3 rounded border-s-[3px] my-2; color: var(--status-error); background-color: var(--message-error-bg); border-color: var(--status-error); @@ -258,6 +258,7 @@ padding: 8px; background-color: var(--surface-code); border-radius: 4px; + direction: ltr; } .message-error-part { @@ -335,12 +336,12 @@ .message-step-start { background-color: var(--message-assistant-bg); - border-left: 4px solid var(--message-assistant-border); + border-inline-start: 4px solid var(--message-assistant-border); } .message-step-finish { background-color: var(--message-assistant-bg); - border-left: 4px solid var(--message-assistant-border); + border-inline-start: 4px solid var(--message-assistant-border); } .message-step-heading { @@ -363,7 +364,7 @@ } .message-step-time { - @apply text-[11px] text-[var(--text-muted)] font-normal ml-auto; + @apply text-[11px] text-[var(--text-muted)] font-normal ms-auto; } .message-step-meta-inline { @@ -390,7 +391,7 @@ .message-reasoning-card { --reasoning-border-color: var(--border-strong, var(--border-base)); background-color: var(--message-assistant-bg); - border-left: 4px solid var(--message-assistant-border); + border-inline-start: 4px solid var(--message-assistant-border); margin-top: 0; margin-bottom: 0; padding: 0; @@ -424,7 +425,7 @@ padding: 0.25rem 0.6rem; font: inherit; color: inherit; - text-align: left; + text-align: start; cursor: pointer; transition: background-color 0.2s ease, box-shadow 0.2s ease; } @@ -546,4 +547,5 @@ color: var(--text-primary); white-space: pre-wrap; margin: 0; + unicode-bidi: plaintext; } diff --git a/packages/ui/src/styles/messaging/message-section.css b/packages/ui/src/styles/messaging/message-section.css index 15ded9e5..7e6f2475 100644 --- a/packages/ui/src/styles/messaging/message-section.css +++ b/packages/ui/src/styles/messaging/message-section.css @@ -207,7 +207,7 @@ .message-scroll-button-wrapper { position: absolute; - right: 1rem; + inset-inline-end: 1rem; bottom: 1rem; display: flex; flex-direction: column; @@ -274,7 +274,7 @@ } .message-quote-button + .message-quote-button { - border-left: 1px solid var(--list-item-highlight-border); + border-inline-start: 1px solid var(--list-item-highlight-border); } .message-quote-button:hover { diff --git a/packages/ui/src/styles/messaging/message-selection.css b/packages/ui/src/styles/messaging/message-selection.css index b6e7eb01..28e9df97 100644 --- a/packages/ui/src/styles/messaging/message-selection.css +++ b/packages/ui/src/styles/messaging/message-selection.css @@ -3,7 +3,7 @@ .message-select-checkbox { width: 14px; height: 14px; - margin-right: 0.5rem; + margin-inline-end: 0.5rem; cursor: pointer; accent-color: var(--status-error); flex: 0 0 auto; @@ -134,7 +134,7 @@ } .message-delete-mode-menu { - right: 0; + inset-inline-end: 0; bottom: calc(100% + 6px); min-width: 150px; width: max-content; diff --git a/packages/ui/src/styles/messaging/message-timeline.css b/packages/ui/src/styles/messaging/message-timeline.css index 613b2220..78aeb927 100644 --- a/packages/ui/src/styles/messaging/message-timeline.css +++ b/packages/ui/src/styles/messaging/message-timeline.css @@ -20,7 +20,7 @@ position: absolute; top: 0; bottom: 0; - right: 64px; + inset-inline-end: 64px; width: 1px; background-color: var(--border-muted); pointer-events: none; @@ -32,7 +32,7 @@ } .message-layout--with-timeline::after { - right: 40px; + inset-inline-end: 40px; } } @@ -311,12 +311,12 @@ /* Tool segments that are part of a group get a left accent border. */ .message-timeline-group-child { - border-left: 3px solid color-mix(in oklab, var(--accent-primary) 35%, transparent); + border-inline-start: 3px solid color-mix(in oklab, var(--accent-primary) 35%, transparent); } /* The assistant "parent" at the bottom of a tool group gets the same border. */ .message-timeline-group-parent { - border-left: 3px solid color-mix(in oklab, var(--accent-primary) 35%, transparent); + border-inline-start: 3px solid color-mix(in oklab, var(--accent-primary) 35%, transparent); } /* Extra spacing before the first tool in a group to separate from the @@ -346,7 +346,7 @@ /* Extend the overlay box into the stream so ribs are not relying on overflow-visible behavior (which is brittle around scroll containers). */ --xray-overhang: calc(var(--max-rib-width, 50vw) + 84px); - left: calc(-1 * var(--xray-overhang)); + inset-inline-start: calc(-1 * var(--xray-overhang)); width: calc(100% + var(--xray-overhang)); overflow: hidden; padding: 0.25rem; @@ -374,10 +374,10 @@ .message-timeline-xray-token-label { position: absolute; - right: 100%; + inset-inline-end: 100%; top: 50%; transform: translateY(-50%); - margin-right: 4px; + margin-inline-end: 4px; height: 1.5rem; display: flex; align-items: center; @@ -403,16 +403,25 @@ var(--status-success) calc(100% - var(--segment-weight) * 100%), var(--status-error) calc(var(--segment-weight) * 100%) ); - border-radius: 3px 0 0 3px; + border-start-start-radius: 3px; + border-end-start-radius: 3px; + border-start-end-radius: 0; + border-end-end-radius: 0; transition: width 0.3s ease, background-color 0.3s ease; box-shadow: -2px 0 4px rgba(0, 0, 0, 0.25); } +[dir="rtl"] .message-timeline-relative-bar { + box-shadow: 2px 0 4px rgba(0, 0, 0, 0.25); +} .message-timeline-absolute-bar { height: 3px; width: calc(var(--segment-weight) * var(--max-rib-width, 50vw)); background-color: var(--text-muted); - border-radius: 2px 0 0 2px; + border-start-start-radius: 2px; + border-end-start-radius: 2px; + border-start-end-radius: 0; + border-end-end-radius: 0; transition: width 0.3s ease; opacity: 0.5; position: relative; @@ -425,7 +434,7 @@ .message-timeline-absolute-bar-overflow::before { content: ""; position: absolute; - left: -1px; + inset-inline-start: -1px; top: -3px; bottom: -3px; width: 3px; diff --git a/packages/ui/src/styles/messaging/prompt-input.css b/packages/ui/src/styles/messaging/prompt-input.css index 8cbfb796..a0cd3ff9 100644 --- a/packages/ui/src/styles/messaging/prompt-input.css +++ b/packages/ui/src/styles/messaging/prompt-input.css @@ -35,7 +35,9 @@ } .prompt-input { - @apply w-full pl-3 pr-10 pt-2.5 border text-sm resize-none outline-none transition-colors; + @apply w-full pt-2.5 border text-sm resize-none outline-none transition-colors; + padding-inline-start: 2.5rem; + padding-inline-end: 0.75rem; font-family: inherit; background-color: var(--surface-base); color: var(--text-primary); @@ -65,8 +67,8 @@ .prompt-input-overlay { position: absolute; bottom: 1rem; - left: 0.75rem; - right: 0.75rem; + inset-inline-start: 0.75rem; + inset-inline-end: 0.75rem; display: flex; flex-wrap: wrap; gap: 0.5rem; @@ -81,11 +83,13 @@ color: var(--text-primary); } -/* Navigation buttons container (expand, prev, next) */ +/* Navigation buttons container (expand, prev, next). + Intentionally at inline-start (left in LTR, right in RTL) so buttons never overlap + the scrollbar, which browsers always place at inline-end. */ .prompt-nav-buttons { position: absolute; top: 0.25rem; - right: 0.25rem; + inset-inline-start: 0.25rem; bottom: 0.25rem; display: flex; flex-direction: column; @@ -160,6 +164,11 @@ @apply opacity-60 cursor-not-allowed; } +/* In RTL: override dir="auto" which defaults to LTR on empty textarea */ +[dir="rtl"] .prompt-input { + direction: rtl; +} + .prompt-input::placeholder { color: var(--text-muted); } @@ -256,7 +265,7 @@ display: none; position: absolute; bottom: calc(100% + 6px); - left: 0; + inset-inline-start: 0; padding: 8px; background-color: var(--surface-base); border: 1px solid var(--border-base); @@ -335,6 +344,7 @@ .prompt-input { min-height: 0; padding: 0.5rem 0.75rem; + padding-inline-start: 2.5rem; /* preserve space for nav buttons */ padding-bottom: 0.75rem; } diff --git a/packages/ui/src/styles/messaging/tool-call.css b/packages/ui/src/styles/messaging/tool-call.css index 4c504b36..55aa2448 100644 --- a/packages/ui/src/styles/messaging/tool-call.css +++ b/packages/ui/src/styles/messaging/tool-call.css @@ -5,7 +5,7 @@ .tool-call-message { @apply flex flex-col gap-2 p-3 w-full; background-color: var(--message-tool-bg); - border-left: 4px solid var(--message-tool-border); + border-inline-start: 4px solid var(--message-tool-border); color: inherit; } @@ -94,7 +94,7 @@ } .tool-call-header-toggle { - @apply flex items-center gap-2 p-2 w-full bg-transparent border-none cursor-pointer text-left; + @apply flex items-center gap-2 p-2 w-full bg-transparent border-none cursor-pointer text-start; font-family: var(--font-family-mono); font-size: 13px; border-radius: 0; @@ -105,7 +105,7 @@ .tool-call-header-toggle::before { content: "▶"; font-size: 11px; - margin-right: 0.35rem; + margin-inline-end: 0.35rem; color: var(--text-secondary); } @@ -159,7 +159,7 @@ } .tool-call-summary { - @apply flex-1 text-left inline-flex items-center gap-2; + @apply flex-1 text-start inline-flex items-center gap-2; color: var(--text-primary); } @@ -168,26 +168,26 @@ } .tool-call-summary[data-tool-icon=""]::before { - margin-right: 0; + margin-inline-end: 0; content: ""; } .tool-call-summary[data-tool-icon]:not([data-tool-icon=""])::before { - margin-right: 0.35rem; + margin-inline-end: 0.35rem; } /* ToolState uses status="completed"; keep "success" as a legacy alias. */ .tool-call-status-completed, .tool-call-status-success { - border-left: 3px solid var(--status-success); + border-inline-start: 3px solid var(--status-success); } .tool-call-status-error { - border-left: 3px solid var(--status-error); + border-inline-start: 3px solid var(--status-error); } .tool-call-status-running { - border-left: 3px solid var(--status-warning); + border-inline-start: 3px solid var(--status-warning); } .tool-call-status-running .tool-call-status { @@ -195,7 +195,7 @@ } .tool-call-status-pending { - border-left: 3px solid var(--accent-primary); + border-inline-start: 3px solid var(--accent-primary); } .tool-call-status-pending .tool-call-summary { @@ -257,7 +257,7 @@ border: none; border-bottom: 1px solid var(--tool-call-border-color); width: 100%; - text-align: left; + text-align: start; font-size: 0.875rem; font-weight: normal; color: var(--text-primary); @@ -267,7 +267,7 @@ .tool-call-io-toggle::before { content: "▶"; font-size: 11px; - margin-right: 0.35rem; + margin-inline-end: 0.35rem; color: var(--text-secondary); } @@ -393,7 +393,7 @@ } .tool-call-awaiting-permission { - border-left-color: var(--status-warning); + border-inline-start-color: var(--status-warning); } .tool-call-permission { @@ -484,7 +484,7 @@ } .tool-call-permission-shortcuts .kbd { - margin-right: 0.25rem; + margin-inline-end: 0.25rem; } .tool-call-permission-queued-text { @@ -549,6 +549,7 @@ min-height: auto; max-height: none; overflow-y: visible; + direction: ltr; } /* Shiki injects inline background colors; force token surfaces. */ @@ -610,7 +611,7 @@ } .tool-call-diagnostics-heading { - @apply flex items-center gap-2 p-2 w-full border-none cursor-pointer text-left; + @apply flex items-center gap-2 p-2 w-full border-none cursor-pointer text-start; font-family: var(--font-family-mono); font-size: 13px; color: var(--text-primary); @@ -634,7 +635,7 @@ .tool-call-diagnostics-heading { - @apply flex items-center gap-2 p-2 w-full border-none cursor-pointer text-left; + @apply flex items-center gap-2 p-2 w-full border-none cursor-pointer text-start; font-family: var(--font-family-mono); font-size: 13px; color: var(--text-primary); @@ -693,8 +694,8 @@ gap: var(--space-xs); max-height: calc(4 * var(--tool-call-line-unit, 1.4em)); overflow-y: scroll; - padding-right: 0; - margin-right: 0; + padding-inline-end: 0; + margin-inline-end: 0; scrollbar-gutter: stable both-edges; scrollbar-width: thin; } @@ -762,6 +763,7 @@ overflow-x: auto; max-height: var(--tool-call-max-height-compact, calc(25 * 1.4em)); overflow-y: scroll; + direction: ltr; } .tool-call-section code { @@ -843,7 +845,7 @@ .tool-call-error-content { background-color: var(--message-error-bg); - border-left: 3px solid var(--status-error); + border-inline-start: 3px solid var(--status-error); padding: 12px; margin: 8px 0; border-radius: 4px; diff --git a/packages/ui/src/styles/messaging/tool-call/task.css b/packages/ui/src/styles/messaging/tool-call/task.css index 83e435ac..d628d6fc 100644 --- a/packages/ui/src/styles/messaging/tool-call/task.css +++ b/packages/ui/src/styles/messaging/tool-call/task.css @@ -86,7 +86,7 @@ .tool-call-task-summary .tool-call::before { content: ""; position: absolute; - left: 0; + inset-inline-start: 0; top: 0; bottom: 0; width: 3px; @@ -117,7 +117,7 @@ align-items: center; gap: 0.4rem; padding: 0.35rem 0.5rem 0.35rem 0.75rem; - border-left: 2px solid var(--tool-call-border-color, var(--border-base)); + border-inline-start: 2px solid var(--tool-call-border-color, var(--border-base)); font-size: var(--font-size-sm); font-family: var(--font-family-mono); line-height: 1.35; @@ -134,19 +134,19 @@ } .tool-call-task-item[data-task-status="completed"] { - border-left-color: var(--status-success); + border-inline-start-color: var(--status-success); } .tool-call-task-item[data-task-status="running"] { - border-left-color: var(--status-warning); + border-inline-start-color: var(--status-warning); } .tool-call-task-item[data-task-status="pending"] { - border-left-color: var(--accent-primary); + border-inline-start-color: var(--accent-primary); } .tool-call-task-item[data-task-status="error"] { - border-left-color: var(--status-error); + border-inline-start-color: var(--status-error); } .tool-call-task-icon { diff --git a/packages/ui/src/styles/messaging/virtual-follow-list.css b/packages/ui/src/styles/messaging/virtual-follow-list.css index de7cf7ad..9392eb6a 100644 --- a/packages/ui/src/styles/messaging/virtual-follow-list.css +++ b/packages/ui/src/styles/messaging/virtual-follow-list.css @@ -46,7 +46,7 @@ .virtual-follow-list-controls-container { position: absolute; bottom: calc(var(--space-md) + env(safe-area-inset-bottom, 0px)); - right: var(--space-md); + inset-inline-end: var(--space-md); z-index: 20; } diff --git a/packages/ui/src/styles/panels/modal.css b/packages/ui/src/styles/panels/modal.css index 4edc3b81..d8540d60 100644 --- a/packages/ui/src/styles/panels/modal.css +++ b/packages/ui/src/styles/panels/modal.css @@ -42,7 +42,7 @@ } .modal-item { - @apply w-full px-4 py-3 flex items-start gap-3 transition-colors cursor-pointer border-none text-left; + @apply w-full px-4 py-3 flex items-start gap-3 transition-colors cursor-pointer border-none text-start; color: var(--text-primary); } diff --git a/packages/ui/src/styles/panels/panel-shell.css b/packages/ui/src/styles/panels/panel-shell.css index d32ee79e..c689ef6f 100644 --- a/packages/ui/src/styles/panels/panel-shell.css +++ b/packages/ui/src/styles/panels/panel-shell.css @@ -77,7 +77,7 @@ } .panel-list-item-content { - @apply flex-1 text-left px-4 py-3 flex items-center justify-between gap-3 outline-none transition-colors w-full min-w-0; + @apply flex-1 text-start px-4 py-3 flex items-center justify-between gap-3 outline-none transition-colors w-full min-w-0; } .panel-list-item-content:hover { diff --git a/packages/ui/src/styles/panels/right-panel.css b/packages/ui/src/styles/panels/right-panel.css index 6b9d2fcd..301ef0cd 100644 --- a/packages/ui/src/styles/panels/right-panel.css +++ b/packages/ui/src/styles/panels/right-panel.css @@ -11,8 +11,8 @@ content: ''; position: absolute; bottom: -1px; - left: 0; - right: 0; + inset-inline-start: 0; + inset-inline-end: 0; height: 1px; background-color: var(--border-base); z-index: 0; @@ -42,7 +42,7 @@ border: 1px solid transparent; border-bottom: none; border-radius: 8px 8px 0 0; - margin-right: 2px; + margin-inline-end: 2px; z-index: 1; } @@ -90,8 +90,8 @@ .file-split-handle { cursor: col-resize; background-color: transparent; - border-left: 1px solid var(--border-base); - border-right: 1px solid var(--border-base); + border-inline-start: 1px solid var(--border-base); + border-inline-end: 1px solid var(--border-base); user-select: none; touch-action: none; } @@ -148,7 +148,7 @@ display: flex; flex-direction: column; background-color: var(--surface-secondary); - border-left: 1px solid var(--border-base); + border-inline-start: 1px solid var(--border-base); /* Monaco uses layered positioned elements; keep overlay well above it. */ z-index: 200; } @@ -334,6 +334,7 @@ .monaco-viewer { width: 100%; height: 100%; + direction: ltr; } .file-viewer-empty { @@ -459,7 +460,7 @@ } .section-label { - margin-left: 2px; + margin-inline-start: 2px; } .section-info-icon { @@ -528,7 +529,7 @@ } .right-panel-empty--left { - @apply items-start justify-start text-left w-full; + @apply items-start justify-start text-start w-full; } .right-panel-empty-text { diff --git a/packages/ui/src/styles/panels/session-layout.css b/packages/ui/src/styles/panels/session-layout.css index f03cf6a7..479c37f7 100644 --- a/packages/ui/src/styles/panels/session-layout.css +++ b/packages/ui/src/styles/panels/session-layout.css @@ -26,10 +26,10 @@ position: absolute; top: 0; bottom: 0; - left: 0; + inset-inline-start: 0; width: min(90vw, 360px); max-width: 360px; - border-right: 1px solid var(--border-base); + border-inline-end: 1px solid var(--border-base); box-shadow: var(--folder-card-shadow); transform: translateX(0); transition: transform 0.25s ease, opacity 0.2s ease; @@ -41,6 +41,9 @@ opacity: 0; pointer-events: none; } +[dir="rtl"] .session-sidebar-collapsed { + transform: translateX(100%); +} .session-sidebar-backdrop { @apply absolute inset-0; @@ -54,7 +57,7 @@ .session-sidebar-menu-button--floating { position: absolute; top: 1rem; - left: 1rem; + inset-inline-start: 1rem; z-index: 20; } @@ -128,7 +131,7 @@ session-sidebar-controls .selector-trigger-primary { .mobile-fullscreen-exit-wrapper { position: fixed; top: calc(env(safe-area-inset-top, 0px) + 12px); - right: calc(env(safe-area-inset-right, 0px) + 12px); + inset-inline-end: calc(env(safe-area-inset-right, 0px) + 12px); z-index: 1250; pointer-events: none; } @@ -143,11 +146,11 @@ session-sidebar-controls .selector-trigger-primary { } .session-resize-handle--left { - right: 0; + inset-inline-end: 0; } .session-resize-handle--right { - left: 0; + inset-inline-start: 0; } .session-resize-handle:hover { @@ -160,14 +163,20 @@ session-sidebar-controls .selector-trigger-primary { } .session-resize-handle--left::before { - right: 0; + inset-inline-end: 0; transform: translateX(50%); } +[dir="rtl"] .session-resize-handle--left::before { + transform: translateX(-50%); +} .session-resize-handle--right::before { - left: 0; + inset-inline-start: 0; transform: translateX(-50%); } +[dir="rtl"] .session-resize-handle--right::before { + transform: translateX(50%); +} .session-list-header { @apply border-b relative; @@ -190,14 +199,14 @@ session-sidebar-controls .selector-trigger-primary { } .session-item-base { - @apply w-full flex flex-col gap-1 px-3 py-2.5 text-left transition-colors outline-none; + @apply w-full flex flex-col gap-1 px-3 py-2.5 text-start transition-colors outline-none; font-family: var(--font-family-sans); font-size: var(--font-size-sm); } .session-item-base.session-item-child { - padding-left: 2.25rem; + padding-inline-start: 2.25rem; position: relative; } @@ -206,7 +215,7 @@ session-sidebar-controls .selector-trigger-primary { position: absolute; top: 0; bottom: 0; - left: 1.125rem; + inset-inline-start: 1.125rem; width: 1px; background-color: var(--text-secondary); opacity: 0.95; @@ -221,7 +230,7 @@ session-sidebar-controls .selector-trigger-primary { content: ""; position: absolute; top: 50%; - left: 1.125rem; + inset-inline-start: 1.125rem; width: 0.875rem; height: 1px; background-color: var(--text-secondary); @@ -231,11 +240,11 @@ session-sidebar-controls .selector-trigger-primary { } .session-item-base.session-item-border-user { - border-left: 4px solid var(--message-user-border); + border-inline-start: 4px solid var(--message-user-border); } .session-item-base.session-item-border-assistant { - border-left: 4px solid var(--message-assistant-border); + border-inline-start: 4px solid var(--message-assistant-border); } .session-item-expander {