diff --git a/.circleci/config.yml b/.circleci/config.yml new file mode 100644 index 000000000000..848a421679fe --- /dev/null +++ b/.circleci/config.yml @@ -0,0 +1,343 @@ +version: 2.1 + +executors: + linux-python-node: + docker: + - image: cimg/python:3.12-node + resource_class: medium + + linux-go: + docker: + - image: cimg/go:1.22 + resource_class: medium + + macos-xcode: + macos: + xcode: "16.4.0" + resource_class: m4pro.medium + shell: /bin/bash --login -eo pipefail + +commands: + checkout-source: + parameters: + submodules: + type: boolean + default: false + steps: + - checkout + - when: + condition: << parameters.submodules >> + steps: + - run: + name: Initialize submodules + no_output_timeout: 35m + command: | + git submodule sync --recursive + git submodule update --init --recursive + + install-bun: + steps: + - run: + name: Install Bun + command: | + BUN_VERSION="1.3.3" + NPM_GLOBAL="$HOME/.npm-global" + mkdir -p "$NPM_GLOBAL" + npm install --global --prefix "$NPM_GLOBAL" "bun@$BUN_VERSION" + BASH_ENV="${BASH_ENV:-$HOME/.bash_env}" + echo "export PATH=\"$NPM_GLOBAL/bin:\$PATH\"" >> "$BASH_ENV" + export PATH="$NPM_GLOBAL/bin:$PATH" + test "$(bun --version)" = "$BUN_VERSION" + + install-zig: + steps: + - run: + name: Install zig + no_output_timeout: 35m + command: | + export HOMEBREW_NO_AUTO_UPDATE=1 + export HOMEBREW_NO_INSTALL_CLEANUP=1 + export HOMEBREW_NO_ENV_HINTS=1 + ./scripts/install-zig-ci.sh + + install-rust: + steps: + - run: + name: Install Rust + no_output_timeout: 15m + command: ./scripts/install-rust-ci.sh + + print-xcode: + steps: + - run: + name: Print Xcode environment + command: | + xcodebuild -version + xcrun --sdk macosx --show-sdk-path + sw_vers + + restore-swift-package-cache: + parameters: + prefix: + type: string + steps: + - restore_cache: + keys: + - v1-spm-<< parameters.prefix >>-{{ checksum "cmux.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved" }} + - v1-spm-<< parameters.prefix >>- + + save-swift-package-cache: + parameters: + prefix: + type: string + path: + type: string + default: .ci-source-packages + steps: + - save_cache: + key: v1-spm-<< parameters.prefix >>-{{ checksum "cmux.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved" }} + paths: + - << parameters.path >> + + restore-zig-cache: + steps: + - restore_cache: + keys: + - v1-zig-{{ checksum "ghostty/build.zig.zon" }}-{{ checksum "ghostty/build.zig.zon.json" }} + - v1-zig- + + save-zig-cache: + steps: + - save_cache: + key: v1-zig-{{ checksum "ghostty/build.zig.zon" }}-{{ checksum "ghostty/build.zig.zon.json" }} + paths: + - ~/.cache/zig + + resolve-swift-packages: + parameters: + scheme: + type: string + source-packages-dir: + type: string + default: .ci-source-packages + steps: + - run: + name: Resolve Swift packages + no_output_timeout: 35m + command: | + SOURCE_PACKAGES_DIR="$PWD/<< parameters.source-packages-dir >>" + mkdir -p "$SOURCE_PACKAGES_DIR" + + for attempt in 1 2 3; do + if xcodebuild -project cmux.xcodeproj -scheme << parameters.scheme >> -configuration Debug \ + -clonedSourcePackagesDirPath "$SOURCE_PACKAGES_DIR" \ + -resolvePackageDependencies; then + exit 0 + fi + if [ "$attempt" -eq 3 ]; then + echo "Failed to resolve Swift packages after 3 attempts" >&2 + exit 1 + fi + echo "Package resolution failed on attempt $attempt, retrying..." + sleep $((attempt * 5)) + done + +jobs: + macos-unit-tests: + executor: macos-xcode + steps: + - checkout-source: + submodules: true + - print-xcode + - install-rust + - restore-swift-package-cache: + prefix: unit + - restore-zig-cache + - run: + name: Download pre-built GhosttyKit.xcframework + no_output_timeout: 35m + command: ./scripts/download-prebuilt-ghosttykit.sh + - resolve-swift-packages: + scheme: cmux-unit + - run: + name: Run unit tests + no_output_timeout: 35m + command: | + export CMUX_SKIP_ZIG_BUILD=1 + SOURCE_PACKAGES_DIR="$PWD/.ci-source-packages" + run_unit_tests() { + xcodebuild -project cmux.xcodeproj -scheme cmux-unit -configuration Debug \ + -clonedSourcePackagesDirPath "$SOURCE_PACKAGES_DIR" \ + -disableAutomaticPackageResolution \ + -destination "platform=macOS" \ + CMUX_SKIP_ZIG_BUILD=1 \ + -skip-testing:cmuxTests/AppDelegateShortcutRoutingTests/testCmdWClosesWindowWhenClosingLastSurfaceInLastWorkspace \ + test 2>&1 + } + + set +e + run_unit_tests | tee /tmp/test-output.txt + EXIT_CODE=${PIPESTATUS[0]} + OUTPUT=$(cat /tmp/test-output.txt) + set -e + + if [ "$EXIT_CODE" -ne 0 ] && echo "$OUTPUT" | grep -q "Could not resolve package dependencies"; then + echo "SwiftPM package resolution failed, clearing caches and retrying once" + rm -rf ~/Library/Caches/org.swift.swiftpm + mkdir -p ~/Library/Caches/org.swift.swiftpm + rm -rf ~/Library/Developer/Xcode/DerivedData/cmux-* + rm -rf "$SOURCE_PACKAGES_DIR" + mkdir -p "$SOURCE_PACKAGES_DIR" + xcodebuild -project cmux.xcodeproj -scheme cmux-unit -configuration Debug \ + -clonedSourcePackagesDirPath "$SOURCE_PACKAGES_DIR" \ + -resolvePackageDependencies \ + CMUX_SKIP_ZIG_BUILD=1 + set +e + run_unit_tests | tee /tmp/test-output.txt + EXIT_CODE=${PIPESTATUS[0]} + OUTPUT=$(cat /tmp/test-output.txt) + set -e + fi + + if [ "$EXIT_CODE" -ne 0 ]; then + SUMMARY=$(echo "$OUTPUT" | grep "Executed.*tests.*with.*failures" | tail -1) + if echo "$SUMMARY" | grep -q "(0 unexpected)"; then + echo "All failures are expected, treating as pass" + else + echo "Unexpected test failures detected" + exit 1 + fi + fi + - run: + name: Run bundled Ghostty theme picker helper regression + no_output_timeout: 35m + command: | + CMUX_SKIP_ZIG_BUILD=1 \ + CMUX_SOURCE_PACKAGES_DIR="$PWD/.ci-source-packages" \ + ./tests/test_bundled_ghostty_theme_picker_helper.sh + - run: + name: Run CLI no-socket regressions + no_output_timeout: 35m + command: | + CLI_BIN="$( + find "$HOME/Library/Developer/Xcode/DerivedData" -path "*/Build/Products/Debug/cmux" -exec stat -f '%m %N' {} \; \ + | sort -nr \ + | head -1 \ + | cut -d' ' -f2- + )" + if [ -z "${CLI_BIN:-}" ] || [ ! -x "$CLI_BIN" ]; then + echo "cmux CLI binary not found in DerivedData" >&2 + exit 1 + fi + + CMUX_CLI_BIN="$CLI_BIN" python3 tests/test_cli_version_memory_guard.py + CMUX_CLI_BIN="$CLI_BIN" python3 tests/test_cli_contract_help.py + CMUX_CLI_BIN="$CLI_BIN" python3 tests/test_cli_layout_focus_contract.py + CMUX_CLI_BIN="$CLI_BIN" python3 tests/test_cli_socket_operation_deadline.py + CMUX_CLI_BIN="$CLI_BIN" python3 tests/test_cli_omo_openagent_plugin_migration.py + CMUX_CLI_BIN="$CLI_BIN" python3 tests/test_cli_socket_autodiscovery.py + CMUX_CLI_BIN="$CLI_BIN" python3 tests/test_claude_hook_clear_running_status.py + - save-swift-package-cache: + prefix: unit + - save-zig-cache + + macos-debug-build: + executor: macos-xcode + steps: + - checkout-source: + submodules: true + - print-xcode + - install-rust + - restore-swift-package-cache: + prefix: debug-build + - restore-zig-cache + - run: + name: Download pre-built GhosttyKit.xcframework + no_output_timeout: 35m + command: ./scripts/download-prebuilt-ghosttykit.sh + - resolve-swift-packages: + scheme: cmux + - run: + name: Build app and capture warnings + no_output_timeout: 35m + command: | + export CMUX_SKIP_ZIG_BUILD=1 + SOURCE_PACKAGES_DIR="$PWD/.ci-source-packages" + xcodebuild -project cmux.xcodeproj -scheme cmux -configuration Debug \ + -clonedSourcePackagesDirPath "$SOURCE_PACKAGES_DIR" \ + -disableAutomaticPackageResolution \ + -destination "platform=macOS" \ + CMUX_SKIP_ZIG_BUILD=1 \ + build 2>&1 | tee /tmp/cmux-build-output.txt + - run: + name: Validate Swift warning budget + command: python3 scripts/swift_warning_budget.py --log /tmp/cmux-build-output.txt + - save-swift-package-cache: + prefix: debug-build + - save-zig-cache + + macos-release-build: + executor: macos-xcode + steps: + - checkout-source: + submodules: true + - print-xcode + - install-rust + - restore-swift-package-cache: + prefix: release + - restore-zig-cache + - run: + name: Download pre-built GhosttyKit.xcframework + no_output_timeout: 35m + command: ./scripts/download-prebuilt-ghosttykit.sh + - resolve-swift-packages: + scheme: cmux + source-packages-dir: .spm-cache + - run: + name: Build universal app (Release) + no_output_timeout: 35m + command: | + export CMUX_SKIP_ZIG_BUILD=1 + xcodebuild -project cmux.xcodeproj -scheme cmux -configuration Release -derivedDataPath build-universal \ + -destination "generic/platform=macOS" \ + -clonedSourcePackagesDirPath .spm-cache \ + -disableAutomaticPackageResolution \ + ARCHS="arm64 x86_64" \ + ONLY_ACTIVE_ARCH=NO \ + CMUX_SKIP_ZIG_BUILD=1 \ + CODE_SIGNING_ALLOWED=NO ASSETCATALOG_COMPILER_APPICON_NAME=AppIcon-Nightly build + - save-swift-package-cache: + prefix: release + path: .spm-cache + - save-zig-cache + +workflows: + ci-trusted: + when: + and: + - << pipeline.git.branch >> + - not: + matches: + pattern: "^pull/.*" + value: << pipeline.git.branch >> + jobs: + - macos-unit-tests + - macos-debug-build + - macos-release-build + + ci-gated: + when: + or: + - matches: + pattern: "^pull/.*" + value: << pipeline.git.branch >> + - << pipeline.git.tag >> + jobs: + - hold-for-approval: + type: approval + - macos-unit-tests: + requires: [hold-for-approval] + - macos-debug-build: + requires: [hold-for-approval] + - macos-release-build: + requires: [hold-for-approval] diff --git a/.github/review-bot-rules/runtime-no-hacky-sleeps.md b/.github/review-bot-rules/runtime-no-hacky-sleeps.md index 4392d5bf55f7..f84638570a1d 100644 --- a/.github/review-bot-rules/runtime-no-hacky-sleeps.md +++ b/.github/review-bot-rules/runtime-no-hacky-sleeps.md @@ -1,8 +1,6 @@ # Runtime No Hacky Sleeps -Scope: TypeScript, JavaScript, shell, and non-Swift build/runtime scripts. Swift timing and blocking primitives are covered by `swift-blocking-runtime.md`. - -GitHub Actions workflow and action YAML is intentionally out of scope. Fixed waits there are CI orchestration unless the PR also changes a covered runtime script that uses the wait as product synchronization. +Scope: TypeScript, JavaScript, shell, and non-Swift runtime scripts. Swift timing and blocking primitives are covered by `swift-blocking-runtime.md`. Flag fixed delays used as synchronization in production application or runtime code. @@ -15,7 +13,6 @@ Report a failure when the diff introduces or materially expands any of these in Allowed cases: - Deterministic sleeps in tests or explicit test-only scaffolding. -- GitHub Actions workflow or action YAML sleeps used only for CI orchestration. - User-visible animation or progress timing where the timer is purely presentation and not coordination. - Production retry or timeout logic implemented through a dedicated cancellation-aware abstraction with bounded deadlines and tests, where the delay is part of the product behavior rather than a race repair. - Existing delay code that the PR does not introduce or worsen. diff --git a/.github/workflows/circleci-auto-approve.yml b/.github/workflows/circleci-auto-approve.yml new file mode 100644 index 000000000000..0c290896f722 --- /dev/null +++ b/.github/workflows/circleci-auto-approve.yml @@ -0,0 +1,44 @@ +name: CircleCI Auto Approval + +on: + pull_request_target: + types: + - opened + - reopened + - synchronize + - ready_for_review + +permissions: + checks: read + contents: read + pull-requests: read + +jobs: + approve-circleci: + if: ${{ github.event.pull_request.draft == false }} + runs-on: ubuntu-latest + timeout-minutes: 20 + concurrency: + group: approve-circleci-${{ github.event.pull_request.number }} + cancel-in-progress: true + steps: + - name: Checkout trusted automation + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + ref: ${{ github.event.repository.default_branch }} + + - name: Approve CircleCI hold for trusted PR authors + env: + GITHUB_TOKEN: ${{ github.token }} + GITHUB_ORG_READ_TOKEN: ${{ secrets.GITHUB_ORG_READ_TOKEN }} + CIRCLECI_TOKEN: ${{ secrets.CIRCLECI_TOKEN }} + GITHUB_REPOSITORY: ${{ github.repository }} + PR_HEAD_REPOSITORY: ${{ github.event.pull_request.head.repo.full_name }} + PR_HEAD_OWNER: ${{ github.event.pull_request.head.repo.owner.login }} + PR_HEAD_OWNER_ID: ${{ github.event.pull_request.head.repo.owner.id }} + PR_HEAD_SHA: ${{ github.event.pull_request.head.sha }} + PR_AUTHOR: ${{ github.event.pull_request.user.login }} + PR_AUTHOR_ID: ${{ github.event.pull_request.user.id }} + TRUSTED_GITHUB_ORG: ${{ vars.CIRCLECI_TRUSTED_GITHUB_ORG || 'manaflow-ai' }} + TRUSTED_GITHUB_USERS: ${{ vars.CIRCLECI_TRUSTED_GITHUB_USERS || 'lawrencecchen:54008264,austinywang:38676809' }} + run: python3 scripts/circleci_auto_approve.py diff --git a/.github/workflows/perf-activation.yml b/.github/workflows/perf-activation.yml index fd2967833239..34da6f5ca70b 100644 --- a/.github/workflows/perf-activation.yml +++ b/.github/workflows/perf-activation.yml @@ -81,40 +81,8 @@ jobs: run: | ./scripts/install-rust-ci.sh - - name: Cache Swift packages - uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 - with: - path: .ci-source-packages - key: spm-${{ hashFiles('cmux.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved') }} - restore-keys: spm- - - - name: Resolve Swift packages - run: | - set -euo pipefail - SOURCE_PACKAGES_DIR="$PWD/.ci-source-packages" - mkdir -p "$SOURCE_PACKAGES_DIR" - - for attempt in 1 2 3; do - if xcodebuild -project cmux.xcodeproj -scheme cmux -configuration Debug \ - -clonedSourcePackagesDirPath "$SOURCE_PACKAGES_DIR" \ - -resolvePackageDependencies; then - exit 0 - fi - if [ "$attempt" -eq 3 ]; then - echo "Failed to resolve Swift packages after 3 attempts" >&2 - exit 1 - fi - echo "Package resolution failed on attempt $attempt, retrying..." - sleep $((attempt * 5)) - done - - name: Build tagged app - run: | - set -euo pipefail - CMUX_SKIP_ZIG_BUILD=1 \ - CMUX_SOURCE_PACKAGES_DIR="$PWD/.ci-source-packages" \ - CMUX_DISABLE_AUTOMATIC_PACKAGE_RESOLUTION=1 \ - ./scripts/reload.sh --tag "$PERF_TAG" + run: ./scripts/reload.sh --tag "$PERF_TAG" - name: Run activation session benchmark run: | diff --git a/.greptile/config.json b/.greptile/config.json index 88094463d818..a6a143815054 100644 --- a/.greptile/config.json +++ b/.greptile/config.json @@ -21,7 +21,7 @@ { "id": "cmux-runtime-no-hacky-sleeps", "rule": "Flag fixed sleeps, delayed dispatch, timers, polling, or wall-clock waits used as synchronization in production non-Swift app/runtime code across TypeScript, JavaScript, shell, or build/runtime scripts. Fail race repairs for lifecycle, focus, rendering, socket, process, filesystem, network, teardown, startup, retry, or shared-state readiness unless they use a real signal or a dedicated cancellation-aware timeout/retry abstraction with tests. Swift files are covered by cmux-swift-blocking-runtime.", - "scope": ["**/*.ts", "**/*.tsx", "**/*.js", "**/*.jsx", "**/*.mjs", "**/*.cjs", "**/*.sh", "**/*.zsh"], + "scope": ["web/app/**/*.ts", "web/app/**/*.tsx", "web/services/**/*.ts", "web/services/**/*.tsx", "web/db/**/*.ts", "web/data/**/*.ts", "web/i18n/**/*.ts", "web/scripts/**/*.ts", "web/scripts/**/*.tsx", "web/scripts/**/*.js", "web/scripts/**/*.jsx", "web/scripts/**/*.mjs", "web/scripts/**/*.cjs", "web/scripts/**/*.sh", "web/scripts/**/*.zsh", "web/*.ts", "web/*.mjs", "scripts/**/*.ts", "scripts/**/*.tsx", "scripts/**/*.js", "scripts/**/*.jsx", "scripts/**/*.mjs", "scripts/**/*.cjs", "scripts/**/*.sh", "scripts/**/*.zsh"], "severity": "high" }, { diff --git a/.greptile/files.json b/.greptile/files.json index 1b093b89e9d7..6c8f56bc5ab7 100644 --- a/.greptile/files.json +++ b/.greptile/files.json @@ -18,7 +18,7 @@ { "path": ".github/review-bot-rules/runtime-no-hacky-sleeps.md", "description": "Source-of-truth cmux review rule for fixed sleeps, delays, and polling used as runtime synchronization.", - "scope": ["**/*.ts", "**/*.tsx", "**/*.js", "**/*.jsx", "**/*.mjs", "**/*.cjs", "**/*.sh", "**/*.zsh"] + "scope": ["web/app/**/*.ts", "web/app/**/*.tsx", "web/services/**/*.ts", "web/services/**/*.tsx", "web/db/**/*.ts", "web/data/**/*.ts", "web/i18n/**/*.ts", "web/scripts/**/*.ts", "web/scripts/**/*.tsx", "web/scripts/**/*.js", "web/scripts/**/*.jsx", "web/scripts/**/*.mjs", "web/scripts/**/*.cjs", "web/scripts/**/*.sh", "web/scripts/**/*.zsh", "web/*.ts", "web/*.mjs", "scripts/**/*.ts", "scripts/**/*.tsx", "scripts/**/*.js", "scripts/**/*.jsx", "scripts/**/*.mjs", "scripts/**/*.cjs", "scripts/**/*.sh", "scripts/**/*.zsh"] }, { "path": ".github/review-bot-rules/full-internationalization.md", diff --git a/.greptile/rules.md b/.greptile/rules.md index 4a66673b53f4..4738c84aa28d 100644 --- a/.greptile/rules.md +++ b/.greptile/rules.md @@ -18,14 +18,6 @@ Review production Swift and runtime changes for: - Architectural fixes that patch symptoms while leaving bad state representable. - User-facing errors, alerts, command output, API error bodies, and recovery copy that expose implementation details. -## Runtime No Hacky Sleeps - -For production non-Swift app/runtime code and build/runtime scripts, flag fixed sleeps, delayed dispatch, timers, polling, or wall-clock waits used as synchronization. - -Fail race repairs for lifecycle, focus, rendering, socket, process, filesystem, network, teardown, startup, retry, or shared-state readiness unless they use a real signal from the owning subsystem or a dedicated cancellation-aware timeout/retry abstraction with tests. - -Pass for deterministic test-only scaffolding, GitHub Actions workflow or action YAML sleeps used only for CI orchestration, pure presentation animation or progress timing, and existing delay code the PR does not introduce or worsen. Swift sleeps are covered by the Swift blocking runtime rule. - ## Full Internationalization For production user-facing text, require complete internationalization across every locale supported by the affected surface. diff --git a/Assets.xcassets/AgentIcons/Antigravity.imageset/Antigravity.png b/Assets.xcassets/AgentIcons/Antigravity.imageset/Antigravity.png deleted file mode 100644 index 134d8b7ba11d..000000000000 Binary files a/Assets.xcassets/AgentIcons/Antigravity.imageset/Antigravity.png and /dev/null differ diff --git a/Assets.xcassets/AgentIcons/Antigravity.imageset/Antigravity@2x.png b/Assets.xcassets/AgentIcons/Antigravity.imageset/Antigravity@2x.png deleted file mode 100644 index b1555c457055..000000000000 Binary files a/Assets.xcassets/AgentIcons/Antigravity.imageset/Antigravity@2x.png and /dev/null differ diff --git a/Assets.xcassets/AgentIcons/Antigravity.imageset/Antigravity@3x.png b/Assets.xcassets/AgentIcons/Antigravity.imageset/Antigravity@3x.png deleted file mode 100644 index a354611a80e8..000000000000 Binary files a/Assets.xcassets/AgentIcons/Antigravity.imageset/Antigravity@3x.png and /dev/null differ diff --git a/Assets.xcassets/AgentIcons/Antigravity.imageset/Contents.json b/Assets.xcassets/AgentIcons/Antigravity.imageset/Contents.json deleted file mode 100644 index 727d156a102d..000000000000 --- a/Assets.xcassets/AgentIcons/Antigravity.imageset/Contents.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "images" : [ - { - "filename" : "Antigravity.png", - "idiom" : "universal", - "scale" : "1x" - }, - { - "filename" : "Antigravity@2x.png", - "idiom" : "universal", - "scale" : "2x" - }, - { - "filename" : "Antigravity@3x.png", - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/Assets.xcassets/AgentIcons/Grok.imageset/Contents.json b/Assets.xcassets/AgentIcons/Grok.imageset/Contents.json deleted file mode 100644 index 82616cc3aa1d..000000000000 --- a/Assets.xcassets/AgentIcons/Grok.imageset/Contents.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "images" : [ - { - "filename" : "Grok.svg", - "idiom" : "universal" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - }, - "properties" : { - "preserves-vector-representation" : true - } -} diff --git a/Assets.xcassets/AgentIcons/Grok.imageset/Grok.svg b/Assets.xcassets/AgentIcons/Grok.imageset/Grok.svg deleted file mode 100644 index 7287b077673c..000000000000 --- a/Assets.xcassets/AgentIcons/Grok.imageset/Grok.svg +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/Packages/CMUXAgentLaunch/Sources/CMUXAgentLaunch/AgentLaunchSanitizer.swift b/Packages/CMUXAgentLaunch/Sources/CMUXAgentLaunch/AgentLaunchSanitizer.swift index 6e73408d6c0a..68ada69bfab5 100644 --- a/Packages/CMUXAgentLaunch/Sources/CMUXAgentLaunch/AgentLaunchSanitizer.swift +++ b/Packages/CMUXAgentLaunch/Sources/CMUXAgentLaunch/AgentLaunchSanitizer.swift @@ -103,8 +103,6 @@ public enum AgentLaunchSanitizer { return preserveOptions(tail, policy: cursorPolicy) case "gemini": return preserveOptions(args, policy: geminiPolicy) - case "antigravity": - return preserveOptions(args, policy: antigravityPolicy) case "opencode": return preserveOptions( args.filter { !isOpenCodeInternalWorkerArgument($0) }, diff --git a/Packages/CMUXAgentLaunch/Sources/CMUXAgentLaunch/AgentLaunchSanitizerPrimaryPolicies.swift b/Packages/CMUXAgentLaunch/Sources/CMUXAgentLaunch/AgentLaunchSanitizerPrimaryPolicies.swift index a16f64053cf3..06a7363e2619 100644 --- a/Packages/CMUXAgentLaunch/Sources/CMUXAgentLaunch/AgentLaunchSanitizerPrimaryPolicies.swift +++ b/Packages/CMUXAgentLaunch/Sources/CMUXAgentLaunch/AgentLaunchSanitizerPrimaryPolicies.swift @@ -425,45 +425,6 @@ extension AgentLaunchSanitizer { ] ) - static let antigravityPolicy = Policy( - valueOptions: [ - "--add-dir", - "--conversation", - "--log-file", - "--print-timeout", - "--prompt", - "-p", - "--sandbox", - ], - optionalValueOptions: [ - "--continue", - "-c", - ], - nonRestorableCommands: [ - "changelog", - "help", - "install", - "plugin", - "plugins", - "update", - ], - droppedOptions: [ - "--continue", - "-c", - "--conversation", - ], - droppedOptionPrefixes: [ - "--conversation=", - ], - rejectOptions: [ - "--prompt", - "-p", - "--prompt-interactive", - "-i", - "--print", - ] - ) - static let cursorPolicy = Policy( valueOptions: [ "--api-key", diff --git a/Packages/CMUXAgentLaunch/Tests/CMUXAgentLaunchTests/AgentLaunchSanitizerTests.swift b/Packages/CMUXAgentLaunch/Tests/CMUXAgentLaunchTests/AgentLaunchSanitizerTests.swift index 7bc0851006a8..f8e321410832 100644 --- a/Packages/CMUXAgentLaunch/Tests/CMUXAgentLaunchTests/AgentLaunchSanitizerTests.swift +++ b/Packages/CMUXAgentLaunch/Tests/CMUXAgentLaunchTests/AgentLaunchSanitizerTests.swift @@ -359,92 +359,6 @@ struct AgentLaunchSanitizerTests { ) } - @Test("Drops Antigravity conversation selectors without replaying prompts") - func dropsAntigravityConversationSelectorsWithoutReplayingPrompts() { - #expect( - AgentLaunchSanitizer.sanitizedLaunchArguments( - [ - "agy", - "--conversation", - "old-conversation", - "--sandbox", - "danger-full-access", - "--add-dir", - "/tmp/extra repo", - "initial prompt should not replay", - ], - launcher: "antigravity", - fallbackKind: "antigravity" - ) == [ - "agy", - "--sandbox", - "danger-full-access", - "--add-dir", - "/tmp/extra repo", - ] - ) - #expect( - AgentLaunchSanitizer.sanitizedLaunchArguments( - ["agy", "--conversation=old-conversation", "--log-file", "/tmp/agy.log"], - launcher: "antigravity", - fallbackKind: "antigravity" - ) == ["agy", "--log-file", "/tmp/agy.log"] - ) - #expect( - AgentLaunchSanitizer.sanitizedLaunchArguments( - ["agy", "--conversation", "--sandbox", "danger-full-access"], - launcher: "antigravity", - fallbackKind: "antigravity" - ) == ["agy"] - ) - #expect( - AgentLaunchSanitizer.sanitizedLaunchArguments( - ["agy", "--continue", "old-conversation", "--sandbox", "danger-full-access"], - launcher: "antigravity", - fallbackKind: "antigravity" - ) == ["agy", "--sandbox", "danger-full-access"] - ) - #expect( - AgentLaunchSanitizer.sanitizedLaunchArguments( - ["agy", "-c", "--sandbox", "danger-full-access"], - launcher: "antigravity", - fallbackKind: "antigravity" - ) == ["agy", "--sandbox", "danger-full-access"] - ) - } - - @Test("Rejects noninteractive Antigravity launches") - func rejectsNoninteractiveAntigravityLaunches() { - #expect( - AgentLaunchSanitizer.sanitizedLaunchArguments( - ["agy", "--print", "--prompt", "summarize"], - launcher: "antigravity", - fallbackKind: "antigravity" - ) == nil - ) - #expect( - AgentLaunchSanitizer.sanitizedLaunchArguments( - ["agy", "--prompt", "summarize"], - launcher: "antigravity", - fallbackKind: "antigravity" - ) == nil - ) - #expect( - AgentLaunchSanitizer.sanitizedLaunchArguments( - ["agy", "-i", "--prompt", "summarize"], - launcher: "antigravity", - fallbackKind: "antigravity" - ) == nil - ) - #expect( - AgentLaunchSanitizer.sanitizedLaunchArguments( - ["agy", "-p", "summarize"], - launcher: "antigravity", - fallbackKind: "antigravity" - ) == nil - ) - } - @Test("Drops Grok optional selectors without swallowing later options") func dropsGrokOptionalSelectorsWithoutSwallowingLaterOptions() { #expect( diff --git a/Resources/Localizable.xcstrings b/Resources/Localizable.xcstrings index db674105e604..d031ab8475d1 100644 --- a/Resources/Localizable.xcstrings +++ b/Resources/Localizable.xcstrings @@ -3,15 +3,6 @@ "version": "1.0", "strings": { "cli.hooks.error.configDirectoryIsFile": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", "value": "cmux could not create the hooks directory: a file exists at %@; remove or rename the conflicting file and re-run `cmux hooks setup`" } }, "ja": { "stringUnit": { "state": "translated", "value": "cmux は hooks ディレクトリを作成できませんでした: %@ にファイルがあります。競合するファイルを削除または名前変更してから `cmux hooks setup` を再実行してください" } } } }, - "cli.hooks.antigravity.aborted": { "extractionState": "manual", "localizations": {"ar":{"stringUnit":{"state":"translated","value":"Aborted."}},"bs":{"stringUnit":{"state":"translated","value":"Aborted."}},"da":{"stringUnit":{"state":"translated","value":"Aborted."}},"de":{"stringUnit":{"state":"translated","value":"Aborted."}},"en":{"stringUnit":{"state":"translated","value":"Aborted."}},"es":{"stringUnit":{"state":"translated","value":"Aborted."}},"fr":{"stringUnit":{"state":"translated","value":"Aborted."}},"it":{"stringUnit":{"state":"translated","value":"Aborted."}},"ja":{"stringUnit":{"state":"translated","value":"中止しました。"}},"ko":{"stringUnit":{"state":"translated","value":"Aborted."}},"nb":{"stringUnit":{"state":"translated","value":"Aborted."}},"pl":{"stringUnit":{"state":"translated","value":"Aborted."}},"pt-BR":{"stringUnit":{"state":"translated","value":"Aborted."}},"ru":{"stringUnit":{"state":"translated","value":"Aborted."}},"th":{"stringUnit":{"state":"translated","value":"Aborted."}},"tr":{"stringUnit":{"state":"translated","value":"Aborted."}},"uk":{"stringUnit":{"state":"translated","value":"Aborted."}},"zh-Hans":{"stringUnit":{"state":"translated","value":"Aborted."}},"zh-Hant":{"stringUnit":{"state":"translated","value":"Aborted."}}} }, - "cli.hooks.antigravity.alreadyUpToDate": { "extractionState": "manual", "localizations": {"ar":{"stringUnit":{"state":"translated","value":"%@ hooks already up to date at %@"}},"bs":{"stringUnit":{"state":"translated","value":"%@ hooks already up to date at %@"}},"da":{"stringUnit":{"state":"translated","value":"%@ hooks already up to date at %@"}},"de":{"stringUnit":{"state":"translated","value":"%@ hooks already up to date at %@"}},"en":{"stringUnit":{"state":"translated","value":"%@ hooks already up to date at %@"}},"es":{"stringUnit":{"state":"translated","value":"%@ hooks already up to date at %@"}},"fr":{"stringUnit":{"state":"translated","value":"%@ hooks already up to date at %@"}},"it":{"stringUnit":{"state":"translated","value":"%@ hooks already up to date at %@"}},"ja":{"stringUnit":{"state":"translated","value":"%@ hooks はすでに %@ で最新です"}},"ko":{"stringUnit":{"state":"translated","value":"%@ hooks already up to date at %@"}},"nb":{"stringUnit":{"state":"translated","value":"%@ hooks already up to date at %@"}},"pl":{"stringUnit":{"state":"translated","value":"%@ hooks already up to date at %@"}},"pt-BR":{"stringUnit":{"state":"translated","value":"%@ hooks already up to date at %@"}},"ru":{"stringUnit":{"state":"translated","value":"%@ hooks already up to date at %@"}},"th":{"stringUnit":{"state":"translated","value":"%@ hooks already up to date at %@"}},"tr":{"stringUnit":{"state":"translated","value":"%@ hooks already up to date at %@"}},"uk":{"stringUnit":{"state":"translated","value":"%@ hooks already up to date at %@"}},"zh-Hans":{"stringUnit":{"state":"translated","value":"%@ hooks already up to date at %@"}},"zh-Hant":{"stringUnit":{"state":"translated","value":"%@ hooks already up to date at %@"}}} }, - "cli.hooks.antigravity.confirmProceed": { "extractionState": "manual", "localizations": {"ar":{"stringUnit":{"state":"translated","value":"\nProceed? [y/N] "}},"bs":{"stringUnit":{"state":"translated","value":"\nProceed? [y/N] "}},"da":{"stringUnit":{"state":"translated","value":"\nProceed? [y/N] "}},"de":{"stringUnit":{"state":"translated","value":"\nProceed? [y/N] "}},"en":{"stringUnit":{"state":"translated","value":"\nProceed? [y/N] "}},"es":{"stringUnit":{"state":"translated","value":"\nProceed? [y/N] "}},"fr":{"stringUnit":{"state":"translated","value":"\nProceed? [y/N] "}},"it":{"stringUnit":{"state":"translated","value":"\nProceed? [y/N] "}},"ja":{"stringUnit":{"state":"translated","value":"\n続行しますか? [y/N] "}},"ko":{"stringUnit":{"state":"translated","value":"\nProceed? [y/N] "}},"nb":{"stringUnit":{"state":"translated","value":"\nProceed? [y/N] "}},"pl":{"stringUnit":{"state":"translated","value":"\nProceed? [y/N] "}},"pt-BR":{"stringUnit":{"state":"translated","value":"\nProceed? [y/N] "}},"ru":{"stringUnit":{"state":"translated","value":"\nProceed? [y/N] "}},"th":{"stringUnit":{"state":"translated","value":"\nProceed? [y/N] "}},"tr":{"stringUnit":{"state":"translated","value":"\nProceed? [y/N] "}},"uk":{"stringUnit":{"state":"translated","value":"\nProceed? [y/N] "}},"zh-Hans":{"stringUnit":{"state":"translated","value":"\nProceed? [y/N] "}},"zh-Hant":{"stringUnit":{"state":"translated","value":"\nProceed? [y/N] "}}} }, - "cli.hooks.antigravity.error.invalidJSON": { "extractionState": "manual", "localizations": {"ar":{"stringUnit":{"state":"translated","value":"%@ exists but is not valid JSON. Fix or remove it before installing hooks."}},"bs":{"stringUnit":{"state":"translated","value":"%@ exists but is not valid JSON. Fix or remove it before installing hooks."}},"da":{"stringUnit":{"state":"translated","value":"%@ exists but is not valid JSON. Fix or remove it before installing hooks."}},"de":{"stringUnit":{"state":"translated","value":"%@ exists but is not valid JSON. Fix or remove it before installing hooks."}},"en":{"stringUnit":{"state":"translated","value":"%@ exists but is not valid JSON. Fix or remove it before installing hooks."}},"es":{"stringUnit":{"state":"translated","value":"%@ exists but is not valid JSON. Fix or remove it before installing hooks."}},"fr":{"stringUnit":{"state":"translated","value":"%@ exists but is not valid JSON. Fix or remove it before installing hooks."}},"it":{"stringUnit":{"state":"translated","value":"%@ exists but is not valid JSON. Fix or remove it before installing hooks."}},"ja":{"stringUnit":{"state":"translated","value":"%@ は存在しますが、有効な JSON ではありません。hooks をインストールする前に修正または削除してください。"}},"ko":{"stringUnit":{"state":"translated","value":"%@ exists but is not valid JSON. Fix or remove it before installing hooks."}},"nb":{"stringUnit":{"state":"translated","value":"%@ exists but is not valid JSON. Fix or remove it before installing hooks."}},"pl":{"stringUnit":{"state":"translated","value":"%@ exists but is not valid JSON. Fix or remove it before installing hooks."}},"pt-BR":{"stringUnit":{"state":"translated","value":"%@ exists but is not valid JSON. Fix or remove it before installing hooks."}},"ru":{"stringUnit":{"state":"translated","value":"%@ exists but is not valid JSON. Fix or remove it before installing hooks."}},"th":{"stringUnit":{"state":"translated","value":"%@ exists but is not valid JSON. Fix or remove it before installing hooks."}},"tr":{"stringUnit":{"state":"translated","value":"%@ exists but is not valid JSON. Fix or remove it before installing hooks."}},"uk":{"stringUnit":{"state":"translated","value":"%@ exists but is not valid JSON. Fix or remove it before installing hooks."}},"zh-Hans":{"stringUnit":{"state":"translated","value":"%@ exists but is not valid JSON. Fix or remove it before installing hooks."}},"zh-Hant":{"stringUnit":{"state":"translated","value":"%@ exists but is not valid JSON. Fix or remove it before installing hooks."}}} }, - "cli.hooks.antigravity.installed": { "extractionState": "manual", "localizations": {"ar":{"stringUnit":{"state":"translated","value":"%@ hooks installed at %@"}},"bs":{"stringUnit":{"state":"translated","value":"%@ hooks installed at %@"}},"da":{"stringUnit":{"state":"translated","value":"%@ hooks installed at %@"}},"de":{"stringUnit":{"state":"translated","value":"%@ hooks installed at %@"}},"en":{"stringUnit":{"state":"translated","value":"%@ hooks installed at %@"}},"es":{"stringUnit":{"state":"translated","value":"%@ hooks installed at %@"}},"fr":{"stringUnit":{"state":"translated","value":"%@ hooks installed at %@"}},"it":{"stringUnit":{"state":"translated","value":"%@ hooks installed at %@"}},"ja":{"stringUnit":{"state":"translated","value":"%@ hooks を %@ にインストールしました"}},"ko":{"stringUnit":{"state":"translated","value":"%@ hooks installed at %@"}},"nb":{"stringUnit":{"state":"translated","value":"%@ hooks installed at %@"}},"pl":{"stringUnit":{"state":"translated","value":"%@ hooks installed at %@"}},"pt-BR":{"stringUnit":{"state":"translated","value":"%@ hooks installed at %@"}},"ru":{"stringUnit":{"state":"translated","value":"%@ hooks installed at %@"}},"th":{"stringUnit":{"state":"translated","value":"%@ hooks installed at %@"}},"tr":{"stringUnit":{"state":"translated","value":"%@ hooks installed at %@"}},"uk":{"stringUnit":{"state":"translated","value":"%@ hooks installed at %@"}},"zh-Hans":{"stringUnit":{"state":"translated","value":"%@ hooks installed at %@"}},"zh-Hant":{"stringUnit":{"state":"translated","value":"%@ hooks installed at %@"}}} }, - "cli.hooks.antigravity.malformedJSON": { "extractionState": "manual", "localizations": {"ar":{"stringUnit":{"state":"translated","value":"Malformed %@ at %@. Fix or remove it before uninstalling hooks."}},"bs":{"stringUnit":{"state":"translated","value":"Malformed %@ at %@. Fix or remove it before uninstalling hooks."}},"da":{"stringUnit":{"state":"translated","value":"Malformed %@ at %@. Fix or remove it before uninstalling hooks."}},"de":{"stringUnit":{"state":"translated","value":"Malformed %@ at %@. Fix or remove it before uninstalling hooks."}},"en":{"stringUnit":{"state":"translated","value":"Malformed %@ at %@. Fix or remove it before uninstalling hooks."}},"es":{"stringUnit":{"state":"translated","value":"Malformed %@ at %@. Fix or remove it before uninstalling hooks."}},"fr":{"stringUnit":{"state":"translated","value":"Malformed %@ at %@. Fix or remove it before uninstalling hooks."}},"it":{"stringUnit":{"state":"translated","value":"Malformed %@ at %@. Fix or remove it before uninstalling hooks."}},"ja":{"stringUnit":{"state":"translated","value":"%@ が %@ で不正な JSON です。hooks をアンインストールする前に修正または削除してください。"}},"ko":{"stringUnit":{"state":"translated","value":"Malformed %@ at %@. Fix or remove it before uninstalling hooks."}},"nb":{"stringUnit":{"state":"translated","value":"Malformed %@ at %@. Fix or remove it before uninstalling hooks."}},"pl":{"stringUnit":{"state":"translated","value":"Malformed %@ at %@. Fix or remove it before uninstalling hooks."}},"pt-BR":{"stringUnit":{"state":"translated","value":"Malformed %@ at %@. Fix or remove it before uninstalling hooks."}},"ru":{"stringUnit":{"state":"translated","value":"Malformed %@ at %@. Fix or remove it before uninstalling hooks."}},"th":{"stringUnit":{"state":"translated","value":"Malformed %@ at %@. Fix or remove it before uninstalling hooks."}},"tr":{"stringUnit":{"state":"translated","value":"Malformed %@ at %@. Fix or remove it before uninstalling hooks."}},"uk":{"stringUnit":{"state":"translated","value":"Malformed %@ at %@. Fix or remove it before uninstalling hooks."}},"zh-Hans":{"stringUnit":{"state":"translated","value":"Malformed %@ at %@. Fix or remove it before uninstalling hooks."}},"zh-Hant":{"stringUnit":{"state":"translated","value":"Malformed %@ at %@. Fix or remove it before uninstalling hooks."}}} }, - "cli.hooks.antigravity.noneFound": { "extractionState": "manual", "localizations": {"ar":{"stringUnit":{"state":"translated","value":"No %@ found at %@"}},"bs":{"stringUnit":{"state":"translated","value":"No %@ found at %@"}},"da":{"stringUnit":{"state":"translated","value":"No %@ found at %@"}},"de":{"stringUnit":{"state":"translated","value":"No %@ found at %@"}},"en":{"stringUnit":{"state":"translated","value":"No %@ found at %@"}},"es":{"stringUnit":{"state":"translated","value":"No %@ found at %@"}},"fr":{"stringUnit":{"state":"translated","value":"No %@ found at %@"}},"it":{"stringUnit":{"state":"translated","value":"No %@ found at %@"}},"ja":{"stringUnit":{"state":"translated","value":"%@ は %@ に見つかりませんでした"}},"ko":{"stringUnit":{"state":"translated","value":"No %@ found at %@"}},"nb":{"stringUnit":{"state":"translated","value":"No %@ found at %@"}},"pl":{"stringUnit":{"state":"translated","value":"No %@ found at %@"}},"pt-BR":{"stringUnit":{"state":"translated","value":"No %@ found at %@"}},"ru":{"stringUnit":{"state":"translated","value":"No %@ found at %@"}},"th":{"stringUnit":{"state":"translated","value":"No %@ found at %@"}},"tr":{"stringUnit":{"state":"translated","value":"No %@ found at %@"}},"uk":{"stringUnit":{"state":"translated","value":"No %@ found at %@"}},"zh-Hans":{"stringUnit":{"state":"translated","value":"No %@ found at %@"}},"zh-Hant":{"stringUnit":{"state":"translated","value":"No %@ found at %@"}}} }, - "cli.hooks.antigravity.removed": { "extractionState": "manual", "localizations": {"ar":{"stringUnit":{"state":"translated","value":"Removed Antigravity cmux hooks from %@"}},"bs":{"stringUnit":{"state":"translated","value":"Removed Antigravity cmux hooks from %@"}},"da":{"stringUnit":{"state":"translated","value":"Removed Antigravity cmux hooks from %@"}},"de":{"stringUnit":{"state":"translated","value":"Removed Antigravity cmux hooks from %@"}},"en":{"stringUnit":{"state":"translated","value":"Removed Antigravity cmux hooks from %@"}},"es":{"stringUnit":{"state":"translated","value":"Removed Antigravity cmux hooks from %@"}},"fr":{"stringUnit":{"state":"translated","value":"Removed Antigravity cmux hooks from %@"}},"it":{"stringUnit":{"state":"translated","value":"Removed Antigravity cmux hooks from %@"}},"ja":{"stringUnit":{"state":"translated","value":"%@ から Antigravity cmux hooks を削除しました"}},"ko":{"stringUnit":{"state":"translated","value":"Removed Antigravity cmux hooks from %@"}},"nb":{"stringUnit":{"state":"translated","value":"Removed Antigravity cmux hooks from %@"}},"pl":{"stringUnit":{"state":"translated","value":"Removed Antigravity cmux hooks from %@"}},"pt-BR":{"stringUnit":{"state":"translated","value":"Removed Antigravity cmux hooks from %@"}},"ru":{"stringUnit":{"state":"translated","value":"Removed Antigravity cmux hooks from %@"}},"th":{"stringUnit":{"state":"translated","value":"Removed Antigravity cmux hooks from %@"}},"tr":{"stringUnit":{"state":"translated","value":"Removed Antigravity cmux hooks from %@"}},"uk":{"stringUnit":{"state":"translated","value":"Removed Antigravity cmux hooks from %@"}},"zh-Hans":{"stringUnit":{"state":"translated","value":"Removed Antigravity cmux hooks from %@"}},"zh-Hant":{"stringUnit":{"state":"translated","value":"Removed Antigravity cmux hooks from %@"}}} }, - "cli.hooks.antigravity.removedZero": { "extractionState": "manual", "localizations": {"ar":{"stringUnit":{"state":"translated","value":"Removed 0 cmux hook(s) from %@"}},"bs":{"stringUnit":{"state":"translated","value":"Removed 0 cmux hook(s) from %@"}},"da":{"stringUnit":{"state":"translated","value":"Removed 0 cmux hook(s) from %@"}},"de":{"stringUnit":{"state":"translated","value":"Removed 0 cmux hook(s) from %@"}},"en":{"stringUnit":{"state":"translated","value":"Removed 0 cmux hook(s) from %@"}},"es":{"stringUnit":{"state":"translated","value":"Removed 0 cmux hook(s) from %@"}},"fr":{"stringUnit":{"state":"translated","value":"Removed 0 cmux hook(s) from %@"}},"it":{"stringUnit":{"state":"translated","value":"Removed 0 cmux hook(s) from %@"}},"ja":{"stringUnit":{"state":"translated","value":"%@ から 0 個の cmux hook を削除しました"}},"ko":{"stringUnit":{"state":"translated","value":"Removed 0 cmux hook(s) from %@"}},"nb":{"stringUnit":{"state":"translated","value":"Removed 0 cmux hook(s) from %@"}},"pl":{"stringUnit":{"state":"translated","value":"Removed 0 cmux hook(s) from %@"}},"pt-BR":{"stringUnit":{"state":"translated","value":"Removed 0 cmux hook(s) from %@"}},"ru":{"stringUnit":{"state":"translated","value":"Removed 0 cmux hook(s) from %@"}},"th":{"stringUnit":{"state":"translated","value":"Removed 0 cmux hook(s) from %@"}},"tr":{"stringUnit":{"state":"translated","value":"Removed 0 cmux hook(s) from %@"}},"uk":{"stringUnit":{"state":"translated","value":"Removed 0 cmux hook(s) from %@"}},"zh-Hans":{"stringUnit":{"state":"translated","value":"Removed 0 cmux hook(s) from %@"}},"zh-Hant":{"stringUnit":{"state":"translated","value":"Removed 0 cmux hook(s) from %@"}}} }, "cli.error.dismissNotificationSelector": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", "value": "dismiss-notification requires exactly one of --id or --all-read" } }, "ja": { "stringUnit": { "state": "translated", "value": "dismiss-notification には --id または --all-read のどちらか一方だけを指定してください" } } } }, "cli.error.markNotificationReadSelector": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", "value": "mark-notification-read requires exactly one selector: --id, --workspace, or --all" } }, "ja": { "stringUnit": { "state": "translated", "value": "mark-notification-read には --id、--workspace、--all のいずれか一つだけを指定してください" } } } }, "cli.error.markNotificationReadSurfaceRequiresWorkspace": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", "value": "--surface requires --workspace" } }, "ja": { "stringUnit": { "state": "translated", "value": "--surface には --workspace が必要です" } } } }, @@ -8744,131 +8735,6 @@ } } }, - "settings.browser.import.detecting": { - "extractionState": "manual", - "localizations": { - "ar": { - "stringUnit": { - "state": "translated", - "value": "جارٍ التحقق من المتصفحات المثبتة..." - } - }, - "bs": { - "stringUnit": { - "state": "translated", - "value": "Provjeravam instalirane preglednike..." - } - }, - "da": { - "stringUnit": { - "state": "translated", - "value": "Kontrollerer installerede browsere..." - } - }, - "de": { - "stringUnit": { - "state": "translated", - "value": "Installierte Browser werden geprüft..." - } - }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Checking installed browsers..." - } - }, - "es": { - "stringUnit": { - "state": "translated", - "value": "Comprobando los navegadores instalados..." - } - }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "Vérification des navigateurs installés..." - } - }, - "it": { - "stringUnit": { - "state": "translated", - "value": "Controllo dei browser installati..." - } - }, - "ja": { - "stringUnit": { - "state": "translated", - "value": "インストール済みブラウザーを確認しています..." - } - }, - "ko": { - "stringUnit": { - "state": "translated", - "value": "설치된 브라우저를 확인하는 중..." - } - }, - "km": { - "stringUnit": { - "state": "translated", - "value": "កំពុងពិនិត្យកម្មវិធីរុករកដែលបានដំឡើង..." - } - }, - "nb": { - "stringUnit": { - "state": "translated", - "value": "Sjekker installerte nettlesere..." - } - }, - "pl": { - "stringUnit": { - "state": "translated", - "value": "Sprawdzanie zainstalowanych przeglądarek..." - } - }, - "pt-BR": { - "stringUnit": { - "state": "translated", - "value": "Verificando navegadores instalados..." - } - }, - "ru": { - "stringUnit": { - "state": "translated", - "value": "Проверяем установленные браузеры..." - } - }, - "th": { - "stringUnit": { - "state": "translated", - "value": "กำลังตรวจสอบเบราว์เซอร์ที่ติดตั้ง..." - } - }, - "tr": { - "stringUnit": { - "state": "translated", - "value": "Yüklü tarayıcılar kontrol ediliyor..." - } - }, - "uk": { - "stringUnit": { - "state": "translated", - "value": "Перевіряємо встановлені браузери..." - } - }, - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "正在检查已安装的浏览器..." - } - }, - "zh-Hant": { - "stringUnit": { - "state": "translated", - "value": "正在檢查已安裝的瀏覽器..." - } - } - } - }, "browser.import.domain": { "extractionState": "manual", "localizations": { @@ -10900,2692 +10766,2654 @@ } } }, - "browser.contextMenu.screenshotPage": { + "browser.dialog.pageSays": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Screenshot Page" + "value": "This page says:" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ページのスクリーンショット" + "value": "このページの内容:" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "截取页面截图" + "value": "此页面显示:" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "擷取頁面截圖" + "value": "此頁面顯示:" } }, "ko": { "stringUnit": { "state": "translated", - "value": "페이지 스크린샷" - } - }, - "km": { - "stringUnit": { - "state": "translated", - "value": "ថតអេក្រង់ទំព័រ" + "value": "이 페이지의 메시지:" } }, "de": { "stringUnit": { "state": "translated", - "value": "Seite als Screenshot aufnehmen" + "value": "Diese Seite meldet:" } }, "es": { "stringUnit": { "state": "translated", - "value": "Capturar página" + "value": "Esta página dice:" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Capture d’écran de la page" + "value": "Cette page indique :" } }, "it": { "stringUnit": { "state": "translated", - "value": "Screenshot pagina" + "value": "Questa pagina dice:" } }, "da": { "stringUnit": { "state": "translated", - "value": "Tag skærmbillede af side" + "value": "Denne side siger:" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Zrzut ekranu strony" + "value": "Ta strona mówi:" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Снимок страницы" + "value": "Сообщение на странице:" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Snimi ekran stranice" + "value": "Ova stranica kaže:" } }, "ar": { "stringUnit": { "state": "translated", - "value": "التقاط لقطة شاشة للصفحة" + "value": "تقول هذه الصفحة:" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Ta skjermbilde av side" + "value": "Denne siden sier:" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Capturar página" + "value": "Esta página diz:" } }, "th": { "stringUnit": { "state": "translated", - "value": "ถ่ายภาพหน้าจอหน้าเว็บ" + "value": "หน้านี้แจ้งว่า:" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Sayfanın ekran görüntüsünü al" + "value": "Bu sayfa diyor ki:" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Знімок сторінки" + "value": "Ця сторінка повідомляє:" } } } }, - "browser.contextMenu.screenshotSection": { + "browser.dialog.pageSaysAt": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Screenshot Section" + "value": "The page at %@ says:" } }, "ja": { "stringUnit": { "state": "translated", - "value": "範囲のスクリーンショット" + "value": "ページ %@ のメッセージ:" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "截取区域截图" + "value": "%@ 页面显示:" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "擷取區域截圖" + "value": "%@ 頁面顯示:" } }, "ko": { "stringUnit": { "state": "translated", - "value": "영역 스크린샷" - } - }, - "km": { - "stringUnit": { - "state": "translated", - "value": "ថតអេក្រង់ផ្នែក" + "value": "%@ 페이지의 메시지:" } }, "de": { "stringUnit": { "state": "translated", - "value": "Bereich als Screenshot aufnehmen" + "value": "Die Seite auf %@ meldet:" } }, "es": { "stringUnit": { "state": "translated", - "value": "Capturar sección" + "value": "La página en %@ dice:" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Capture d’écran de la section" + "value": "La page à %@ indique :" } }, "it": { "stringUnit": { "state": "translated", - "value": "Screenshot sezione" + "value": "La pagina su %@ dice:" } }, "da": { "stringUnit": { "state": "translated", - "value": "Tag skærmbillede af område" + "value": "Siden på %@ siger:" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Zrzut ekranu sekcji" + "value": "Strona pod adresem %@ mówi:" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Снимок области" + "value": "Страница %@ сообщает:" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Snimi ekran odjeljka" + "value": "Stranica na %@ kaže:" } }, "ar": { "stringUnit": { "state": "translated", - "value": "التقاط لقطة شاشة للقسم" + "value": "تقول الصفحة في %@:" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Ta skjermbilde av område" + "value": "Siden på %@ sier:" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Capturar seção" + "value": "A página em %@ diz:" } }, "th": { "stringUnit": { "state": "translated", - "value": "ถ่ายภาพหน้าจอเฉพาะส่วน" + "value": "หน้าที่ %@ แจ้งว่า:" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Bölümün ekran görüntüsünü al" + "value": "%@ sayfası diyor ki:" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Знімок області" + "value": "Сторінка %@ повідомляє:" } } } }, - "browser.screenshotPage.copy.help": { + "browser.downloadInProgress": { "extractionState": "manual", "localizations": { - "ar": { + "en": { "stringUnit": { "state": "translated", - "value": "نسخ لقطة شاشة الصفحة إلى الحافظة" + "value": "Download in progress" } }, - "bs": { + "ja": { "stringUnit": { "state": "translated", - "value": "Snimi stranicu u međuspremnik" + "value": "ダウンロード中" } }, - "da": { + "zh-Hans": { "stringUnit": { "state": "translated", - "value": "Skærmbillede af side til udklipsholder" + "value": "下载进行中" } }, - "de": { + "zh-Hant": { "stringUnit": { "state": "translated", - "value": "Seiten-Screenshot in die Zwischenablage" + "value": "正在下載" } }, - "en": { + "ko": { + "stringUnit": { + "state": "translated", + "value": "다운로드 진행 중" + } + }, + "de": { "stringUnit": { "state": "translated", - "value": "Screenshot Page to Clipboard" + "value": "Download läuft" } }, "es": { "stringUnit": { "state": "translated", - "value": "Capturar página al portapapeles" + "value": "Descarga en curso" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Capture de la page vers le presse-papiers" + "value": "Téléchargement en cours" } }, "it": { "stringUnit": { "state": "translated", - "value": "Screenshot pagina negli appunti" + "value": "Download in corso" } }, - "ja": { + "da": { "stringUnit": { "state": "translated", - "value": "ページのスクリーンショットをクリップボードへ" + "value": "Download i gang" } }, - "km": { + "pl": { "stringUnit": { "state": "translated", - "value": "ថតអេក្រង់ទំព័រទៅក្តារតម្បៀតខ្ទាស់" + "value": "Pobieranie w toku" } }, - "ko": { + "ru": { "stringUnit": { "state": "translated", - "value": "페이지 스크린샷을 클립보드로 복사" + "value": "Загрузка выполняется" } }, - "nb": { + "bs": { "stringUnit": { "state": "translated", - "value": "Skjermbilde av side til utklippstavlen" + "value": "Preuzimanje u toku" } }, - "pl": { + "ar": { "stringUnit": { "state": "translated", - "value": "Zrzut ekranu strony do schowka" + "value": "التنزيل قيد التقدم" } }, - "pt-BR": { + "nb": { "stringUnit": { "state": "translated", - "value": "Capturar página para a área de transferência" + "value": "Nedlasting pågår" } }, - "ru": { + "pt-BR": { "stringUnit": { "state": "translated", - "value": "Снимок страницы в буфер обмена" + "value": "Download em andamento" } }, "th": { "stringUnit": { "state": "translated", - "value": "ถ่ายภาพหน้าจอหน้าเว็บไปยังคลิปบอร์ด" + "value": "กำลังดาวน์โหลด" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Sayfanın ekran görüntüsünü panoya kopyala" + "value": "İndirme devam ediyor" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Знімок сторінки до буфера обміну" - } - }, - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "将页面截图复制到剪贴板" - } - }, - "zh-Hant": { - "stringUnit": { - "state": "translated", - "value": "將頁面截圖複製到剪貼簿" + "value": "Завантаження виконується" } } } }, - "browser.screenshotPage.copied": { + "browser.downloading": { "extractionState": "manual", "localizations": { - "ar": { + "en": { "stringUnit": { "state": "translated", - "value": "تم النسخ" + "value": "Downloading..." } }, - "bs": { + "ja": { "stringUnit": { "state": "translated", - "value": "Kopirano" + "value": "ダウンロード中..." } }, - "da": { + "zh-Hans": { "stringUnit": { "state": "translated", - "value": "Kopieret" + "value": "正在下载..." } }, - "de": { + "zh-Hant": { "stringUnit": { "state": "translated", - "value": "Kopiert" + "value": "下載中..." } }, - "en": { + "ko": { "stringUnit": { "state": "translated", - "value": "Copied" + "value": "다운로드 중..." + } + }, + "de": { + "stringUnit": { + "state": "translated", + "value": "Wird heruntergeladen …" } }, "es": { "stringUnit": { "state": "translated", - "value": "Copiado" + "value": "Descargando..." } }, "fr": { "stringUnit": { "state": "translated", - "value": "Copié" + "value": "Téléchargement..." } }, "it": { "stringUnit": { "state": "translated", - "value": "Copiato" + "value": "Download in corso..." } }, - "ja": { + "da": { "stringUnit": { "state": "translated", - "value": "コピー済み" + "value": "Downloader…" } }, - "km": { + "pl": { "stringUnit": { "state": "translated", - "value": "បានចម្លង" + "value": "Pobieranie…" } }, - "ko": { + "ru": { "stringUnit": { "state": "translated", - "value": "복사됨" + "value": "Загрузка..." } }, - "nb": { + "bs": { "stringUnit": { "state": "translated", - "value": "Kopiert" + "value": "Preuzimanje..." } }, - "pl": { + "ar": { "stringUnit": { "state": "translated", - "value": "Skopiowano" + "value": "جارٍ التنزيل…" } }, - "pt-BR": { + "nb": { "stringUnit": { "state": "translated", - "value": "Copiado" + "value": "Laster ned …" } }, - "ru": { + "pt-BR": { "stringUnit": { "state": "translated", - "value": "Скопировано" + "value": "Baixando..." } }, "th": { "stringUnit": { "state": "translated", - "value": "คัดลอกแล้ว" + "value": "กำลังดาวน์โหลด..." } }, "tr": { "stringUnit": { "state": "translated", - "value": "Kopyalandı" + "value": "İndiriliyor..." } }, "uk": { "stringUnit": { "state": "translated", - "value": "Скопійовано" - } - }, - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "已复制" - } - }, - "zh-Hant": { - "stringUnit": { - "state": "translated", - "value": "已複製" + "value": "Завантаження…" } } } }, - "browser.screenshotPage.copied.help": { + "browser.error.cantOpen.title": { "extractionState": "manual", "localizations": { - "ar": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Can't open this page" + } + }, + "ja": { "stringUnit": { "state": "translated", - "value": "تم نسخ لقطة الشاشة إلى الحافظة" + "value": "このページを開けません" } }, - "bs": { + "zh-Hans": { "stringUnit": { "state": "translated", - "value": "Snimak ekrana je kopiran u međuspremnik" + "value": "无法打开此页面" } }, - "da": { + "zh-Hant": { "stringUnit": { "state": "translated", - "value": "Skærmbillede kopieret til udklipsholder" + "value": "無法開啟此頁面" } }, - "de": { + "ko": { "stringUnit": { "state": "translated", - "value": "Screenshot in die Zwischenablage kopiert" + "value": "이 페이지를 열 수 없습니다" } }, - "en": { + "de": { "stringUnit": { "state": "translated", - "value": "Screenshot copied to clipboard" + "value": "Diese Seite kann nicht geöffnet werden" } }, "es": { "stringUnit": { "state": "translated", - "value": "Captura de pantalla copiada al portapapeles" + "value": "No se puede abrir esta página" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Capture d’écran copiée dans le presse-papiers" + "value": "Impossible d'ouvrir cette page" } }, "it": { "stringUnit": { "state": "translated", - "value": "Screenshot copiato negli appunti" + "value": "Impossibile aprire questa pagina" } }, - "ja": { + "da": { "stringUnit": { "state": "translated", - "value": "スクリーンショットをクリップボードにコピーしました" + "value": "Kan ikke åbne denne side" } }, - "km": { + "pl": { "stringUnit": { "state": "translated", - "value": "បានចម្លងរូបថតអេក្រង់ទៅក្តារតម្បៀតខ្ទាស់" + "value": "Nie można otworzyć tej strony" } }, - "ko": { + "ru": { "stringUnit": { "state": "translated", - "value": "스크린샷이 클립보드에 복사됨" + "value": "Не удается открыть эту страницу" } }, - "nb": { + "bs": { "stringUnit": { "state": "translated", - "value": "Skjermbilde kopiert til utklippstavlen" + "value": "Nije moguće otvoriti ovu stranicu" } }, - "pl": { + "ar": { "stringUnit": { "state": "translated", - "value": "Zrzut ekranu skopiowany do schowka" + "value": "لا يمكن فتح هذه الصفحة" } }, - "pt-BR": { + "nb": { "stringUnit": { "state": "translated", - "value": "Captura de tela copiada para a área de transferência" + "value": "Kan ikke åpne denne siden" } }, - "ru": { + "pt-BR": { "stringUnit": { "state": "translated", - "value": "Снимок экрана скопирован в буфер обмена" + "value": "Não foi possível abrir esta página" } }, "th": { "stringUnit": { "state": "translated", - "value": "คัดลอกภาพหน้าจอไปยังคลิปบอร์ดแล้ว" + "value": "ไม่สามารถเปิดหน้านี้ได้" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Ekran görüntüsü panoya kopyalandı" + "value": "Bu sayfa açılamıyor" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Знімок екрана скопійовано до буфера обміну" - } - }, - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "截图已复制到剪贴板" - } - }, - "zh-Hant": { - "stringUnit": { - "state": "translated", - "value": "截圖已複製到剪貼簿" + "value": "Не вдається відкрити цю сторінку" } } } }, - "browser.screenshotSection.instructions": { + "browser.error.cantReach.messageSite": { "extractionState": "manual", "localizations": { - "ar": { + "en": { "stringUnit": { "state": "translated", - "value": "انقر واسحب للتحديد. Esc للإلغاء." + "value": "The site refused to connect. Check that a server is running on this address." } }, - "bs": { + "ja": { "stringUnit": { "state": "translated", - "value": "Kliknite i povucite za odabir. Esc otkazuje." + "value": "サイトに接続できませんでした。このアドレスでサーバーが実行されていることを確認してください。" } }, - "da": { + "zh-Hans": { + "stringUnit": { + "state": "translated", + "value": "网站拒绝了连接。请检查此地址上是否有服务器正在运行。" + } + }, + "zh-Hant": { "stringUnit": { "state": "translated", - "value": "Klik og træk for at vælge. Esc annullerer." + "value": "網站拒絕連線。請確認此位址上有伺服器正在運行。" } }, - "de": { + "ko": { "stringUnit": { "state": "translated", - "value": "Zum Auswählen klicken und ziehen. Esc bricht ab." + "value": "사이트에서 연결을 거부했습니다. 이 주소에서 서버가 실행 중인지 확인하세요." } }, - "en": { + "de": { "stringUnit": { "state": "translated", - "value": "Click and drag to select. Esc cancels." + "value": "Die Website hat die Verbindung verweigert. Überprüfen Sie, ob ein Server unter dieser Adresse läuft." } }, "es": { "stringUnit": { "state": "translated", - "value": "Haz clic y arrastra para seleccionar. Esc cancela." + "value": "El sitio rechazó la conexión. Comprueba que haya un servidor en ejecución en esta dirección." } }, "fr": { "stringUnit": { "state": "translated", - "value": "Cliquez et faites glisser pour sélectionner. Échap annule." + "value": "Le site a refusé la connexion. Vérifiez qu'un serveur est bien en cours d'exécution à cette adresse." } }, "it": { "stringUnit": { "state": "translated", - "value": "Fai clic e trascina per selezionare. Esc annulla." + "value": "Il sito ha rifiutato la connessione. Verifica che un server sia in esecuzione su questo indirizzo." } }, - "ja": { + "da": { "stringUnit": { "state": "translated", - "value": "ドラッグで選択。Escでキャンセル。" + "value": "Siden nægtede forbindelsen. Kontroller at en server kører på denne adresse." } }, - "km": { + "pl": { "stringUnit": { "state": "translated", - "value": "ចុចហើយអូសដើម្បីជ្រើស។ Esc បោះបង់។" + "value": "Serwer odmówił połączenia. Sprawdź, czy pod tym adresem działa serwer." } }, - "ko": { + "ru": { "stringUnit": { "state": "translated", - "value": "선택하려면 클릭하고 드래그하세요. Esc 취소." + "value": "Сайт отклонил подключение. Убедитесь, что сервер запущен по этому адресу." } }, - "nb": { + "bs": { "stringUnit": { "state": "translated", - "value": "Klikk og dra for å velge. Esc avbryter." + "value": "Stranica je odbila vezu. Provjerite da li je server pokrenut na ovoj adresi." } }, - "pl": { + "ar": { "stringUnit": { "state": "translated", - "value": "Kliknij i przeciągnij, aby zaznaczyć. Esc anuluje." + "value": "رفض الموقع الاتصال. تأكد من تشغيل خادم على هذا العنوان." } }, - "pt-BR": { + "nb": { "stringUnit": { "state": "translated", - "value": "Clique e arraste para selecionar. Esc cancela." + "value": "Nettstedet nektet tilkobling. Kontroller at en server kjører på denne adressen." } }, - "ru": { + "pt-BR": { "stringUnit": { "state": "translated", - "value": "Нажмите и перетащите, чтобы выбрать. Esc отменяет." + "value": "O site recusou a conexão. Verifique se há um servidor em execução neste endereço." } }, "th": { "stringUnit": { "state": "translated", - "value": "คลิกแล้วลากเพื่อเลือก กด Esc เพื่อยกเลิก" + "value": "เว็บไซต์ปฏิเสธการเชื่อมต่อ ตรวจสอบว่ามีเซิร์ฟเวอร์ทำงานบนที่อยู่นี้" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Seçmek için tıklayıp sürükleyin. Esc iptal eder." + "value": "Site bağlantıyı reddetti. Bu adreste bir sunucunun çalışıp çalışmadığını kontrol edin." } }, "uk": { "stringUnit": { "state": "translated", - "value": "Клацніть і перетягніть, щоб вибрати. Esc скасовує." - } - }, - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "点击并拖动以选择。按 Esc 取消。" - } - }, - "zh-Hant": { - "stringUnit": { - "state": "translated", - "value": "按一下並拖移以選取。按 Esc 取消。" + "value": "Сайт відмовив у з'єднанні. Перевірте, чи працює сервер за цією адресою." } } } }, - "browser.screenshot.error.captureAreaTooLarge": { - "extractionState": "manual", - "localizations": { - "ar": {"stringUnit": {"state": "needs_review", "value": "The page is too large to capture."}}, - "bs": {"stringUnit": {"state": "needs_review", "value": "The page is too large to capture."}}, - "da": {"stringUnit": {"state": "needs_review", "value": "The page is too large to capture."}}, - "de": {"stringUnit": {"state": "translated", "value": "Die Seite ist zu groß, um sie zu erfassen."}}, - "en": {"stringUnit": {"state": "translated", "value": "The page is too large to capture."}}, - "es": {"stringUnit": {"state": "translated", "value": "La página es demasiado grande para capturarla."}}, - "fr": {"stringUnit": {"state": "translated", "value": "La page est trop grande pour être capturée."}}, - "it": {"stringUnit": {"state": "translated", "value": "La pagina è troppo grande per essere acquisita."}}, - "ja": {"stringUnit": {"state": "translated", "value": "ページが大きすぎるためキャプチャできません。"}}, - "km": {"stringUnit": {"state": "needs_review", "value": "The page is too large to capture."}}, - "ko": {"stringUnit": {"state": "translated", "value": "페이지가 너무 커서 캡처할 수 없습니다."}}, - "nb": {"stringUnit": {"state": "translated", "value": "Siden er for stor til å fanges."}}, - "pl": {"stringUnit": {"state": "needs_review", "value": "The page is too large to capture."}}, - "pt-BR": {"stringUnit": {"state": "translated", "value": "A página é grande demais para capturar."}}, - "ru": {"stringUnit": {"state": "translated", "value": "Страница слишком велика для снимка экрана."}}, - "th": {"stringUnit": {"state": "needs_review", "value": "The page is too large to capture."}}, - "tr": {"stringUnit": {"state": "needs_review", "value": "The page is too large to capture."}}, - "uk": {"stringUnit": {"state": "translated", "value": "Сторінка завелика для знімка екрана."}}, - "zh-Hans": {"stringUnit": {"state": "translated", "value": "页面太大,无法捕获。"}}, - "zh-Hant": {"stringUnit": {"state": "translated", "value": "頁面太大,無法擷取。"}} - } - }, - "browser.screenshot.error.emptySnapshot": { - "extractionState": "manual", - "localizations": { - "ar": {"stringUnit": {"state": "needs_review", "value": "No screenshot was returned."}}, - "bs": {"stringUnit": {"state": "needs_review", "value": "No screenshot was returned."}}, - "da": {"stringUnit": {"state": "needs_review", "value": "No screenshot was returned."}}, - "de": {"stringUnit": {"state": "translated", "value": "Es wurde kein Screenshot zurückgegeben."}}, - "en": {"stringUnit": {"state": "translated", "value": "No screenshot was returned."}}, - "es": {"stringUnit": {"state": "translated", "value": "No se devolvió ninguna captura de pantalla."}}, - "fr": {"stringUnit": {"state": "translated", "value": "Aucune capture d’écran n’a été renvoyée."}}, - "it": {"stringUnit": {"state": "translated", "value": "Non è stato restituito alcuno screenshot."}}, - "ja": {"stringUnit": {"state": "translated", "value": "スクリーンショットが返されませんでした。"}}, - "km": {"stringUnit": {"state": "needs_review", "value": "No screenshot was returned."}}, - "ko": {"stringUnit": {"state": "translated", "value": "스크린샷이 반환되지 않았습니다."}}, - "nb": {"stringUnit": {"state": "translated", "value": "Det ble ikke returnert noe skjermbilde."}}, - "pl": {"stringUnit": {"state": "needs_review", "value": "No screenshot was returned."}}, - "pt-BR": {"stringUnit": {"state": "translated", "value": "Nenhuma captura de tela foi retornada."}}, - "ru": {"stringUnit": {"state": "translated", "value": "Снимок экрана не был возвращён."}}, - "th": {"stringUnit": {"state": "needs_review", "value": "No screenshot was returned."}}, - "tr": {"stringUnit": {"state": "needs_review", "value": "No screenshot was returned."}}, - "uk": {"stringUnit": {"state": "translated", "value": "Знімок екрана не було повернуто."}}, - "zh-Hans": {"stringUnit": {"state": "translated", "value": "未返回屏幕截图。"}}, - "zh-Hant": {"stringUnit": {"state": "translated", "value": "未傳回螢幕截圖。"}} - } - }, - "browser.screenshot.error.invalidImageRepresentation": { - "extractionState": "manual", - "localizations": { - "ar": {"stringUnit": {"state": "needs_review", "value": "The screenshot image could not be encoded."}}, - "bs": {"stringUnit": {"state": "needs_review", "value": "The screenshot image could not be encoded."}}, - "da": {"stringUnit": {"state": "needs_review", "value": "The screenshot image could not be encoded."}}, - "de": {"stringUnit": {"state": "translated", "value": "Das Screenshot-Bild konnte nicht codiert werden."}}, - "en": {"stringUnit": {"state": "translated", "value": "The screenshot image could not be encoded."}}, - "es": {"stringUnit": {"state": "translated", "value": "No se pudo codificar la imagen de la captura de pantalla."}}, - "fr": {"stringUnit": {"state": "translated", "value": "L’image de la capture d’écran n’a pas pu être encodée."}}, - "it": {"stringUnit": {"state": "translated", "value": "Non è stato possibile codificare l’immagine dello screenshot."}}, - "ja": {"stringUnit": {"state": "translated", "value": "スクリーンショット画像をエンコードできませんでした。"}}, - "km": {"stringUnit": {"state": "needs_review", "value": "The screenshot image could not be encoded."}}, - "ko": {"stringUnit": {"state": "translated", "value": "스크린샷 이미지를 인코딩할 수 없습니다."}}, - "nb": {"stringUnit": {"state": "translated", "value": "Skjermbildet kunne ikke kodes."}}, - "pl": {"stringUnit": {"state": "needs_review", "value": "The screenshot image could not be encoded."}}, - "pt-BR": {"stringUnit": {"state": "translated", "value": "Não foi possível codificar a imagem da captura de tela."}}, - "ru": {"stringUnit": {"state": "translated", "value": "Не удалось закодировать изображение снимка экрана."}}, - "th": {"stringUnit": {"state": "needs_review", "value": "The screenshot image could not be encoded."}}, - "tr": {"stringUnit": {"state": "needs_review", "value": "The screenshot image could not be encoded."}}, - "uk": {"stringUnit": {"state": "translated", "value": "Не вдалося закодувати зображення знімка екрана."}}, - "zh-Hans": {"stringUnit": {"state": "translated", "value": "无法编码屏幕截图图像。"}}, - "zh-Hant": {"stringUnit": {"state": "translated", "value": "無法編碼螢幕截圖影像。"}} - } - }, - "browser.screenshot.error.invalidSelection": { - "extractionState": "manual", - "localizations": { - "ar": {"stringUnit": {"state": "needs_review", "value": "The screenshot selection is empty or outside the browser view."}}, - "bs": {"stringUnit": {"state": "needs_review", "value": "The screenshot selection is empty or outside the browser view."}}, - "da": {"stringUnit": {"state": "needs_review", "value": "The screenshot selection is empty or outside the browser view."}}, - "de": {"stringUnit": {"state": "translated", "value": "Die Screenshot-Auswahl ist leer oder liegt außerhalb der Browseransicht."}}, - "en": {"stringUnit": {"state": "translated", "value": "The screenshot selection is empty or outside the browser view."}}, - "es": {"stringUnit": {"state": "translated", "value": "La selección de captura de pantalla está vacía o fuera de la vista del navegador."}}, - "fr": {"stringUnit": {"state": "translated", "value": "La sélection de capture d’écran est vide ou en dehors de la vue du navigateur."}}, - "it": {"stringUnit": {"state": "translated", "value": "La selezione dello screenshot è vuota o fuori dalla vista del browser."}}, - "ja": {"stringUnit": {"state": "translated", "value": "スクリーンショットの選択範囲が空か、ブラウザ表示の外側です。"}}, - "km": {"stringUnit": {"state": "needs_review", "value": "The screenshot selection is empty or outside the browser view."}}, - "ko": {"stringUnit": {"state": "translated", "value": "스크린샷 선택 영역이 비어 있거나 브라우저 보기 밖에 있습니다."}}, - "nb": {"stringUnit": {"state": "translated", "value": "Skjermbildeutvalget er tomt eller utenfor nettleservisningen."}}, - "pl": {"stringUnit": {"state": "needs_review", "value": "The screenshot selection is empty or outside the browser view."}}, - "pt-BR": {"stringUnit": {"state": "translated", "value": "A seleção da captura de tela está vazia ou fora da visualização do navegador."}}, - "ru": {"stringUnit": {"state": "translated", "value": "Область снимка экрана пуста или находится за пределами области просмотра браузера."}}, - "th": {"stringUnit": {"state": "needs_review", "value": "The screenshot selection is empty or outside the browser view."}}, - "tr": {"stringUnit": {"state": "needs_review", "value": "The screenshot selection is empty or outside the browser view."}}, - "uk": {"stringUnit": {"state": "translated", "value": "Область знімка екрана порожня або поза межами подання браузера."}}, - "zh-Hans": {"stringUnit": {"state": "translated", "value": "屏幕截图选择区域为空或位于浏览器视图之外。"}}, - "zh-Hant": {"stringUnit": {"state": "translated", "value": "螢幕截圖選取範圍為空或位於瀏覽器檢視之外。"}} - } - }, - "browser.screenshot.error.pasteboardWriteFailed": { - "extractionState": "manual", - "localizations": { - "ar": {"stringUnit": {"state": "needs_review", "value": "The screenshot could not be written to the clipboard."}}, - "bs": {"stringUnit": {"state": "needs_review", "value": "The screenshot could not be written to the clipboard."}}, - "da": {"stringUnit": {"state": "needs_review", "value": "The screenshot could not be written to the clipboard."}}, - "de": {"stringUnit": {"state": "translated", "value": "Der Screenshot konnte nicht in die Zwischenablage geschrieben werden."}}, - "en": {"stringUnit": {"state": "translated", "value": "The screenshot could not be written to the clipboard."}}, - "es": {"stringUnit": {"state": "translated", "value": "No se pudo escribir la captura de pantalla en el portapapeles."}}, - "fr": {"stringUnit": {"state": "translated", "value": "La capture d’écran n’a pas pu être écrite dans le presse-papiers."}}, - "it": {"stringUnit": {"state": "translated", "value": "Non è stato possibile scrivere lo screenshot negli appunti."}}, - "ja": {"stringUnit": {"state": "translated", "value": "スクリーンショットをクリップボードに書き込めませんでした。"}}, - "km": {"stringUnit": {"state": "needs_review", "value": "The screenshot could not be written to the clipboard."}}, - "ko": {"stringUnit": {"state": "translated", "value": "스크린샷을 클립보드에 쓸 수 없습니다."}}, - "nb": {"stringUnit": {"state": "translated", "value": "Skjermbildet kunne ikke skrives til utklippstavlen."}}, - "pl": {"stringUnit": {"state": "needs_review", "value": "The screenshot could not be written to the clipboard."}}, - "pt-BR": {"stringUnit": {"state": "translated", "value": "Não foi possível gravar a captura de tela na área de transferência."}}, - "ru": {"stringUnit": {"state": "translated", "value": "Не удалось записать снимок экрана в буфер обмена."}}, - "th": {"stringUnit": {"state": "needs_review", "value": "The screenshot could not be written to the clipboard."}}, - "tr": {"stringUnit": {"state": "needs_review", "value": "The screenshot could not be written to the clipboard."}}, - "uk": {"stringUnit": {"state": "translated", "value": "Не вдалося записати знімок екрана до буфера обміну."}}, - "zh-Hans": {"stringUnit": {"state": "translated", "value": "无法将屏幕截图写入剪贴板。"}}, - "zh-Hant": {"stringUnit": {"state": "translated", "value": "無法將螢幕截圖寫入剪貼簿。"}} - } - }, - "browser.screenshot.error.webContentMetricsUnavailable": { - "extractionState": "manual", - "localizations": { - "ar": {"stringUnit": {"state": "needs_review", "value": "The page dimensions could not be read."}}, - "bs": {"stringUnit": {"state": "needs_review", "value": "The page dimensions could not be read."}}, - "da": {"stringUnit": {"state": "needs_review", "value": "The page dimensions could not be read."}}, - "de": {"stringUnit": {"state": "translated", "value": "Die Seitenabmessungen konnten nicht gelesen werden."}}, - "en": {"stringUnit": {"state": "translated", "value": "The page dimensions could not be read."}}, - "es": {"stringUnit": {"state": "translated", "value": "No se pudieron leer las dimensiones de la página."}}, - "fr": {"stringUnit": {"state": "translated", "value": "Les dimensions de la page n’ont pas pu être lues."}}, - "it": {"stringUnit": {"state": "translated", "value": "Non è stato possibile leggere le dimensioni della pagina."}}, - "ja": {"stringUnit": {"state": "translated", "value": "ページの寸法を読み取れませんでした。"}}, - "km": {"stringUnit": {"state": "needs_review", "value": "The page dimensions could not be read."}}, - "ko": {"stringUnit": {"state": "translated", "value": "페이지 크기를 읽을 수 없습니다."}}, - "nb": {"stringUnit": {"state": "translated", "value": "Sidedimensjonene kunne ikke leses."}}, - "pl": {"stringUnit": {"state": "needs_review", "value": "The page dimensions could not be read."}}, - "pt-BR": {"stringUnit": {"state": "translated", "value": "Não foi possível ler as dimensões da página."}}, - "ru": {"stringUnit": {"state": "translated", "value": "Не удалось прочитать размеры страницы."}}, - "th": {"stringUnit": {"state": "needs_review", "value": "The page dimensions could not be read."}}, - "tr": {"stringUnit": {"state": "needs_review", "value": "The page dimensions could not be read."}}, - "uk": {"stringUnit": {"state": "translated", "value": "Не вдалося прочитати розміри сторінки."}}, - "zh-Hans": {"stringUnit": {"state": "translated", "value": "无法读取页面尺寸。"}}, - "zh-Hant": {"stringUnit": {"state": "translated", "value": "無法讀取頁面尺寸。"}} - } - }, - "browser.dialog.pageSays": { + "browser.error.cantReach.messageURL": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "This page says:" + "value": "%@ refused to connect. Check that a server is running on this address." } }, "ja": { "stringUnit": { "state": "translated", - "value": "このページの内容:" + "value": "%@ に接続できませんでした。このアドレスでサーバーが実行されていることを確認してください。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "此页面显示:" + "value": "%@ 拒绝了连接。请检查此地址上是否有服务器正在运行。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "此頁面顯示:" + "value": "%@ 拒絕連線。請確認此位址上有伺服器正在運行。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "이 페이지의 메시지:" + "value": "%@에서 연결을 거부했습니다. 이 주소에서 서버가 실행 중인지 확인하세요." } }, "de": { "stringUnit": { "state": "translated", - "value": "Diese Seite meldet:" + "value": "%@ hat die Verbindung verweigert. Überprüfen Sie, ob ein Server unter dieser Adresse läuft." } }, "es": { "stringUnit": { "state": "translated", - "value": "Esta página dice:" + "value": "%@ rechazó la conexión. Comprueba que haya un servidor en ejecución en esta dirección." } }, "fr": { "stringUnit": { "state": "translated", - "value": "Cette page indique :" + "value": "%@ a refusé la connexion. Vérifiez qu'un serveur est bien en cours d'exécution à cette adresse." } }, "it": { "stringUnit": { "state": "translated", - "value": "Questa pagina dice:" + "value": "%@ ha rifiutato la connessione. Verifica che un server sia in esecuzione su questo indirizzo." } }, "da": { "stringUnit": { "state": "translated", - "value": "Denne side siger:" + "value": "%@ nægtede forbindelsen. Kontroller at en server kører på denne adresse." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Ta strona mówi:" + "value": "%@ odmówił połączenia. Sprawdź, czy pod tym adresem działa serwer." } }, "ru": { "stringUnit": { "state": "translated", - "value": "Сообщение на странице:" + "value": "%@ отклонил подключение. Убедитесь, что сервер запущен по этому адресу." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Ova stranica kaže:" + "value": "%@ je odbio vezu. Provjerite da li je server pokrenut na ovoj adresi." } }, "ar": { "stringUnit": { "state": "translated", - "value": "تقول هذه الصفحة:" + "value": "رفض %@ الاتصال. تأكد من تشغيل خادم على هذا العنوان." } }, "nb": { "stringUnit": { "state": "translated", - "value": "Denne siden sier:" + "value": "%@ nektet tilkobling. Kontroller at en server kjører på denne adressen." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Esta página diz:" + "value": "%@ recusou a conexão. Verifique se há um servidor em execução neste endereço." } }, "th": { "stringUnit": { "state": "translated", - "value": "หน้านี้แจ้งว่า:" + "value": "%@ ปฏิเสธการเชื่อมต่อ ตรวจสอบว่ามีเซิร์ฟเวอร์ทำงานบนที่อยู่นี้" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Bu sayfa diyor ki:" + "value": "%@ bağlantıyı reddetti. Bu adreste bir sunucunun çalışıp çalışmadığını kontrol edin." } }, "uk": { "stringUnit": { "state": "translated", - "value": "Ця сторінка повідомляє:" + "value": "%@ відмовив у з'єднанні. Перевірте, чи працює сервер за цією адресою." } } } }, - "browser.dialog.pageSaysAt": { + "browser.error.cantReach.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "The page at %@ says:" + "value": "Can't reach this page" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ページ %@ のメッセージ:" + "value": "このページに到達できません" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "%@ 页面显示:" + "value": "无法访问此页面" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "%@ 頁面顯示:" + "value": "無法連線至此頁面" } }, "ko": { "stringUnit": { "state": "translated", - "value": "%@ 페이지의 메시지:" + "value": "이 페이지에 연결할 수 없습니다" } }, "de": { "stringUnit": { "state": "translated", - "value": "Die Seite auf %@ meldet:" + "value": "Diese Seite ist nicht erreichbar" } }, "es": { "stringUnit": { "state": "translated", - "value": "La página en %@ dice:" + "value": "No se puede acceder a esta página" } }, "fr": { "stringUnit": { "state": "translated", - "value": "La page à %@ indique :" + "value": "Impossible d'atteindre cette page" } }, "it": { "stringUnit": { "state": "translated", - "value": "La pagina su %@ dice:" + "value": "Impossibile raggiungere questa pagina" } }, "da": { "stringUnit": { "state": "translated", - "value": "Siden på %@ siger:" + "value": "Kan ikke nå denne side" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Strona pod adresem %@ mówi:" + "value": "Nie można uzyskać dostępu do tej strony" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Страница %@ сообщает:" + "value": "Не удается подключиться к странице" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Stranica na %@ kaže:" + "value": "Nije moguće dosegnuti ovu stranicu" } }, "ar": { "stringUnit": { "state": "translated", - "value": "تقول الصفحة في %@:" + "value": "لا يمكن الوصول إلى هذه الصفحة" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Siden på %@ sier:" + "value": "Kan ikke nå denne siden" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "A página em %@ diz:" + "value": "Não foi possível acessar esta página" } }, "th": { "stringUnit": { "state": "translated", - "value": "หน้าที่ %@ แจ้งว่า:" + "value": "ไม่สามารถเข้าถึงหน้านี้ได้" } }, "tr": { "stringUnit": { "state": "translated", - "value": "%@ sayfası diyor ki:" + "value": "Bu sayfaya ulaşılamıyor" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Сторінка %@ повідомляє:" + "value": "Не вдається відкрити цю сторінку" } } } }, - "browser.downloadInProgress": { + "browser.error.checkNetwork": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Download in progress" + "value": "Check your network connection and try again." } }, "ja": { "stringUnit": { "state": "translated", - "value": "ダウンロード中" + "value": "ネットワーク接続を確認してもう一度お試しください。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "下载进行中" + "value": "请检查您的网络连接,然后重试。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "正在下載" + "value": "請檢查您的網路連線後再試一次。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "다운로드 진행 중" + "value": "네트워크 연결을 확인하고 다시 시도하세요." } }, "de": { "stringUnit": { "state": "translated", - "value": "Download läuft" + "value": "Überprüfen Sie Ihre Netzwerkverbindung und versuchen Sie es erneut." } }, "es": { "stringUnit": { "state": "translated", - "value": "Descarga en curso" + "value": "Comprueba tu conexión de red e inténtalo de nuevo." } }, "fr": { "stringUnit": { "state": "translated", - "value": "Téléchargement en cours" + "value": "Vérifiez votre connexion réseau et réessayez." } }, "it": { "stringUnit": { "state": "translated", - "value": "Download in corso" + "value": "Controlla la connessione di rete e riprova." } }, "da": { "stringUnit": { "state": "translated", - "value": "Download i gang" + "value": "Kontroller din netværksforbindelse, og prøv igen." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Pobieranie w toku" + "value": "Sprawdź połączenie sieciowe i spróbuj ponownie." } }, "ru": { "stringUnit": { "state": "translated", - "value": "Загрузка выполняется" + "value": "Проверьте сетевое подключение и повторите попытку." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Preuzimanje u toku" + "value": "Provjerite mrežnu vezu i pokušajte ponovo." } }, "ar": { "stringUnit": { "state": "translated", - "value": "التنزيل قيد التقدم" + "value": "تحقق من اتصال الشبكة وحاول مجددًا." } }, "nb": { "stringUnit": { "state": "translated", - "value": "Nedlasting pågår" + "value": "Kontroller nettverkstilkoblingen og prøv igjen." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Download em andamento" + "value": "Verifique sua conexão de rede e tente novamente." } }, "th": { "stringUnit": { "state": "translated", - "value": "กำลังดาวน์โหลด" + "value": "ตรวจสอบการเชื่อมต่อเครือข่ายแล้วลองอีกครั้ง" } }, "tr": { "stringUnit": { "state": "translated", - "value": "İndirme devam ediyor" + "value": "Ağ bağlantınızı kontrol edip tekrar deneyin." } }, "uk": { "stringUnit": { "state": "translated", - "value": "Завантаження виконується" + "value": "Перевірте підключення до мережі та спробуйте ще раз." } } } }, - "browser.downloading": { + "browser.error.frameLoadInterrupted": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Downloading..." + "value": "Frame load interrupted" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ダウンロード中..." + "value": "フレームの読み込みが中断されました" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "正在下载..." + "value": "页面框架加载中断" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "下載中..." + "value": "頁框載入中斷" } }, "ko": { "stringUnit": { "state": "translated", - "value": "다운로드 중..." + "value": "프레임 로딩이 중단되었습니다" } }, "de": { "stringUnit": { "state": "translated", - "value": "Wird heruntergeladen …" + "value": "Laden des Frames unterbrochen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Descargando..." + "value": "Carga del marco interrumpida" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Téléchargement..." + "value": "Chargement du cadre interrompu" } }, "it": { "stringUnit": { "state": "translated", - "value": "Download in corso..." + "value": "Caricamento del frame interrotto" } }, "da": { "stringUnit": { "state": "translated", - "value": "Downloader…" + "value": "Indlæsning af ramme blev afbrudt" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Pobieranie…" + "value": "Ładowanie ramki zostało przerwane" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Загрузка..." + "value": "Загрузка фрейма прервана" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Preuzimanje..." + "value": "Učitavanje okvira je prekinuto" } }, "ar": { "stringUnit": { "state": "translated", - "value": "جارٍ التنزيل…" + "value": "تم قطع تحميل الإطار" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Laster ned …" + "value": "Innlasting av ramme ble avbrutt" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Baixando..." + "value": "Carregamento do frame interrompido" } }, "th": { "stringUnit": { "state": "translated", - "value": "กำลังดาวน์โหลด..." + "value": "การโหลดเฟรมถูกขัดจังหวะ" } }, "tr": { "stringUnit": { "state": "translated", - "value": "İndiriliyor..." + "value": "Çerçeve yüklemesi kesildi" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Завантаження…" + "value": "Завантаження фрейму перервано" } } } }, - "browser.error.cantOpen.title": { + "browser.externalOpenFailure.copyLink": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Can't open this page" + "value": "Copy Link" } }, "ja": { "stringUnit": { "state": "translated", - "value": "このページを開けません" + "value": "リンクをコピー" + } + } + } + }, + "browser.externalOpenFailure.message": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "cmux could not open this link. You can copy it and open it in another app." + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "cmux はこのリンクを開けませんでした。リンクをコピーして別のアプリで開けます。" + } + } + } + }, + "browser.externalOpenFailure.title": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Cannot Open Link" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "リンクを開けません" + } + } + } + }, + "browser.externalOpenPrompt.message": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "A web page in cmux wants to open a link in another app. You can stay in the browser instead." + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "cmux のウェブページが別のアプリでリンクを開こうとしています。代わりにブラウザに留まることもできます。" + } + } + } + }, + "browser.externalOpenPrompt.openApp": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Open App" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "アプリを開く" + } + } + } + }, + "browser.externalOpenPrompt.stayInBrowser": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Stay in Browser" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "ブラウザに留まる" + } + } + } + }, + "browser.externalOpenPrompt.title": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Open External App?" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "外部アプリを開きますか?" + } + } + } + }, + "browser.error.insecure.message": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "%@ uses plain HTTP, so traffic can be read or modified on the network.\n\nOpen this URL in your default browser, or proceed in cmux." + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "%@ は HTTP 接続を使用しているため、通信内容がネットワーク上で読み取られたり改ざんされる可能性があります。\n\nデフォルトブラウザで開くか、cmux で続行してください。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "无法打开此页面" + "value": "%@ 使用纯 HTTP 连接,网络上的流量可能被读取或修改。\n\n请在默认浏览器中打开此 URL,或在 cmux 中继续访问。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "無法開啟此頁面" + "value": "%@ 使用未加密的 HTTP,網路上的流量可能被讀取或竄改。\n\n在您的預設瀏覽器中開啟此 URL,或在 cmux 中繼續。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "이 페이지를 열 수 없습니다" + "value": "%@은(는) 일반 HTTP를 사용하므로, 네트워크에서 트래픽이 읽히거나 변조될 수 있습니다.\n\n기본 브라우저에서 이 URL을 열거나, cmux에서 계속 진행하세요." } }, "de": { "stringUnit": { "state": "translated", - "value": "Diese Seite kann nicht geöffnet werden" + "value": "%@ verwendet unverschlüsseltes HTTP, daher kann der Datenverkehr im Netzwerk gelesen oder verändert werden.\n\nÖffnen Sie diese URL in Ihrem Standardbrowser oder fahren Sie in cmux fort." } }, "es": { "stringUnit": { "state": "translated", - "value": "No se puede abrir esta página" + "value": "%@ usa HTTP sin cifrar, por lo que el tráfico puede ser leído o modificado en la red.\n\nAbre esta URL en tu navegador predeterminado o continúa en cmux." } }, "fr": { "stringUnit": { "state": "translated", - "value": "Impossible d'ouvrir cette page" + "value": "%@ utilise le protocole HTTP non chiffré, le trafic peut donc être lu ou modifié sur le réseau.\n\nOuvrez cette URL dans votre navigateur par défaut ou continuez dans cmux." } }, "it": { "stringUnit": { "state": "translated", - "value": "Impossibile aprire questa pagina" + "value": "%@ utilizza HTTP non crittografato, quindi il traffico può essere letto o modificato sulla rete.\n\nApri questo URL nel browser predefinito oppure continua in cmux." } }, "da": { "stringUnit": { "state": "translated", - "value": "Kan ikke åbne denne side" + "value": "%@ bruger almindelig HTTP, så trafikken kan læses eller ændres på netværket.\n\nÅbn denne URL i din standardbrowser, eller fortsæt i cmux." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Nie można otworzyć tej strony" + "value": "%@ używa zwykłego HTTP, więc ruch sieciowy może być odczytany lub zmodyfikowany.\n\nOtwórz ten URL w domyślnej przeglądarce lub kontynuuj w cmux." } }, "ru": { "stringUnit": { "state": "translated", - "value": "Не удается открыть эту страницу" + "value": "%@ использует незащищенный протокол HTTP, поэтому трафик может быть перехвачен или изменен в сети.\n\nОткройте этот URL в браузере по умолчанию или продолжите в cmux." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Nije moguće otvoriti ovu stranicu" + "value": "%@ koristi čisti HTTP, pa se promet može čitati ili mijenjati na mreži.\n\nOtvorite ovaj URL u podrazumijevanom pregledniku ili nastavite u cmux." } }, "ar": { "stringUnit": { "state": "translated", - "value": "لا يمكن فتح هذه الصفحة" + "value": "يستخدم %@ بروتوكول HTTP غير مشفر، لذا يمكن قراءة حركة البيانات أو تعديلها على الشبكة.\n\nافتح هذا URL في متصفحك الافتراضي، أو تابع في cmux." } }, "nb": { "stringUnit": { "state": "translated", - "value": "Kan ikke åpne denne siden" + "value": "%@ bruker vanlig HTTP, så trafikk kan leses eller endres på nettverket.\n\nÅpne denne URL-en i standard nettleser, eller fortsett i cmux." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Não foi possível abrir esta página" + "value": "%@ usa HTTP simples, então o tráfego pode ser lido ou modificado na rede.\n\nAbra esta URL no seu navegador padrão ou continue no cmux." } }, "th": { "stringUnit": { "state": "translated", - "value": "ไม่สามารถเปิดหน้านี้ได้" + "value": "%@ ใช้ HTTP แบบธรรมดา ดังนั้นข้อมูลอาจถูกอ่านหรือแก้ไขบนเครือข่ายได้\n\nเปิด URL นี้ในเบราว์เซอร์เริ่มต้น หรือดำเนินการต่อใน cmux" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Bu sayfa açılamıyor" + "value": "%@ düz HTTP kullanıyor, bu nedenle trafik ağda okunabilir veya değiştirilebilir.\n\nBu URL'yi varsayılan tarayıcınızda açın ya da cmux'ta devam edin." } }, "uk": { "stringUnit": { "state": "translated", - "value": "Не вдається відкрити цю сторінку" + "value": "%@ використовує незахищений HTTP, тому трафік може бути прочитаний або змінений у мережі.\n\nВідкрийте цю URL-адресу у стандартному браузері або продовжте в cmux, якщо довіряєте цьому ресурсу." } } } }, - "browser.error.cantReach.messageSite": { + "browser.error.insecure.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "The site refused to connect. Check that a server is running on this address." + "value": "Connection isn't secure" } }, "ja": { "stringUnit": { "state": "translated", - "value": "サイトに接続できませんでした。このアドレスでサーバーが実行されていることを確認してください。" + "value": "接続は安全ではありません" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "网站拒绝了连接。请检查此地址上是否有服务器正在运行。" + "value": "连接不安全" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "網站拒絕連線。請確認此位址上有伺服器正在運行。" + "value": "連線不安全" } }, "ko": { "stringUnit": { "state": "translated", - "value": "사이트에서 연결을 거부했습니다. 이 주소에서 서버가 실행 중인지 확인하세요." + "value": "연결이 안전하지 않습니다" } }, "de": { "stringUnit": { "state": "translated", - "value": "Die Website hat die Verbindung verweigert. Überprüfen Sie, ob ein Server unter dieser Adresse läuft." + "value": "Verbindung ist nicht sicher" } }, "es": { "stringUnit": { "state": "translated", - "value": "El sitio rechazó la conexión. Comprueba que haya un servidor en ejecución en esta dirección." + "value": "La conexión no es segura" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Le site a refusé la connexion. Vérifiez qu'un serveur est bien en cours d'exécution à cette adresse." + "value": "La connexion n'est pas sécurisée" } }, "it": { "stringUnit": { "state": "translated", - "value": "Il sito ha rifiutato la connessione. Verifica che un server sia in esecuzione su questo indirizzo." + "value": "La connessione non è sicura" } }, "da": { "stringUnit": { "state": "translated", - "value": "Siden nægtede forbindelsen. Kontroller at en server kører på denne adresse." + "value": "Forbindelsen er ikke sikker" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Serwer odmówił połączenia. Sprawdź, czy pod tym adresem działa serwer." + "value": "Połączenie nie jest bezpieczne" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Сайт отклонил подключение. Убедитесь, что сервер запущен по этому адресу." + "value": "Подключение не защищено" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Stranica je odbila vezu. Provjerite da li je server pokrenut na ovoj adresi." + "value": "Veza nije sigurna" } }, "ar": { "stringUnit": { "state": "translated", - "value": "رفض الموقع الاتصال. تأكد من تشغيل خادم على هذا العنوان." + "value": "الاتصال غير آمن" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Nettstedet nektet tilkobling. Kontroller at en server kjører på denne adressen." + "value": "Tilkoblingen er ikke sikker" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "O site recusou a conexão. Verifique se há um servidor em execução neste endereço." + "value": "A conexão não é segura" } }, "th": { "stringUnit": { "state": "translated", - "value": "เว็บไซต์ปฏิเสธการเชื่อมต่อ ตรวจสอบว่ามีเซิร์ฟเวอร์ทำงานบนที่อยู่นี้" + "value": "การเชื่อมต่อไม่ปลอดภัย" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Site bağlantıyı reddetti. Bu adreste bir sunucunun çalışıp çalışmadığını kontrol edin." + "value": "Bağlantı güvenli değil" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Сайт відмовив у з'єднанні. Перевірте, чи працює сервер за цією адресою." + "value": "З'єднання незахищене" } } } }, - "browser.error.cantReach.messageURL": { + "browser.error.invalidCertificate": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "%@ refused to connect. Check that a server is running on this address." + "value": "The certificate for this site is invalid." } }, "ja": { "stringUnit": { "state": "translated", - "value": "%@ に接続できませんでした。このアドレスでサーバーが実行されていることを確認してください。" + "value": "このサイトの証明書が無効です。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "%@ 拒绝了连接。请检查此地址上是否有服务器正在运行。" + "value": "此网站的证书无效。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "%@ 拒絕連線。請確認此位址上有伺服器正在運行。" + "value": "此網站的憑證無效。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "%@에서 연결을 거부했습니다. 이 주소에서 서버가 실행 중인지 확인하세요." + "value": "이 사이트의 인증서가 유효하지 않습니다." } }, "de": { "stringUnit": { "state": "translated", - "value": "%@ hat die Verbindung verweigert. Überprüfen Sie, ob ein Server unter dieser Adresse läuft." + "value": "Das Zertifikat für diese Website ist ungültig." } }, "es": { "stringUnit": { "state": "translated", - "value": "%@ rechazó la conexión. Comprueba que haya un servidor en ejecución en esta dirección." + "value": "El certificado de este sitio no es válido." } }, "fr": { "stringUnit": { "state": "translated", - "value": "%@ a refusé la connexion. Vérifiez qu'un serveur est bien en cours d'exécution à cette adresse." + "value": "Le certificat de ce site n'est pas valide." } }, "it": { "stringUnit": { "state": "translated", - "value": "%@ ha rifiutato la connessione. Verifica che un server sia in esecuzione su questo indirizzo." + "value": "Il certificato per questo sito non è valido." } }, "da": { "stringUnit": { "state": "translated", - "value": "%@ nægtede forbindelsen. Kontroller at en server kører på denne adresse." + "value": "Certifikatet for denne side er ugyldigt." } }, "pl": { "stringUnit": { "state": "translated", - "value": "%@ odmówił połączenia. Sprawdź, czy pod tym adresem działa serwer." + "value": "Certyfikat tej strony jest nieprawidłowy." } }, "ru": { "stringUnit": { "state": "translated", - "value": "%@ отклонил подключение. Убедитесь, что сервер запущен по этому адресу." + "value": "Сертификат этого сайта недействителен." } }, "bs": { "stringUnit": { "state": "translated", - "value": "%@ je odbio vezu. Provjerite da li je server pokrenut na ovoj adresi." + "value": "Certifikat za ovu stranicu je nevažeći." } }, "ar": { "stringUnit": { "state": "translated", - "value": "رفض %@ الاتصال. تأكد من تشغيل خادم على هذا العنوان." + "value": "شهادة هذا الموقع غير صالحة." } }, "nb": { "stringUnit": { "state": "translated", - "value": "%@ nektet tilkobling. Kontroller at en server kjører på denne adressen." + "value": "Sertifikatet for dette nettstedet er ugyldig." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "%@ recusou a conexão. Verifique se há um servidor em execução neste endereço." + "value": "O certificado deste site é inválido." } }, "th": { "stringUnit": { "state": "translated", - "value": "%@ ปฏิเสธการเชื่อมต่อ ตรวจสอบว่ามีเซิร์ฟเวอร์ทำงานบนที่อยู่นี้" + "value": "ใบรับรองสำหรับเว็บไซต์นี้ไม่ถูกต้อง" } }, "tr": { "stringUnit": { "state": "translated", - "value": "%@ bağlantıyı reddetti. Bu adreste bir sunucunun çalışıp çalışmadığını kontrol edin." + "value": "Bu sitenin sertifikası geçersiz." } }, "uk": { "stringUnit": { "state": "translated", - "value": "%@ відмовив у з'єднанні. Перевірте, чи працює сервер за цією адресою." + "value": "Сертифікат цього сайту недійсний." } } } }, - "browser.error.cantReach.title": { + "browser.error.noInternet": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Can't reach this page" + "value": "No internet connection" } }, "ja": { "stringUnit": { "state": "translated", - "value": "このページに到達できません" + "value": "インターネット接続がありません" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "无法访问此页面" + "value": "无互联网连接" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "無法連線至此頁面" + "value": "沒有網際網路連線" } }, "ko": { "stringUnit": { "state": "translated", - "value": "이 페이지에 연결할 수 없습니다" + "value": "인터넷에 연결되어 있지 않습니다" } }, "de": { "stringUnit": { "state": "translated", - "value": "Diese Seite ist nicht erreichbar" + "value": "Keine Internetverbindung" } }, "es": { "stringUnit": { "state": "translated", - "value": "No se puede acceder a esta página" + "value": "Sin conexión a internet" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Impossible d'atteindre cette page" + "value": "Aucune connexion Internet" } }, "it": { "stringUnit": { "state": "translated", - "value": "Impossibile raggiungere questa pagina" + "value": "Nessuna connessione a internet" } }, "da": { "stringUnit": { "state": "translated", - "value": "Kan ikke nå denne side" + "value": "Ingen internetforbindelse" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Nie można uzyskać dostępu do tej strony" + "value": "Brak połączenia z internetem" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Не удается подключиться к странице" + "value": "Нет подключения к интернету" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Nije moguće dosegnuti ovu stranicu" + "value": "Nema internetske veze" } }, "ar": { "stringUnit": { "state": "translated", - "value": "لا يمكن الوصول إلى هذه الصفحة" + "value": "لا يوجد اتصال بالإنترنت" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Kan ikke nå denne siden" + "value": "Ingen internettforbindelse" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Não foi possível acessar esta página" + "value": "Sem conexão com a internet" } }, "th": { "stringUnit": { "state": "translated", - "value": "ไม่สามารถเข้าถึงหน้านี้ได้" + "value": "ไม่มีการเชื่อมต่ออินเทอร์เน็ต" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Bu sayfaya ulaşılamıyor" + "value": "İnternet bağlantısı yok" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Не вдається відкрити цю сторінку" + "value": "Немає підключення до інтернету" } } } }, - "browser.error.checkNetwork": { + "browser.error.reload": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Check your network connection and try again." + "value": "Reload" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ネットワーク接続を確認してもう一度お試しください。" + "value": "再読み込み" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "请检查您的网络连接,然后重试。" + "value": "重新加载" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "請檢查您的網路連線後再試一次。" + "value": "重新載入" } }, "ko": { "stringUnit": { "state": "translated", - "value": "네트워크 연결을 확인하고 다시 시도하세요." + "value": "새로고침" } }, "de": { "stringUnit": { "state": "translated", - "value": "Überprüfen Sie Ihre Netzwerkverbindung und versuchen Sie es erneut." + "value": "Neu laden" } }, "es": { "stringUnit": { "state": "translated", - "value": "Comprueba tu conexión de red e inténtalo de nuevo." + "value": "Recargar" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Vérifiez votre connexion réseau et réessayez." + "value": "Recharger" } }, "it": { "stringUnit": { "state": "translated", - "value": "Controlla la connessione di rete e riprova." + "value": "Ricarica" } }, "da": { "stringUnit": { "state": "translated", - "value": "Kontroller din netværksforbindelse, og prøv igen." + "value": "Genindlæs" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Sprawdź połączenie sieciowe i spróbuj ponownie." + "value": "Odśwież" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Проверьте сетевое подключение и повторите попытку." + "value": "Перезагрузить" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Provjerite mrežnu vezu i pokušajte ponovo." + "value": "Ponovo učitaj" } }, "ar": { "stringUnit": { "state": "translated", - "value": "تحقق من اتصال الشبكة وحاول مجددًا." + "value": "إعادة تحميل" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Kontroller nettverkstilkoblingen og prøv igjen." + "value": "Last inn på nytt" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Verifique sua conexão de rede e tente novamente." + "value": "Recarregar" } }, "th": { "stringUnit": { "state": "translated", - "value": "ตรวจสอบการเชื่อมต่อเครือข่ายแล้วลองอีกครั้ง" + "value": "โหลดใหม่" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Ağ bağlantınızı kontrol edip tekrar deneyin." + "value": "Yeniden Yükle" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Перевірте підключення до мережі та спробуйте ще раз." + "value": "Перезавантажити" } } } }, - "browser.error.frameLoadInterrupted": { + "browser.goBack": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Frame load interrupted" + "value": "Go Back" } }, "ja": { "stringUnit": { "state": "translated", - "value": "フレームの読み込みが中断されました" + "value": "戻る" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "页面框架加载中断" + "value": "后退" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "頁框載入中斷" + "value": "上一頁" } }, "ko": { "stringUnit": { "state": "translated", - "value": "프레임 로딩이 중단되었습니다" + "value": "뒤로" } }, "de": { "stringUnit": { "state": "translated", - "value": "Laden des Frames unterbrochen" + "value": "Zurück" } }, "es": { "stringUnit": { "state": "translated", - "value": "Carga del marco interrumpida" + "value": "Retroceder" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Chargement du cadre interrompu" + "value": "Page précédente" } }, "it": { "stringUnit": { "state": "translated", - "value": "Caricamento del frame interrotto" + "value": "Indietro" } }, "da": { "stringUnit": { "state": "translated", - "value": "Indlæsning af ramme blev afbrudt" + "value": "Gå tilbage" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Ładowanie ramki zostało przerwane" + "value": "Wstecz" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Загрузка фрейма прервана" + "value": "Назад" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Učitavanje okvira je prekinuto" + "value": "Nazad" } }, "ar": { "stringUnit": { "state": "translated", - "value": "تم قطع تحميل الإطار" + "value": "رجوع" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Innlasting av ramme ble avbrutt" + "value": "Gå tilbake" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Carregamento do frame interrompido" + "value": "Voltar" } }, "th": { "stringUnit": { "state": "translated", - "value": "การโหลดเฟรมถูกขัดจังหวะ" + "value": "ย้อนกลับ" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Çerçeve yüklemesi kesildi" + "value": "Geri Git" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Завантаження фрейму перервано" + "value": "Назад" } } } }, - "browser.externalOpenFailure.copyLink": { + "browser.goForward": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Copy Link" + "value": "Go Forward" } }, "ja": { "stringUnit": { "state": "translated", - "value": "リンクをコピー" + "value": "進む" } - } - } - }, - "browser.externalOpenFailure.message": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "zh-Hans": { "stringUnit": { "state": "translated", - "value": "cmux could not open this link. You can copy it and open it in another app." + "value": "前进" } }, - "ja": { + "zh-Hant": { "stringUnit": { "state": "translated", - "value": "cmux はこのリンクを開けませんでした。リンクをコピーして別のアプリで開けます。" + "value": "下一頁" } - } - } - }, - "browser.externalOpenFailure.title": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "ko": { "stringUnit": { "state": "translated", - "value": "Cannot Open Link" + "value": "앞으로" } }, - "ja": { + "de": { "stringUnit": { "state": "translated", - "value": "リンクを開けません" + "value": "Vor" } - } - } - }, - "browser.externalOpenPrompt.message": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "es": { "stringUnit": { "state": "translated", - "value": "A web page in cmux wants to open a link in another app. You can stay in the browser instead." + "value": "Avanzar" } }, - "ja": { + "fr": { "stringUnit": { "state": "translated", - "value": "cmux のウェブページが別のアプリでリンクを開こうとしています。代わりにブラウザに留まることもできます。" + "value": "Page suivante" } - } - } - }, - "browser.externalOpenPrompt.openApp": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "it": { "stringUnit": { "state": "translated", - "value": "Open App" + "value": "Avanti" } }, - "ja": { + "da": { "stringUnit": { "state": "translated", - "value": "アプリを開く" + "value": "Gå frem" } - } - } - }, - "browser.externalOpenPrompt.stayInBrowser": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "pl": { "stringUnit": { "state": "translated", - "value": "Stay in Browser" + "value": "Do przodu" } }, - "ja": { + "ru": { "stringUnit": { "state": "translated", - "value": "ブラウザに留まる" + "value": "Вперед" } - } - } - }, - "browser.externalOpenPrompt.title": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "bs": { "stringUnit": { "state": "translated", - "value": "Open External App?" + "value": "Naprijed" } }, - "ja": { + "ar": { "stringUnit": { "state": "translated", - "value": "外部アプリを開きますか?" + "value": "تقدم" } - } - } - }, - "browser.error.insecure.message": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "nb": { "stringUnit": { "state": "translated", - "value": "%@ uses plain HTTP, so traffic can be read or modified on the network.\n\nOpen this URL in your default browser, or proceed in cmux." + "value": "Gå fremover" + } + }, + "pt-BR": { + "stringUnit": { + "state": "translated", + "value": "Avançar" + } + }, + "th": { + "stringUnit": { + "state": "translated", + "value": "ไปข้างหน้า" + } + }, + "tr": { + "stringUnit": { + "state": "translated", + "value": "İleri Git" + } + }, + "uk": { + "stringUnit": { + "state": "translated", + "value": "Вперед" + } + } + } + }, + "browser.goToURL": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "go to URL" } }, "ja": { "stringUnit": { "state": "translated", - "value": "%@ は HTTP 接続を使用しているため、通信内容がネットワーク上で読み取られたり改ざんされる可能性があります。\n\nデフォルトブラウザで開くか、cmux で続行してください。" + "value": "URLに移動" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "%@ 使用纯 HTTP 连接,网络上的流量可能被读取或修改。\n\n请在默认浏览器中打开此 URL,或在 cmux 中继续访问。" + "value": "前往 URL" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "%@ 使用未加密的 HTTP,網路上的流量可能被讀取或竄改。\n\n在您的預設瀏覽器中開啟此 URL,或在 cmux 中繼續。" + "value": "前往 URL" } }, "ko": { "stringUnit": { "state": "translated", - "value": "%@은(는) 일반 HTTP를 사용하므로, 네트워크에서 트래픽이 읽히거나 변조될 수 있습니다.\n\n기본 브라우저에서 이 URL을 열거나, cmux에서 계속 진행하세요." + "value": "URL로 이동" } }, "de": { "stringUnit": { "state": "translated", - "value": "%@ verwendet unverschlüsseltes HTTP, daher kann der Datenverkehr im Netzwerk gelesen oder verändert werden.\n\nÖffnen Sie diese URL in Ihrem Standardbrowser oder fahren Sie in cmux fort." + "value": "URL aufrufen" } }, "es": { "stringUnit": { "state": "translated", - "value": "%@ usa HTTP sin cifrar, por lo que el tráfico puede ser leído o modificado en la red.\n\nAbre esta URL en tu navegador predeterminado o continúa en cmux." + "value": "ir a URL" } }, "fr": { "stringUnit": { "state": "translated", - "value": "%@ utilise le protocole HTTP non chiffré, le trafic peut donc être lu ou modifié sur le réseau.\n\nOuvrez cette URL dans votre navigateur par défaut ou continuez dans cmux." + "value": "accéder à l'URL" } }, "it": { "stringUnit": { "state": "translated", - "value": "%@ utilizza HTTP non crittografato, quindi il traffico può essere letto o modificato sulla rete.\n\nApri questo URL nel browser predefinito oppure continua in cmux." + "value": "vai all'URL" } }, "da": { "stringUnit": { "state": "translated", - "value": "%@ bruger almindelig HTTP, så trafikken kan læses eller ændres på netværket.\n\nÅbn denne URL i din standardbrowser, eller fortsæt i cmux." + "value": "gå til URL" } }, "pl": { "stringUnit": { "state": "translated", - "value": "%@ używa zwykłego HTTP, więc ruch sieciowy może być odczytany lub zmodyfikowany.\n\nOtwórz ten URL w domyślnej przeglądarce lub kontynuuj w cmux." + "value": "przejdź do URL" } }, "ru": { "stringUnit": { "state": "translated", - "value": "%@ использует незащищенный протокол HTTP, поэтому трафик может быть перехвачен или изменен в сети.\n\nОткройте этот URL в браузере по умолчанию или продолжите в cmux." + "value": "перейти по URL" } }, "bs": { "stringUnit": { "state": "translated", - "value": "%@ koristi čisti HTTP, pa se promet može čitati ili mijenjati na mreži.\n\nOtvorite ovaj URL u podrazumijevanom pregledniku ili nastavite u cmux." + "value": "idi na URL" } }, "ar": { "stringUnit": { "state": "translated", - "value": "يستخدم %@ بروتوكول HTTP غير مشفر، لذا يمكن قراءة حركة البيانات أو تعديلها على الشبكة.\n\nافتح هذا URL في متصفحك الافتراضي، أو تابع في cmux." + "value": "انتقل إلى URL" } }, "nb": { "stringUnit": { "state": "translated", - "value": "%@ bruker vanlig HTTP, så trafikk kan leses eller endres på nettverket.\n\nÅpne denne URL-en i standard nettleser, eller fortsett i cmux." + "value": "gå til URL" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "%@ usa HTTP simples, então o tráfego pode ser lido ou modificado na rede.\n\nAbra esta URL no seu navegador padrão ou continue no cmux." + "value": "ir para URL" } }, "th": { "stringUnit": { "state": "translated", - "value": "%@ ใช้ HTTP แบบธรรมดา ดังนั้นข้อมูลอาจถูกอ่านหรือแก้ไขบนเครือข่ายได้\n\nเปิด URL นี้ในเบราว์เซอร์เริ่มต้น หรือดำเนินการต่อใน cmux" + "value": "ไปที่ URL" } }, "tr": { "stringUnit": { "state": "translated", - "value": "%@ düz HTTP kullanıyor, bu nedenle trafik ağda okunabilir veya değiştirilebilir.\n\nBu URL'yi varsayılan tarayıcınızda açın ya da cmux'ta devam edin." + "value": "URL'ye git" } }, "uk": { "stringUnit": { "state": "translated", - "value": "%@ використовує незахищений HTTP, тому трафік може бути прочитаний або змінений у мережі.\n\nВідкрийте цю URL-адресу у стандартному браузері або продовжте в cmux, якщо довіряєте цьому ресурсу." + "value": "перейти за URL" } } } }, - "browser.error.insecure.title": { + "browser.newTab": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Connection isn't secure" + "value": "New tab" } }, "ja": { "stringUnit": { "state": "translated", - "value": "接続は安全ではありません" + "value": "新規タブ" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "连接不安全" + "value": "新建标签页" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "連線不安全" + "value": "新增標籤頁" } }, "ko": { "stringUnit": { "state": "translated", - "value": "연결이 안전하지 않습니다" + "value": "새 탭" } }, "de": { "stringUnit": { "state": "translated", - "value": "Verbindung ist nicht sicher" + "value": "Neuer Tab" } }, "es": { "stringUnit": { "state": "translated", - "value": "La conexión no es segura" + "value": "Nueva pestaña" } }, "fr": { "stringUnit": { "state": "translated", - "value": "La connexion n'est pas sécurisée" + "value": "Nouvel onglet" } }, "it": { "stringUnit": { "state": "translated", - "value": "La connessione non è sicura" + "value": "Nuova scheda" } }, "da": { "stringUnit": { "state": "translated", - "value": "Forbindelsen er ikke sikker" + "value": "Ny fane" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Połączenie nie jest bezpieczne" + "value": "Nowa karta" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Подключение не защищено" + "value": "Новая вкладка" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Veza nije sigurna" + "value": "Novi tab" } }, "ar": { "stringUnit": { "state": "translated", - "value": "الاتصال غير آمن" + "value": "لسان جديد" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Tilkoblingen er ikke sikker" + "value": "Ny fane" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "A conexão não é segura" + "value": "Nova aba" } }, "th": { "stringUnit": { "state": "translated", - "value": "การเชื่อมต่อไม่ปลอดภัย" + "value": "แท็บใหม่" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Bağlantı güvenli değil" + "value": "Yeni sekme" } }, "uk": { "stringUnit": { "state": "translated", - "value": "З'єднання незахищене" + "value": "Нова вкладка" } } } }, - "browser.error.invalidCertificate": { + "browser.openInDefaultBrowser": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "The certificate for this site is invalid." + "value": "Open in Default Browser" } }, "ja": { "stringUnit": { "state": "translated", - "value": "このサイトの証明書が無効です。" + "value": "デフォルトブラウザで開く" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "此网站的证书无效。" + "value": "在默认浏览器中打开" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "此網站的憑證無效。" + "value": "在預設瀏覽器中開啟" } }, "ko": { "stringUnit": { "state": "translated", - "value": "이 사이트의 인증서가 유효하지 않습니다." + "value": "기본 브라우저에서 열기" } }, "de": { "stringUnit": { "state": "translated", - "value": "Das Zertifikat für diese Website ist ungültig." + "value": "Im Standardbrowser öffnen" } }, "es": { "stringUnit": { "state": "translated", - "value": "El certificado de este sitio no es válido." + "value": "Abrir en el navegador predeterminado" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Le certificat de ce site n'est pas valide." + "value": "Ouvrir dans le navigateur par défaut" } }, "it": { "stringUnit": { "state": "translated", - "value": "Il certificato per questo sito non è valido." + "value": "Apri nel browser predefinito" } }, "da": { "stringUnit": { "state": "translated", - "value": "Certifikatet for denne side er ugyldigt." + "value": "Åbn i standardbrowser" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Certyfikat tej strony jest nieprawidłowy." + "value": "Otwórz w domyślnej przeglądarce" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Сертификат этого сайта недействителен." + "value": "Открыть в браузере по умолчанию" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Certifikat za ovu stranicu je nevažeći." + "value": "Otvori u podrazumijevanom pregledniku" } }, "ar": { "stringUnit": { "state": "translated", - "value": "شهادة هذا الموقع غير صالحة." + "value": "فتح في المتصفح الافتراضي" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Sertifikatet for dette nettstedet er ugyldig." + "value": "Åpne i standard nettleser" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "O certificado deste site é inválido." + "value": "Abrir no Navegador Padrão" } }, "th": { "stringUnit": { "state": "translated", - "value": "ใบรับรองสำหรับเว็บไซต์นี้ไม่ถูกต้อง" + "value": "เปิดในเบราว์เซอร์เริ่มต้น" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Bu sitenin sertifikası geçersiz." + "value": "Varsayılan Tarayıcıda Aç" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Сертифікат цього сайту недійсний." + "value": "Відкрити у стандартному браузері" } } } }, - "browser.error.noInternet": { + "browser.popup.loadingTitle": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "No internet connection" + "value": "Loading…" } }, "ja": { "stringUnit": { "state": "translated", - "value": "インターネット接続がありません" + "value": "読み込み中…" + } + }, + "uk": { + "stringUnit": { + "state": "translated", + "value": "Завантаження…" + } + }, + "ko": { + "stringUnit": { + "state": "translated", + "value": "로딩 중…" + } + } + } + }, + "browser.proceedInCmux": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Proceed in cmux" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "cmux で続行" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "无互联网连接" + "value": "在 cmux 中继续" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "沒有網際網路連線" + "value": "在 cmux 中繼續" } }, "ko": { "stringUnit": { "state": "translated", - "value": "인터넷에 연결되어 있지 않습니다" + "value": "cmux에서 계속" } }, "de": { "stringUnit": { "state": "translated", - "value": "Keine Internetverbindung" + "value": "In cmux fortfahren" } }, "es": { "stringUnit": { "state": "translated", - "value": "Sin conexión a internet" + "value": "Continuar en cmux" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Aucune connexion Internet" + "value": "Continuer dans cmux" } }, "it": { "stringUnit": { "state": "translated", - "value": "Nessuna connessione a internet" + "value": "Continua in cmux" } }, "da": { "stringUnit": { "state": "translated", - "value": "Ingen internetforbindelse" + "value": "Fortsæt i cmux" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Brak połączenia z internetem" + "value": "Kontynuuj w cmux" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Нет подключения к интернету" + "value": "Продолжить в cmux" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Nema internetske veze" + "value": "Nastavi u cmux" } }, "ar": { "stringUnit": { "state": "translated", - "value": "لا يوجد اتصال بالإنترنت" + "value": "المتابعة في cmux" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Ingen internettforbindelse" + "value": "Fortsett i cmux" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Sem conexão com a internet" + "value": "Continuar no cmux" } }, "th": { "stringUnit": { "state": "translated", - "value": "ไม่มีการเชื่อมต่ออินเทอร์เน็ต" + "value": "ดำเนินการต่อใน cmux" } }, "tr": { "stringUnit": { "state": "translated", - "value": "İnternet bağlantısı yok" + "value": "cmux'ta devam et" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Немає підключення до інтернету" + "value": "Продовжити в cmux" } } } }, - "browser.error.reload": { + "browser.reload": { "extractionState": "manual", "localizations": { "en": { @@ -13704,5682 +13532,5858 @@ } } }, - "browser.goBack": { + "browser.reactGrab": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Go Back" + "value": "Inject React Grab" } }, "ja": { "stringUnit": { "state": "translated", - "value": "戻る" + "value": "React Grabを注入" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "后退" + "value": "注入 React Grab" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "上一頁" + "value": "注入 React Grab" } }, "ko": { "stringUnit": { "state": "translated", - "value": "뒤로" + "value": "React Grab 주입" } }, "de": { "stringUnit": { "state": "translated", - "value": "Zurück" + "value": "React Grab einfügen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Retroceder" + "value": "Inyectar React Grab" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Page précédente" + "value": "Injecter React Grab" + } + } + } + }, + "browser.search.placeholder": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Search" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "検索" + } + }, + "zh-Hans": { + "stringUnit": { + "state": "translated", + "value": "搜索" + } + }, + "zh-Hant": { + "stringUnit": { + "state": "translated", + "value": "搜尋" + } + }, + "ko": { + "stringUnit": { + "state": "translated", + "value": "검색" + } + }, + "de": { + "stringUnit": { + "state": "translated", + "value": "Suchen" + } + }, + "es": { + "stringUnit": { + "state": "translated", + "value": "Buscar" + } + }, + "fr": { + "stringUnit": { + "state": "translated", + "value": "Rechercher" } }, "it": { "stringUnit": { "state": "translated", - "value": "Indietro" + "value": "Cerca" } }, "da": { "stringUnit": { "state": "translated", - "value": "Gå tilbage" + "value": "Søg" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Wstecz" + "value": "Szukaj" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Назад" + "value": "Поиск" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Nazad" + "value": "Pretraži" } }, "ar": { "stringUnit": { "state": "translated", - "value": "رجوع" + "value": "بحث" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Gå tilbake" + "value": "Søk" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Voltar" + "value": "Pesquisar" } }, "th": { "stringUnit": { "state": "translated", - "value": "ย้อนกลับ" + "value": "ค้นหา" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Geri Git" + "value": "Ara" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Назад" + "value": "Пошук" } } } }, - "browser.goForward": { + "browser.stop": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Go Forward" + "value": "Stop" } }, "ja": { "stringUnit": { "state": "translated", - "value": "進む" + "value": "停止" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "前进" + "value": "停止" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "下一頁" + "value": "停止" } }, "ko": { "stringUnit": { "state": "translated", - "value": "앞으로" + "value": "중단" } }, "de": { "stringUnit": { "state": "translated", - "value": "Vor" + "value": "Stopp" } }, "es": { "stringUnit": { "state": "translated", - "value": "Avanzar" + "value": "Detener" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Page suivante" + "value": "Arrêter" } }, "it": { "stringUnit": { "state": "translated", - "value": "Avanti" + "value": "Interrompi" } }, "da": { "stringUnit": { "state": "translated", - "value": "Gå frem" + "value": "Stop" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Do przodu" + "value": "Zatrzymaj" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Вперед" + "value": "Стоп" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Naprijed" + "value": "Zaustavi" } }, "ar": { "stringUnit": { "state": "translated", - "value": "تقدم" + "value": "إيقاف" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Gå fremover" + "value": "Stopp" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Avançar" + "value": "Parar" } }, "th": { "stringUnit": { "state": "translated", - "value": "ไปข้างหน้า" + "value": "หยุด" } }, "tr": { "stringUnit": { "state": "translated", - "value": "İleri Git" + "value": "Durdur" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Вперед" + "value": "Зупинити" } } } }, - "browser.goToURL": { + "browser.switchToTab": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "go to URL" + "value": "Switch to tab" } }, "ja": { "stringUnit": { "state": "translated", - "value": "URLに移動" + "value": "タブに切替" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "前往 URL" + "value": "切换到标签页" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "前往 URL" + "value": "切換至標籤頁" } }, "ko": { "stringUnit": { "state": "translated", - "value": "URL로 이동" + "value": "탭으로 전환" } }, "de": { "stringUnit": { "state": "translated", - "value": "URL aufrufen" + "value": "Zum Tab wechseln" } }, "es": { "stringUnit": { "state": "translated", - "value": "ir a URL" + "value": "Cambiar a pestaña" } }, "fr": { "stringUnit": { "state": "translated", - "value": "accéder à l'URL" + "value": "Basculer vers l'onglet" } }, "it": { "stringUnit": { "state": "translated", - "value": "vai all'URL" + "value": "Passa alla scheda" } }, "da": { "stringUnit": { "state": "translated", - "value": "gå til URL" + "value": "Skift til fane" } }, "pl": { "stringUnit": { "state": "translated", - "value": "przejdź do URL" + "value": "Przełącz na kartę" } }, "ru": { "stringUnit": { "state": "translated", - "value": "перейти по URL" + "value": "Перейти к вкладке" } }, "bs": { "stringUnit": { "state": "translated", - "value": "idi na URL" + "value": "Prebaci se na tab" } }, "ar": { "stringUnit": { "state": "translated", - "value": "انتقل إلى URL" + "value": "التبديل إلى اللسان" } }, "nb": { "stringUnit": { "state": "translated", - "value": "gå til URL" + "value": "Bytt til fane" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "ir para URL" + "value": "Alternar para aba" } }, "th": { "stringUnit": { "state": "translated", - "value": "ไปที่ URL" + "value": "สลับไปยังแท็บ" } }, "tr": { "stringUnit": { "state": "translated", - "value": "URL'ye git" + "value": "Sekmeye geç" } }, "uk": { "stringUnit": { "state": "translated", - "value": "перейти за URL" + "value": "Перейти до вкладки" } } } }, - "browser.newTab": { + "browser.toggleDevTools": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "New tab" + "value": "Toggle Developer Tools" } }, "ja": { "stringUnit": { "state": "translated", - "value": "新規タブ" + "value": "デベロッパツールを切替" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "新建标签页" + "value": "切换开发者工具" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "新增標籤頁" + "value": "切換開發者工具" } }, "ko": { "stringUnit": { "state": "translated", - "value": "새 탭" + "value": "개발자 도구 전환" } }, "de": { "stringUnit": { "state": "translated", - "value": "Neuer Tab" + "value": "Entwicklerwerkzeuge ein-/ausblenden" } }, "es": { "stringUnit": { "state": "translated", - "value": "Nueva pestaña" + "value": "Alternar herramientas de desarrollo" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Nouvel onglet" + "value": "Afficher/masquer les outils de développement" } }, "it": { "stringUnit": { "state": "translated", - "value": "Nuova scheda" + "value": "Attiva/Disattiva Strumenti sviluppatore" } }, "da": { "stringUnit": { "state": "translated", - "value": "Ny fane" + "value": "Slå udviklerværktøjer til/fra" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Nowa karta" + "value": "Przełącz narzędzia deweloperskie" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Новая вкладка" + "value": "Инструменты разработчика" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Novi tab" + "value": "Prebaci razvojne alate" } }, "ar": { "stringUnit": { "state": "translated", - "value": "لسان جديد" + "value": "تبديل أدوات المطور" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Ny fane" + "value": "Slå utviklerverktøy av/på" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Nova aba" + "value": "Alternar Ferramentas do Desenvolvedor" } }, "th": { "stringUnit": { "state": "translated", - "value": "แท็บใหม่" + "value": "สลับเครื่องมือนักพัฒนา" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Yeni sekme" + "value": "Geliştirici Araçlarını Aç/Kapat" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Нова вкладка" + "value": "Перемкнути інструменти розробника" } } } }, - "browser.openInDefaultBrowser": { + "cli.install.adminRequired": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Open in Default Browser" + "value": "Administrator privileges were required to write to /usr/local/bin." } }, "ja": { "stringUnit": { "state": "translated", - "value": "デフォルトブラウザで開く" + "value": "/usr/local/binへの書き込みに管理者権限が必要でした。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "在默认浏览器中打开" + "value": "写入 /usr/local/bin 需要管理员权限。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "在預設瀏覽器中開啟" + "value": "寫入 /usr/local/bin 需要管理者權限。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "기본 브라우저에서 열기" + "value": "/usr/local/bin에 기록하기 위해 관리자 권한이 필요합니다." } }, "de": { "stringUnit": { "state": "translated", - "value": "Im Standardbrowser öffnen" + "value": "Zum Schreiben in /usr/local/bin waren Administratorrechte erforderlich." } }, "es": { "stringUnit": { "state": "translated", - "value": "Abrir en el navegador predeterminado" + "value": "Se requirieron privilegios de administrador para escribir en /usr/local/bin." } }, "fr": { "stringUnit": { "state": "translated", - "value": "Ouvrir dans le navigateur par défaut" + "value": "Des privilèges d'administrateur étaient nécessaires pour écrire dans /usr/local/bin." } }, "it": { "stringUnit": { "state": "translated", - "value": "Apri nel browser predefinito" + "value": "Sono stati richiesti i privilegi di amministratore per scrivere in /usr/local/bin." } }, "da": { "stringUnit": { "state": "translated", - "value": "Åbn i standardbrowser" + "value": "Administratorrettigheder var nødvendige for at skrive til /usr/local/bin." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Otwórz w domyślnej przeglądarce" + "value": "Do zapisu w /usr/local/bin wymagane były uprawnienia administratora." } }, "ru": { "stringUnit": { "state": "translated", - "value": "Открыть в браузере по умолчанию" + "value": "Для записи в /usr/local/bin потребовались права администратора." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Otvori u podrazumijevanom pregledniku" + "value": "Potrebne su administratorske privilegije za pisanje u /usr/local/bin." } }, "ar": { "stringUnit": { "state": "translated", - "value": "فتح في المتصفح الافتراضي" + "value": "كانت صلاحيات المسؤول مطلوبة للكتابة في /usr/local/bin." } }, "nb": { "stringUnit": { "state": "translated", - "value": "Åpne i standard nettleser" + "value": "Administratorrettigheter var nødvendig for å skrive til /usr/local/bin." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Abrir no Navegador Padrão" + "value": "Privilégios de administrador foram necessários para gravar em /usr/local/bin." } }, "th": { "stringUnit": { "state": "translated", - "value": "เปิดในเบราว์เซอร์เริ่มต้น" + "value": "ต้องใช้สิทธิ์ผู้ดูแลระบบเพื่อเขียนไปยัง /usr/local/bin" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Varsayılan Tarayıcıda Aç" + "value": "/usr/local/bin dizinine yazmak için yönetici ayrıcalıkları gerekiyordu." } }, "uk": { "stringUnit": { "state": "translated", - "value": "Відкрити у стандартному браузері" + "value": "Для запису в /usr/local/bin потрібні права адміністратора." } } } }, - "browser.popup.loadingTitle": { + "cli.install.symlinkCreated": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Loading…" + "value": "Created symlink:\n\n%1$@ -> %2$@" } }, "ja": { "stringUnit": { "state": "translated", - "value": "読み込み中…" + "value": "シンボリックリンクを作成しました:\n\n%1$@ -> %2$@" } }, - "uk": { + "zh-Hans": { "stringUnit": { "state": "translated", - "value": "Завантаження…" + "value": "已创建符号链接:\n\n%1$@ -> %2$@" } }, - "ko": { + "zh-Hant": { "stringUnit": { "state": "translated", - "value": "로딩 중…" + "value": "已建立符號連結:\n\n%1$@ -> %2$@" } - } - } - }, - "browser.proceedInCmux": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "ko": { "stringUnit": { "state": "translated", - "value": "Proceed in cmux" + "value": "심볼릭 링크 생성 완료:\n\n%1$@ -> %2$@" } }, - "ja": { + "de": { "stringUnit": { "state": "translated", - "value": "cmux で続行" + "value": "Symbolische Verknüpfung erstellt:\n\n%1$@ -> %2$@" } }, - "zh-Hans": { + "es": { "stringUnit": { "state": "translated", - "value": "在 cmux 中继续" + "value": "Enlace simbólico creado:\n\n%1$@ -> %2$@" } }, - "zh-Hant": { + "fr": { "stringUnit": { "state": "translated", - "value": "在 cmux 中繼續" - } - }, - "ko": { - "stringUnit": { - "state": "translated", - "value": "cmux에서 계속" - } - }, - "de": { - "stringUnit": { - "state": "translated", - "value": "In cmux fortfahren" - } - }, - "es": { - "stringUnit": { - "state": "translated", - "value": "Continuar en cmux" - } - }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "Continuer dans cmux" + "value": "Lien symbolique créé :\n\n%1$@ -> %2$@" } }, "it": { "stringUnit": { "state": "translated", - "value": "Continua in cmux" + "value": "Collegamento simbolico creato:\n\n%1$@ -> %2$@" } }, "da": { "stringUnit": { "state": "translated", - "value": "Fortsæt i cmux" + "value": "Symbolsk link oprettet:\n%1$@ -> %2$@" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Kontynuuj w cmux" + "value": "Utworzono dowiązanie symboliczne:\n\n%1$@ -> %2$@" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Продолжить в cmux" + "value": "Создана символическая ссылка:\n\n%1$@ -> %2$@" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Nastavi u cmux" + "value": "Kreirana simbolička veza:\n\n%1$@ -> %2$@" } }, "ar": { "stringUnit": { "state": "translated", - "value": "المتابعة في cmux" + "value": "تم إنشاء رابط رمزي:\n\n%1$@ -> %2$@" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Fortsett i cmux" + "value": "Opprettet symbolsk lenke:\n\n%1$@ -> %2$@" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Continuar no cmux" + "value": "Link simbólico criado:\n\n%1$@ -> %2$@" } }, "th": { "stringUnit": { "state": "translated", - "value": "ดำเนินการต่อใน cmux" + "value": "สร้างลิงก์สัญลักษณ์แล้ว:\n\n%1$@ -> %2$@" } }, "tr": { "stringUnit": { "state": "translated", - "value": "cmux'ta devam et" + "value": "Sembolik bağ oluşturuldu:\n\n%1$@ -> %2$@" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Продовжити в cmux" + "value": "Створено символічне посилання:\n\n%1$@ -> %2$@" } } } }, - "browser.reload": { + "cli.installFailed": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Reload" + "value": "Couldn't Install cmux CLI" } }, "ja": { "stringUnit": { "state": "translated", - "value": "再読み込み" + "value": "cmux CLI をインストールできませんでした" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "重新加载" + "value": "无法安装 cmux CLI" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "重新載入" + "value": "無法安裝 cmux CLI" } }, "ko": { "stringUnit": { "state": "translated", - "value": "새로고침" + "value": "cmux CLI를 설치할 수 없습니다" } }, "de": { "stringUnit": { "state": "translated", - "value": "Neu laden" + "value": "cmux CLI konnte nicht installiert werden" } }, "es": { "stringUnit": { "state": "translated", - "value": "Recargar" + "value": "No se pudo instalar la CLI de cmux" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Recharger" + "value": "Impossible d'installer la CLI cmux" } }, "it": { "stringUnit": { "state": "translated", - "value": "Ricarica" + "value": "Impossibile installare la CLI di cmux" } }, "da": { "stringUnit": { "state": "translated", - "value": "Genindlæs" + "value": "Kunne ikke installere cmux CLI" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Odśwież" + "value": "Nie udało się zainstalować CLI cmux" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Перезагрузить" + "value": "Не удалось установить cmux CLI" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Ponovo učitaj" + "value": "Nije moguće instalirati cmux CLI" } }, "ar": { "stringUnit": { "state": "translated", - "value": "إعادة تحميل" + "value": "تعذر تثبيت واجهة أوامر cmux" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Last inn på nytt" + "value": "Kunne ikke installere cmux CLI" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Recarregar" + "value": "Não Foi Possível Instalar o CLI do cmux" } }, "th": { "stringUnit": { "state": "translated", - "value": "โหลดใหม่" + "value": "ไม่สามารถติดตั้ง cmux CLI ได้" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Yeniden Yükle" + "value": "cmux CLI Yüklenemedi" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Перезавантажити" - } - } - } - }, - "browser.reactGrab": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Inject React Grab" - } - }, - "ja": { - "stringUnit": { - "state": "translated", - "value": "React Grabを注入" - } - }, - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "注入 React Grab" - } - }, - "zh-Hant": { - "stringUnit": { - "state": "translated", - "value": "注入 React Grab" - } - }, - "ko": { - "stringUnit": { - "state": "translated", - "value": "React Grab 주입" - } - }, - "de": { - "stringUnit": { - "state": "translated", - "value": "React Grab einfügen" - } - }, - "es": { - "stringUnit": { - "state": "translated", - "value": "Inyectar React Grab" - } - }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "Injecter React Grab" + "value": "Не вдалося встановити cmux CLI" } } } }, - "browser.search.placeholder": { + "cli.installed": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Search" + "value": "cmux CLI Installed" } }, "ja": { "stringUnit": { "state": "translated", - "value": "検索" + "value": "cmux CLI がインストールされました" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "搜索" + "value": "cmux CLI 已安装" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "搜尋" + "value": "cmux CLI 已安裝" } }, "ko": { "stringUnit": { "state": "translated", - "value": "검색" + "value": "cmux CLI 설치 완료" } }, "de": { "stringUnit": { "state": "translated", - "value": "Suchen" + "value": "cmux CLI installiert" } }, "es": { "stringUnit": { "state": "translated", - "value": "Buscar" + "value": "CLI de cmux instalada" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Rechercher" + "value": "CLI cmux installée" } }, "it": { "stringUnit": { "state": "translated", - "value": "Cerca" + "value": "CLI di cmux installata" } }, "da": { "stringUnit": { "state": "translated", - "value": "Søg" + "value": "cmux CLI installeret" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Szukaj" + "value": "CLI cmux zainstalowane" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Поиск" + "value": "cmux CLI установлен" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Pretraži" + "value": "cmux CLI instaliran" } }, "ar": { "stringUnit": { "state": "translated", - "value": "بحث" + "value": "تم تثبيت واجهة أوامر cmux" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Søk" + "value": "cmux CLI installert" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Pesquisar" + "value": "CLI do cmux Instalado" } }, "th": { "stringUnit": { "state": "translated", - "value": "ค้นหา" + "value": "ติดตั้ง cmux CLI แล้ว" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Ara" + "value": "cmux CLI Yüklendi" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Пошук" + "value": "cmux CLI встановлено" } } } }, - "browser.stop": { + "cli.uninstall.adminRequired": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Stop" + "value": "Administrator privileges were required to modify /usr/local/bin." } }, "ja": { "stringUnit": { "state": "translated", - "value": "停止" + "value": "/usr/local/binの変更に管理者権限が必要でした。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "停止" + "value": "修改 /usr/local/bin 需要管理员权限。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "停止" + "value": "修改 /usr/local/bin 需要管理者權限。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "중단" + "value": "/usr/local/bin을 수정하기 위해 관리자 권한이 필요합니다." } }, "de": { "stringUnit": { "state": "translated", - "value": "Stopp" + "value": "Zum Ändern von /usr/local/bin waren Administratorrechte erforderlich." } }, "es": { "stringUnit": { "state": "translated", - "value": "Detener" + "value": "Se requirieron privilegios de administrador para modificar /usr/local/bin." } }, "fr": { "stringUnit": { "state": "translated", - "value": "Arrêter" + "value": "Des privilèges d'administrateur étaient nécessaires pour modifier /usr/local/bin." } }, "it": { "stringUnit": { "state": "translated", - "value": "Interrompi" + "value": "Sono stati richiesti i privilegi di amministratore per modificare /usr/local/bin." } }, "da": { "stringUnit": { "state": "translated", - "value": "Stop" + "value": "Administratorrettigheder var nødvendige for at ændre /usr/local/bin." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Zatrzymaj" + "value": "Do modyfikacji /usr/local/bin wymagane były uprawnienia administratora." } }, "ru": { "stringUnit": { "state": "translated", - "value": "Стоп" + "value": "Для изменения /usr/local/bin потребовались права администратора." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Zaustavi" + "value": "Potrebne su administratorske privilegije za izmjenu /usr/local/bin." } }, "ar": { "stringUnit": { "state": "translated", - "value": "إيقاف" + "value": "كانت صلاحيات المسؤول مطلوبة لتعديل /usr/local/bin." } }, "nb": { "stringUnit": { "state": "translated", - "value": "Stopp" + "value": "Administratorrettigheter var nødvendig for å endre /usr/local/bin." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Parar" + "value": "Privilégios de administrador foram necessários para modificar /usr/local/bin." } }, "th": { "stringUnit": { "state": "translated", - "value": "หยุด" + "value": "ต้องใช้สิทธิ์ผู้ดูแลระบบเพื่อแก้ไข /usr/local/bin" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Durdur" + "value": "/usr/local/bin dizinini değiştirmek için yönetici ayrıcalıkları gerekiyordu." } }, "uk": { "stringUnit": { "state": "translated", - "value": "Зупинити" + "value": "Для зміни /usr/local/bin потрібні права адміністратора." } } } }, - "browser.switchToTab": { + "cli.uninstall.notFound": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Switch to tab" + "value": "No cmux CLI symlink was found at %@." } }, "ja": { "stringUnit": { "state": "translated", - "value": "タブに切替" + "value": "%@にcmux CLIのシンボリックリンクが見つかりませんでした。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "切换到标签页" + "value": "在 %@ 处未找到 cmux CLI 符号链接。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "切換至標籤頁" + "value": "在 %@ 找不到 cmux CLI 的符號連結。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "탭으로 전환" + "value": "%@에서 cmux CLI 심볼릭 링크를 찾을 수 없습니다." } }, "de": { "stringUnit": { "state": "translated", - "value": "Zum Tab wechseln" + "value": "Es wurde keine symbolische Verknüpfung für cmux CLI unter %@ gefunden." } }, "es": { "stringUnit": { "state": "translated", - "value": "Cambiar a pestaña" + "value": "No se encontró ningún enlace simbólico de la CLI de cmux en %@." } }, "fr": { "stringUnit": { "state": "translated", - "value": "Basculer vers l'onglet" + "value": "Aucun lien symbolique de la CLI cmux n'a été trouvé à l'emplacement %@." } }, "it": { "stringUnit": { "state": "translated", - "value": "Passa alla scheda" + "value": "Nessun collegamento simbolico della CLI di cmux trovato in %@." } }, "da": { "stringUnit": { "state": "translated", - "value": "Skift til fane" + "value": "Intet cmux CLI symbolsk link blev fundet på %@." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Przełącz na kartę" + "value": "Nie znaleziono dowiązania symbolicznego CLI cmux pod adresem %@." } }, "ru": { "stringUnit": { "state": "translated", - "value": "Перейти к вкладке" + "value": "Символическая ссылка cmux CLI не найдена по пути %@." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Prebaci se na tab" + "value": "Simbolička veza cmux CLI nije pronađena na %@." } }, "ar": { "stringUnit": { "state": "translated", - "value": "التبديل إلى اللسان" + "value": "لم يتم العثور على رابط رمزي لواجهة أوامر cmux في %@." } }, "nb": { "stringUnit": { "state": "translated", - "value": "Bytt til fane" + "value": "Ingen cmux CLI-symbolsk lenke ble funnet på %@." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Alternar para aba" + "value": "Nenhum link simbólico do CLI do cmux foi encontrado em %@." } }, "th": { "stringUnit": { "state": "translated", - "value": "สลับไปยังแท็บ" + "value": "ไม่พบลิงก์สัญลักษณ์ cmux CLI ที่ %@" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Sekmeye geç" + "value": "%@ konumunda cmux CLI sembolik bağı bulunamadı." } }, "uk": { "stringUnit": { "state": "translated", - "value": "Перейти до вкладки" + "value": "Символічне посилання cmux CLI не знайдено за адресою %@." } } } }, - "browser.toggleDevTools": { + "cli.uninstall.removed": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Toggle Developer Tools" + "value": "Removed %@." } }, "ja": { "stringUnit": { "state": "translated", - "value": "デベロッパツールを切替" + "value": "%@を削除しました。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "切换开发者工具" + "value": "已移除 %@。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "切換開發者工具" + "value": "已移除 %@。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "개발자 도구 전환" + "value": "%@을(를) 제거했습니다." } }, "de": { "stringUnit": { "state": "translated", - "value": "Entwicklerwerkzeuge ein-/ausblenden" + "value": "%@ wurde entfernt." } }, "es": { "stringUnit": { "state": "translated", - "value": "Alternar herramientas de desarrollo" + "value": "Se eliminó %@." } }, "fr": { "stringUnit": { "state": "translated", - "value": "Afficher/masquer les outils de développement" + "value": "%@ a été supprimé." } }, "it": { "stringUnit": { "state": "translated", - "value": "Attiva/Disattiva Strumenti sviluppatore" + "value": "Rimosso %@." } }, "da": { "stringUnit": { "state": "translated", - "value": "Slå udviklerværktøjer til/fra" + "value": "Fjernede %@." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Przełącz narzędzia deweloperskie" + "value": "Usunięto %@." } }, "ru": { "stringUnit": { "state": "translated", - "value": "Инструменты разработчика" + "value": "Удалено: %@." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Prebaci razvojne alate" + "value": "Uklonjeno %@." } }, "ar": { "stringUnit": { "state": "translated", - "value": "تبديل أدوات المطور" + "value": "تمت إزالة %@." } }, "nb": { "stringUnit": { "state": "translated", - "value": "Slå utviklerverktøy av/på" + "value": "Fjernet %@." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Alternar Ferramentas do Desenvolvedor" + "value": "%@ removido." } }, "th": { "stringUnit": { "state": "translated", - "value": "สลับเครื่องมือนักพัฒนา" + "value": "ลบ %@ แล้ว" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Geliştirici Araçlarını Aç/Kapat" + "value": "%@ kaldırıldı." } }, "uk": { "stringUnit": { "state": "translated", - "value": "Перемкнути інструменти розробника" + "value": "Видалено %@." } } } }, - "cli.install.adminRequired": { + "cli.uninstallFailed": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Administrator privileges were required to write to /usr/local/bin." + "value": "Couldn't Uninstall cmux CLI" } }, "ja": { "stringUnit": { "state": "translated", - "value": "/usr/local/binへの書き込みに管理者権限が必要でした。" + "value": "cmux CLI をアンインストールできませんでした" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "写入 /usr/local/bin 需要管理员权限。" + "value": "无法卸载 cmux CLI" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "寫入 /usr/local/bin 需要管理者權限。" + "value": "無法解除安裝 cmux CLI" } }, "ko": { "stringUnit": { "state": "translated", - "value": "/usr/local/bin에 기록하기 위해 관리자 권한이 필요합니다." + "value": "cmux CLI를 제거할 수 없습니다" } }, "de": { "stringUnit": { "state": "translated", - "value": "Zum Schreiben in /usr/local/bin waren Administratorrechte erforderlich." + "value": "cmux CLI konnte nicht deinstalliert werden" } }, "es": { "stringUnit": { "state": "translated", - "value": "Se requirieron privilegios de administrador para escribir en /usr/local/bin." + "value": "No se pudo desinstalar la CLI de cmux" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Des privilèges d'administrateur étaient nécessaires pour écrire dans /usr/local/bin." + "value": "Impossible de désinstaller la CLI cmux" } }, "it": { "stringUnit": { "state": "translated", - "value": "Sono stati richiesti i privilegi di amministratore per scrivere in /usr/local/bin." + "value": "Impossibile disinstallare la CLI di cmux" } }, "da": { "stringUnit": { "state": "translated", - "value": "Administratorrettigheder var nødvendige for at skrive til /usr/local/bin." + "value": "Kunne ikke afinstallere cmux CLI" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Do zapisu w /usr/local/bin wymagane były uprawnienia administratora." + "value": "Nie udało się odinstalować CLI cmux" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Для записи в /usr/local/bin потребовались права администратора." + "value": "Не удалось удалить cmux CLI" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Potrebne su administratorske privilegije za pisanje u /usr/local/bin." + "value": "Nije moguće deinstalirati cmux CLI" } }, "ar": { "stringUnit": { "state": "translated", - "value": "كانت صلاحيات المسؤول مطلوبة للكتابة في /usr/local/bin." + "value": "تعذر إلغاء تثبيت واجهة أوامر cmux" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Administratorrettigheter var nødvendig for å skrive til /usr/local/bin." + "value": "Kunne ikke avinstallere cmux CLI" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Privilégios de administrador foram necessários para gravar em /usr/local/bin." + "value": "Não Foi Possível Desinstalar o CLI do cmux" } }, "th": { "stringUnit": { "state": "translated", - "value": "ต้องใช้สิทธิ์ผู้ดูแลระบบเพื่อเขียนไปยัง /usr/local/bin" + "value": "ไม่สามารถถอนการติดตั้ง cmux CLI ได้" } }, "tr": { "stringUnit": { "state": "translated", - "value": "/usr/local/bin dizinine yazmak için yönetici ayrıcalıkları gerekiyordu." + "value": "cmux CLI Kaldırılamadı" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Для запису в /usr/local/bin потрібні права адміністратора." + "value": "Не вдалося видалити cmux CLI" } } } }, - "cli.install.symlinkCreated": { + "cli.uninstalled": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Created symlink:\n\n%1$@ -> %2$@" + "value": "cmux CLI Uninstalled" } }, "ja": { "stringUnit": { "state": "translated", - "value": "シンボリックリンクを作成しました:\n\n%1$@ -> %2$@" + "value": "cmux CLI がアンインストールされました" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "已创建符号链接:\n\n%1$@ -> %2$@" + "value": "cmux CLI 已卸载" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "已建立符號連結:\n\n%1$@ -> %2$@" + "value": "cmux CLI 已解除安裝" } }, "ko": { "stringUnit": { "state": "translated", - "value": "심볼릭 링크 생성 완료:\n\n%1$@ -> %2$@" + "value": "cmux CLI 제거 완료" } }, "de": { "stringUnit": { "state": "translated", - "value": "Symbolische Verknüpfung erstellt:\n\n%1$@ -> %2$@" + "value": "cmux CLI deinstalliert" } }, "es": { "stringUnit": { "state": "translated", - "value": "Enlace simbólico creado:\n\n%1$@ -> %2$@" + "value": "CLI de cmux desinstalada" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Lien symbolique créé :\n\n%1$@ -> %2$@" + "value": "CLI cmux désinstallée" } }, "it": { "stringUnit": { "state": "translated", - "value": "Collegamento simbolico creato:\n\n%1$@ -> %2$@" + "value": "CLI di cmux disinstallata" } }, "da": { "stringUnit": { "state": "translated", - "value": "Symbolsk link oprettet:\n%1$@ -> %2$@" + "value": "cmux CLI afinstalleret" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Utworzono dowiązanie symboliczne:\n\n%1$@ -> %2$@" + "value": "CLI cmux odinstalowane" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Создана символическая ссылка:\n\n%1$@ -> %2$@" + "value": "cmux CLI удален" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Kreirana simbolička veza:\n\n%1$@ -> %2$@" + "value": "cmux CLI deinstaliran" } }, "ar": { "stringUnit": { "state": "translated", - "value": "تم إنشاء رابط رمزي:\n\n%1$@ -> %2$@" + "value": "تم إلغاء تثبيت واجهة أوامر cmux" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Opprettet symbolsk lenke:\n\n%1$@ -> %2$@" + "value": "cmux CLI avinstallert" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Link simbólico criado:\n\n%1$@ -> %2$@" + "value": "CLI do cmux Desinstalado" } }, "th": { "stringUnit": { "state": "translated", - "value": "สร้างลิงก์สัญลักษณ์แล้ว:\n\n%1$@ -> %2$@" + "value": "ถอนการติดตั้ง cmux CLI แล้ว" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Sembolik bağ oluşturuldu:\n\n%1$@ -> %2$@" + "value": "cmux CLI Kaldırıldı" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Створено символічне посилання:\n\n%1$@ -> %2$@" + "value": "cmux CLI видалено" } } } }, - "cli.installFailed": { + "command.applyUpdateIfAvailable.subtitle": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Couldn't Install cmux CLI" + "value": "Global" } }, "ja": { "stringUnit": { "state": "translated", - "value": "cmux CLI をインストールできませんでした" + "value": "グローバル" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "无法安装 cmux CLI" + "value": "全局" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "無法安裝 cmux CLI" + "value": "全域" } }, "ko": { "stringUnit": { "state": "translated", - "value": "cmux CLI를 설치할 수 없습니다" + "value": "전역" } }, "de": { "stringUnit": { "state": "translated", - "value": "cmux CLI konnte nicht installiert werden" + "value": "Global" } }, "es": { "stringUnit": { "state": "translated", - "value": "No se pudo instalar la CLI de cmux" + "value": "Global" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Impossible d'installer la CLI cmux" + "value": "Général" } }, "it": { "stringUnit": { "state": "translated", - "value": "Impossibile installare la CLI di cmux" + "value": "Globale" } }, "da": { "stringUnit": { "state": "translated", - "value": "Kunne ikke installere cmux CLI" + "value": "Globalt" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Nie udało się zainstalować CLI cmux" + "value": "Globalne" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Не удалось установить cmux CLI" + "value": "Глобальные" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Nije moguće instalirati cmux CLI" + "value": "Globalno" } }, "ar": { "stringUnit": { "state": "translated", - "value": "تعذر تثبيت واجهة أوامر cmux" + "value": "عام" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Kunne ikke installere cmux CLI" + "value": "Globalt" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Não Foi Possível Instalar o CLI do cmux" + "value": "Global" } }, "th": { "stringUnit": { "state": "translated", - "value": "ไม่สามารถติดตั้ง cmux CLI ได้" + "value": "ทั่วไป" } }, "tr": { "stringUnit": { "state": "translated", - "value": "cmux CLI Yüklenemedi" + "value": "Genel" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Не вдалося встановити cmux CLI" + "value": "Глобальна" } } } }, - "cli.installed": { + "command.applyUpdateIfAvailable.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "cmux CLI Installed" + "value": "Apply Update (If Available)" } }, "ja": { "stringUnit": { "state": "translated", - "value": "cmux CLI がインストールされました" + "value": "アップデートを適用(利用可能な場合)" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "cmux CLI 已安装" + "value": "应用更新(如果可用)" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "cmux CLI 已安裝" + "value": "套用更新(如果有的話)" } }, "ko": { "stringUnit": { "state": "translated", - "value": "cmux CLI 설치 완료" + "value": "업데이트 적용 (사용 가능한 경우)" } }, "de": { "stringUnit": { "state": "translated", - "value": "cmux CLI installiert" + "value": "Update anwenden (falls verfügbar)" } }, "es": { "stringUnit": { "state": "translated", - "value": "CLI de cmux instalada" + "value": "Aplicar actualización (si está disponible)" } }, "fr": { "stringUnit": { "state": "translated", - "value": "CLI cmux installée" + "value": "Appliquer la mise à jour (si disponible)" } }, "it": { "stringUnit": { "state": "translated", - "value": "CLI di cmux installata" + "value": "Applica aggiornamento (se disponibile)" } }, "da": { "stringUnit": { "state": "translated", - "value": "cmux CLI installeret" + "value": "Anvend opdatering (hvis tilgængelig)" } }, "pl": { "stringUnit": { "state": "translated", - "value": "CLI cmux zainstalowane" + "value": "Zastosuj aktualizację (jeśli dostępna)" } }, "ru": { "stringUnit": { "state": "translated", - "value": "cmux CLI установлен" + "value": "Применить обновление (если доступно)" } }, "bs": { "stringUnit": { "state": "translated", - "value": "cmux CLI instaliran" + "value": "Primijeni ažuriranje (ako je dostupno)" } }, "ar": { "stringUnit": { "state": "translated", - "value": "تم تثبيت واجهة أوامر cmux" + "value": "تطبيق التحديث (إن توفر)" } }, "nb": { "stringUnit": { "state": "translated", - "value": "cmux CLI installert" + "value": "Installer oppdatering (hvis tilgjengelig)" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "CLI do cmux Instalado" + "value": "Aplicar Atualização (Se Disponível)" } }, "th": { "stringUnit": { "state": "translated", - "value": "ติดตั้ง cmux CLI แล้ว" + "value": "ติดตั้งอัปเดต (ถ้ามี)" } }, "tr": { "stringUnit": { "state": "translated", - "value": "cmux CLI Yüklendi" + "value": "Güncellemeyi Uygula (Varsa)" } }, "uk": { "stringUnit": { "state": "translated", - "value": "cmux CLI встановлено" + "value": "Застосувати оновлення (якщо доступне)" } } } }, - "cli.uninstall.adminRequired": { + "command.attemptUpdate.subtitle": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Administrator privileges were required to modify /usr/local/bin." + "value": "Global" } }, "ja": { "stringUnit": { "state": "translated", - "value": "/usr/local/binの変更に管理者権限が必要でした。" + "value": "グローバル" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "修改 /usr/local/bin 需要管理员权限。" + "value": "全局" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "修改 /usr/local/bin 需要管理者權限。" + "value": "全域" } }, "ko": { "stringUnit": { "state": "translated", - "value": "/usr/local/bin을 수정하기 위해 관리자 권한이 필요합니다." + "value": "전역" } }, "de": { "stringUnit": { "state": "translated", - "value": "Zum Ändern von /usr/local/bin waren Administratorrechte erforderlich." + "value": "Global" } }, "es": { "stringUnit": { "state": "translated", - "value": "Se requirieron privilegios de administrador para modificar /usr/local/bin." + "value": "Global" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Des privilèges d'administrateur étaient nécessaires pour modifier /usr/local/bin." + "value": "Général" } }, "it": { "stringUnit": { "state": "translated", - "value": "Sono stati richiesti i privilegi di amministratore per modificare /usr/local/bin." + "value": "Globale" } }, "da": { "stringUnit": { "state": "translated", - "value": "Administratorrettigheder var nødvendige for at ændre /usr/local/bin." + "value": "Globalt" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Do modyfikacji /usr/local/bin wymagane były uprawnienia administratora." + "value": "Globalne" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Для изменения /usr/local/bin потребовались права администратора." + "value": "Глобальные" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Potrebne su administratorske privilegije za izmjenu /usr/local/bin." + "value": "Globalno" } }, "ar": { "stringUnit": { "state": "translated", - "value": "كانت صلاحيات المسؤول مطلوبة لتعديل /usr/local/bin." + "value": "عام" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Administratorrettigheter var nødvendig for å endre /usr/local/bin." + "value": "Globalt" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Privilégios de administrador foram necessários para modificar /usr/local/bin." + "value": "Global" } }, "th": { "stringUnit": { "state": "translated", - "value": "ต้องใช้สิทธิ์ผู้ดูแลระบบเพื่อแก้ไข /usr/local/bin" + "value": "ทั่วไป" } }, "tr": { "stringUnit": { "state": "translated", - "value": "/usr/local/bin dizinini değiştirmek için yönetici ayrıcalıkları gerekiyordu." + "value": "Genel" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Для зміни /usr/local/bin потрібні права адміністратора." + "value": "Глобальна" } } } }, - "cli.uninstall.notFound": { + "command.attemptUpdate.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "No cmux CLI symlink was found at %@." + "value": "Attempt Update" } }, "ja": { "stringUnit": { "state": "translated", - "value": "%@にcmux CLIのシンボリックリンクが見つかりませんでした。" + "value": "アップデートを試行" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "在 %@ 处未找到 cmux CLI 符号链接。" + "value": "尝试更新" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "在 %@ 找不到 cmux CLI 的符號連結。" + "value": "嘗試更新" } }, "ko": { "stringUnit": { "state": "translated", - "value": "%@에서 cmux CLI 심볼릭 링크를 찾을 수 없습니다." + "value": "업데이트 시도" } }, "de": { "stringUnit": { "state": "translated", - "value": "Es wurde keine symbolische Verknüpfung für cmux CLI unter %@ gefunden." + "value": "Update versuchen" } }, "es": { "stringUnit": { "state": "translated", - "value": "No se encontró ningún enlace simbólico de la CLI de cmux en %@." + "value": "Intentar actualización" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Aucun lien symbolique de la CLI cmux n'a été trouvé à l'emplacement %@." + "value": "Tenter la mise à jour" } }, "it": { "stringUnit": { "state": "translated", - "value": "Nessun collegamento simbolico della CLI di cmux trovato in %@." + "value": "Tenta aggiornamento" } }, "da": { "stringUnit": { "state": "translated", - "value": "Intet cmux CLI symbolsk link blev fundet på %@." + "value": "Forsøg opdatering" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Nie znaleziono dowiązania symbolicznego CLI cmux pod adresem %@." + "value": "Spróbuj zaktualizować" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Символическая ссылка cmux CLI не найдена по пути %@." + "value": "Попытаться обновить" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Simbolička veza cmux CLI nije pronađena na %@." + "value": "Pokušaj ažuriranje" } }, "ar": { "stringUnit": { "state": "translated", - "value": "لم يتم العثور على رابط رمزي لواجهة أوامر cmux في %@." + "value": "محاولة التحديث" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Ingen cmux CLI-symbolsk lenke ble funnet på %@." + "value": "Forsøk oppdatering" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Nenhum link simbólico do CLI do cmux foi encontrado em %@." + "value": "Tentar Atualização" } }, "th": { "stringUnit": { "state": "translated", - "value": "ไม่พบลิงก์สัญลักษณ์ cmux CLI ที่ %@" + "value": "ลองอัปเดต" } }, "tr": { "stringUnit": { "state": "translated", - "value": "%@ konumunda cmux CLI sembolik bağı bulunamadı." + "value": "Güncellemeyi Dene" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Символічне посилання cmux CLI не знайдено за адресою %@." + "value": "Спробувати оновити" } } } }, - "cli.uninstall.removed": { + "command.browserBack.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Removed %@." + "value": "Back" } }, "ja": { "stringUnit": { "state": "translated", - "value": "%@を削除しました。" + "value": "戻る" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "已移除 %@。" + "value": "后退" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "已移除 %@。" + "value": "上一頁" } }, "ko": { "stringUnit": { "state": "translated", - "value": "%@을(를) 제거했습니다." + "value": "뒤로" } }, "de": { "stringUnit": { "state": "translated", - "value": "%@ wurde entfernt." + "value": "Zurück" } }, "es": { "stringUnit": { "state": "translated", - "value": "Se eliminó %@." + "value": "Atrás" } }, "fr": { "stringUnit": { "state": "translated", - "value": "%@ a été supprimé." + "value": "Précédent" } }, "it": { "stringUnit": { "state": "translated", - "value": "Rimosso %@." + "value": "Indietro" } }, "da": { "stringUnit": { "state": "translated", - "value": "Fjernede %@." + "value": "Tilbage" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Usunięto %@." + "value": "Wstecz" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Удалено: %@." + "value": "Назад" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Uklonjeno %@." + "value": "Nazad" } }, "ar": { "stringUnit": { "state": "translated", - "value": "تمت إزالة %@." + "value": "رجوع" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Fjernet %@." + "value": "Tilbake" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "%@ removido." + "value": "Voltar" } }, "th": { "stringUnit": { "state": "translated", - "value": "ลบ %@ แล้ว" + "value": "ย้อนกลับ" } }, "tr": { "stringUnit": { "state": "translated", - "value": "%@ kaldırıldı." + "value": "Geri" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Видалено %@." + "value": "Назад" } } } }, - "cli.uninstallFailed": { + "command.browserClearHistory.subtitle": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Couldn't Uninstall cmux CLI" + "value": "Browser" } }, "ja": { "stringUnit": { "state": "translated", - "value": "cmux CLI をアンインストールできませんでした" + "value": "ブラウザ" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "无法卸载 cmux CLI" + "value": "浏览器" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "無法解除安裝 cmux CLI" + "value": "瀏覽器" } }, "ko": { "stringUnit": { "state": "translated", - "value": "cmux CLI를 제거할 수 없습니다" + "value": "브라우저" } }, "de": { "stringUnit": { "state": "translated", - "value": "cmux CLI konnte nicht deinstalliert werden" + "value": "Browser" } }, "es": { "stringUnit": { "state": "translated", - "value": "No se pudo desinstalar la CLI de cmux" + "value": "Navegador" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Impossible de désinstaller la CLI cmux" + "value": "Navigateur" } }, "it": { "stringUnit": { "state": "translated", - "value": "Impossibile disinstallare la CLI di cmux" + "value": "Browser" } }, "da": { "stringUnit": { "state": "translated", - "value": "Kunne ikke afinstallere cmux CLI" + "value": "Browser" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Nie udało się odinstalować CLI cmux" + "value": "Przeglądarka" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Не удалось удалить cmux CLI" + "value": "Браузер" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Nije moguće deinstalirati cmux CLI" + "value": "Preglednik" } }, "ar": { "stringUnit": { "state": "translated", - "value": "تعذر إلغاء تثبيت واجهة أوامر cmux" + "value": "المتصفح" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Kunne ikke avinstallere cmux CLI" + "value": "Nettleser" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Não Foi Possível Desinstalar o CLI do cmux" + "value": "Navegador" } }, "th": { "stringUnit": { "state": "translated", - "value": "ไม่สามารถถอนการติดตั้ง cmux CLI ได้" + "value": "เบราว์เซอร์" } }, "tr": { "stringUnit": { "state": "translated", - "value": "cmux CLI Kaldırılamadı" + "value": "Tarayıcı" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Не вдалося видалити cmux CLI" + "value": "Браузер" } } } }, - "cli.uninstalled": { + "command.browserClearHistory.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "cmux CLI Uninstalled" + "value": "Clear Browser History" } }, "ja": { "stringUnit": { "state": "translated", - "value": "cmux CLI がアンインストールされました" + "value": "ブラウザ履歴をクリア" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "cmux CLI 已卸载" + "value": "清除浏览器历史记录" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "cmux CLI 已解除安裝" + "value": "清除瀏覽記錄" } }, "ko": { "stringUnit": { "state": "translated", - "value": "cmux CLI 제거 완료" + "value": "브라우저 기록 지우기" } }, "de": { "stringUnit": { "state": "translated", - "value": "cmux CLI deinstalliert" + "value": "Browserverlauf löschen" } }, "es": { "stringUnit": { "state": "translated", - "value": "CLI de cmux desinstalada" + "value": "Borrar historial del navegador" } }, "fr": { "stringUnit": { "state": "translated", - "value": "CLI cmux désinstallée" + "value": "Effacer l'historique du navigateur" } }, "it": { "stringUnit": { "state": "translated", - "value": "CLI di cmux disinstallata" + "value": "Cancella cronologia browser" } }, "da": { "stringUnit": { "state": "translated", - "value": "cmux CLI afinstalleret" + "value": "Ryd browserhistorik" } }, "pl": { "stringUnit": { "state": "translated", - "value": "CLI cmux odinstalowane" + "value": "Wyczyść historię przeglądarki" } }, "ru": { "stringUnit": { "state": "translated", - "value": "cmux CLI удален" + "value": "Очистить историю браузера" } }, "bs": { "stringUnit": { "state": "translated", - "value": "cmux CLI deinstaliran" + "value": "Obriši historiju preglednika" } }, "ar": { "stringUnit": { "state": "translated", - "value": "تم إلغاء تثبيت واجهة أوامر cmux" + "value": "مسح سجل المتصفح" } }, "nb": { "stringUnit": { "state": "translated", - "value": "cmux CLI avinstallert" + "value": "Tøm nettleserhistorikk" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "CLI do cmux Desinstalado" + "value": "Limpar Histórico do Navegador" } }, "th": { "stringUnit": { "state": "translated", - "value": "ถอนการติดตั้ง cmux CLI แล้ว" + "value": "ล้างประวัติเบราว์เซอร์" } }, "tr": { "stringUnit": { "state": "translated", - "value": "cmux CLI Kaldırıldı" + "value": "Tarayıcı Geçmişini Temizle" } }, "uk": { "stringUnit": { "state": "translated", - "value": "cmux CLI видалено" + "value": "Очистити історію браузера" } } } }, - "command.applyUpdateIfAvailable.subtitle": { + "command.browserConsole.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Global" + "value": "Show JavaScript Console" } }, "ja": { "stringUnit": { "state": "translated", - "value": "グローバル" + "value": "JavaScriptコンソールを表示" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "全局" + "value": "显示 JavaScript 控制台" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "全域" + "value": "顯示 JavaScript 主控台" } }, "ko": { "stringUnit": { "state": "translated", - "value": "전역" + "value": "JavaScript 콘솔 표시" } }, "de": { "stringUnit": { "state": "translated", - "value": "Global" + "value": "JavaScript-Konsole anzeigen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Global" + "value": "Mostrar consola de JavaScript" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Général" + "value": "Afficher la console JavaScript" } }, "it": { "stringUnit": { "state": "translated", - "value": "Globale" + "value": "Mostra console JavaScript" } }, "da": { "stringUnit": { "state": "translated", - "value": "Globalt" + "value": "Vis JavaScript-konsol" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Globalne" + "value": "Pokaż konsolę JavaScript" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Глобальные" + "value": "Показать консоль JavaScript" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Globalno" + "value": "Prikaži JavaScript konzolu" } }, "ar": { "stringUnit": { "state": "translated", - "value": "عام" + "value": "عرض وحدة تحكم JavaScript" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Globalt" + "value": "Vis JavaScript-konsoll" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Global" + "value": "Mostrar Console JavaScript" } }, "th": { "stringUnit": { "state": "translated", - "value": "ทั่วไป" + "value": "แสดงคอนโซล JavaScript" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Genel" + "value": "JavaScript Konsolunu Göster" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Глобальна" + "value": "Показати консоль JavaScript" } } } }, - "command.applyUpdateIfAvailable.title": { + "command.browserDuplicateRight.subtitle": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Apply Update (If Available)" + "value": "Browser Layout" } }, "ja": { "stringUnit": { "state": "translated", - "value": "アップデートを適用(利用可能な場合)" + "value": "ブラウザレイアウト" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "应用更新(如果可用)" + "value": "浏览器布局" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "套用更新(如果有的話)" + "value": "瀏覽器版面" } }, "ko": { "stringUnit": { "state": "translated", - "value": "업데이트 적용 (사용 가능한 경우)" + "value": "브라우저 레이아웃" } }, "de": { "stringUnit": { "state": "translated", - "value": "Update anwenden (falls verfügbar)" + "value": "Browser-Layout" } }, "es": { "stringUnit": { "state": "translated", - "value": "Aplicar actualización (si está disponible)" + "value": "Disposición del navegador" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Appliquer la mise à jour (si disponible)" + "value": "Disposition du navigateur" } }, "it": { "stringUnit": { "state": "translated", - "value": "Applica aggiornamento (se disponibile)" + "value": "Layout browser" } }, "da": { "stringUnit": { "state": "translated", - "value": "Anvend opdatering (hvis tilgængelig)" + "value": "Browserlayout" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Zastosuj aktualizację (jeśli dostępna)" + "value": "Układ przeglądarki" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Применить обновление (если доступно)" + "value": "Макет браузера" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Primijeni ažuriranje (ako je dostupno)" + "value": "Raspored preglednika" } }, "ar": { "stringUnit": { "state": "translated", - "value": "تطبيق التحديث (إن توفر)" + "value": "تخطيط المتصفح" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Installer oppdatering (hvis tilgjengelig)" + "value": "Nettleseroppsett" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Aplicar Atualização (Se Disponível)" + "value": "Layout do Navegador" } }, "th": { "stringUnit": { "state": "translated", - "value": "ติดตั้งอัปเดต (ถ้ามี)" + "value": "เค้าโครงเบราว์เซอร์" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Güncellemeyi Uygula (Varsa)" + "value": "Tarayıcı Düzeni" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Застосувати оновлення (якщо доступне)" + "value": "Макет браузера" } } } }, - "command.attemptUpdate.subtitle": { + "command.browserDuplicateRight.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Global" + "value": "Duplicate Browser to the Right" } }, "ja": { "stringUnit": { "state": "translated", - "value": "グローバル" + "value": "ブラウザを右に複製" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "全局" + "value": "向右复制浏览器" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "全域" + "value": "將瀏覽器複製到右側" } }, "ko": { "stringUnit": { "state": "translated", - "value": "전역" + "value": "브라우저를 오른쪽으로 복제" } }, "de": { "stringUnit": { "state": "translated", - "value": "Global" + "value": "Browser nach rechts duplizieren" } }, "es": { "stringUnit": { "state": "translated", - "value": "Global" + "value": "Duplicar navegador a la derecha" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Général" + "value": "Dupliquer le navigateur à droite" } }, "it": { "stringUnit": { "state": "translated", - "value": "Globale" + "value": "Duplica browser a destra" } }, "da": { "stringUnit": { "state": "translated", - "value": "Globalt" + "value": "Dupliker browser til højre" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Globalne" + "value": "Duplikuj przeglądarkę na prawo" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Глобальные" + "value": "Дублировать браузер вправо" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Globalno" + "value": "Dupliciraj preglednik desno" } }, "ar": { "stringUnit": { "state": "translated", - "value": "عام" + "value": "نسخ المتصفح إلى اليمين" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Globalt" + "value": "Dupliser nettleser til høyre" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Global" + "value": "Duplicar Navegador à Direita" } }, "th": { "stringUnit": { "state": "translated", - "value": "ทั่วไป" + "value": "ทำซ้ำเบราว์เซอร์ไปทางขวา" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Genel" + "value": "Tarayıcıyı Sağa Çoğalt" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Глобальна" + "value": "Дублювати браузер праворуч" } } } }, - "command.attemptUpdate.title": { + "command.browserFocusAddressBar.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Attempt Update" + "value": "Focus Address Bar" } }, "ja": { "stringUnit": { "state": "translated", - "value": "アップデートを試行" + "value": "アドレスバーにフォーカス" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "尝试更新" + "value": "聚焦地址栏" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "嘗試更新" + "value": "聚焦網址列" } }, "ko": { "stringUnit": { "state": "translated", - "value": "업데이트 시도" + "value": "주소 표시줄 포커스" } }, "de": { "stringUnit": { "state": "translated", - "value": "Update versuchen" + "value": "Adressleiste fokussieren" } }, "es": { "stringUnit": { "state": "translated", - "value": "Intentar actualización" + "value": "Enfocar barra de direcciones" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Tenter la mise à jour" + "value": "Activer la barre d'adresse" } }, "it": { "stringUnit": { "state": "translated", - "value": "Tenta aggiornamento" + "value": "Porta il focus sulla barra degli indirizzi" } }, "da": { "stringUnit": { "state": "translated", - "value": "Forsøg opdatering" + "value": "Fokuser adresselinjen" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Spróbuj zaktualizować" + "value": "Ustaw fokus na pasku adresu" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Попытаться обновить" + "value": "Перейти к адресной строке" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Pokušaj ažuriranje" + "value": "Fokusiraj adresnu traku" } }, "ar": { "stringUnit": { "state": "translated", - "value": "محاولة التحديث" + "value": "التركيز على شريط العنوان" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Forsøk oppdatering" + "value": "Fokuser adressefeltet" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Tentar Atualização" + "value": "Focar na Barra de Endereço" } }, "th": { "stringUnit": { "state": "translated", - "value": "ลองอัปเดต" + "value": "โฟกัสแถบที่อยู่" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Güncellemeyi Dene" + "value": "Adres Çubuğuna Odaklan" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Спробувати оновити" + "value": "Фокус на адресному рядку" } } } }, - "command.browserBack.title": { + "command.browserForward.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Back" + "value": "Forward" } }, "ja": { "stringUnit": { "state": "translated", - "value": "戻る" + "value": "進む" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "后退" + "value": "前进" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "上一頁" + "value": "下一頁" } }, "ko": { "stringUnit": { "state": "translated", - "value": "뒤로" + "value": "앞으로" } }, "de": { "stringUnit": { "state": "translated", - "value": "Zurück" + "value": "Vor" } }, "es": { "stringUnit": { "state": "translated", - "value": "Atrás" + "value": "Adelante" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Précédent" + "value": "Suivant" } }, "it": { "stringUnit": { "state": "translated", - "value": "Indietro" + "value": "Avanti" } }, "da": { "stringUnit": { "state": "translated", - "value": "Tilbage" + "value": "Frem" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Wstecz" + "value": "Do przodu" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Назад" + "value": "Вперед" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Nazad" + "value": "Naprijed" } }, "ar": { "stringUnit": { "state": "translated", - "value": "رجوع" + "value": "تقدم" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Tilbake" + "value": "Fremover" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Voltar" + "value": "Avançar" } }, "th": { "stringUnit": { "state": "translated", - "value": "ย้อนกลับ" + "value": "ไปข้างหน้า" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Geri" + "value": "İleri" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Назад" + "value": "Вперед" } } } }, - "command.browserClearHistory.subtitle": { + "command.browserOpenDefault.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Browser" + "value": "Open Current Page in Default Browser" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ブラウザ" + "value": "現在のページをデフォルトブラウザで開く" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "浏览器" + "value": "在默认浏览器中打开当前页面" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "瀏覽器" + "value": "在預設瀏覽器中開啟目前頁面" } }, "ko": { "stringUnit": { "state": "translated", - "value": "브라우저" + "value": "현재 페이지를 기본 브라우저에서 열기" } }, "de": { "stringUnit": { "state": "translated", - "value": "Browser" + "value": "Aktuelle Seite im Standardbrowser öffnen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Navegador" + "value": "Abrir página actual en el navegador predeterminado" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Navigateur" + "value": "Ouvrir la page dans le navigateur par défaut" } }, "it": { "stringUnit": { "state": "translated", - "value": "Browser" + "value": "Apri la pagina corrente nel browser predefinito" } }, "da": { "stringUnit": { "state": "translated", - "value": "Browser" + "value": "Åbn aktuel side i standardbrowser" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Przeglądarka" + "value": "Otwórz bieżącą stronę w domyślnej przeglądarce" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Браузер" + "value": "Открыть текущую страницу в браузере по умолчанию" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Preglednik" + "value": "Otvori trenutnu stranicu u podrazumijevanom pregledniku" } }, "ar": { "stringUnit": { "state": "translated", - "value": "المتصفح" + "value": "فتح الصفحة الحالية في المتصفح الافتراضي" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Nettleser" + "value": "Åpne gjeldende side i standard nettleser" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Navegador" + "value": "Abrir Página Atual no Navegador Padrão" } }, "th": { "stringUnit": { "state": "translated", - "value": "เบราว์เซอร์" + "value": "เปิดหน้าปัจจุบันในเบราว์เซอร์เริ่มต้น" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Tarayıcı" + "value": "Geçerli Sayfayı Varsayılan Tarayıcıda Aç" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Браузер" + "value": "Відкрити поточну сторінку у стандартному браузері" } } } }, - "command.browserClearHistory.title": { + "command.browserReload.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Clear Browser History" + "value": "Reload Page" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ブラウザ履歴をクリア" + "value": "ページを再読み込み" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "清除浏览器历史记录" + "value": "重新加载页面" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "清除瀏覽記錄" + "value": "重新載入頁面" } }, "ko": { "stringUnit": { "state": "translated", - "value": "브라우저 기록 지우기" + "value": "페이지 새로고침" } }, "de": { "stringUnit": { "state": "translated", - "value": "Browserverlauf löschen" + "value": "Seite neu laden" } }, "es": { "stringUnit": { "state": "translated", - "value": "Borrar historial del navegador" + "value": "Recargar página" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Effacer l'historique du navigateur" + "value": "Recharger la page" } }, "it": { "stringUnit": { "state": "translated", - "value": "Cancella cronologia browser" + "value": "Ricarica pagina" } }, "da": { "stringUnit": { "state": "translated", - "value": "Ryd browserhistorik" + "value": "Genindlæs side" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Wyczyść historię przeglądarki" + "value": "Odśwież stronę" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Очистить историю браузера" + "value": "Перезагрузить страницу" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Obriši historiju preglednika" + "value": "Ponovo učitaj stranicu" } }, "ar": { "stringUnit": { "state": "translated", - "value": "مسح سجل المتصفح" + "value": "إعادة تحميل الصفحة" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Tøm nettleserhistorikk" + "value": "Last inn siden på nytt" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Limpar Histórico do Navegador" + "value": "Recarregar Página" } }, "th": { "stringUnit": { "state": "translated", - "value": "ล้างประวัติเบราว์เซอร์" + "value": "โหลดหน้าใหม่" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Tarayıcı Geçmişini Temizle" + "value": "Sayfayı Yeniden Yükle" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Очистити історію браузера" + "value": "Перезавантажити сторінку" } } } }, - "command.browserConsole.title": { + "command.browserSplitDown.subtitle": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Show JavaScript Console" + "value": "Browser Layout" } }, "ja": { "stringUnit": { "state": "translated", - "value": "JavaScriptコンソールを表示" + "value": "ブラウザレイアウト" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "显示 JavaScript 控制台" + "value": "浏览器布局" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "顯示 JavaScript 主控台" + "value": "瀏覽器版面" } }, "ko": { "stringUnit": { "state": "translated", - "value": "JavaScript 콘솔 표시" + "value": "브라우저 레이아웃" } }, "de": { "stringUnit": { "state": "translated", - "value": "JavaScript-Konsole anzeigen" + "value": "Browser-Layout" } }, "es": { "stringUnit": { "state": "translated", - "value": "Mostrar consola de JavaScript" + "value": "Disposición del navegador" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Afficher la console JavaScript" + "value": "Disposition du navigateur" } }, "it": { "stringUnit": { "state": "translated", - "value": "Mostra console JavaScript" + "value": "Layout browser" } }, "da": { "stringUnit": { "state": "translated", - "value": "Vis JavaScript-konsol" + "value": "Browserlayout" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Pokaż konsolę JavaScript" + "value": "Układ przeglądarki" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Показать консоль JavaScript" + "value": "Макет браузера" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Prikaži JavaScript konzolu" + "value": "Raspored preglednika" } }, "ar": { "stringUnit": { "state": "translated", - "value": "عرض وحدة تحكم JavaScript" + "value": "تخطيط المتصفح" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Vis JavaScript-konsoll" + "value": "Nettleseroppsett" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Mostrar Console JavaScript" + "value": "Layout do Navegador" } }, "th": { "stringUnit": { "state": "translated", - "value": "แสดงคอนโซล JavaScript" + "value": "เค้าโครงเบราว์เซอร์" } }, "tr": { "stringUnit": { "state": "translated", - "value": "JavaScript Konsolunu Göster" + "value": "Tarayıcı Düzeni" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Показати консоль JavaScript" + "value": "Макет браузера" } } } }, - "command.browserDuplicateRight.subtitle": { + "command.browserSplitDown.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Browser Layout" + "value": "Split Browser Down" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ブラウザレイアウト" + "value": "ブラウザを下に分割" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "浏览器布局" + "value": "向下拆分浏览器" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "瀏覽器版面" + "value": "向下分割瀏覽器" } }, "ko": { "stringUnit": { "state": "translated", - "value": "브라우저 레이아웃" + "value": "브라우저를 아래로 분할" } }, "de": { "stringUnit": { "state": "translated", - "value": "Browser-Layout" + "value": "Browser nach unten teilen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Disposición del navegador" + "value": "Dividir navegador hacia abajo" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Disposition du navigateur" + "value": "Diviser le navigateur vers le bas" } }, "it": { "stringUnit": { "state": "translated", - "value": "Layout browser" + "value": "Dividi browser in basso" } }, "da": { "stringUnit": { "state": "translated", - "value": "Browserlayout" + "value": "Opdel browser nedad" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Układ przeglądarki" + "value": "Podziel przeglądarkę w dół" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Макет браузера" + "value": "Разделить браузер вниз" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Raspored preglednika" + "value": "Podijeli preglednik dolje" } }, "ar": { "stringUnit": { "state": "translated", - "value": "تخطيط المتصفح" + "value": "تقسيم المتصفح للأسفل" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Nettleseroppsett" + "value": "Del nettleser ned" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Layout do Navegador" + "value": "Dividir Navegador para Baixo" } }, "th": { "stringUnit": { "state": "translated", - "value": "เค้าโครงเบราว์เซอร์" + "value": "แยกเบราว์เซอร์ลงล่าง" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Tarayıcı Düzeni" + "value": "Tarayıcıyı Aşağı Böl" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Макет браузера" + "value": "Розділити браузер вниз" } } } }, - "command.browserDuplicateRight.title": { + "command.browserSplitRight.subtitle": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Duplicate Browser to the Right" + "value": "Browser Layout" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ブラウザを右に複製" + "value": "ブラウザレイアウト" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "向右复制浏览器" + "value": "浏览器布局" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "將瀏覽器複製到右側" + "value": "瀏覽器版面" } }, "ko": { "stringUnit": { "state": "translated", - "value": "브라우저를 오른쪽으로 복제" + "value": "브라우저 레이아웃" } }, "de": { "stringUnit": { "state": "translated", - "value": "Browser nach rechts duplizieren" + "value": "Browser-Layout" } }, "es": { "stringUnit": { "state": "translated", - "value": "Duplicar navegador a la derecha" + "value": "Disposición del navegador" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Dupliquer le navigateur à droite" + "value": "Disposition du navigateur" } }, "it": { "stringUnit": { "state": "translated", - "value": "Duplica browser a destra" + "value": "Layout browser" } }, "da": { "stringUnit": { "state": "translated", - "value": "Dupliker browser til højre" + "value": "Browserlayout" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Duplikuj przeglądarkę na prawo" + "value": "Układ przeglądarki" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Дублировать браузер вправо" + "value": "Макет браузера" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Dupliciraj preglednik desno" + "value": "Raspored preglednika" } }, "ar": { "stringUnit": { "state": "translated", - "value": "نسخ المتصفح إلى اليمين" + "value": "تخطيط المتصفح" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Dupliser nettleser til høyre" + "value": "Nettleseroppsett" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Duplicar Navegador à Direita" + "value": "Layout do Navegador" } }, "th": { "stringUnit": { "state": "translated", - "value": "ทำซ้ำเบราว์เซอร์ไปทางขวา" + "value": "เค้าโครงเบราว์เซอร์" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Tarayıcıyı Sağa Çoğalt" + "value": "Tarayıcı Düzeni" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Дублювати браузер праворуч" + "value": "Макет браузера" } } } }, - "command.browserFocusAddressBar.title": { + "command.browserSplitRight.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Focus Address Bar" + "value": "Split Browser Right" } }, "ja": { "stringUnit": { "state": "translated", - "value": "アドレスバーにフォーカス" + "value": "ブラウザを右に分割" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "聚焦地址栏" + "value": "向右拆分浏览器" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "聚焦網址列" + "value": "向右分割瀏覽器" } }, "ko": { "stringUnit": { "state": "translated", - "value": "주소 표시줄 포커스" + "value": "브라우저를 오른쪽으로 분할" } }, "de": { "stringUnit": { "state": "translated", - "value": "Adressleiste fokussieren" + "value": "Browser nach rechts teilen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Enfocar barra de direcciones" + "value": "Dividir navegador a la derecha" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Activer la barre d'adresse" + "value": "Diviser le navigateur à droite" } }, "it": { "stringUnit": { "state": "translated", - "value": "Porta il focus sulla barra degli indirizzi" + "value": "Dividi browser a destra" } }, "da": { "stringUnit": { "state": "translated", - "value": "Fokuser adresselinjen" + "value": "Opdel browser til højre" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Ustaw fokus na pasku adresu" + "value": "Podziel przeglądarkę w prawo" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Перейти к адресной строке" + "value": "Разделить браузер вправо" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Fokusiraj adresnu traku" + "value": "Podijeli preglednik desno" } }, "ar": { "stringUnit": { "state": "translated", - "value": "التركيز على شريط العنوان" + "value": "تقسيم المتصفح لليمين" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Fokuser adressefeltet" + "value": "Del nettleser til høyre" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Focar na Barra de Endereço" + "value": "Dividir Navegador à Direita" } }, "th": { "stringUnit": { "state": "translated", - "value": "โฟกัสแถบที่อยู่" + "value": "แยกเบราว์เซอร์ไปทางขวา" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Adres Çubuğuna Odaklan" + "value": "Tarayıcıyı Sağa Böl" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Фокус на адресному рядку" + "value": "Розділити браузер праворуч" } } } }, - "command.browserForward.title": { + "command.browserToggleDevTools.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Forward" + "value": "Toggle Developer Tools" } }, "ja": { "stringUnit": { "state": "translated", - "value": "進む" + "value": "デベロッパツールの切り替え" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "前进" + "value": "切换开发者工具" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "下一頁" + "value": "切換開發者工具" } }, "ko": { "stringUnit": { "state": "translated", - "value": "앞으로" + "value": "개발자 도구 전환" } }, "de": { "stringUnit": { "state": "translated", - "value": "Vor" + "value": "Entwicklerwerkzeuge ein-/ausblenden" } }, "es": { "stringUnit": { "state": "translated", - "value": "Adelante" + "value": "Alternar herramientas de desarrollo" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Suivant" + "value": "Afficher/masquer les outils de développement" } }, "it": { "stringUnit": { "state": "translated", - "value": "Avanti" + "value": "Attiva/Disattiva Strumenti sviluppatore" } }, "da": { "stringUnit": { "state": "translated", - "value": "Frem" + "value": "Slå udviklerværktøjer til/fra" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Do przodu" + "value": "Przełącz narzędzia deweloperskie" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Вперед" + "value": "Инструменты разработчика" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Naprijed" + "value": "Prebaci razvojne alate" } }, "ar": { "stringUnit": { "state": "translated", - "value": "تقدم" + "value": "تبديل أدوات المطور" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Fremover" + "value": "Slå utviklerverktøy av/på" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Avançar" + "value": "Alternar Ferramentas do Desenvolvedor" } }, "th": { "stringUnit": { "state": "translated", - "value": "ไปข้างหน้า" + "value": "สลับเครื่องมือนักพัฒนา" } }, "tr": { "stringUnit": { "state": "translated", - "value": "İleri" + "value": "Geliştirici Araçlarını Aç/Kapat" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Вперед" + "value": "Перемкнути інструменти розробника" } } } }, - "command.browserOpenDefault.title": { + "command.browserZoomIn.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Open Current Page in Default Browser" + "value": "Zoom In" } }, "ja": { "stringUnit": { "state": "translated", - "value": "現在のページをデフォルトブラウザで開く" + "value": "拡大" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "在默认浏览器中打开当前页面" + "value": "放大" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "在預設瀏覽器中開啟目前頁面" + "value": "放大" } }, "ko": { "stringUnit": { "state": "translated", - "value": "현재 페이지를 기본 브라우저에서 열기" + "value": "확대" } }, "de": { "stringUnit": { "state": "translated", - "value": "Aktuelle Seite im Standardbrowser öffnen" + "value": "Einzoomen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Abrir página actual en el navegador predeterminado" + "value": "Ampliar" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Ouvrir la page dans le navigateur par défaut" + "value": "Zoom avant" } }, "it": { "stringUnit": { "state": "translated", - "value": "Apri la pagina corrente nel browser predefinito" + "value": "Ingrandisci" } }, "da": { "stringUnit": { "state": "translated", - "value": "Åbn aktuel side i standardbrowser" + "value": "Zoom ind" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Otwórz bieżącą stronę w domyślnej przeglądarce" + "value": "Powiększ" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Открыть текущую страницу в браузере по умолчанию" + "value": "Увеличить" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Otvori trenutnu stranicu u podrazumijevanom pregledniku" + "value": "Uvećaj" } }, "ar": { "stringUnit": { "state": "translated", - "value": "فتح الصفحة الحالية في المتصفح الافتراضي" + "value": "تكبير" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Åpne gjeldende side i standard nettleser" + "value": "Zoom inn" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Abrir Página Atual no Navegador Padrão" + "value": "Aumentar Zoom" } }, "th": { "stringUnit": { "state": "translated", - "value": "เปิดหน้าปัจจุบันในเบราว์เซอร์เริ่มต้น" + "value": "ซูมเข้า" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Geçerli Sayfayı Varsayılan Tarayıcıda Aç" + "value": "Yakınlaştır" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Відкрити поточну сторінку у стандартному браузері" + "value": "Збільшити" } } } }, - "command.browserReload.title": { + "command.browserZoomOut.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Reload Page" + "value": "Zoom Out" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ページを再読み込み" + "value": "縮小" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "重新加载页面" + "value": "缩小" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "重新載入頁面" + "value": "縮小" } }, "ko": { "stringUnit": { "state": "translated", - "value": "페이지 새로고침" + "value": "축소" } }, "de": { "stringUnit": { "state": "translated", - "value": "Seite neu laden" + "value": "Auszoomen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Recargar página" + "value": "Reducir" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Recharger la page" + "value": "Zoom arrière" } }, "it": { "stringUnit": { "state": "translated", - "value": "Ricarica pagina" + "value": "Riduci" } }, "da": { "stringUnit": { "state": "translated", - "value": "Genindlæs side" + "value": "Zoom ud" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Odśwież stronę" + "value": "Pomniejsz" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Перезагрузить страницу" + "value": "Уменьшить" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Ponovo učitaj stranicu" + "value": "Umanji" } }, "ar": { "stringUnit": { "state": "translated", - "value": "إعادة تحميل الصفحة" + "value": "تصغير" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Last inn siden på nytt" + "value": "Zoom ut" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Recarregar Página" + "value": "Diminuir Zoom" } }, "th": { "stringUnit": { "state": "translated", - "value": "โหลดหน้าใหม่" + "value": "ซูมออก" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Sayfayı Yeniden Yükle" + "value": "Uzaklaştır" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Перезавантажити сторінку" + "value": "Зменшити" } } } }, - "command.browserSplitDown.subtitle": { + "command.browserZoomReset.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Browser Layout" + "value": "Actual Size" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ブラウザレイアウト" + "value": "実際のサイズ" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "浏览器布局" + "value": "实际大小" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "瀏覽器版面" + "value": "實際大小" } }, "ko": { "stringUnit": { "state": "translated", - "value": "브라우저 레이아웃" + "value": "실제 크기" } }, "de": { "stringUnit": { "state": "translated", - "value": "Browser-Layout" + "value": "Originalgröße" } }, "es": { "stringUnit": { "state": "translated", - "value": "Disposición del navegador" + "value": "Tamaño real" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Disposition du navigateur" + "value": "Taille réelle" } }, "it": { "stringUnit": { "state": "translated", - "value": "Layout browser" + "value": "Dimensione reale" } }, "da": { "stringUnit": { "state": "translated", - "value": "Browserlayout" + "value": "Faktisk størrelse" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Układ przeglądarki" + "value": "Rozmiar rzeczywisty" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Макет браузера" + "value": "Фактический размер" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Raspored preglednika" + "value": "Stvarna veličina" } }, "ar": { "stringUnit": { "state": "translated", - "value": "تخطيط المتصفح" + "value": "الحجم الفعلي" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Nettleseroppsett" + "value": "Faktisk størrelse" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Layout do Navegador" + "value": "Tamanho Real" } }, "th": { "stringUnit": { "state": "translated", - "value": "เค้าโครงเบราว์เซอร์" + "value": "ขนาดจริง" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Tarayıcı Düzeni" + "value": "Gerçek Boyut" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Макет браузера" + "value": "Фактичний розмір" } } } }, - "command.browserSplitDown.title": { + "command.checkForUpdates.subtitle": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Split Browser Down" + "value": "Global" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ブラウザを下に分割" + "value": "グローバル" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "向下拆分浏览器" + "value": "全局" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "向下分割瀏覽器" + "value": "全域" } }, "ko": { "stringUnit": { "state": "translated", - "value": "브라우저를 아래로 분할" + "value": "전역" } }, "de": { "stringUnit": { "state": "translated", - "value": "Browser nach unten teilen" + "value": "Global" } }, "es": { "stringUnit": { "state": "translated", - "value": "Dividir navegador hacia abajo" + "value": "Global" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Diviser le navigateur vers le bas" + "value": "Général" } }, "it": { "stringUnit": { "state": "translated", - "value": "Dividi browser in basso" + "value": "Globale" } }, "da": { "stringUnit": { "state": "translated", - "value": "Opdel browser nedad" + "value": "Globalt" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Podziel przeglądarkę w dół" + "value": "Globalne" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Разделить браузер вниз" + "value": "Глобальные" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Podijeli preglednik dolje" + "value": "Globalno" } }, "ar": { "stringUnit": { "state": "translated", - "value": "تقسيم المتصفح للأسفل" + "value": "عام" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Del nettleser ned" + "value": "Globalt" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Dividir Navegador para Baixo" + "value": "Global" } }, "th": { "stringUnit": { "state": "translated", - "value": "แยกเบราว์เซอร์ลงล่าง" + "value": "ทั่วไป" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Tarayıcıyı Aşağı Böl" + "value": "Genel" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Розділити браузер вниз" + "value": "Глобальна" } } } }, - "command.browserSplitRight.subtitle": { + "command.checkForUpdates.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Browser Layout" + "value": "Check for Updates" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ブラウザレイアウト" + "value": "アップデートを確認" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "浏览器布局" + "value": "检查更新" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "瀏覽器版面" + "value": "檢查更新" } }, "ko": { "stringUnit": { "state": "translated", - "value": "브라우저 레이아웃" + "value": "업데이트 확인" } }, "de": { "stringUnit": { "state": "translated", - "value": "Browser-Layout" + "value": "Nach Updates suchen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Disposición del navegador" + "value": "Buscar actualizaciones" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Disposition du navigateur" + "value": "Rechercher des mises à jour" } }, "it": { "stringUnit": { "state": "translated", - "value": "Layout browser" + "value": "Verifica aggiornamenti" } }, "da": { "stringUnit": { "state": "translated", - "value": "Browserlayout" + "value": "Søg efter opdateringer" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Układ przeglądarki" + "value": "Sprawdź aktualizacje" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Макет браузера" + "value": "Проверить обновления" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Raspored preglednika" + "value": "Provjeri ažuriranja" } }, "ar": { "stringUnit": { "state": "translated", - "value": "تخطيط المتصفح" + "value": "التحقق من التحديثات" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Nettleseroppsett" + "value": "Se etter oppdateringer" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Layout do Navegador" + "value": "Buscar Atualizações" } }, "th": { "stringUnit": { "state": "translated", - "value": "เค้าโครงเบราว์เซอร์" + "value": "ตรวจหาอัปเดต" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Tarayıcı Düzeni" + "value": "Güncellemeleri Denetle" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Макет браузера" + "value": "Перевірити оновлення" } } } }, - "command.browserSplitRight.title": { + "command.clearTabName.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Split Browser Right" + "value": "Clear Tab Name" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ブラウザを右に分割" + "value": "タブ名をクリア" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "向右拆分浏览器" + "value": "清除标签页名称" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "向右分割瀏覽器" + "value": "清除標籤頁名稱" } }, "ko": { "stringUnit": { "state": "translated", - "value": "브라우저를 오른쪽으로 분할" + "value": "탭 이름 지우기" } }, "de": { "stringUnit": { "state": "translated", - "value": "Browser nach rechts teilen" + "value": "Tab-Name löschen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Dividir navegador a la derecha" + "value": "Borrar nombre de pestaña" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Diviser le navigateur à droite" + "value": "Effacer le nom de l'onglet" } }, "it": { "stringUnit": { "state": "translated", - "value": "Dividi browser a destra" + "value": "Cancella nome scheda" } }, "da": { "stringUnit": { "state": "translated", - "value": "Opdel browser til højre" + "value": "Ryd fanenavn" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Podziel przeglądarkę w prawo" + "value": "Wyczyść nazwę karty" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Разделить браузер вправо" + "value": "Очистить имя вкладки" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Podijeli preglednik desno" + "value": "Obriši naziv taba" } }, "ar": { "stringUnit": { "state": "translated", - "value": "تقسيم المتصفح لليمين" + "value": "مسح اسم اللسان" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Del nettleser til høyre" + "value": "Fjern fanenavn" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Dividir Navegador à Direita" + "value": "Limpar Nome da Aba" } }, "th": { "stringUnit": { "state": "translated", - "value": "แยกเบราว์เซอร์ไปทางขวา" + "value": "ล้างชื่อแท็บ" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Tarayıcıyı Sağa Böl" + "value": "Sekme Adını Temizle" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Розділити браузер праворуч" + "value": "Скинути назву вкладки" } } } }, - "command.browserToggleDevTools.title": { + "command.clearWorkspaceName.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Toggle Developer Tools" + "value": "Clear Workspace Name" } }, "ja": { "stringUnit": { "state": "translated", - "value": "デベロッパツールの切り替え" + "value": "ワークスペース名をクリア" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "切换开发者工具" + "value": "清除工作区名称" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "切換開發者工具" + "value": "清除工作區名稱" } }, "ko": { "stringUnit": { "state": "translated", - "value": "개발자 도구 전환" + "value": "작업 공간 이름 지우기" } }, "de": { "stringUnit": { "state": "translated", - "value": "Entwicklerwerkzeuge ein-/ausblenden" + "value": "Arbeitsbereichsname löschen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Alternar herramientas de desarrollo" + "value": "Borrar nombre del espacio de trabajo" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Afficher/masquer les outils de développement" + "value": "Effacer le nom de l'espace de travail" } }, "it": { "stringUnit": { "state": "translated", - "value": "Attiva/Disattiva Strumenti sviluppatore" + "value": "Cancella nome area di lavoro" } }, "da": { "stringUnit": { "state": "translated", - "value": "Slå udviklerværktøjer til/fra" + "value": "Ryd arbejdsområdenavn" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Przełącz narzędzia deweloperskie" + "value": "Wyczyść nazwę przestrzeni roboczej" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Инструменты разработчика" + "value": "Очистить имя рабочего пространства" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Prebaci razvojne alate" + "value": "Obriši naziv radnog prostora" } }, "ar": { "stringUnit": { "state": "translated", - "value": "تبديل أدوات المطور" + "value": "مسح اسم مساحة العمل" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Slå utviklerverktøy av/på" + "value": "Fjern arbeidsområdenavn" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Alternar Ferramentas do Desenvolvedor" + "value": "Limpar Nome da Área de Trabalho" } }, "th": { "stringUnit": { "state": "translated", - "value": "สลับเครื่องมือนักพัฒนา" + "value": "ล้างชื่อเวิร์กสเปซ" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Geliştirici Araçlarını Aç/Kapat" + "value": "Çalışma Alanı Adını Temizle" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Перемкнути інструменти розробника" + "value": "Скинути назву робочої області" } } } }, - "command.browserZoomIn.title": { + "command.cloudVM.failed.exit": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Zoom In" + "value": "cmux vm new exited with status %d." } }, "ja": { "stringUnit": { "state": "translated", - "value": "拡大" + "value": "cmux vm new がステータス %d で終了しました。" } - }, - "zh-Hans": { + } + } + }, + "command.cloudVM.failed.action.exit": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "放大" + "value": "Open a terminal and run `cmux auth status`, `cmux vm ls`, then `cmux vm new`. If you hit the active VM limit, delete one with `cmux vm rm ` and retry." } }, - "zh-Hant": { + "ja": { "stringUnit": { "state": "translated", - "value": "放大" + "value": "ターミナルを開いて `cmux auth status`、`cmux vm ls`、`cmux vm new` を実行してください。アクティブな VM 数の上限に達している場合は `cmux vm rm ` で削除してから再試行してください。" } - }, - "ko": { + } + } + }, + "command.cloudVM.failed.action.launch": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "확대" + "value": "Reload cmux so the bundled CLI is available, then try again. If it still fails, run `cmux vm new` in a terminal and send us the output." } }, - "de": { + "ja": { "stringUnit": { "state": "translated", - "value": "Einzoomen" + "value": "バンドルされた CLI を使えるように cmux を再読み込みしてから再試行してください。それでも失敗する場合は、ターミナルで `cmux vm new` を実行して出力を送ってください。" } - }, - "es": { + } + } + }, + "command.cloudVM.failed.action.missingCLI": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Ampliar" + "value": "Install or reload a fresh cmux build, then try Start Cloud VM again. You can also run `cmux vm new` in a terminal to see the full error." } }, - "fr": { + "ja": { "stringUnit": { "state": "translated", - "value": "Zoom avant" + "value": "新しい cmux ビルドをインストールまたは再読み込みしてから、Start Cloud VM をもう一度試してください。ターミナルで `cmux vm new` を実行すると完全なエラーも確認できます。" } - }, - "it": { + } + } + }, + "command.cloudVM.failed.details": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Ingrandisci" + "value": "Details:" } }, - "da": { + "ja": { "stringUnit": { "state": "translated", - "value": "Zoom ind" + "value": "詳細:" } - }, - "pl": { + } + } + }, + "command.cloudVM.failed.details.hidden": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Powiększ" + "value": "Additional technical details are available in logs." } }, - "ru": { + "ja": { "stringUnit": { "state": "translated", - "value": "Увеличить" + "value": "追加の技術的な詳細はログで確認できます。" } - }, - "bs": { + } + } + }, + "command.cloudVM.failed.launch": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Uvećaj" + "value": "cmux vm new could not be launched." } }, - "ar": { + "ja": { "stringUnit": { "state": "translated", - "value": "تكبير" + "value": "cmux vm new を起動できませんでした。" } - }, - "nb": { + } + } + }, + "command.cloudVM.failed.missingCLI": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Zoom inn" + "value": "The bundled cmux CLI is missing from this app build." } }, - "pt-BR": { + "ja": { "stringUnit": { "state": "translated", - "value": "Aumentar Zoom" + "value": "このアプリビルドにはバンドルされた cmux CLI がありません。" } - }, - "th": { - "stringUnit": { - "state": "translated", - "value": "ซูมเข้า" + } + } + }, + "command.cloudVM.failed.title": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Couldn't Start Cloud VM" } }, - "tr": { + "ja": { "stringUnit": { "state": "translated", - "value": "Yakınlaştır" + "value": "Cloud VMを開始できませんでした" + } + } + } + }, + "command.cloudVM.failed.whatToTry": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "What to try:" } }, - "uk": { + "ja": { "stringUnit": { "state": "translated", - "value": "Збільшити" + "value": "試すこと:" } } } }, - "command.browserZoomOut.title": { + "command.cloudVM.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Zoom Out" + "value": "Start Cloud VM" } }, "ja": { "stringUnit": { "state": "translated", - "value": "縮小" + "value": "Cloud VMを開始" + } + } + } + }, + "command.closeTab.subtitle": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Tab" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "タブ" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "缩小" + "value": "标签页" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "縮小" + "value": "標籤頁" } }, "ko": { "stringUnit": { "state": "translated", - "value": "축소" + "value": "탭" } }, "de": { "stringUnit": { "state": "translated", - "value": "Auszoomen" + "value": "Tab" } }, "es": { "stringUnit": { "state": "translated", - "value": "Reducir" + "value": "Pestaña" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Zoom arrière" + "value": "Onglet" } }, "it": { "stringUnit": { "state": "translated", - "value": "Riduci" + "value": "Scheda" } }, "da": { "stringUnit": { "state": "translated", - "value": "Zoom ud" + "value": "Fane" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Pomniejsz" + "value": "Karta" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Уменьшить" + "value": "Вкладка" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Umanji" + "value": "Tab" } }, "ar": { "stringUnit": { "state": "translated", - "value": "تصغير" + "value": "لسان" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Zoom ut" + "value": "Fane" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Diminuir Zoom" + "value": "Aba" } }, "th": { "stringUnit": { "state": "translated", - "value": "ซูมออก" + "value": "แท็บ" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Uzaklaştır" + "value": "Sekme" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Зменшити" + "value": "Вкладка" } } } }, - "command.browserZoomReset.title": { + "command.closeTab.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Actual Size" + "value": "Close Tab" } }, "ja": { "stringUnit": { "state": "translated", - "value": "実際のサイズ" + "value": "タブを閉じる" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "实际大小" + "value": "关闭标签页" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "實際大小" + "value": "關閉標籤頁" } }, "ko": { "stringUnit": { "state": "translated", - "value": "실제 크기" + "value": "탭 닫기" } }, "de": { "stringUnit": { "state": "translated", - "value": "Originalgröße" + "value": "Tab schließen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Tamaño real" + "value": "Cerrar pestaña" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Taille réelle" + "value": "Fermer l'onglet" } }, "it": { "stringUnit": { "state": "translated", - "value": "Dimensione reale" + "value": "Chiudi scheda" } }, "da": { "stringUnit": { "state": "translated", - "value": "Faktisk størrelse" + "value": "Luk fane" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Rozmiar rzeczywisty" + "value": "Zamknij kartę" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Фактический размер" + "value": "Закрыть вкладку" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Stvarna veličina" + "value": "Zatvori tab" } }, "ar": { "stringUnit": { "state": "translated", - "value": "الحجم الفعلي" + "value": "إغلاق اللسان" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Faktisk størrelse" + "value": "Lukk fane" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Tamanho Real" + "value": "Fechar Aba" } }, "th": { "stringUnit": { "state": "translated", - "value": "ขนาดจริง" + "value": "ปิดแท็บ" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Gerçek Boyut" + "value": "Sekmeyi Kapat" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Фактичний розмір" + "value": "Закрити вкладку" } } } }, - "command.checkForUpdates.subtitle": { + "command.closeWindow.subtitle": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Global" + "value": "Window" } }, "ja": { "stringUnit": { "state": "translated", - "value": "グローバル" + "value": "ウインドウ" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "全局" + "value": "窗口" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "全域" + "value": "視窗" } }, "ko": { "stringUnit": { "state": "translated", - "value": "전역" + "value": "윈도우" } }, "de": { "stringUnit": { "state": "translated", - "value": "Global" + "value": "Fenster" } }, "es": { "stringUnit": { "state": "translated", - "value": "Global" + "value": "Ventana" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Général" + "value": "Fenêtre" } }, "it": { "stringUnit": { "state": "translated", - "value": "Globale" + "value": "Finestra" } }, "da": { "stringUnit": { "state": "translated", - "value": "Globalt" + "value": "Vindue" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Globalne" + "value": "Okno" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Глобальные" + "value": "Окно" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Globalno" + "value": "Prozor" } }, "ar": { "stringUnit": { "state": "translated", - "value": "عام" + "value": "نافذة" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Globalt" + "value": "Vindu" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Global" + "value": "Janela" } }, "th": { "stringUnit": { "state": "translated", - "value": "ทั่วไป" + "value": "หน้าต่าง" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Genel" + "value": "Pencere" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Глобальна" + "value": "Вікно" } } } }, - "command.checkForUpdates.title": { + "command.closeWindow.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Check for Updates" + "value": "Close Window" } }, "ja": { "stringUnit": { "state": "translated", - "value": "アップデートを確認" + "value": "ウインドウを閉じる" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "检查更新" + "value": "关闭窗口" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "檢查更新" + "value": "關閉視窗" } }, "ko": { "stringUnit": { "state": "translated", - "value": "업데이트 확인" + "value": "윈도우 닫기" } }, "de": { "stringUnit": { "state": "translated", - "value": "Nach Updates suchen" + "value": "Fenster schließen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Buscar actualizaciones" + "value": "Cerrar ventana" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Rechercher des mises à jour" + "value": "Fermer la fenêtre" } }, "it": { "stringUnit": { "state": "translated", - "value": "Verifica aggiornamenti" + "value": "Chiudi finestra" } }, "da": { "stringUnit": { "state": "translated", - "value": "Søg efter opdateringer" + "value": "Luk vindue" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Sprawdź aktualizacje" + "value": "Zamknij okno" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Проверить обновления" + "value": "Закрыть окно" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Provjeri ažuriranja" + "value": "Zatvori prozor" } }, "ar": { "stringUnit": { "state": "translated", - "value": "التحقق من التحديثات" + "value": "إغلاق النافذة" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Se etter oppdateringer" + "value": "Lukk vindu" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Buscar Atualizações" + "value": "Fechar Janela" } }, "th": { "stringUnit": { "state": "translated", - "value": "ตรวจหาอัปเดต" + "value": "ปิดหน้าต่าง" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Güncellemeleri Denetle" + "value": "Pencereyi Kapat" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Перевірити оновлення" + "value": "Закрити вікно" } } } }, - "command.clearTabName.title": { + "command.copyPaneID.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Clear Tab Name" + "value": "Copy Pane ID" } }, "ja": { "stringUnit": { "state": "translated", - "value": "タブ名をクリア" + "value": "ペインIDをコピー" + } + }, + "ko": { + "stringUnit": { + "state": "translated", + "value": "패널 ID 복사" + } + } + } + }, + "command.copySurfaceID.title": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Copy Surface ID" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "サーフェスIDをコピー" + } + }, + "ko": { + "stringUnit": { + "state": "translated", + "value": "서피스 ID 복사" + } + } + } + }, + "command.copyWorkspaceIDAndRef.title": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Copy Workspace ID and Ref" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "ワークスペースIDと参照をコピー" + } + }, + "ko": { + "stringUnit": { + "state": "translated", + "value": "워크스페이스 ID 및 참조 복사" + } + } + } + }, + "command.closeWorkspace.subtitle": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Workspace" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "ワークスペース" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "清除标签页名称" + "value": "工作区" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "清除標籤頁名稱" + "value": "工作區" } }, "ko": { "stringUnit": { "state": "translated", - "value": "탭 이름 지우기" + "value": "작업 공간" } }, "de": { "stringUnit": { "state": "translated", - "value": "Tab-Name löschen" + "value": "Arbeitsbereich" } }, "es": { "stringUnit": { "state": "translated", - "value": "Borrar nombre de pestaña" + "value": "Espacio de trabajo" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Effacer le nom de l'onglet" + "value": "Espace de travail" } }, "it": { "stringUnit": { "state": "translated", - "value": "Cancella nome scheda" + "value": "Area di lavoro" } }, "da": { "stringUnit": { "state": "translated", - "value": "Ryd fanenavn" + "value": "Arbejdsområde" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Wyczyść nazwę karty" + "value": "Przestrzeń robocza" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Очистить имя вкладки" + "value": "Рабочее пространство" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Obriši naziv taba" + "value": "Radni prostor" } }, "ar": { "stringUnit": { "state": "translated", - "value": "مسح اسم اللسان" + "value": "مساحة العمل" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Fjern fanenavn" + "value": "Arbeidsområde" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Limpar Nome da Aba" + "value": "Área de Trabalho" } }, "th": { "stringUnit": { "state": "translated", - "value": "ล้างชื่อแท็บ" + "value": "เวิร์กสเปซ" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Sekme Adını Temizle" + "value": "Çalışma Alanı" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Скинути назву вкладки" + "value": "Робоча область" } } } }, - "command.clearWorkspaceName.title": { + "command.closeWorkspace.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Clear Workspace Name" + "value": "Close Workspace" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ワークスペース名をクリア" + "value": "ワークスペースを閉じる" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "清除工作区名称" + "value": "关闭工作区" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "清除工作區名稱" + "value": "關閉工作區" } }, "ko": { "stringUnit": { "state": "translated", - "value": "작업 공간 이름 지우기" + "value": "작업 공간 닫기" } }, "de": { "stringUnit": { "state": "translated", - "value": "Arbeitsbereichsname löschen" + "value": "Arbeitsbereich schließen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Borrar nombre del espacio de trabajo" + "value": "Cerrar espacio de trabajo" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Effacer le nom de l'espace de travail" + "value": "Fermer l'espace de travail" } }, "it": { "stringUnit": { "state": "translated", - "value": "Cancella nome area di lavoro" + "value": "Chiudi area di lavoro" } }, "da": { "stringUnit": { "state": "translated", - "value": "Ryd arbejdsområdenavn" + "value": "Luk arbejdsområde" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Wyczyść nazwę przestrzeni roboczej" + "value": "Zamknij przestrzeń roboczą" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Очистить имя рабочего пространства" + "value": "Закрыть рабочее пространство" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Obriši naziv radnog prostora" + "value": "Zatvori radni prostor" } }, "ar": { "stringUnit": { "state": "translated", - "value": "مسح اسم مساحة العمل" + "value": "إغلاق مساحة العمل" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Fjern arbeidsområdenavn" + "value": "Lukk arbeidsområde" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Limpar Nome da Área de Trabalho" + "value": "Fechar Área de Trabalho" } }, "th": { "stringUnit": { "state": "translated", - "value": "ล้างชื่อเวิร์กสเปซ" + "value": "ปิดเวิร์กสเปซ" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Çalışma Alanı Adını Temizle" + "value": "Çalışma Alanını Kapat" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Скинути назву робочої області" + "value": "Закрити робочу область" } } } }, - "command.cloudVM.failed.exit": { + "dialog.cmuxConfig.confirmCommand.cancel": { "extractionState": "manual", "localizations": { - "en": { + "ar": { "stringUnit": { "state": "translated", - "value": "cmux vm new exited with status %d." + "value": "إلغاء" } }, - "ja": { + "bs": { "stringUnit": { "state": "translated", - "value": "cmux vm new がステータス %d で終了しました。" + "value": "Otkaži" } - } - } - }, - "command.cloudVM.failed.action.exit": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "da": { "stringUnit": { "state": "translated", - "value": "Open a terminal and run `cmux auth status`, `cmux vm ls`, then `cmux vm new`. If you hit the active VM limit, delete one with `cmux vm rm ` and retry." + "value": "Annuller" } }, - "ja": { + "de": { "stringUnit": { "state": "translated", - "value": "ターミナルを開いて `cmux auth status`、`cmux vm ls`、`cmux vm new` を実行してください。アクティブな VM 数の上限に達している場合は `cmux vm rm ` で削除してから再試行してください。" + "value": "Abbrechen" } - } - } - }, - "command.cloudVM.failed.action.launch": { - "extractionState": "manual", - "localizations": { + }, "en": { "stringUnit": { "state": "translated", - "value": "Reload cmux so the bundled CLI is available, then try again. If it still fails, run `cmux vm new` in a terminal and send us the output." + "value": "Cancel" + } + }, + "es": { + "stringUnit": { + "state": "translated", + "value": "Cancelar" + } + }, + "fr": { + "stringUnit": { + "state": "translated", + "value": "Annuler" + } + }, + "it": { + "stringUnit": { + "state": "translated", + "value": "Annulla" } }, "ja": { "stringUnit": { "state": "translated", - "value": "バンドルされた CLI を使えるように cmux を再読み込みしてから再試行してください。それでも失敗する場合は、ターミナルで `cmux vm new` を実行して出力を送ってください。" + "value": "キャンセル" + } + }, + "ko": { + "stringUnit": { + "state": "translated", + "value": "취소" + } + }, + "nb": { + "stringUnit": { + "state": "translated", + "value": "Avbryt" + } + }, + "pl": { + "stringUnit": { + "state": "translated", + "value": "Anuluj" + } + }, + "pt-BR": { + "stringUnit": { + "state": "translated", + "value": "Cancelar" + } + }, + "ru": { + "stringUnit": { + "state": "translated", + "value": "Отмена" + } + }, + "th": { + "stringUnit": { + "state": "translated", + "value": "ยกเลิก" + } + }, + "tr": { + "stringUnit": { + "state": "translated", + "value": "İptal" + } + }, + "zh-Hans": { + "stringUnit": { + "state": "translated", + "value": "取消" + } + }, + "zh-Hant": { + "stringUnit": { + "state": "translated", + "value": "取消" + } + }, + "uk": { + "stringUnit": { + "state": "translated", + "value": "Скасувати" } } } }, - "command.cloudVM.failed.action.missingCLI": { + "dialog.sshURL.blocked.ok": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Install or reload a fresh cmux build, then try Start Cloud VM again. You can also run `cmux vm new` in a terminal to see the full error." + "value": "OK" } }, "ja": { "stringUnit": { "state": "translated", - "value": "新しい cmux ビルドをインストールまたは再読み込みしてから、Start Cloud VM をもう一度試してください。ターミナルで `cmux vm new` を実行すると完全なエラーも確認できます。" + "value": "OK" } } } }, - "command.cloudVM.failed.details": { + "dialog.sshURL.blocked.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Details:" + "value": "cmux SSH Link Blocked" } }, "ja": { "stringUnit": { "state": "translated", - "value": "詳細:" + "value": "cmux SSH リンクをブロックしました" } } } }, - "command.cloudVM.failed.details.hidden": { + "dialog.sshURL.launchFailed.exit": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Additional technical details are available in logs." + "value": "cmux ssh exited with status %d." } }, "ja": { "stringUnit": { "state": "translated", - "value": "追加の技術的な詳細はログで確認できます。" + "value": "cmux ssh はステータス %d で終了しました。" } } } }, - "command.cloudVM.failed.launch": { + "dialog.sshURL.launchFailed.launch": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "cmux vm new could not be launched." + "value": "cmux ssh could not be launched." } }, "ja": { "stringUnit": { "state": "translated", - "value": "cmux vm new を起動できませんでした。" + "value": "cmux ssh を起動できませんでした。" } } } }, - "command.cloudVM.failed.missingCLI": { + "dialog.sshURL.launchFailed.missingCLI": { "extractionState": "manual", "localizations": { "en": { @@ -19391,5240 +19395,5556 @@ "ja": { "stringUnit": { "state": "translated", - "value": "このアプリビルドにはバンドルされた cmux CLI がありません。" + "value": "このアプリビルドに同梱されている cmux CLI が見つかりません。" } } } }, - "command.cloudVM.failed.title": { + "dialog.sshURL.launchFailed.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Couldn't Start Cloud VM" + "value": "Couldn't Open SSH Link" } }, "ja": { "stringUnit": { "state": "translated", - "value": "Cloud VMを開始できませんでした" + "value": "SSH リンクを開けませんでした" } } } }, - "command.cloudVM.failed.whatToTry": { + "dialog.sshURL.cancel": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "What to try:" + "value": "Cancel" } }, "ja": { "stringUnit": { "state": "translated", - "value": "試すこと:" + "value": "キャンセル" } } } }, - "command.cloudVM.title": { + "dialog.sshURL.checkbox": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Start Cloud VM" + "value": "I trust this SSH target and want cmux to connect." } }, "ja": { "stringUnit": { "state": "translated", - "value": "Cloud VMを開始" + "value": "この SSH 接続先を信頼し、cmux で接続することに同意します。" } } } }, - "command.closeTab.subtitle": { + "dialog.sshURL.commandLabel": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Tab" + "value": "Command preview:" } }, "ja": { "stringUnit": { "state": "translated", - "value": "タブ" + "value": "コマンドのプレビュー:" } - }, - "zh-Hans": { + } + } + }, + "dialog.sshURL.targetLabel": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "标签页" + "value": "SSH target: %@" } }, - "zh-Hant": { + "ja": { "stringUnit": { "state": "translated", - "value": "標籤頁" + "value": "SSH 接続先: %@" } - }, - "ko": { + } + } + }, + "dialog.sshURL.error.destinationContainsUnsafeCharacters": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "탭" + "value": "The SSH host or user contains unsupported or hidden characters, so cmux refused to use it." } }, - "de": { + "ja": { "stringUnit": { "state": "translated", - "value": "Tab" + "value": "SSH ホストまたはユーザーに未対応の文字または隠れた文字が含まれているため、cmux は使用を拒否しました。" } - }, - "es": { + } + } + }, + "dialog.sshURL.error.destinationTooLong": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Pestaña" + "value": "The SSH target is too long. The maximum length is %lld characters." } }, - "fr": { + "ja": { "stringUnit": { "state": "translated", - "value": "Onglet" + "value": "SSH 接続先が長すぎます。最大長は %lld 文字です。" } - }, - "it": { + } + } + }, + "dialog.sshURL.error.missingDestination": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Scheda" + "value": "The link did not include an SSH host." } }, - "da": { + "ja": { "stringUnit": { "state": "translated", - "value": "Fane" + "value": "リンクに SSH ホストが含まれていません。" } - }, - "pl": { + } + } + }, + "dialog.sshURL.error.multipleLinks": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Karta" + "value": "Only one SSH link can be opened at a time." } }, - "ru": { + "ja": { "stringUnit": { "state": "translated", - "value": "Вкладка" + "value": "一度に開ける SSH リンクは 1 つだけです。" } - }, - "bs": { + } + } + }, + "dialog.sshURL.error.titleContainsControlCharacters": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Tab" + "value": "The workspace title contains hidden control or formatting characters, so cmux refused to use it." } }, - "ar": { + "ja": { "stringUnit": { "state": "translated", - "value": "لسان" + "value": "ワークスペース名に隠れた制御文字または書式制御文字が含まれているため、cmux は使用を拒否しました。" } - }, - "nb": { + } + } + }, + "dialog.sshURL.error.titleTooLong": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Fane" + "value": "The workspace title is too long. The maximum length is %lld characters." } }, - "pt-BR": { + "ja": { "stringUnit": { "state": "translated", - "value": "Aba" + "value": "ワークスペース名が長すぎます。最大長は %lld 文字です。" } - }, - "th": { + } + } + }, + "dialog.sshURL.error.invalidIntegerParameter": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "แท็บ" + "value": "The SSH link included an invalid integer value for parameter: %@" } }, - "tr": { + "ja": { "stringUnit": { "state": "translated", - "value": "Sekme" + "value": "SSH リンクのパラメータに無効な整数値が含まれています: %@" + } + } + } + }, + "dialog.sshURL.error.invalidHostKeyPolicy": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "The SSH link included an invalid host key policy for parameter: %@" } }, - "uk": { + "ja": { "stringUnit": { "state": "translated", - "value": "Вкладка" + "value": "SSH リンクのパラメータに無効なホストキー確認ポリシーが含まれています: %@" } } } }, - "command.closeTab.title": { + "dialog.sshURL.error.destinationStartsWithDash": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Close Tab" + "value": "The SSH host or user cannot start with a dash." } }, "ja": { "stringUnit": { "state": "translated", - "value": "タブを閉じる" + "value": "SSH ホストまたはユーザーをダッシュで始めることはできません。" } - }, - "zh-Hans": { + } + } + }, + "dialog.sshURL.error.conflictingDestinationParameters": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "关闭标签页" + "value": "The link included conflicting SSH target fields." } }, - "zh-Hant": { + "ja": { "stringUnit": { "state": "translated", - "value": "關閉標籤頁" + "value": "リンクに競合する SSH 接続先フィールドが含まれています。" } - }, - "ko": { + } + } + }, + "dialog.sshURL.error.conflictingTitleParameters": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "탭 닫기" + "value": "The link included both title and name. Use only one workspace title field." } }, - "de": { + "ja": { "stringUnit": { "state": "translated", - "value": "Tab schließen" + "value": "リンクに title と name の両方が含まれています。ワークスペース名のフィールドは 1 つだけ使用してください。" } - }, - "es": { + } + } + }, + "dialog.sshURL.error.duplicateParameter": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Cerrar pestaña" + "value": "The SSH link repeated a parameter: %@" } }, - "fr": { + "ja": { "stringUnit": { "state": "translated", - "value": "Fermer l'onglet" + "value": "SSH リンクで同じパラメータが繰り返されています: %@" } - }, - "it": { + } + } + }, + "dialog.sshURL.error.unsupportedParameter": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Chiudi scheda" + "value": "The SSH link included an unsupported parameter: %@" } }, - "da": { + "ja": { "stringUnit": { "state": "translated", - "value": "Luk fane" + "value": "SSH リンクに未対応のパラメータが含まれています: %@" } - }, - "pl": { + } + } + }, + "dialog.sshURL.error.invalidPort": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Zamknij kartę" + "value": "The SSH port must be between 1 and 65535." } }, - "ru": { + "ja": { "stringUnit": { "state": "translated", - "value": "Закрыть вкладку" + "value": "SSH ポートは 1 から 65535 の範囲で指定してください。" } - }, - "bs": { + } + } + }, + "dialog.sshURL.error.invalidBooleanParameter": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Zatvori tab" + "value": "The SSH link included an invalid boolean value for parameter: %@" } }, - "ar": { + "ja": { "stringUnit": { "state": "translated", - "value": "إغلاق اللسان" + "value": "SSH リンクのパラメータに無効な真偽値が含まれています: %@" } - }, - "nb": { + } + } + }, + "dialog.sshURL.message": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Lukk fane" + "value": "A %@:// link is asking cmux to open an SSH workspace. cmux cannot verify which website or app opened this link.\n\nSSH may use your local SSH config, keys, agent settings, ProxyCommand, LocalCommand, and forwarding rules for this target. External links cannot supply arbitrary SSH options. Only continue if you trust this SSH target." } }, - "pt-BR": { + "ja": { "stringUnit": { "state": "translated", - "value": "Fechar Aba" + "value": "%@:// リンクが SSH ワークスペースを開くよう cmux に要求しています。cmux は、このリンクを開いた Web サイトやアプリを確認できません。\n\nSSH はこの接続先に対して、ローカルの SSH 設定、鍵、エージェント設定、ProxyCommand、LocalCommand、ポート転送ルールを使用する場合があります。外部リンクは任意の SSH オプションを指定できません。この SSH 接続先を信頼している場合のみ続行してください。" } - }, - "th": { + } + } + }, + "dialog.sshURL.run": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "ปิดแท็บ" + "value": "Connect" } }, - "tr": { + "ja": { "stringUnit": { "state": "translated", - "value": "Sekmeyi Kapat" + "value": "接続" + } + } + } + }, + "dialog.sshURL.title": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Open an SSH Connection From an External Link?" } }, - "uk": { + "ja": { "stringUnit": { "state": "translated", - "value": "Закрити вкладку" + "value": "外部リンクから SSH 接続を開きますか?" } } } }, - "command.closeWindow.subtitle": { + "dialog.cmuxConfig.confirmCommand.messageWithCommand": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Window" + "value": "This project action comes from:\n\n%@\n\nIt will run:\n\n%@" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ウインドウ" + "value": "このプロジェクトアクションは次の設定から読み込まれました:\n\n%@\n\n実行内容:\n\n%@" } - }, - "zh-Hans": { + } + } + }, + "dialog.cmuxConfig.confirmCommand.run": { + "extractionState": "manual", + "localizations": { + "ar": { "stringUnit": { "state": "translated", - "value": "窗口" + "value": "تشغيل" } }, - "zh-Hant": { + "bs": { "stringUnit": { "state": "translated", - "value": "視窗" + "value": "Pokreni" } }, - "ko": { + "da": { "stringUnit": { "state": "translated", - "value": "윈도우" + "value": "Kør" } }, "de": { "stringUnit": { "state": "translated", - "value": "Fenster" + "value": "Ausführen" + } + }, + "en": { + "stringUnit": { + "state": "translated", + "value": "Run Once" } }, "es": { "stringUnit": { "state": "translated", - "value": "Ventana" + "value": "Ejecutar" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Fenêtre" + "value": "Exécuter" } }, "it": { "stringUnit": { "state": "translated", - "value": "Finestra" + "value": "Esegui" } }, - "da": { + "ja": { "stringUnit": { "state": "translated", - "value": "Vindue" + "value": "1回のみ実行" } }, - "pl": { + "ko": { "stringUnit": { "state": "translated", - "value": "Okno" + "value": "실행" } }, - "ru": { + "nb": { "stringUnit": { "state": "translated", - "value": "Окно" + "value": "Kjør" } }, - "bs": { + "pl": { "stringUnit": { "state": "translated", - "value": "Prozor" + "value": "Uruchom" } }, - "ar": { + "pt-BR": { "stringUnit": { "state": "translated", - "value": "نافذة" + "value": "Executar" } }, - "nb": { + "ru": { "stringUnit": { "state": "translated", - "value": "Vindu" + "value": "Выполнить" } }, - "pt-BR": { + "th": { "stringUnit": { "state": "translated", - "value": "Janela" + "value": "รัน" } }, - "th": { + "tr": { "stringUnit": { "state": "translated", - "value": "หน้าต่าง" + "value": "Çalıştır" } }, - "tr": { + "zh-Hans": { "stringUnit": { "state": "translated", - "value": "Pencere" + "value": "运行" + } + }, + "zh-Hant": { + "stringUnit": { + "state": "translated", + "value": "執行" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Вікно" + "value": "Виконати" } } } }, - "command.closeWindow.title": { + "dialog.cmuxConfig.confirmCommand.trustAndRun": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Close Window" + "value": "Trust and Run" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ウインドウを閉じる" + "value": "信頼して実行" } - }, - "zh-Hans": { + } + } + }, + "dialog.cmuxConfig.confirmCommand.title": { + "extractionState": "manual", + "localizations": { + "ar": { "stringUnit": { "state": "translated", - "value": "关闭窗口" + "value": "تشغيل الأمر" } }, - "zh-Hant": { + "bs": { "stringUnit": { "state": "translated", - "value": "關閉視窗" + "value": "Pokreni naredbu" } }, - "ko": { + "da": { "stringUnit": { "state": "translated", - "value": "윈도우 닫기" + "value": "Kør kommando" } }, "de": { "stringUnit": { "state": "translated", - "value": "Fenster schließen" + "value": "Befehl ausführen" } }, - "es": { + "en": { "stringUnit": { "state": "translated", - "value": "Cerrar ventana" + "value": "Run Project Action?" } }, - "fr": { + "es": { "stringUnit": { "state": "translated", - "value": "Fermer la fenêtre" + "value": "Ejecutar comando" } }, - "it": { + "fr": { "stringUnit": { "state": "translated", - "value": "Chiudi finestra" + "value": "Exécuter la commande" } }, - "da": { + "it": { "stringUnit": { "state": "translated", - "value": "Luk vindue" + "value": "Esegui comando" } }, - "pl": { + "ja": { "stringUnit": { "state": "translated", - "value": "Zamknij okno" + "value": "プロジェクトアクションを実行しますか?" } }, - "ru": { + "ko": { "stringUnit": { "state": "translated", - "value": "Закрыть окно" + "value": "명령 실행" } }, - "bs": { + "nb": { "stringUnit": { "state": "translated", - "value": "Zatvori prozor" + "value": "Kjør kommando" } }, - "ar": { + "pl": { "stringUnit": { "state": "translated", - "value": "إغلاق النافذة" + "value": "Uruchom polecenie" } }, - "nb": { + "pt-BR": { "stringUnit": { "state": "translated", - "value": "Lukk vindu" + "value": "Executar comando" } }, - "pt-BR": { + "ru": { "stringUnit": { "state": "translated", - "value": "Fechar Janela" + "value": "Выполнить команду" } }, "th": { "stringUnit": { "state": "translated", - "value": "ปิดหน้าต่าง" + "value": "รันคำสั่ง" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Pencereyi Kapat" + "value": "Komutu Çalıştır" } }, - "uk": { - "stringUnit": { - "state": "translated", - "value": "Закрити вікно" - } - } - } - }, - "command.copyPaneID.title": { - "extractionState": "manual", - "localizations": { - "en": { + "zh-Hans": { "stringUnit": { "state": "translated", - "value": "Copy Pane ID" + "value": "运行命令" } }, - "ja": { + "zh-Hant": { "stringUnit": { "state": "translated", - "value": "ペインIDをコピー" + "value": "執行命令" } }, - "ko": { + "uk": { "stringUnit": { "state": "translated", - "value": "패널 ID 복사" + "value": "Виконати команду" } } } }, - "command.copySurfaceID.title": { + "dialog.cmuxConfig.confirmRestart.cancel": { "extractionState": "manual", "localizations": { - "en": { + "ar": { "stringUnit": { "state": "translated", - "value": "Copy Surface ID" + "value": "إلغاء" } }, - "ja": { + "bs": { "stringUnit": { "state": "translated", - "value": "サーフェスIDをコピー" + "value": "Otkaži" } }, - "ko": { + "da": { "stringUnit": { "state": "translated", - "value": "서피스 ID 복사" + "value": "Annuller" } - } - } - }, - "command.copyWorkspaceIDAndRef.title": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "de": { "stringUnit": { "state": "translated", - "value": "Copy Workspace ID and Ref" + "value": "Abbrechen" } }, - "ja": { + "en": { "stringUnit": { "state": "translated", - "value": "ワークスペースIDと参照をコピー" + "value": "Cancel" } }, - "ko": { + "es": { "stringUnit": { "state": "translated", - "value": "워크스페이스 ID 및 참조 복사" + "value": "Cancelar" } - } - } - }, - "command.closeWorkspace.subtitle": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "fr": { "stringUnit": { "state": "translated", - "value": "Workspace" + "value": "Annuler" } }, - "ja": { + "it": { "stringUnit": { "state": "translated", - "value": "ワークスペース" + "value": "Annulla" } }, - "zh-Hans": { + "ja": { "stringUnit": { "state": "translated", - "value": "工作区" + "value": "キャンセル" } }, - "zh-Hant": { + "ko": { "stringUnit": { "state": "translated", - "value": "工作區" + "value": "취소" } }, - "ko": { + "nb": { "stringUnit": { "state": "translated", - "value": "작업 공간" + "value": "Avbryt" } }, - "de": { + "pl": { "stringUnit": { "state": "translated", - "value": "Arbeitsbereich" + "value": "Anuluj" } }, - "es": { + "pt-BR": { "stringUnit": { "state": "translated", - "value": "Espacio de trabajo" + "value": "Cancelar" } }, - "fr": { + "ru": { "stringUnit": { "state": "translated", - "value": "Espace de travail" + "value": "Отмена" } }, - "it": { + "th": { "stringUnit": { "state": "translated", - "value": "Area di lavoro" + "value": "ยกเลิก" } }, - "da": { + "tr": { "stringUnit": { "state": "translated", - "value": "Arbejdsområde" + "value": "İptal" } }, - "pl": { + "zh-Hans": { "stringUnit": { "state": "translated", - "value": "Przestrzeń robocza" + "value": "取消" } }, - "ru": { + "zh-Hant": { "stringUnit": { "state": "translated", - "value": "Рабочее пространство" + "value": "取消" + } + }, + "uk": { + "stringUnit": { + "state": "translated", + "value": "Скасувати" + } + } + } + }, + "dialog.cmuxConfig.confirmRestart.message": { + "extractionState": "manual", + "localizations": { + "ar": { + "stringUnit": { + "state": "translated", + "value": "مساحة العمل بهذا الاسم موجودة بالفعل. هل تريد إغلاقها وإنشاء واحدة جديدة؟" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Radni prostor" + "value": "Radni prostor s ovim imenom već postoji. Zatvoriti ga i kreirati novi?" } }, - "ar": { + "da": { "stringUnit": { "state": "translated", - "value": "مساحة العمل" + "value": "Et arbejdsområde med dette navn eksisterer allerede. Luk det og opret et nyt?" + } + }, + "de": { + "stringUnit": { + "state": "translated", + "value": "Ein Arbeitsbereich mit diesem Namen existiert bereits. Schließen und neu erstellen?" + } + }, + "en": { + "stringUnit": { + "state": "translated", + "value": "A workspace with this name already exists. Close it and create a new one?" + } + }, + "es": { + "stringUnit": { + "state": "translated", + "value": "Ya existe un espacio de trabajo con este nombre. ¿Cerrarlo y crear uno nuevo?" + } + }, + "fr": { + "stringUnit": { + "state": "translated", + "value": "Un espace de travail portant ce nom existe déjà. Le fermer et en créer un nouveau ?" + } + }, + "it": { + "stringUnit": { + "state": "translated", + "value": "Esiste già un'area di lavoro con questo nome. Chiuderla e crearne una nuova?" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "この名前のワークスペースは既に存在します。閉じて新しく作成しますか?" + } + }, + "ko": { + "stringUnit": { + "state": "translated", + "value": "같은 이름의 워크스페이스가 이미 있습니다. 닫고 새로 만드시겠습니까?" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Arbeidsområde" + "value": "Et arbeidsområde med dette navnet finnes allerede. Lukke det og opprette et nytt?" + } + }, + "pl": { + "stringUnit": { + "state": "translated", + "value": "Przestrzeń robocza o tej nazwie już istnieje. Zamknąć ją i utworzyć nową?" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Área de Trabalho" + "value": "Um espaço de trabalho com este nome já existe. Fechar e criar um novo?" + } + }, + "ru": { + "stringUnit": { + "state": "translated", + "value": "Рабочая область с таким именем уже существует. Закрыть её и создать новую?" } }, "th": { "stringUnit": { "state": "translated", - "value": "เวิร์กสเปซ" + "value": "พื้นที่ทำงานที่มีชื่อนี้มีอยู่แล้ว ปิดและสร้างใหม่หรือไม่?" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Çalışma Alanı" + "value": "Bu adda bir çalışma alanı zaten var. Kapatıp yenisini oluşturulsun mu?" + } + }, + "zh-Hans": { + "stringUnit": { + "state": "translated", + "value": "同名工作区已存在。关闭并新建吗?" + } + }, + "zh-Hant": { + "stringUnit": { + "state": "translated", + "value": "同名工作區已存在。關閉並新建嗎?" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Робоча область" + "value": "Робоча область з такою назвою вже існує. Закрити її та створити нову?" } } } }, - "command.closeWorkspace.title": { + "dialog.cmuxConfig.confirmRestart.recreate": { "extractionState": "manual", "localizations": { - "en": { + "ar": { "stringUnit": { "state": "translated", - "value": "Close Workspace" + "value": "إعادة إنشاء" } }, - "ja": { + "bs": { "stringUnit": { "state": "translated", - "value": "ワークスペースを閉じる" + "value": "Ponovo kreiraj" } }, - "zh-Hans": { + "da": { "stringUnit": { "state": "translated", - "value": "关闭工作区" + "value": "Genskab" } }, - "zh-Hant": { + "de": { "stringUnit": { "state": "translated", - "value": "關閉工作區" + "value": "Neu erstellen" } }, - "ko": { + "en": { "stringUnit": { "state": "translated", - "value": "작업 공간 닫기" + "value": "Recreate" } }, - "de": { + "es": { "stringUnit": { "state": "translated", - "value": "Arbeitsbereich schließen" + "value": "Recrear" } }, - "es": { + "fr": { "stringUnit": { "state": "translated", - "value": "Cerrar espacio de trabajo" + "value": "Recréer" } }, - "fr": { + "it": { "stringUnit": { "state": "translated", - "value": "Fermer l'espace de travail" + "value": "Ricrea" } }, - "it": { + "ja": { "stringUnit": { "state": "translated", - "value": "Chiudi area di lavoro" + "value": "再作成" } }, - "da": { + "ko": { "stringUnit": { "state": "translated", - "value": "Luk arbejdsområde" + "value": "다시 만들기" } }, - "pl": { + "nb": { "stringUnit": { "state": "translated", - "value": "Zamknij przestrzeń roboczą" + "value": "Opprett på nytt" } }, - "ru": { + "pl": { "stringUnit": { "state": "translated", - "value": "Закрыть рабочее пространство" + "value": "Utwórz ponownie" } }, - "bs": { + "pt-BR": { "stringUnit": { "state": "translated", - "value": "Zatvori radni prostor" + "value": "Recriar" } }, - "ar": { + "ru": { "stringUnit": { "state": "translated", - "value": "إغلاق مساحة العمل" + "value": "Пересоздать" } }, - "nb": { + "th": { "stringUnit": { "state": "translated", - "value": "Lukk arbeidsområde" + "value": "สร้างใหม่" } }, - "pt-BR": { + "tr": { "stringUnit": { "state": "translated", - "value": "Fechar Área de Trabalho" + "value": "Yeniden Oluştur" } }, - "th": { + "zh-Hans": { "stringUnit": { "state": "translated", - "value": "ปิดเวิร์กสเปซ" + "value": "重新创建" } }, - "tr": { + "zh-Hant": { "stringUnit": { "state": "translated", - "value": "Çalışma Alanını Kapat" + "value": "重新建立" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Закрити робочу область" + "value": "Створити заново" } } } }, - "dialog.cmuxConfig.confirmCommand.cancel": { + "dialog.cmuxConfig.confirmRestart.title": { "extractionState": "manual", "localizations": { "ar": { "stringUnit": { "state": "translated", - "value": "إلغاء" + "value": "مساحة العمل موجودة بالفعل" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Otkaži" + "value": "Radni prostor već postoji" } }, "da": { "stringUnit": { "state": "translated", - "value": "Annuller" + "value": "Arbejdsområdet eksisterer allerede" } }, "de": { "stringUnit": { "state": "translated", - "value": "Abbrechen" + "value": "Arbeitsbereich existiert bereits" } }, "en": { "stringUnit": { "state": "translated", - "value": "Cancel" + "value": "Workspace Already Exists" } }, "es": { "stringUnit": { "state": "translated", - "value": "Cancelar" + "value": "El espacio de trabajo ya existe" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Annuler" + "value": "L'espace de travail existe déjà" } }, "it": { "stringUnit": { "state": "translated", - "value": "Annulla" + "value": "L'area di lavoro esiste già" } }, "ja": { "stringUnit": { "state": "translated", - "value": "キャンセル" + "value": "ワークスペースは既に存在します" } }, "ko": { "stringUnit": { "state": "translated", - "value": "취소" + "value": "워크스페이스가 이미 존재합니다" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Avbryt" + "value": "Arbeidsområdet finnes allerede" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Anuluj" + "value": "Przestrzeń robocza już istnieje" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Cancelar" + "value": "O espaço de trabalho já existe" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Отмена" + "value": "Рабочая область уже существует" } }, "th": { "stringUnit": { "state": "translated", - "value": "ยกเลิก" + "value": "พื้นที่ทำงานมีอยู่แล้ว" } }, "tr": { "stringUnit": { "state": "translated", - "value": "İptal" + "value": "Çalışma Alanı Zaten Var" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "取消" + "value": "工作区已存在" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "取消" + "value": "工作區已存在" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Скасувати" + "value": "Робоча область вже існує" } } } }, - "dialog.sshURL.blocked.ok": { + "command.cmuxConfig.subtitle": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "OK" + "value": "cmux.json" } }, "ja": { "stringUnit": { "state": "translated", - "value": "OK" + "value": "cmux.json" } - } - } - }, - "dialog.sshURL.blocked.title": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "zh-Hans": { "stringUnit": { "state": "translated", - "value": "cmux SSH Link Blocked" + "value": "cmux.json" } }, - "ja": { + "zh-Hant": { "stringUnit": { "state": "translated", - "value": "cmux SSH リンクをブロックしました" + "value": "cmux.json" } - } - } - }, - "dialog.sshURL.launchFailed.exit": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "ko": { "stringUnit": { "state": "translated", - "value": "cmux ssh exited with status %d." + "value": "cmux.json" } }, - "ja": { + "de": { "stringUnit": { "state": "translated", - "value": "cmux ssh はステータス %d で終了しました。" + "value": "cmux.json" } - } - } - }, - "dialog.sshURL.launchFailed.launch": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "es": { "stringUnit": { "state": "translated", - "value": "cmux ssh could not be launched." + "value": "cmux.json" } }, - "ja": { + "fr": { "stringUnit": { "state": "translated", - "value": "cmux ssh を起動できませんでした。" + "value": "cmux.json" } - } - } - }, - "dialog.sshURL.launchFailed.missingCLI": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "it": { "stringUnit": { "state": "translated", - "value": "The bundled cmux CLI is missing from this app build." + "value": "cmux.json" } }, - "ja": { + "da": { "stringUnit": { "state": "translated", - "value": "このアプリビルドに同梱されている cmux CLI が見つかりません。" + "value": "cmux.json" } - } - } - }, - "dialog.sshURL.launchFailed.title": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "pl": { "stringUnit": { "state": "translated", - "value": "Couldn't Open SSH Link" + "value": "cmux.json" } }, - "ja": { + "ru": { "stringUnit": { "state": "translated", - "value": "SSH リンクを開けませんでした" + "value": "cmux.json" } - } - } - }, - "dialog.sshURL.cancel": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "bs": { "stringUnit": { "state": "translated", - "value": "Cancel" + "value": "cmux.json" } }, - "ja": { + "ar": { "stringUnit": { "state": "translated", - "value": "キャンセル" + "value": "cmux.json" + } + }, + "nb": { + "stringUnit": { + "state": "translated", + "value": "cmux.json" + } + }, + "pt-BR": { + "stringUnit": { + "state": "translated", + "value": "cmux.json" + } + }, + "th": { + "stringUnit": { + "state": "translated", + "value": "cmux.json" + } + }, + "tr": { + "stringUnit": { + "state": "translated", + "value": "cmux.json" + } + }, + "uk": { + "stringUnit": { + "state": "translated", + "value": "cmux.json" } } } }, - "dialog.sshURL.checkbox": { + "command.cmuxConfig.defaultClaudeCodeTitle": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "I trust this SSH target and want cmux to connect." + "value": "Claude Code" } }, "ja": { "stringUnit": { "state": "translated", - "value": "この SSH 接続先を信頼し、cmux で接続することに同意します。" + "value": "Claude Code" } } } }, - "dialog.sshURL.commandLabel": { + "command.cmuxConfig.defaultCodexTitle": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Command preview:" + "value": "Codex" } }, "ja": { "stringUnit": { "state": "translated", - "value": "コマンドのプレビュー:" + "value": "Codex" } } } }, - "dialog.sshURL.targetLabel": { + "agent.codex.error.defaultMessage": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "SSH target: %@" + "value": "Codex reported an error" } }, "ja": { "stringUnit": { "state": "translated", - "value": "SSH 接続先: %@" + "value": "Codex でエラーが発生しました" } } } }, - "dialog.sshURL.error.destinationContainsUnsafeCharacters": { + "agent.codex.error.noFinalResponse": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "The SSH host or user contains unsupported or hidden characters, so cmux refused to use it." + "value": "Codex ended before sending a final response" } }, "ja": { "stringUnit": { "state": "translated", - "value": "SSH ホストまたはユーザーに未対応の文字または隠れた文字が含まれているため、cmux は使用を拒否しました。" + "value": "Codex は最終応答を送信する前に終了しました" } } } }, - "dialog.sshURL.error.destinationTooLong": { + "agent.claude.completion.subtitle.completed": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "The SSH target is too long. The maximum length is %lld characters." + "value": "Completed" } }, "ja": { "stringUnit": { "state": "translated", - "value": "SSH 接続先が長すぎます。最大長は %lld 文字です。" + "value": "完了" } } } }, - "dialog.sshURL.error.missingDestination": { + "agent.claude.completion.subtitle.completedInProject": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "The link did not include an SSH host." + "value": "Completed in %@" } }, "ja": { "stringUnit": { "state": "translated", - "value": "リンクに SSH ホストが含まれていません。" + "value": "%@ で完了" } } } }, - "dialog.sshURL.error.multipleLinks": { + "agent.codex.completion.body.sessionCompleted": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Only one SSH link can be opened at a time." + "value": "%@ session completed" } }, "ja": { "stringUnit": { "state": "translated", - "value": "一度に開ける SSH リンクは 1 つだけです。" + "value": "%@ セッションが完了しました" } } } }, - "dialog.sshURL.error.titleContainsControlCharacters": { + "agent.codex.completion.subtitle.completed": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "The workspace title contains hidden control or formatting characters, so cmux refused to use it." + "value": "Completed" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ワークスペース名に隠れた制御文字または書式制御文字が含まれているため、cmux は使用を拒否しました。" + "value": "完了" } } } }, - "dialog.sshURL.error.titleTooLong": { + "agent.codex.completion.subtitle.completedInProject": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "The workspace title is too long. The maximum length is %lld characters." + "value": "Completed in %@" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ワークスペース名が長すぎます。最大長は %lld 文字です。" + "value": "%@ で完了" } } } }, - "dialog.sshURL.error.invalidIntegerParameter": { + "agent.codex.error.status.auth": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "The SSH link included an invalid integer value for parameter: %@" + "value": "Codex auth error" } }, "ja": { "stringUnit": { "state": "translated", - "value": "SSH リンクのパラメータに無効な整数値が含まれています: %@" + "value": "Codex 認証エラー" } } } }, - "dialog.sshURL.error.invalidHostKeyPolicy": { + "agent.codex.error.status.generic": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "The SSH link included an invalid host key policy for parameter: %@" + "value": "Codex error" } }, "ja": { "stringUnit": { "state": "translated", - "value": "SSH リンクのパラメータに無効なホストキー確認ポリシーが含まれています: %@" + "value": "Codex エラー" } } } }, - "dialog.sshURL.error.destinationStartsWithDash": { + "agent.codex.error.status.network": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "The SSH host or user cannot start with a dash." + "value": "Codex network error" } }, "ja": { "stringUnit": { "state": "translated", - "value": "SSH ホストまたはユーザーをダッシュで始めることはできません。" + "value": "Codex ネットワークエラー" } } } }, - "dialog.sshURL.error.conflictingDestinationParameters": { + "agent.codex.error.status.rateLimit": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "The link included conflicting SSH target fields." + "value": "Codex rate limit" } }, "ja": { "stringUnit": { "state": "translated", - "value": "リンクに競合する SSH 接続先フィールドが含まれています。" + "value": "Codex レート制限" } } } }, - "dialog.sshURL.error.conflictingTitleParameters": { + "agent.codex.input.body.needsInput": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "The link included both title and name. Use only one workspace title field." + "value": "Codex is asking a question" } }, "ja": { "stringUnit": { "state": "translated", - "value": "リンクに title と name の両方が含まれています。ワークスペース名のフィールドは 1 つだけ使用してください。" + "value": "Codex が質問しています" } } } }, - "dialog.sshURL.error.duplicateParameter": { + "agent.codex.input.status.needsInput": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "The SSH link repeated a parameter: %@" + "value": "Codex needs input" } }, "ja": { "stringUnit": { "state": "translated", - "value": "SSH リンクで同じパラメータが繰り返されています: %@" + "value": "Codex 入力待ち" } } } }, - "dialog.sshURL.error.unsupportedParameter": { + "agent.codex.input.subtitle.waiting": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "The SSH link included an unsupported parameter: %@" + "value": "Waiting" } }, "ja": { "stringUnit": { "state": "translated", - "value": "SSH リンクに未対応のパラメータが含まれています: %@" + "value": "待機状態" } } } }, - "dialog.sshURL.error.invalidPort": { + "agent.codex.status.idle": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "The SSH port must be between 1 and 65535." + "value": "Idle" } }, "ja": { "stringUnit": { "state": "translated", - "value": "SSH ポートは 1 から 65535 の範囲で指定してください。" + "value": "入力待ち" } } } }, - "dialog.sshURL.error.invalidBooleanParameter": { + "agent.generic.notification.body.approvalNeeded": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "The SSH link included an invalid boolean value for parameter: %@" + "value": "Approval needed" } }, "ja": { "stringUnit": { "state": "translated", - "value": "SSH リンクのパラメータに無効な真偽値が含まれています: %@" + "value": "承認が必要です" } } } }, - "dialog.sshURL.message": { + "agent.generic.notification.body.needsAttention": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "A %@:// link is asking cmux to open an SSH workspace. cmux cannot verify which website or app opened this link.\n\nSSH may use your local SSH config, keys, agent settings, ProxyCommand, LocalCommand, and forwarding rules for this target. External links cannot supply arbitrary SSH options. Only continue if you trust this SSH target." + "value": "%@ needs your attention" } }, "ja": { "stringUnit": { "state": "translated", - "value": "%@:// リンクが SSH ワークスペースを開くよう cmux に要求しています。cmux は、このリンクを開いた Web サイトやアプリを確認できません。\n\nSSH はこの接続先に対して、ローカルの SSH 設定、鍵、エージェント設定、ProxyCommand、LocalCommand、ポート転送ルールを使用する場合があります。外部リンクは任意の SSH オプションを指定できません。この SSH 接続先を信頼している場合のみ続行してください。" + "value": "%@ の確認が必要です" } } } }, - "dialog.sshURL.run": { + "agent.generic.notification.body.reportedError": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Connect" + "value": "%@ reported an error" } }, "ja": { "stringUnit": { "state": "translated", - "value": "接続" + "value": "%@ がエラーを報告しました" } } } }, - "dialog.sshURL.title": { + "agent.generic.notification.body.sentNotification": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Open an SSH Connection From an External Link?" + "value": "%@ sent a notification" } }, "ja": { "stringUnit": { "state": "translated", - "value": "外部リンクから SSH 接続を開きますか?" + "value": "%@ から通知が届きました" } } } }, - "dialog.cmuxConfig.confirmCommand.messageWithCommand": { + "agent.generic.notification.body.taskCompleted": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "This project action comes from:\n\n%@\n\nIt will run:\n\n%@" + "value": "Task completed" } }, "ja": { "stringUnit": { "state": "translated", - "value": "このプロジェクトアクションは次の設定から読み込まれました:\n\n%@\n\n実行内容:\n\n%@" + "value": "タスクが完了しました" } } } }, - "dialog.cmuxConfig.confirmCommand.run": { + "agent.generic.notification.body.waitingForInput": { "extractionState": "manual", "localizations": { - "ar": { + "en": { "stringUnit": { "state": "translated", - "value": "تشغيل" + "value": "Waiting for input" } }, - "bs": { + "ja": { "stringUnit": { "state": "translated", - "value": "Pokreni" + "value": "入力待ち" } - }, - "da": { + } + } + }, + "agent.generic.notification.status.error": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Kør" + "value": "%@ error" } }, - "de": { + "ja": { "stringUnit": { "state": "translated", - "value": "Ausführen" + "value": "%@ エラー" } - }, + } + } + }, + "agent.generic.notification.status.idle": { + "extractionState": "manual", + "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Run Once" + "value": "Idle" } }, - "es": { + "ja": { "stringUnit": { "state": "translated", - "value": "Ejecutar" + "value": "待機中" } - }, - "fr": { + } + } + }, + "agent.generic.notification.status.needsInput": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Exécuter" + "value": "%@ needs input" } }, - "it": { + "ja": { "stringUnit": { "state": "translated", - "value": "Esegui" + "value": "%@ 入力待ち" + } + } + } + }, + "agent.generic.notification.subtitle.attention": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Attention" } }, "ja": { "stringUnit": { "state": "translated", - "value": "1回のみ実行" + "value": "確認" } - }, - "ko": { + } + } + }, + "agent.generic.notification.subtitle.completed": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "실행" + "value": "Completed" } }, - "nb": { + "ja": { "stringUnit": { "state": "translated", - "value": "Kjør" + "value": "完了" } - }, - "pl": { + } + } + }, + "agent.generic.notification.subtitle.error": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Uruchom" + "value": "Error" } }, - "pt-BR": { + "ja": { "stringUnit": { "state": "translated", - "value": "Executar" + "value": "エラー" } - }, - "ru": { + } + } + }, + "agent.generic.notification.subtitle.permission": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Выполнить" + "value": "Permission" } }, - "th": { + "ja": { "stringUnit": { "state": "translated", - "value": "รัน" + "value": "権限" + } + } + } + }, + "agent.generic.notification.subtitle.waiting": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Waiting" } }, - "tr": { + "ja": { "stringUnit": { "state": "translated", - "value": "Çalıştır" + "value": "待機中" + } + } + } + }, + "agent.codex.error.subtitle.auth": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Auth error" } }, - "zh-Hans": { + "ja": { "stringUnit": { "state": "translated", - "value": "运行" + "value": "認証エラー" + } + } + } + }, + "agent.codex.error.subtitle.generic": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Error" } }, - "zh-Hant": { + "ja": { "stringUnit": { "state": "translated", - "value": "執行" + "value": "エラー" + } + } + } + }, + "agent.codex.error.subtitle.network": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Network error" } }, - "uk": { + "ja": { "stringUnit": { "state": "translated", - "value": "Виконати" + "value": "ネットワークエラー" } } } }, - "dialog.cmuxConfig.confirmCommand.trustAndRun": { + "agent.codex.error.subtitle.rateLimit": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Trust and Run" + "value": "Rate limit" } }, "ja": { "stringUnit": { "state": "translated", - "value": "信頼して実行" + "value": "レート制限" } } } }, - "dialog.cmuxConfig.confirmCommand.title": { + "command.cmuxConfig.customTitle": { "extractionState": "manual", "localizations": { "ar": { "stringUnit": { "state": "translated", - "value": "تشغيل الأمر" + "value": "مخصص: %@" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Pokreni naredbu" + "value": "Prilagođeno: %@" } }, "da": { "stringUnit": { "state": "translated", - "value": "Kør kommando" + "value": "Brugerdefineret: %@" } }, "de": { "stringUnit": { "state": "translated", - "value": "Befehl ausführen" + "value": "Benutzerdefiniert: %@" } }, "en": { "stringUnit": { "state": "translated", - "value": "Run Project Action?" + "value": "Custom: %@" } }, "es": { "stringUnit": { "state": "translated", - "value": "Ejecutar comando" + "value": "Personalizado: %@" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Exécuter la commande" + "value": "Personnalisé : %@" } }, "it": { "stringUnit": { "state": "translated", - "value": "Esegui comando" + "value": "Personalizzato: %@" } }, "ja": { "stringUnit": { "state": "translated", - "value": "プロジェクトアクションを実行しますか?" + "value": "カスタム: %@" } }, "ko": { "stringUnit": { "state": "translated", - "value": "명령 실행" + "value": "사용자 정의: %@" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Kjør kommando" + "value": "Egendefinert: %@" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Uruchom polecenie" + "value": "Niestandardowe: %@" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Executar comando" + "value": "Personalizado: %@" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Выполнить команду" + "value": "Пользовательское: %@" } }, "th": { "stringUnit": { "state": "translated", - "value": "รันคำสั่ง" + "value": "กำหนดเอง: %@" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Komutu Çalıştır" + "value": "Özel: %@" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "运行命令" + "value": "自定义: %@" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "執行命令" + "value": "自訂: %@" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Виконати команду" + "value": "Власне: %@" } } } }, - "dialog.cmuxConfig.confirmRestart.cancel": { + "command.cmuxConfig.issue.newWorkspaceActionRequiresWorkspaceCommand.detail": { "extractionState": "manual", "localizations": { - "ar": { + "en": { "stringUnit": { "state": "translated", - "value": "إلغاء" + "value": "%@ must reference a workspace command action" } }, - "bs": { + "ja": { "stringUnit": { "state": "translated", - "value": "Otkaži" + "value": "%@ はワークスペースコマンドアクションを参照する必要があります" } - }, - "da": { + } + } + }, + "command.cmuxConfig.issue.newWorkspaceActionNotFound.detail": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Annuller" + "value": "%@ references missing action '%@'" } }, - "de": { + "ja": { "stringUnit": { "state": "translated", - "value": "Abbrechen" + "value": "%@ は存在しないアクション '%@' を参照しています" } - }, + } + } + }, + "command.cmuxConfig.issue.newWorkspaceCommandNotFound.detail": { + "extractionState": "manual", + "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Cancel" - } - }, - "es": { - "stringUnit": { - "state": "translated", - "value": "Cancelar" + "value": "%@ references missing command '%@'" } }, - "fr": { + "ja": { "stringUnit": { "state": "translated", - "value": "Annuler" + "value": "%@ は存在しないコマンド '%@' を参照しています" } - }, - "it": { + } + } + }, + "command.cmuxConfig.issue.newWorkspaceCommandRequiresWorkspace.detail": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Annulla" + "value": "%@ '%@' must reference a workspace command" } }, "ja": { "stringUnit": { "state": "translated", - "value": "キャンセル" + "value": "%@ '%@' はワークスペースコマンドを参照する必要があります" } - }, - "ko": { + } + } + }, + "command.cmuxConfig.issue.schemaError.detail": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "취소" + "value": "%@" } }, - "nb": { + "ja": { "stringUnit": { "state": "translated", - "value": "Avbryt" + "value": "%@" } - }, - "pl": { + } + } + }, + "command.cmuxConfig.issue.schemaError.fallback": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Anuluj" + "value": "Invalid cmux.json" } }, - "pt-BR": { + "ja": { "stringUnit": { "state": "translated", - "value": "Cancelar" + "value": "無効な cmux.json" } - }, - "ru": { + } + } + }, + "command.cmuxConfig.issue.schemaError.title": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Отмена" + "value": "cmux.json Schema Error" } }, - "th": { + "ja": { "stringUnit": { "state": "translated", - "value": "ยกเลิก" + "value": "cmux.json スキーマエラー" } - }, - "tr": { + } + } + }, + "command.cmuxConfig.issue.subtitle": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "İptal" + "value": "%@: %@" } }, - "zh-Hans": { + "ja": { "stringUnit": { "state": "translated", - "value": "取消" + "value": "%@: %@" } - }, - "zh-Hant": { + } + } + }, + "command.cmuxConfig.issue.warning.title": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "取消" + "value": "cmux.json Configuration Warning" } }, - "uk": { + "ja": { "stringUnit": { "state": "translated", - "value": "Скасувати" + "value": "cmux.json 設定警告" } } } }, - "dialog.cmuxConfig.confirmRestart.message": { + "command.equalizeSplits.title": { "extractionState": "manual", "localizations": { - "ar": { + "en": { "stringUnit": { "state": "translated", - "value": "مساحة العمل بهذا الاسم موجودة بالفعل. هل تريد إغلاقها وإنشاء واحدة جديدة؟" + "value": "Equalize Splits" } }, - "bs": { + "ja": { "stringUnit": { "state": "translated", - "value": "Radni prostor s ovim imenom već postoji. Zatvoriti ga i kreirati novi?" + "value": "分割を均等にする" } }, - "da": { + "zh-Hans": { "stringUnit": { "state": "translated", - "value": "Et arbejdsområde med dette navn eksisterer allerede. Luk det og opret et nyt?" + "value": "均分面板" } }, - "de": { + "zh-Hant": { "stringUnit": { "state": "translated", - "value": "Ein Arbeitsbereich mit diesem Namen existiert bereits. Schließen und neu erstellen?" + "value": "均等分割" } }, - "en": { + "ko": { "stringUnit": { "state": "translated", - "value": "A workspace with this name already exists. Close it and create a new one?" + "value": "분할 균등화" } }, - "es": { + "de": { "stringUnit": { "state": "translated", - "value": "Ya existe un espacio de trabajo con este nombre. ¿Cerrarlo y crear uno nuevo?" + "value": "Teilungen angleichen" } }, - "fr": { + "es": { "stringUnit": { "state": "translated", - "value": "Un espace de travail portant ce nom existe déjà. Le fermer et en créer un nouveau ?" + "value": "Igualar divisiones" } }, - "it": { + "fr": { "stringUnit": { "state": "translated", - "value": "Esiste già un'area di lavoro con questo nome. Chiuderla e crearne una nuova?" + "value": "Égaliser les divisions" } }, - "ja": { + "it": { "stringUnit": { "state": "translated", - "value": "この名前のワークスペースは既に存在します。閉じて新しく作成しますか?" + "value": "Equalizza divisioni" } }, - "ko": { + "da": { "stringUnit": { "state": "translated", - "value": "같은 이름의 워크스페이스가 이미 있습니다. 닫고 새로 만드시겠습니까?" + "value": "Udlign opdelinger" } }, - "nb": { + "pl": { "stringUnit": { "state": "translated", - "value": "Et arbeidsområde med dette navnet finnes allerede. Lukke det og opprette et nytt?" + "value": "Wyrównaj podziały" } }, - "pl": { + "ru": { "stringUnit": { "state": "translated", - "value": "Przestrzeń robocza o tej nazwie już istnieje. Zamknąć ją i utworzyć nową?" + "value": "Выровнять разделение" } }, - "pt-BR": { + "bs": { "stringUnit": { "state": "translated", - "value": "Um espaço de trabalho com este nome já existe. Fechar e criar um novo?" + "value": "Izjednači podjele" } }, - "ru": { + "ar": { "stringUnit": { "state": "translated", - "value": "Рабочая область с таким именем уже существует. Закрыть её и создать новую?" + "value": "تسوية التقسيمات" } }, - "th": { + "nb": { "stringUnit": { "state": "translated", - "value": "พื้นที่ทำงานที่มีชื่อนี้มีอยู่แล้ว ปิดและสร้างใหม่หรือไม่?" + "value": "Gjør delinger like" } }, - "tr": { + "pt-BR": { "stringUnit": { "state": "translated", - "value": "Bu adda bir çalışma alanı zaten var. Kapatıp yenisini oluşturulsun mu?" + "value": "Equalizar Divisões" } }, - "zh-Hans": { + "th": { "stringUnit": { "state": "translated", - "value": "同名工作区已存在。关闭并新建吗?" + "value": "ปรับขนาดช่องแยกให้เท่ากัน" } }, - "zh-Hant": { + "tr": { "stringUnit": { "state": "translated", - "value": "同名工作區已存在。關閉並新建嗎?" + "value": "Bölmeleri Eşitle" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Робоча область з такою назвою вже існує. Закрити її та створити нову?" + "value": "Вирівняти розділення" } } } }, - "dialog.cmuxConfig.confirmRestart.recreate": { + "command.enableMatchTerminalBackground.title": { "extractionState": "manual", "localizations": { - "ar": { + "en": { "stringUnit": { "state": "translated", - "value": "إعادة إنشاء" + "value": "Enable Match Terminal Background" } }, - "bs": { + "ja": { "stringUnit": { "state": "translated", - "value": "Ponovo kreiraj" + "value": "ターミナルの背景に合わせる" } - }, - "da": { + } + } + }, + "command.disableMatchTerminalBackground.title": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Genskab" + "value": "Disable Match Terminal Background" } }, - "de": { + "ja": { "stringUnit": { "state": "translated", - "value": "Neu erstellen" + "value": "ターミナルの背景に合わせる設定を無効にする" } - }, + } + } + }, + "command.matchTerminalBackground.subtitle": { + "extractionState": "manual", + "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Recreate" - } - }, - "es": { - "stringUnit": { - "state": "translated", - "value": "Recrear" + "value": "Sidebar" } }, - "fr": { + "ja": { "stringUnit": { "state": "translated", - "value": "Recréer" + "value": "サイドバー" } - }, - "it": { + } + } + }, + "command.toggleSetting.disableTitle": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Ricrea" + "value": "Disable %@" } }, "ja": { "stringUnit": { "state": "translated", - "value": "再作成" + "value": "%@を無効化" } - }, - "ko": { + } + } + }, + "command.toggleSetting.enableTitle": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "다시 만들기" + "value": "Enable %@" } }, - "nb": { + "ja": { "stringUnit": { "state": "translated", - "value": "Opprett på nytt" + "value": "%@を有効化" } - }, - "pl": { + } + } + }, + "command.toggleSetting.subtitle": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Utwórz ponownie" + "value": "%@ • %@" } }, - "pt-BR": { + "ja": { "stringUnit": { "state": "translated", - "value": "Recriar" + "value": "%@ • %@" + } + } + } + }, + "command.toggleSetting.state.on": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "On" } }, - "ru": { + "ja": { "stringUnit": { "state": "translated", - "value": "Пересоздать" + "value": "オン" + } + } + } + }, + "command.toggleSetting.state.off": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Off" } }, - "th": { + "ja": { "stringUnit": { "state": "translated", - "value": "สร้างใหม่" + "value": "オフ" + } + } + } + }, + "command.enableMinimalMode.title": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Enable Minimal Mode" } }, - "tr": { + "ja": { "stringUnit": { "state": "translated", - "value": "Yeniden Oluştur" + "value": "ミニマルモードを有効にする" } }, - "zh-Hans": { + "uk": { "stringUnit": { "state": "translated", - "value": "重新创建" + "value": "Увімкнути мінімальний режим" } }, - "zh-Hant": { + "ko": { "stringUnit": { "state": "translated", - "value": "重新建立" + "value": "미니멀 모드 활성화" + } + } + } + }, + "command.browserAvailability.subtitle": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Browser" } }, - "uk": { + "ja": { "stringUnit": { "state": "translated", - "value": "Створити заново" + "value": "ブラウザ" } } } }, - "dialog.cmuxConfig.confirmRestart.title": { + "command.disableBrowser.title": { "extractionState": "manual", "localizations": { - "ar": { + "en": { "stringUnit": { "state": "translated", - "value": "مساحة العمل موجودة بالفعل" + "value": "Disable cmux Browser" } }, - "bs": { + "ja": { "stringUnit": { "state": "translated", - "value": "Radni prostor već postoji" + "value": "cmuxブラウザを無効にする" + } + } + } + }, + "command.disableMinimalMode.title": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Disable Minimal Mode" } }, - "da": { + "ja": { "stringUnit": { "state": "translated", - "value": "Arbejdsområdet eksisterer allerede" + "value": "ミニマルモードを無効にする" } }, - "de": { + "uk": { "stringUnit": { "state": "translated", - "value": "Arbeitsbereich existiert bereits" + "value": "Вимкнути мінімальний режим" } }, + "ko": { + "stringUnit": { + "state": "translated", + "value": "미니멀 모드 비활성화" + } + } + } + }, + "command.enableBrowser.title": { + "extractionState": "manual", + "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Workspace Already Exists" + "value": "Enable cmux Browser" } }, - "es": { + "ja": { "stringUnit": { "state": "translated", - "value": "El espacio de trabajo ya existe" + "value": "cmuxブラウザを有効にする" + } + } + } + }, + "command.installCLI.subtitle": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "CLI" } }, - "fr": { + "ja": { "stringUnit": { "state": "translated", - "value": "L'espace de travail existe déjà" + "value": "CLI" } }, - "it": { + "zh-Hans": { "stringUnit": { "state": "translated", - "value": "L'area di lavoro esiste già" + "value": "CLI" } }, - "ja": { + "zh-Hant": { "stringUnit": { "state": "translated", - "value": "ワークスペースは既に存在します" + "value": "CLI" } }, "ko": { "stringUnit": { "state": "translated", - "value": "워크스페이스가 이미 존재합니다" + "value": "CLI" } }, - "nb": { + "de": { "stringUnit": { "state": "translated", - "value": "Arbeidsområdet finnes allerede" + "value": "CLI" } }, - "pl": { + "es": { "stringUnit": { "state": "translated", - "value": "Przestrzeń robocza już istnieje" + "value": "CLI" } }, - "pt-BR": { + "fr": { "stringUnit": { "state": "translated", - "value": "O espaço de trabalho já existe" + "value": "CLI" + } + }, + "it": { + "stringUnit": { + "state": "translated", + "value": "CLI" + } + }, + "da": { + "stringUnit": { + "state": "translated", + "value": "CLI" + } + }, + "pl": { + "stringUnit": { + "state": "translated", + "value": "CLI" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Рабочая область уже существует" + "value": "CLI" } }, - "th": { + "bs": { "stringUnit": { "state": "translated", - "value": "พื้นที่ทำงานมีอยู่แล้ว" + "value": "CLI" } }, - "tr": { + "ar": { "stringUnit": { "state": "translated", - "value": "Çalışma Alanı Zaten Var" + "value": "واجهة الأوامر" } }, - "zh-Hans": { + "nb": { "stringUnit": { "state": "translated", - "value": "工作区已存在" + "value": "CLI" } }, - "zh-Hant": { + "pt-BR": { "stringUnit": { "state": "translated", - "value": "工作區已存在" + "value": "CLI" + } + }, + "th": { + "stringUnit": { + "state": "translated", + "value": "CLI" + } + }, + "tr": { + "stringUnit": { + "state": "translated", + "value": "CLI" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Робоча область вже існує" + "value": "CLI" } } } }, - "command.cmuxConfig.subtitle": { + "command.installCLI.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "cmux.json" + "value": "Shell Command: Install 'cmux' in PATH" } }, "ja": { "stringUnit": { "state": "translated", - "value": "cmux.json" + "value": "シェルコマンド: 'cmux'をPATHにインストール" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "cmux.json" + "value": "Shell 命令:将 'cmux' 安装到 PATH" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "cmux.json" + "value": "Shell 指令:將「cmux」安裝至 PATH" } }, "ko": { "stringUnit": { "state": "translated", - "value": "cmux.json" + "value": "셸 명령어: PATH에 'cmux' 설치" } }, "de": { "stringUnit": { "state": "translated", - "value": "cmux.json" + "value": "Shell-Befehl: 'cmux' im PATH installieren" } }, "es": { "stringUnit": { "state": "translated", - "value": "cmux.json" + "value": "Comando de shell: Instalar 'cmux' en PATH" } }, "fr": { "stringUnit": { "state": "translated", - "value": "cmux.json" + "value": "Commande Shell : installer « cmux » dans le PATH" } }, "it": { "stringUnit": { "state": "translated", - "value": "cmux.json" + "value": "Comando shell: installa 'cmux' nel PATH" } }, "da": { "stringUnit": { "state": "translated", - "value": "cmux.json" + "value": "Skalkommando: Installer 'cmux' i PATH" } }, "pl": { "stringUnit": { "state": "translated", - "value": "cmux.json" + "value": "Polecenie powłoki: Zainstaluj „cmux” w PATH" } }, "ru": { "stringUnit": { "state": "translated", - "value": "cmux.json" + "value": "Команда оболочки: установить «cmux» в PATH" } }, "bs": { "stringUnit": { "state": "translated", - "value": "cmux.json" + "value": "Shell naredba: Instaliraj 'cmux' u PATH" } }, "ar": { "stringUnit": { "state": "translated", - "value": "cmux.json" + "value": "أمر الصدفة: تثبيت 'cmux' في PATH" } }, "nb": { "stringUnit": { "state": "translated", - "value": "cmux.json" + "value": "Skallkommando: Installer «cmux» i PATH" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "cmux.json" + "value": "Comando Shell: Instalar 'cmux' no PATH" } }, "th": { "stringUnit": { "state": "translated", - "value": "cmux.json" + "value": "คำสั่ง Shell: ติดตั้ง 'cmux' ใน PATH" } }, "tr": { "stringUnit": { "state": "translated", - "value": "cmux.json" + "value": "Kabuk Komutu: 'cmux'u PATH'e Yükle" } }, "uk": { "stringUnit": { "state": "translated", - "value": "cmux.json" + "value": "Команда оболонки: встановити 'cmux' у PATH" } } } }, - "command.cmuxConfig.defaultClaudeCodeTitle": { + "command.jumpUnread.subtitle": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Claude Code" + "value": "Notifications" } }, "ja": { "stringUnit": { "state": "translated", - "value": "Claude Code" + "value": "通知" } - } - } - }, - "command.cmuxConfig.defaultCodexTitle": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "zh-Hans": { "stringUnit": { "state": "translated", - "value": "Codex" + "value": "通知" } }, - "ja": { + "zh-Hant": { "stringUnit": { "state": "translated", - "value": "Codex" + "value": "通知" } - } - } - }, - "agent.codex.error.defaultMessage": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "ko": { "stringUnit": { "state": "translated", - "value": "Codex reported an error" + "value": "알림" } }, - "ja": { + "de": { "stringUnit": { "state": "translated", - "value": "Codex でエラーが発生しました" + "value": "Benachrichtigungen" } - } - } - }, - "agent.codex.error.noFinalResponse": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "es": { "stringUnit": { "state": "translated", - "value": "Codex ended before sending a final response" + "value": "Notificaciones" } }, - "ja": { + "fr": { "stringUnit": { "state": "translated", - "value": "Codex は最終応答を送信する前に終了しました" + "value": "Notifications" } - } - } - }, - "agent.claude.completion.subtitle.completed": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "it": { "stringUnit": { "state": "translated", - "value": "Completed" + "value": "Notifiche" } }, - "ja": { + "da": { "stringUnit": { "state": "translated", - "value": "完了" + "value": "Notifikationer" } - } - } - }, - "agent.claude.completion.subtitle.completedInProject": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "pl": { "stringUnit": { "state": "translated", - "value": "Completed in %@" + "value": "Powiadomienia" } }, - "ja": { + "ru": { "stringUnit": { "state": "translated", - "value": "%@ で完了" + "value": "Уведомления" } - } - } - }, - "agent.codex.completion.body.sessionCompleted": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "bs": { "stringUnit": { "state": "translated", - "value": "%@ session completed" + "value": "Obavještenja" } }, - "ja": { + "ar": { "stringUnit": { "state": "translated", - "value": "%@ セッションが完了しました" + "value": "الإشعارات" } - } - } - }, - "agent.codex.completion.subtitle.completed": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "nb": { "stringUnit": { "state": "translated", - "value": "Completed" + "value": "Varsler" } }, - "ja": { + "pt-BR": { "stringUnit": { "state": "translated", - "value": "完了" + "value": "Notificações" } - } - } - }, - "agent.codex.completion.subtitle.completedInProject": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "th": { "stringUnit": { "state": "translated", - "value": "Completed in %@" + "value": "การแจ้งเตือน" } }, - "ja": { + "tr": { "stringUnit": { "state": "translated", - "value": "%@ で完了" + "value": "Bildirimler" + } + }, + "uk": { + "stringUnit": { + "state": "translated", + "value": "Сповіщення" } } } }, - "agent.codex.error.status.auth": { + "command.jumpUnread.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Codex auth error" + "value": "Jump to Latest Unread" } }, "ja": { "stringUnit": { "state": "translated", - "value": "Codex 認証エラー" + "value": "最新の未読にジャンプ" } - } - } - }, - "agent.codex.error.status.generic": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "zh-Hans": { "stringUnit": { "state": "translated", - "value": "Codex error" + "value": "跳转到最新未读" } }, - "ja": { + "zh-Hant": { "stringUnit": { "state": "translated", - "value": "Codex エラー" + "value": "跳至最新未讀" } - } - } - }, - "agent.codex.error.status.network": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "ko": { "stringUnit": { "state": "translated", - "value": "Codex network error" + "value": "최신 읽지 않은 항목으로 이동" } }, - "ja": { + "de": { "stringUnit": { "state": "translated", - "value": "Codex ネットワークエラー" + "value": "Zur letzten ungelesenen springen" } - } - } - }, - "agent.codex.error.status.rateLimit": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "es": { "stringUnit": { "state": "translated", - "value": "Codex rate limit" + "value": "Ir a la última no leída" } }, - "ja": { + "fr": { "stringUnit": { "state": "translated", - "value": "Codex レート制限" + "value": "Aller au dernier message non lu" } - } - } - }, - "agent.codex.input.body.needsInput": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "it": { "stringUnit": { "state": "translated", - "value": "Codex is asking a question" + "value": "Vai all'ultimo non letto" } }, - "ja": { + "da": { "stringUnit": { "state": "translated", - "value": "Codex が質問しています" + "value": "Gå til seneste ulæste" } - } - } - }, - "agent.codex.input.status.needsInput": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "pl": { "stringUnit": { "state": "translated", - "value": "Codex needs input" + "value": "Przejdź do najnowszego nieprzeczytanego" } }, - "ja": { + "ru": { "stringUnit": { "state": "translated", - "value": "Codex 入力待ち" + "value": "Перейти к последнему непрочитанному" } - } - } - }, - "agent.codex.input.subtitle.waiting": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "bs": { "stringUnit": { "state": "translated", - "value": "Waiting" + "value": "Skoči na najnovije nepročitano" } }, - "ja": { + "ar": { "stringUnit": { "state": "translated", - "value": "待機状態" + "value": "الانتقال إلى أحدث غير مقروء" } - } - } - }, - "agent.codex.status.idle": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "nb": { "stringUnit": { "state": "translated", - "value": "Idle" + "value": "Gå til siste uleste" } }, - "ja": { + "pt-BR": { "stringUnit": { "state": "translated", - "value": "入力待ち" + "value": "Ir para Última Não Lida" + } + }, + "th": { + "stringUnit": { + "state": "translated", + "value": "ข้ามไปยังรายการยังไม่อ่านล่าสุด" + } + }, + "tr": { + "stringUnit": { + "state": "translated", + "value": "Son Okunmamışa Atla" + } + }, + "uk": { + "stringUnit": { + "state": "translated", + "value": "Перейти до останнього непрочитаного" } } } }, - "agent.generic.notification.body.approvalNeeded": { + "command.toggleUnread.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Approval needed" + "value": "Toggle Unread" } }, "ja": { "stringUnit": { "state": "translated", - "value": "承認が必要です" + "value": "未読を切り替え" } } } }, - "agent.generic.notification.body.needsAttention": { + "command.markOldestUnreadAndJumpNext.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "%@ needs your attention" + "value": "Mark as Oldest Unread and Jump to Next Latest Unread" } }, "ja": { "stringUnit": { "state": "translated", - "value": "%@ の確認が必要です" + "value": "最古の未読としてマークして次の最新未読にジャンプ" } } } }, - "agent.generic.notification.body.reportedError": { + "command.markTabRead.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "%@ reported an error" + "value": "Mark Tab as Read" } }, "ja": { "stringUnit": { "state": "translated", - "value": "%@ がエラーを報告しました" + "value": "タブを既読にする" } - } - } - }, - "agent.generic.notification.body.sentNotification": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "zh-Hans": { "stringUnit": { "state": "translated", - "value": "%@ sent a notification" + "value": "将标签页标记为已读" } }, - "ja": { + "zh-Hant": { "stringUnit": { "state": "translated", - "value": "%@ から通知が届きました" + "value": "將標籤頁標為已讀" } - } - } - }, - "agent.generic.notification.body.taskCompleted": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "ko": { "stringUnit": { "state": "translated", - "value": "Task completed" + "value": "탭을 읽음으로 표시" } }, - "ja": { + "de": { "stringUnit": { "state": "translated", - "value": "タスクが完了しました" + "value": "Tab als gelesen markieren" } - } - } - }, - "agent.generic.notification.body.waitingForInput": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "es": { "stringUnit": { "state": "translated", - "value": "Waiting for input" + "value": "Marcar pestaña como leída" } }, - "ja": { + "fr": { "stringUnit": { "state": "translated", - "value": "入力待ち" + "value": "Marquer l'onglet comme lu" } - } - } - }, - "agent.generic.notification.status.error": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "it": { "stringUnit": { "state": "translated", - "value": "%@ error" + "value": "Segna scheda come letta" } }, - "ja": { + "da": { "stringUnit": { "state": "translated", - "value": "%@ エラー" + "value": "Marker fane som læst" } - } - } - }, - "agent.generic.notification.status.idle": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "pl": { "stringUnit": { "state": "translated", - "value": "Idle" + "value": "Oznacz kartę jako przeczytaną" } }, - "ja": { + "ru": { "stringUnit": { "state": "translated", - "value": "待機中" + "value": "Отметить вкладку как прочитанную" } - } - } - }, - "agent.generic.notification.status.needsInput": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "bs": { "stringUnit": { "state": "translated", - "value": "%@ needs input" + "value": "Označi tab kao pročitan" } }, - "ja": { + "ar": { "stringUnit": { "state": "translated", - "value": "%@ 入力待ち" + "value": "تعليم اللسان كمقروء" } - } - } - }, - "agent.generic.notification.subtitle.attention": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "nb": { "stringUnit": { "state": "translated", - "value": "Attention" + "value": "Merk fane som lest" } }, - "ja": { + "pt-BR": { "stringUnit": { "state": "translated", - "value": "確認" + "value": "Marcar Aba como Lida" } - } - } - }, - "agent.generic.notification.subtitle.completed": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "th": { "stringUnit": { "state": "translated", - "value": "Completed" + "value": "ทำเครื่องหมายแท็บว่าอ่านแล้ว" } }, - "ja": { + "tr": { "stringUnit": { "state": "translated", - "value": "完了" + "value": "Sekmeyi Okundu Olarak İşaretle" + } + }, + "uk": { + "stringUnit": { + "state": "translated", + "value": "Позначити вкладку як прочитану" } } } }, - "agent.generic.notification.subtitle.error": { + "command.markTabUnread.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Error" + "value": "Mark Tab as Unread" } }, "ja": { "stringUnit": { "state": "translated", - "value": "エラー" + "value": "タブを未読にする" } - } - } - }, - "agent.generic.notification.subtitle.permission": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "zh-Hans": { "stringUnit": { "state": "translated", - "value": "Permission" + "value": "将标签页标记为未读" } }, - "ja": { + "zh-Hant": { "stringUnit": { "state": "translated", - "value": "権限" + "value": "將標籤頁標為未讀" } - } - } - }, - "agent.generic.notification.subtitle.waiting": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "ko": { "stringUnit": { "state": "translated", - "value": "Waiting" + "value": "탭을 읽지 않음으로 표시" } }, - "ja": { + "de": { "stringUnit": { "state": "translated", - "value": "待機中" + "value": "Tab als ungelesen markieren" } - } - } - }, - "agent.generic.status.running": { "extractionState": "manual", "localizations": {"ar":{"stringUnit":{"state":"translated","value":"Running"}},"bs":{"stringUnit":{"state":"translated","value":"Running"}},"da":{"stringUnit":{"state":"translated","value":"Running"}},"de":{"stringUnit":{"state":"translated","value":"Running"}},"en":{"stringUnit":{"state":"translated","value":"Running"}},"es":{"stringUnit":{"state":"translated","value":"Running"}},"fr":{"stringUnit":{"state":"translated","value":"Running"}},"it":{"stringUnit":{"state":"translated","value":"Running"}},"ja":{"stringUnit":{"state":"translated","value":"実行中"}},"ko":{"stringUnit":{"state":"translated","value":"Running"}},"nb":{"stringUnit":{"state":"translated","value":"Running"}},"pl":{"stringUnit":{"state":"translated","value":"Running"}},"pt-BR":{"stringUnit":{"state":"translated","value":"Running"}},"ru":{"stringUnit":{"state":"translated","value":"Running"}},"th":{"stringUnit":{"state":"translated","value":"Running"}},"tr":{"stringUnit":{"state":"translated","value":"Running"}},"uk":{"stringUnit":{"state":"translated","value":"Running"}},"zh-Hans":{"stringUnit":{"state":"translated","value":"Running"}},"zh-Hant":{"stringUnit":{"state":"translated","value":"Running"}}} }, - "agent.codex.error.subtitle.auth": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "es": { "stringUnit": { "state": "translated", - "value": "Auth error" + "value": "Marcar pestaña como no leída" } }, - "ja": { + "fr": { "stringUnit": { "state": "translated", - "value": "認証エラー" + "value": "Marquer l'onglet comme non lu" } - } - } - }, - "agent.codex.error.subtitle.generic": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "it": { "stringUnit": { "state": "translated", - "value": "Error" + "value": "Segna scheda come non letta" } }, - "ja": { + "da": { "stringUnit": { "state": "translated", - "value": "エラー" + "value": "Marker fane som ulæst" } - } - } - }, - "agent.codex.error.subtitle.network": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "pl": { "stringUnit": { "state": "translated", - "value": "Network error" + "value": "Oznacz kartę jako nieprzeczytaną" } }, - "ja": { + "ru": { "stringUnit": { "state": "translated", - "value": "ネットワークエラー" + "value": "Отметить вкладку как непрочитанную" } - } - } - }, - "agent.codex.error.subtitle.rateLimit": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "bs": { "stringUnit": { "state": "translated", - "value": "Rate limit" + "value": "Označi tab kao nepročitan" } }, - "ja": { + "ar": { "stringUnit": { "state": "translated", - "value": "レート制限" + "value": "تعليم اللسان كغير مقروء" + } + }, + "nb": { + "stringUnit": { + "state": "translated", + "value": "Merk fane som ulest" + } + }, + "pt-BR": { + "stringUnit": { + "state": "translated", + "value": "Marcar Aba como Não Lida" + } + }, + "th": { + "stringUnit": { + "state": "translated", + "value": "ทำเครื่องหมายแท็บว่ายังไม่อ่าน" + } + }, + "tr": { + "stringUnit": { + "state": "translated", + "value": "Sekmeyi Okunmadı Olarak İşaretle" + } + }, + "uk": { + "stringUnit": { + "state": "translated", + "value": "Позначити вкладку як непрочитану" } } } }, - "command.cmuxConfig.customTitle": { + "command.newBrowserTab.subtitle": { "extractionState": "manual", "localizations": { - "ar": { + "en": { "stringUnit": { "state": "translated", - "value": "مخصص: %@" + "value": "Tab" } }, - "bs": { + "ja": { "stringUnit": { "state": "translated", - "value": "Prilagođeno: %@" + "value": "タブ" } }, - "da": { + "zh-Hans": { "stringUnit": { "state": "translated", - "value": "Brugerdefineret: %@" + "value": "标签页" } }, - "de": { + "zh-Hant": { "stringUnit": { "state": "translated", - "value": "Benutzerdefiniert: %@" + "value": "標籤頁" } }, - "en": { + "ko": { "stringUnit": { "state": "translated", - "value": "Custom: %@" + "value": "탭" } }, - "es": { + "de": { "stringUnit": { "state": "translated", - "value": "Personalizado: %@" + "value": "Tab" } }, - "fr": { + "es": { "stringUnit": { "state": "translated", - "value": "Personnalisé : %@" + "value": "Pestaña" } }, - "it": { + "fr": { "stringUnit": { "state": "translated", - "value": "Personalizzato: %@" + "value": "Onglet" } }, - "ja": { + "it": { "stringUnit": { "state": "translated", - "value": "カスタム: %@" + "value": "Scheda" } }, - "ko": { + "da": { "stringUnit": { "state": "translated", - "value": "사용자 정의: %@" + "value": "Fane" } }, - "nb": { + "pl": { "stringUnit": { "state": "translated", - "value": "Egendefinert: %@" + "value": "Karta" } }, - "pl": { + "ru": { "stringUnit": { "state": "translated", - "value": "Niestandardowe: %@" + "value": "Вкладка" } }, - "pt-BR": { + "bs": { "stringUnit": { "state": "translated", - "value": "Personalizado: %@" + "value": "Tab" } }, - "ru": { + "ar": { "stringUnit": { "state": "translated", - "value": "Пользовательское: %@" + "value": "لسان" } }, - "th": { + "nb": { "stringUnit": { "state": "translated", - "value": "กำหนดเอง: %@" + "value": "Fane" } }, - "tr": { + "pt-BR": { "stringUnit": { "state": "translated", - "value": "Özel: %@" + "value": "Aba" } }, - "zh-Hans": { + "th": { "stringUnit": { "state": "translated", - "value": "自定义: %@" + "value": "แท็บ" } }, - "zh-Hant": { + "tr": { "stringUnit": { "state": "translated", - "value": "自訂: %@" + "value": "Sekme" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Власне: %@" + "value": "Вкладка" } } } }, - "command.cmuxConfig.issue.newWorkspaceActionRequiresWorkspaceCommand.detail": { + "command.newBrowserTab.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "%@ must reference a workspace command action" + "value": "New Tab (Browser)" } }, "ja": { "stringUnit": { "state": "translated", - "value": "%@ はワークスペースコマンドアクションを参照する必要があります" + "value": "新規タブ(ブラウザ)" } - } - } - }, - "command.cmuxConfig.issue.newWorkspaceActionNotFound.detail": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "zh-Hans": { "stringUnit": { "state": "translated", - "value": "%@ references missing action '%@'" + "value": "新建标签页(浏览器)" } }, - "ja": { + "zh-Hant": { "stringUnit": { "state": "translated", - "value": "%@ は存在しないアクション '%@' を参照しています" + "value": "新增標籤頁(瀏覽器)" } - } - } - }, - "command.cmuxConfig.issue.newWorkspaceCommandNotFound.detail": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "ko": { "stringUnit": { "state": "translated", - "value": "%@ references missing command '%@'" + "value": "새 탭 (브라우저)" } }, - "ja": { + "de": { "stringUnit": { "state": "translated", - "value": "%@ は存在しないコマンド '%@' を参照しています" + "value": "Neuer Tab (Browser)" } - } - } - }, - "command.cmuxConfig.issue.newWorkspaceCommandRequiresWorkspace.detail": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "es": { "stringUnit": { "state": "translated", - "value": "%@ '%@' must reference a workspace command" + "value": "Nueva pestaña (Navegador)" } }, - "ja": { + "fr": { "stringUnit": { "state": "translated", - "value": "%@ '%@' はワークスペースコマンドを参照する必要があります" + "value": "Nouvel onglet (navigateur)" } - } - } - }, - "command.cmuxConfig.issue.schemaError.detail": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "it": { "stringUnit": { "state": "translated", - "value": "%@" + "value": "Nuova scheda (browser)" } }, - "ja": { + "da": { "stringUnit": { "state": "translated", - "value": "%@" + "value": "Ny fane (browser)" } - } - } - }, - "command.cmuxConfig.issue.schemaError.fallback": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "pl": { "stringUnit": { "state": "translated", - "value": "Invalid cmux.json" + "value": "Nowa karta (Przeglądarka)" } }, - "ja": { + "ru": { "stringUnit": { "state": "translated", - "value": "無効な cmux.json" + "value": "Новая вкладка (Браузер)" } - } - } - }, - "command.cmuxConfig.issue.schemaError.title": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "bs": { "stringUnit": { "state": "translated", - "value": "cmux.json Schema Error" + "value": "Novi tab (Preglednik)" } }, - "ja": { + "ar": { "stringUnit": { "state": "translated", - "value": "cmux.json スキーマエラー" + "value": "لسان جديد (متصفح)" } - } - } - }, - "command.cmuxConfig.issue.subtitle": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "nb": { "stringUnit": { "state": "translated", - "value": "%@: %@" + "value": "Ny fane (nettleser)" } }, - "ja": { + "pt-BR": { "stringUnit": { "state": "translated", - "value": "%@: %@" + "value": "Nova Aba (Navegador)" } - } - } - }, - "command.cmuxConfig.issue.warning.title": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "th": { "stringUnit": { "state": "translated", - "value": "cmux.json Configuration Warning" + "value": "แท็บใหม่ (เบราว์เซอร์)" } }, - "ja": { + "tr": { "stringUnit": { "state": "translated", - "value": "cmux.json 設定警告" + "value": "Yeni Sekme (Tarayıcı)" + } + }, + "uk": { + "stringUnit": { + "state": "translated", + "value": "Нова вкладка (Браузер)" } } } }, - "command.equalizeSplits.title": { + "command.newTerminalTab.subtitle": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Equalize Splits" + "value": "Tab" } }, "ja": { "stringUnit": { "state": "translated", - "value": "分割を均等にする" + "value": "タブ" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "均分面板" + "value": "标签页" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "均等分割" + "value": "標籤頁" } }, "ko": { "stringUnit": { "state": "translated", - "value": "분할 균등화" + "value": "탭" } }, "de": { "stringUnit": { "state": "translated", - "value": "Teilungen angleichen" + "value": "Tab" } }, "es": { "stringUnit": { "state": "translated", - "value": "Igualar divisiones" + "value": "Pestaña" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Égaliser les divisions" + "value": "Onglet" } }, "it": { "stringUnit": { "state": "translated", - "value": "Equalizza divisioni" + "value": "Scheda" } }, "da": { "stringUnit": { "state": "translated", - "value": "Udlign opdelinger" + "value": "Fane" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Wyrównaj podziały" + "value": "Karta" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Выровнять разделение" + "value": "Вкладка" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Izjednači podjele" + "value": "Tab" } }, "ar": { "stringUnit": { "state": "translated", - "value": "تسوية التقسيمات" + "value": "لسان" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Gjør delinger like" + "value": "Fane" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Equalizar Divisões" + "value": "Aba" } }, "th": { "stringUnit": { "state": "translated", - "value": "ปรับขนาดช่องแยกให้เท่ากัน" + "value": "แท็บ" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Bölmeleri Eşitle" + "value": "Sekme" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Вирівняти розділення" + "value": "Вкладка" } } } }, - "command.enableMatchTerminalBackground.title": { + "command.newTerminalTab.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Enable Match Terminal Background" + "value": "New Tab (Terminal)" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ターミナルの背景に合わせる" - } - } - } - }, - "command.disableMatchTerminalBackground.title": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Disable Match Terminal Background" + "value": "新規タブ(ターミナル)" } }, - "ja": { - "stringUnit": { - "state": "translated", - "value": "ターミナルの背景に合わせる設定を無効にする" - } - } - } - }, - "command.matchTerminalBackground.subtitle": { - "extractionState": "manual", - "localizations": { - "en": { + "zh-Hans": { "stringUnit": { "state": "translated", - "value": "Sidebar" + "value": "新建标签页(终端)" } }, - "ja": { - "stringUnit": { - "state": "translated", - "value": "サイドバー" - } - } - } - }, - "command.toggleSetting.disableTitle": { - "extractionState": "manual", - "localizations": { - "en": { + "zh-Hant": { "stringUnit": { "state": "translated", - "value": "Disable %@" + "value": "新增標籤頁(終端機)" } }, - "ja": { - "stringUnit": { - "state": "translated", - "value": "%@を無効化" - } - } - } - }, - "command.toggleSetting.enableTitle": { - "extractionState": "manual", - "localizations": { - "en": { + "ko": { "stringUnit": { "state": "translated", - "value": "Enable %@" + "value": "새 탭 (터미널)" } }, - "ja": { - "stringUnit": { - "state": "translated", - "value": "%@を有効化" - } - } - } - }, - "command.toggleSetting.subtitle": { - "extractionState": "manual", - "localizations": { - "en": { + "de": { "stringUnit": { "state": "translated", - "value": "%@ • %@" + "value": "Neuer Tab (Terminal)" } }, - "ja": { - "stringUnit": { - "state": "translated", - "value": "%@ • %@" - } - } - } - }, - "command.toggleSetting.state.on": { - "extractionState": "manual", - "localizations": { - "en": { + "es": { "stringUnit": { "state": "translated", - "value": "On" + "value": "Nueva pestaña (Terminal)" } }, - "ja": { - "stringUnit": { - "state": "translated", - "value": "オン" - } - } - } - }, - "command.toggleSetting.state.off": { - "extractionState": "manual", - "localizations": { - "en": { + "fr": { "stringUnit": { "state": "translated", - "value": "Off" + "value": "Nouvel onglet (terminal)" } }, - "ja": { - "stringUnit": { - "state": "translated", - "value": "オフ" - } - } - } - }, - "command.enableMinimalMode.title": { - "extractionState": "manual", - "localizations": { - "en": { + "it": { "stringUnit": { "state": "translated", - "value": "Enable Minimal Mode" + "value": "Nuova scheda (terminale)" } }, - "ja": { + "da": { "stringUnit": { "state": "translated", - "value": "ミニマルモードを有効にする" + "value": "Ny fane (terminal)" } }, - "uk": { + "pl": { "stringUnit": { "state": "translated", - "value": "Увімкнути мінімальний режим" + "value": "Nowa karta (Terminal)" } }, - "ko": { - "stringUnit": { - "state": "translated", - "value": "미니멀 모드 활성화" - } - } - } - }, - "command.browserAvailability.subtitle": { - "extractionState": "manual", - "localizations": { - "en": { + "ru": { "stringUnit": { "state": "translated", - "value": "Browser" + "value": "Новая вкладка (Терминал)" } }, - "ja": { - "stringUnit": { - "state": "translated", - "value": "ブラウザ" - } - } - } - }, - "command.disableBrowser.title": { - "extractionState": "manual", - "localizations": { - "en": { + "bs": { "stringUnit": { "state": "translated", - "value": "Disable cmux Browser" + "value": "Novi tab (Terminal)" } }, - "ja": { - "stringUnit": { - "state": "translated", - "value": "cmuxブラウザを無効にする" - } - } - } - }, - "command.disableMinimalMode.title": { - "extractionState": "manual", - "localizations": { - "en": { + "ar": { "stringUnit": { "state": "translated", - "value": "Disable Minimal Mode" + "value": "لسان جديد (طرفية)" } }, - "ja": { + "nb": { "stringUnit": { "state": "translated", - "value": "ミニマルモードを無効にする" + "value": "Ny fane (terminal)" } }, - "uk": { + "pt-BR": { "stringUnit": { "state": "translated", - "value": "Вимкнути мінімальний режим" + "value": "Nova Aba (Terminal)" } }, - "ko": { + "th": { "stringUnit": { "state": "translated", - "value": "미니멀 모드 비활성화" + "value": "แท็บใหม่ (เทอร์มินัล)" } - } - } - }, - "command.enableBrowser.title": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "tr": { "stringUnit": { "state": "translated", - "value": "Enable cmux Browser" + "value": "Yeni Sekme (Terminal)" } }, - "ja": { + "uk": { "stringUnit": { "state": "translated", - "value": "cmuxブラウザを有効にする" + "value": "Нова вкладка (Термінал)" } } } }, - "command.installCLI.subtitle": { + "command.newWindow.subtitle": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "CLI" + "value": "Window" } }, "ja": { "stringUnit": { "state": "translated", - "value": "CLI" + "value": "ウインドウ" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "CLI" + "value": "窗口" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "CLI" + "value": "視窗" } }, "ko": { "stringUnit": { "state": "translated", - "value": "CLI" + "value": "윈도우" } }, "de": { "stringUnit": { "state": "translated", - "value": "CLI" + "value": "Fenster" } }, "es": { "stringUnit": { "state": "translated", - "value": "CLI" + "value": "Ventana" } }, "fr": { "stringUnit": { "state": "translated", - "value": "CLI" + "value": "Fenêtre" } }, "it": { "stringUnit": { "state": "translated", - "value": "CLI" + "value": "Finestra" } }, "da": { "stringUnit": { "state": "translated", - "value": "CLI" + "value": "Vindue" } }, "pl": { "stringUnit": { "state": "translated", - "value": "CLI" + "value": "Okno" } }, "ru": { "stringUnit": { "state": "translated", - "value": "CLI" + "value": "Окно" } }, "bs": { "stringUnit": { "state": "translated", - "value": "CLI" + "value": "Prozor" } }, "ar": { "stringUnit": { "state": "translated", - "value": "واجهة الأوامر" + "value": "نافذة" } }, "nb": { "stringUnit": { "state": "translated", - "value": "CLI" + "value": "Vindu" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "CLI" + "value": "Janela" } }, "th": { "stringUnit": { "state": "translated", - "value": "CLI" + "value": "หน้าต่าง" } }, "tr": { "stringUnit": { "state": "translated", - "value": "CLI" + "value": "Pencere" } }, "uk": { "stringUnit": { "state": "translated", - "value": "CLI" + "value": "Вікно" } } } }, - "command.installCLI.title": { + "command.newWindow.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Shell Command: Install 'cmux' in PATH" + "value": "New Window" } }, "ja": { "stringUnit": { "state": "translated", - "value": "シェルコマンド: 'cmux'をPATHにインストール" + "value": "新規ウインドウ" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "Shell 命令:将 'cmux' 安装到 PATH" + "value": "新建窗口" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "Shell 指令:將「cmux」安裝至 PATH" + "value": "新增視窗" } }, "ko": { "stringUnit": { "state": "translated", - "value": "셸 명령어: PATH에 'cmux' 설치" + "value": "새 윈도우" } }, "de": { "stringUnit": { "state": "translated", - "value": "Shell-Befehl: 'cmux' im PATH installieren" + "value": "Neues Fenster" } }, "es": { "stringUnit": { "state": "translated", - "value": "Comando de shell: Instalar 'cmux' en PATH" + "value": "Nueva ventana" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Commande Shell : installer « cmux » dans le PATH" + "value": "Nouvelle fenêtre" } }, "it": { "stringUnit": { "state": "translated", - "value": "Comando shell: installa 'cmux' nel PATH" + "value": "Nuova finestra" } }, "da": { "stringUnit": { "state": "translated", - "value": "Skalkommando: Installer 'cmux' i PATH" + "value": "Nyt vindue" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Polecenie powłoki: Zainstaluj „cmux” w PATH" + "value": "Nowe okno" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Команда оболочки: установить «cmux» в PATH" + "value": "Новое окно" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Shell naredba: Instaliraj 'cmux' u PATH" + "value": "Novi prozor" } }, "ar": { "stringUnit": { "state": "translated", - "value": "أمر الصدفة: تثبيت 'cmux' في PATH" + "value": "نافذة جديدة" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Skallkommando: Installer «cmux» i PATH" + "value": "Nytt vindu" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Comando Shell: Instalar 'cmux' no PATH" + "value": "Nova Janela" } }, "th": { "stringUnit": { "state": "translated", - "value": "คำสั่ง Shell: ติดตั้ง 'cmux' ใน PATH" + "value": "หน้าต่างใหม่" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Kabuk Komutu: 'cmux'u PATH'e Yükle" + "value": "Yeni Pencere" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Команда оболонки: встановити 'cmux' у PATH" + "value": "Нове вікно" } } } }, - "command.jumpUnread.subtitle": { + "command.newWorkspace.subtitle": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Notifications" + "value": "Workspace" } }, "ja": { "stringUnit": { "state": "translated", - "value": "通知" + "value": "ワークスペース" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "通知" + "value": "工作区" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "通知" + "value": "工作區" } }, "ko": { "stringUnit": { "state": "translated", - "value": "알림" + "value": "작업 공간" } }, "de": { "stringUnit": { "state": "translated", - "value": "Benachrichtigungen" + "value": "Arbeitsbereich" } }, "es": { "stringUnit": { "state": "translated", - "value": "Notificaciones" + "value": "Espacio de trabajo" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Notifications" + "value": "Espace de travail" } }, "it": { "stringUnit": { "state": "translated", - "value": "Notifiche" + "value": "Area di lavoro" } }, "da": { "stringUnit": { "state": "translated", - "value": "Notifikationer" + "value": "Arbejdsområde" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Powiadomienia" + "value": "Przestrzeń robocza" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Уведомления" + "value": "Рабочее пространство" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Obavještenja" + "value": "Radni prostor" } }, "ar": { "stringUnit": { "state": "translated", - "value": "الإشعارات" + "value": "مساحة العمل" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Varsler" + "value": "Arbeidsområde" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Notificações" + "value": "Área de Trabalho" } }, "th": { "stringUnit": { "state": "translated", - "value": "การแจ้งเตือน" + "value": "เวิร์กสเปซ" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Bildirimler" + "value": "Çalışma Alanı" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Сповіщення" + "value": "Робоча область" } } } }, - "command.jumpUnread.title": { + "command.newWorkspace.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Jump to Latest Unread" + "value": "New Workspace" } }, "ja": { "stringUnit": { "state": "translated", - "value": "最新の未読にジャンプ" + "value": "新規ワークスペース" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "跳转到最新未读" + "value": "新建工作区" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "跳至最新未讀" + "value": "新增工作區" } }, "ko": { "stringUnit": { "state": "translated", - "value": "최신 읽지 않은 항목으로 이동" + "value": "새 작업 공간" } }, "de": { "stringUnit": { "state": "translated", - "value": "Zur letzten ungelesenen springen" + "value": "Neuer Arbeitsbereich" } }, "es": { "stringUnit": { "state": "translated", - "value": "Ir a la última no leída" + "value": "Nuevo espacio de trabajo" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Aller au dernier message non lu" + "value": "Nouvel espace de travail" } }, "it": { "stringUnit": { "state": "translated", - "value": "Vai all'ultimo non letto" + "value": "Nuova area di lavoro" } }, "da": { "stringUnit": { "state": "translated", - "value": "Gå til seneste ulæste" + "value": "Nyt arbejdsområde" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Przejdź do najnowszego nieprzeczytanego" + "value": "Nowa przestrzeń robocza" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Перейти к последнему непрочитанному" + "value": "Новое рабочее пространство" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Skoči na najnovije nepročitano" + "value": "Novi radni prostor" } }, "ar": { "stringUnit": { "state": "translated", - "value": "الانتقال إلى أحدث غير مقروء" + "value": "مساحة عمل جديدة" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Gå til siste uleste" + "value": "Nytt arbeidsområde" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Ir para Última Não Lida" + "value": "Nova Área de Trabalho" } }, "th": { "stringUnit": { "state": "translated", - "value": "ข้ามไปยังรายการยังไม่อ่านล่าสุด" + "value": "เวิร์กสเปซใหม่" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Son Okunmamışa Atla" + "value": "Yeni Çalışma Alanı" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Перейти до останнього непрочитаного" - } - } - } - }, - "command.toggleUnread.title": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Toggle Unread" - } - }, - "ja": { - "stringUnit": { - "state": "translated", - "value": "未読を切り替え" - } - } - } - }, - "command.markOldestUnreadAndJumpNext.title": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Mark as Oldest Unread and Jump to Next Latest Unread" - } - }, - "ja": { - "stringUnit": { - "state": "translated", - "value": "最古の未読としてマークして次の最新未読にジャンプ" + "value": "Нова робоча область" } } } }, - "command.markTabRead.title": { + "command.nextTabInPane.subtitle": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Mark Tab as Read" + "value": "Tab Navigation" } }, "ja": { "stringUnit": { "state": "translated", - "value": "タブを既読にする" + "value": "タブナビゲーション" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "将标签页标记为已读" + "value": "标签页导航" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "將標籤頁標為已讀" + "value": "標籤頁導覽" } }, "ko": { "stringUnit": { "state": "translated", - "value": "탭을 읽음으로 표시" + "value": "탭 탐색" } }, "de": { "stringUnit": { "state": "translated", - "value": "Tab als gelesen markieren" + "value": "Tab-Navigation" } }, "es": { "stringUnit": { "state": "translated", - "value": "Marcar pestaña como leída" + "value": "Navegación de pestañas" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Marquer l'onglet comme lu" + "value": "Navigation par onglets" } }, "it": { "stringUnit": { "state": "translated", - "value": "Segna scheda come letta" + "value": "Navigazione schede" } }, "da": { "stringUnit": { "state": "translated", - "value": "Marker fane som læst" + "value": "Fanenavigation" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Oznacz kartę jako przeczytaną" + "value": "Nawigacja po kartach" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Отметить вкладку как прочитанную" + "value": "Навигация по вкладкам" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Označi tab kao pročitan" + "value": "Navigacija tabovima" } }, "ar": { "stringUnit": { "state": "translated", - "value": "تعليم اللسان كمقروء" + "value": "التنقل بين الألسنة" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Merk fane som lest" + "value": "Fanenavigering" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Marcar Aba como Lida" + "value": "Navegação de Abas" } }, "th": { "stringUnit": { "state": "translated", - "value": "ทำเครื่องหมายแท็บว่าอ่านแล้ว" + "value": "การนำทางแท็บ" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Sekmeyi Okundu Olarak İşaretle" + "value": "Sekme Gezinme" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Позначити вкладку як прочитану" + "value": "Навігація вкладками" } } } }, - "command.markTabUnread.title": { + "command.nextTabInPane.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Mark Tab as Unread" + "value": "Next Tab in Pane" } }, "ja": { "stringUnit": { "state": "translated", - "value": "タブを未読にする" + "value": "ペイン内の次のタブ" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "将标签页标记为未读" + "value": "下一个面板标签页" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "將標籤頁標為未讀" + "value": "面板中的下一個標籤頁" } }, "ko": { "stringUnit": { "state": "translated", - "value": "탭을 읽지 않음으로 표시" + "value": "패널 내 다음 탭" } }, "de": { "stringUnit": { "state": "translated", - "value": "Tab als ungelesen markieren" + "value": "Nächster Tab im Bereich" } }, "es": { "stringUnit": { "state": "translated", - "value": "Marcar pestaña como no leída" + "value": "Siguiente pestaña en el panel" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Marquer l'onglet comme non lu" + "value": "Onglet suivant dans le panneau" } }, "it": { "stringUnit": { "state": "translated", - "value": "Segna scheda come non letta" + "value": "Scheda successiva nel pannello" } }, "da": { "stringUnit": { "state": "translated", - "value": "Marker fane som ulæst" + "value": "Næste fane i panel" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Oznacz kartę jako nieprzeczytaną" + "value": "Następna karta w panelu" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Отметить вкладку как непрочитанную" + "value": "Следующая вкладка в панели" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Označi tab kao nepročitan" + "value": "Sljedeći tab u panelu" } }, "ar": { "stringUnit": { "state": "translated", - "value": "تعليم اللسان كغير مقروء" + "value": "اللسان التالي في اللوحة" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Merk fane som ulest" + "value": "Neste fane i panelet" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Marcar Aba como Não Lida" + "value": "Próxima Aba no Painel" } }, "th": { "stringUnit": { "state": "translated", - "value": "ทำเครื่องหมายแท็บว่ายังไม่อ่าน" + "value": "แท็บถัดไปในบานหน้าต่าง" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Sekmeyi Okunmadı Olarak İşaretle" + "value": "Bölmedeki Sonraki Sekme" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Позначити вкладку як непрочитану" + "value": "Наступна вкладка в панелі" } } } }, - "command.newBrowserTab.subtitle": { + "command.nextWorkspace.subtitle": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Tab" + "value": "Workspace Navigation" } }, "ja": { "stringUnit": { "state": "translated", - "value": "タブ" + "value": "ワークスペースナビゲーション" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "标签页" + "value": "工作区导航" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "標籤頁" + "value": "工作區導覽" } }, "ko": { "stringUnit": { "state": "translated", - "value": "탭" + "value": "작업 공간 탐색" } }, "de": { "stringUnit": { "state": "translated", - "value": "Tab" + "value": "Arbeitsbereich-Navigation" } }, "es": { "stringUnit": { "state": "translated", - "value": "Pestaña" + "value": "Navegación de espacios de trabajo" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Onglet" + "value": "Navigation par espaces de travail" } }, "it": { "stringUnit": { "state": "translated", - "value": "Scheda" + "value": "Navigazione aree di lavoro" } }, "da": { "stringUnit": { "state": "translated", - "value": "Fane" + "value": "Arbejdsområdenavigation" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Karta" + "value": "Nawigacja po przestrzeniach roboczych" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Вкладка" + "value": "Навигация по рабочим пространствам" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Tab" + "value": "Navigacija radnim prostorima" } }, "ar": { "stringUnit": { "state": "translated", - "value": "لسان" + "value": "التنقل بين مساحات العمل" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Fane" + "value": "Arbeidsområdenavigering" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Aba" + "value": "Navegação de Áreas de Trabalho" } }, "th": { "stringUnit": { "state": "translated", - "value": "แท็บ" + "value": "การนำทางเวิร์กสเปซ" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Sekme" + "value": "Çalışma Alanı Gezinme" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Вкладка" + "value": "Навігація робочими областями" } } } }, - "command.newBrowserTab.title": { + "command.nextWorkspace.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "New Tab (Browser)" + "value": "Next Workspace" } }, "ja": { "stringUnit": { "state": "translated", - "value": "新規タブ(ブラウザ)" + "value": "次のワークスペース" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "新建标签页(浏览器)" + "value": "下一个工作区" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "新增標籤頁(瀏覽器)" + "value": "下一個工作區" } }, "ko": { "stringUnit": { "state": "translated", - "value": "새 탭 (브라우저)" + "value": "다음 작업 공간" } }, "de": { "stringUnit": { "state": "translated", - "value": "Neuer Tab (Browser)" + "value": "Nächster Arbeitsbereich" } }, "es": { "stringUnit": { "state": "translated", - "value": "Nueva pestaña (Navegador)" + "value": "Siguiente espacio de trabajo" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Nouvel onglet (navigateur)" + "value": "Espace de travail suivant" } }, "it": { "stringUnit": { "state": "translated", - "value": "Nuova scheda (browser)" + "value": "Area di lavoro successiva" } }, "da": { "stringUnit": { "state": "translated", - "value": "Ny fane (browser)" + "value": "Næste arbejdsområde" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Nowa karta (Przeglądarka)" + "value": "Następna przestrzeń robocza" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Новая вкладка (Браузер)" + "value": "Следующее рабочее пространство" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Novi tab (Preglednik)" + "value": "Sljedeći radni prostor" } }, "ar": { "stringUnit": { "state": "translated", - "value": "لسان جديد (متصفح)" + "value": "مساحة العمل التالية" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Ny fane (nettleser)" + "value": "Neste arbeidsområde" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Nova Aba (Navegador)" + "value": "Próxima Área de Trabalho" } }, "th": { "stringUnit": { "state": "translated", - "value": "แท็บใหม่ (เบราว์เซอร์)" + "value": "เวิร์กสเปซถัดไป" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Yeni Sekme (Tarayıcı)" + "value": "Sonraki Çalışma Alanı" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Нова вкладка (Браузер)" + "value": "Наступна робоча область" } } } }, - "command.newTerminalTab.subtitle": { + "command.openFolder.subtitle": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Tab" + "value": "Workspace" } }, "ja": { "stringUnit": { "state": "translated", - "value": "タブ" + "value": "ワークスペース" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "标签页" + "value": "工作区" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "標籤頁" + "value": "工作區" } }, "ko": { "stringUnit": { "state": "translated", - "value": "탭" + "value": "작업 공간" } }, "de": { "stringUnit": { "state": "translated", - "value": "Tab" + "value": "Arbeitsbereich" } }, "es": { "stringUnit": { "state": "translated", - "value": "Pestaña" + "value": "Espacio de trabajo" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Onglet" + "value": "Espace de travail" } }, "it": { "stringUnit": { "state": "translated", - "value": "Scheda" + "value": "Area di lavoro" } }, "da": { "stringUnit": { "state": "translated", - "value": "Fane" + "value": "Arbejdsområde" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Karta" + "value": "Przestrzeń robocza" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Вкладка" + "value": "Рабочее пространство" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Tab" + "value": "Radni prostor" } }, "ar": { "stringUnit": { "state": "translated", - "value": "لسان" + "value": "مساحة العمل" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Fane" + "value": "Arbeidsområde" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Aba" + "value": "Área de Trabalho" } }, "th": { "stringUnit": { "state": "translated", - "value": "แท็บ" + "value": "เวิร์กสเปซ" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Sekme" + "value": "Çalışma Alanı" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Вкладка" + "value": "Робоча область" } } } }, - "command.newTerminalTab.title": { + "command.openFolder.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "New Tab (Terminal)" + "value": "Open Folder…" } }, "ja": { "stringUnit": { "state": "translated", - "value": "新規タブ(ターミナル)" + "value": "フォルダを開く…" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "新建标签页(终端)" + "value": "打开文件夹..." } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "新增標籤頁(終端機)" + "value": "開啟資料夾..." } }, "ko": { "stringUnit": { "state": "translated", - "value": "새 탭 (터미널)" + "value": "폴더 열기…" } }, "de": { "stringUnit": { "state": "translated", - "value": "Neuer Tab (Terminal)" + "value": "Ordner öffnen …" } }, "es": { "stringUnit": { "state": "translated", - "value": "Nueva pestaña (Terminal)" + "value": "Abrir carpeta…" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Nouvel onglet (terminal)" + "value": "Ouvrir un dossier..." } }, "it": { "stringUnit": { "state": "translated", - "value": "Nuova scheda (terminale)" + "value": "Apri cartella…" } }, "da": { "stringUnit": { "state": "translated", - "value": "Ny fane (terminal)" + "value": "Åbn mappe…" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Nowa karta (Terminal)" + "value": "Otwórz folder…" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Новая вкладка (Терминал)" + "value": "Открыть папку..." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Novi tab (Terminal)" + "value": "Otvori folder…" } }, "ar": { "stringUnit": { "state": "translated", - "value": "لسان جديد (طرفية)" + "value": "فتح مجلد…" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Ny fane (terminal)" + "value": "Åpne mappe …" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Nova Aba (Terminal)" + "value": "Abrir Pasta…" } }, "th": { "stringUnit": { "state": "translated", - "value": "แท็บใหม่ (เทอร์มินัล)" + "value": "เปิดโฟลเดอร์..." } }, "tr": { "stringUnit": { "state": "translated", - "value": "Yeni Sekme (Terminal)" + "value": "Klasör Aç…" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Нова вкладка (Термінал)" + "value": "Відкрити теку…" } } } }, - "command.newWindow.subtitle": { + "command.openFolderInVSCodeInline.subtitle": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Window" + "value": "VS Code Inline" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ウインドウ" + "value": "VS Code インライン" + } + }, + "ko": { + "stringUnit": { + "state": "translated", + "value": "VS Code 인라인" + } + } + } + }, + "command.openFolderInVSCodeInline.title": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Open Folder in VS Code (Inline)…" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "フォルダを VS Code で開く(インライン)…" + } + }, + "ko": { + "stringUnit": { + "state": "translated", + "value": "VS Code에서 폴더 열기 (인라인)…" + } + } + } + }, + "command.openSettings.subtitle": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Global" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "グローバル" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "窗口" + "value": "全局" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "視窗" + "value": "全域" } }, "ko": { "stringUnit": { "state": "translated", - "value": "윈도우" + "value": "전역" } }, "de": { "stringUnit": { "state": "translated", - "value": "Fenster" + "value": "Global" } }, "es": { "stringUnit": { "state": "translated", - "value": "Ventana" + "value": "Global" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Fenêtre" + "value": "Général" } }, "it": { "stringUnit": { "state": "translated", - "value": "Finestra" + "value": "Globale" } }, "da": { "stringUnit": { "state": "translated", - "value": "Vindue" + "value": "Globalt" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Okno" + "value": "Globalne" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Окно" + "value": "Глобальные" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Prozor" + "value": "Globalno" } }, "ar": { "stringUnit": { "state": "translated", - "value": "نافذة" + "value": "عام" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Vindu" + "value": "Globalt" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Janela" + "value": "Global" } }, "th": { "stringUnit": { "state": "translated", - "value": "หน้าต่าง" + "value": "ทั่วไป" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Pencere" + "value": "Genel" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Вікно" + "value": "Глобальна" } } } }, - "command.newWindow.title": { + "command.openSettings.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "New Window" + "value": "Open Settings" } }, "ja": { "stringUnit": { "state": "translated", - "value": "新規ウインドウ" + "value": "設定を開く" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "新建窗口" + "value": "打开设置" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "新增視窗" + "value": "開啟設定" } }, "ko": { "stringUnit": { "state": "translated", - "value": "새 윈도우" + "value": "설정 열기" } }, "de": { "stringUnit": { "state": "translated", - "value": "Neues Fenster" + "value": "Einstellungen öffnen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Nueva ventana" + "value": "Abrir ajustes" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Nouvelle fenêtre" + "value": "Ouvrir les réglages" } }, "it": { "stringUnit": { "state": "translated", - "value": "Nuova finestra" + "value": "Apri impostazioni" } }, "da": { "stringUnit": { "state": "translated", - "value": "Nyt vindue" + "value": "Åbn indstillinger" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Nowe okno" + "value": "Otwórz ustawienia" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Новое окно" + "value": "Открыть настройки" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Novi prozor" + "value": "Otvori postavke" } }, "ar": { "stringUnit": { "state": "translated", - "value": "نافذة جديدة" + "value": "فتح الإعدادات" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Nytt vindu" + "value": "Åpne innstillinger" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Nova Janela" + "value": "Abrir Ajustes" } }, "th": { "stringUnit": { "state": "translated", - "value": "หน้าต่างใหม่" + "value": "เปิดการตั้งค่า" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Yeni Pencere" + "value": "Ayarları Aç" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Нове вікно" + "value": "Відкрити налаштування" } } } }, - "command.newWorkspace.subtitle": { + "command.openWorkspacePRLinks.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Workspace" + "value": "Open All Workspace PR Links" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ワークスペース" + "value": "ワークスペースのPRリンクをすべて開く" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "工作区" + "value": "打开工作区所有 PR 链接" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "工作區" + "value": "開啟所有工作區 PR 連結" } }, "ko": { "stringUnit": { "state": "translated", - "value": "작업 공간" + "value": "작업 공간 PR 링크 모두 열기" } }, "de": { "stringUnit": { "state": "translated", - "value": "Arbeitsbereich" + "value": "Alle PR-Links des Arbeitsbereichs öffnen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Espacio de trabajo" + "value": "Abrir todos los enlaces de PR del espacio de trabajo" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Espace de travail" + "value": "Ouvrir tous les liens PR de l'espace de travail" } }, "it": { "stringUnit": { "state": "translated", - "value": "Area di lavoro" + "value": "Apri tutti i link PR dell'area di lavoro" } }, "da": { "stringUnit": { "state": "translated", - "value": "Arbejdsområde" + "value": "Åbn alle PR-links for arbejdsområde" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Przestrzeń robocza" + "value": "Otwórz wszystkie linki PR przestrzeni roboczej" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Рабочее пространство" + "value": "Открыть все ссылки PR рабочего пространства" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Radni prostor" + "value": "Otvori sve PR linkove radnog prostora" } }, "ar": { "stringUnit": { "state": "translated", - "value": "مساحة العمل" + "value": "فتح جميع روابط طلبات السحب في مساحة العمل" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Arbeidsområde" + "value": "Åpne alle PR-lenker for arbeidsområdet" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Área de Trabalho" + "value": "Abrir Todos os Links de PR da Área de Trabalho" } }, "th": { "stringUnit": { "state": "translated", - "value": "เวิร์กสเปซ" + "value": "เปิดลิงก์ PR ทั้งหมดของเวิร์กสเปซ" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Çalışma Alanı" + "value": "Tüm Çalışma Alanı PR Bağlantılarını Aç" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Робоча область" + "value": "Відкрити всі PR-посилання робочої області" } } } }, - "command.newWorkspace.title": { + "command.pinTab.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "New Workspace" + "value": "Pin Tab" } }, "ja": { "stringUnit": { "state": "translated", - "value": "新規ワークスペース" + "value": "タブをピンで固定" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "新建工作区" + "value": "固定标签页" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "新增工作區" + "value": "釘選標籤頁" } }, "ko": { "stringUnit": { "state": "translated", - "value": "새 작업 공간" + "value": "탭 고정" } }, "de": { "stringUnit": { "state": "translated", - "value": "Neuer Arbeitsbereich" + "value": "Tab anheften" } }, "es": { "stringUnit": { "state": "translated", - "value": "Nuevo espacio de trabajo" + "value": "Fijar pestaña" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Nouvel espace de travail" + "value": "Épingler l'onglet" } }, "it": { "stringUnit": { "state": "translated", - "value": "Nuova area di lavoro" + "value": "Fissa scheda" } }, "da": { "stringUnit": { "state": "translated", - "value": "Nyt arbejdsområde" + "value": "Fastgør fane" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Nowa przestrzeń robocza" + "value": "Przypnij kartę" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Новое рабочее пространство" + "value": "Закрепить вкладку" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Novi radni prostor" + "value": "Zakači tab" } }, "ar": { "stringUnit": { "state": "translated", - "value": "مساحة عمل جديدة" + "value": "تثبيت اللسان" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Nytt arbeidsområde" + "value": "Fest fane" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Nova Área de Trabalho" + "value": "Fixar Aba" } }, "th": { "stringUnit": { "state": "translated", - "value": "เวิร์กสเปซใหม่" + "value": "ปักหมุดแท็บ" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Yeni Çalışma Alanı" + "value": "Sekmeyi Sabitle" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Нова робоча область" + "value": "Закріпити вкладку" } } } }, - "command.nextTabInPane.subtitle": { + "command.pinWorkspace.title": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Pin Workspace" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "ワークスペースをピンで固定" + } + }, + "zh-Hans": { + "stringUnit": { + "state": "translated", + "value": "固定工作区" + } + }, + "zh-Hant": { + "stringUnit": { + "state": "translated", + "value": "釘選工作區" + } + }, + "ko": { + "stringUnit": { + "state": "translated", + "value": "작업 공간 고정" + } + }, + "de": { + "stringUnit": { + "state": "translated", + "value": "Arbeitsbereich anheften" + } + }, + "es": { + "stringUnit": { + "state": "translated", + "value": "Fijar espacio de trabajo" + } + }, + "fr": { + "stringUnit": { + "state": "translated", + "value": "Épingler l'espace de travail" + } + }, + "it": { + "stringUnit": { + "state": "translated", + "value": "Fissa area di lavoro" + } + }, + "da": { + "stringUnit": { + "state": "translated", + "value": "Fastgør arbejdsområde" + } + }, + "pl": { + "stringUnit": { + "state": "translated", + "value": "Przypnij przestrzeń roboczą" + } + }, + "ru": { + "stringUnit": { + "state": "translated", + "value": "Закрепить рабочее пространство" + } + }, + "bs": { + "stringUnit": { + "state": "translated", + "value": "Zakači radni prostor" + } + }, + "ar": { + "stringUnit": { + "state": "translated", + "value": "تثبيت مساحة العمل" + } + }, + "nb": { + "stringUnit": { + "state": "translated", + "value": "Fest arbeidsområde" + } + }, + "pt-BR": { + "stringUnit": { + "state": "translated", + "value": "Fixar Área de Trabalho" + } + }, + "th": { + "stringUnit": { + "state": "translated", + "value": "ปักหมุดเวิร์กสเปซ" + } + }, + "tr": { + "stringUnit": { + "state": "translated", + "value": "Çalışma Alanını Sabitle" + } + }, + "uk": { + "stringUnit": { + "state": "translated", + "value": "Закріпити робочу область" + } + } + } + }, + "command.previousTabInPane.subtitle": { "extractionState": "manual", "localizations": { "en": { @@ -24743,126 +25063,126 @@ } } }, - "command.nextTabInPane.title": { + "command.previousTabInPane.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Next Tab in Pane" + "value": "Previous Tab in Pane" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ペイン内の次のタブ" + "value": "ペイン内の前のタブ" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "下一个面板标签页" + "value": "上一个面板标签页" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "面板中的下一個標籤頁" + "value": "面板中的上一個標籤頁" } }, "ko": { "stringUnit": { "state": "translated", - "value": "패널 내 다음 탭" + "value": "패널 내 이전 탭" } }, "de": { "stringUnit": { "state": "translated", - "value": "Nächster Tab im Bereich" + "value": "Vorheriger Tab im Bereich" } }, "es": { "stringUnit": { "state": "translated", - "value": "Siguiente pestaña en el panel" + "value": "Pestaña anterior en el panel" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Onglet suivant dans le panneau" + "value": "Onglet précédent dans le panneau" } }, "it": { "stringUnit": { "state": "translated", - "value": "Scheda successiva nel pannello" + "value": "Scheda precedente nel pannello" } }, "da": { "stringUnit": { "state": "translated", - "value": "Næste fane i panel" + "value": "Forrige fane i panel" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Następna karta w panelu" + "value": "Poprzednia karta w panelu" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Следующая вкладка в панели" + "value": "Предыдущая вкладка в панели" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Sljedeći tab u panelu" + "value": "Prethodni tab u panelu" } }, "ar": { "stringUnit": { "state": "translated", - "value": "اللسان التالي في اللوحة" + "value": "اللسان السابق في اللوحة" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Neste fane i panelet" + "value": "Forrige fane i panelet" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Próxima Aba no Painel" + "value": "Aba Anterior no Painel" } }, "th": { "stringUnit": { "state": "translated", - "value": "แท็บถัดไปในบานหน้าต่าง" + "value": "แท็บก่อนหน้าในบานหน้าต่าง" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Bölmedeki Sonraki Sekme" + "value": "Bölmedeki Önceki Sekme" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Наступна вкладка в панелі" + "value": "Попередня вкладка в панелі" } } } }, - "command.nextWorkspace.subtitle": { + "command.previousWorkspace.subtitle": { "extractionState": "manual", "localizations": { "en": { @@ -24981,2943 +25301,3101 @@ } } }, - "command.nextWorkspace.title": { + "command.previousWorkspace.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Next Workspace" + "value": "Previous Workspace" } }, "ja": { "stringUnit": { "state": "translated", - "value": "次のワークスペース" + "value": "前のワークスペース" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "下一个工作区" + "value": "上一个工作区" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "下一個工作區" + "value": "上一個工作區" } }, "ko": { "stringUnit": { "state": "translated", - "value": "다음 작업 공간" + "value": "이전 작업 공간" } }, "de": { "stringUnit": { "state": "translated", - "value": "Nächster Arbeitsbereich" + "value": "Vorheriger Arbeitsbereich" } }, "es": { "stringUnit": { "state": "translated", - "value": "Siguiente espacio de trabajo" + "value": "Espacio de trabajo anterior" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Espace de travail suivant" + "value": "Espace de travail précédent" } }, "it": { "stringUnit": { "state": "translated", - "value": "Area di lavoro successiva" + "value": "Area di lavoro precedente" } }, "da": { "stringUnit": { "state": "translated", - "value": "Næste arbejdsområde" + "value": "Forrige arbejdsområde" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Następna przestrzeń robocza" + "value": "Poprzednia przestrzeń robocza" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Следующее рабочее пространство" + "value": "Предыдущее рабочее пространство" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Sljedeći radni prostor" + "value": "Prethodni radni prostor" } }, "ar": { "stringUnit": { "state": "translated", - "value": "مساحة العمل التالية" + "value": "مساحة العمل السابقة" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Neste arbeidsområde" + "value": "Forrige arbeidsområde" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Próxima Área de Trabalho" + "value": "Área de Trabalho Anterior" } }, "th": { "stringUnit": { "state": "translated", - "value": "เวิร์กสเปซถัดไป" + "value": "เวิร์กสเปซก่อนหน้า" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Sonraki Çalışma Alanı" + "value": "Önceki Çalışma Alanı" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Наступна робоча область" + "value": "Попередня робоча область" } } } }, - "command.openFolder.subtitle": { + "command.renameTab.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Workspace" + "value": "Rename Tab…" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ワークスペース" + "value": "タブの名称変更…" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "工作区" + "value": "重命名标签页..." } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "工作區" + "value": "重新命名標籤頁..." } }, "ko": { "stringUnit": { "state": "translated", - "value": "작업 공간" + "value": "탭 이름 변경…" } }, "de": { "stringUnit": { "state": "translated", - "value": "Arbeitsbereich" + "value": "Tab umbenennen …" } }, "es": { "stringUnit": { "state": "translated", - "value": "Espacio de trabajo" + "value": "Renombrar pestaña…" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Espace de travail" + "value": "Renommer l'onglet..." } }, "it": { "stringUnit": { "state": "translated", - "value": "Area di lavoro" + "value": "Rinomina scheda…" } }, "da": { "stringUnit": { "state": "translated", - "value": "Arbejdsområde" + "value": "Omdøb fane…" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Przestrzeń robocza" + "value": "Zmień nazwę karty…" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Рабочее пространство" + "value": "Переименовать вкладку..." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Radni prostor" + "value": "Preimenuj tab…" } }, "ar": { "stringUnit": { "state": "translated", - "value": "مساحة العمل" + "value": "إعادة تسمية اللسان…" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Arbeidsområde" + "value": "Gi fanen nytt navn …" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Área de Trabalho" + "value": "Renomear Aba…" } }, "th": { "stringUnit": { "state": "translated", - "value": "เวิร์กสเปซ" + "value": "เปลี่ยนชื่อแท็บ..." } }, "tr": { "stringUnit": { "state": "translated", - "value": "Çalışma Alanı" + "value": "Sekmeyi Yeniden Adlandır…" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Робоча область" + "value": "Перейменувати вкладку…" } } } }, - "command.openFolder.title": { + "command.renameWorkspace.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Open Folder…" + "value": "Rename Workspace…" } }, "ja": { "stringUnit": { "state": "translated", - "value": "フォルダを開く…" + "value": "ワークスペースの名称変更…" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "打开文件夹..." + "value": "重命名工作区..." } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "開啟資料夾..." + "value": "重新命名工作區..." } }, "ko": { "stringUnit": { "state": "translated", - "value": "폴더 열기…" + "value": "작업 공간 이름 변경…" } }, "de": { "stringUnit": { "state": "translated", - "value": "Ordner öffnen …" + "value": "Arbeitsbereich umbenennen …" } }, "es": { "stringUnit": { "state": "translated", - "value": "Abrir carpeta…" + "value": "Renombrar espacio de trabajo…" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Ouvrir un dossier..." + "value": "Renommer l'espace de travail..." } }, "it": { "stringUnit": { "state": "translated", - "value": "Apri cartella…" + "value": "Rinomina area di lavoro…" } }, "da": { "stringUnit": { "state": "translated", - "value": "Åbn mappe…" + "value": "Omdøb arbejdsområde…" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Otwórz folder…" + "value": "Zmień nazwę przestrzeni roboczej…" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Открыть папку..." + "value": "Переименовать рабочее пространство..." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Otvori folder…" + "value": "Preimenuj radni prostor…" } }, "ar": { "stringUnit": { "state": "translated", - "value": "فتح مجلد…" + "value": "إعادة تسمية مساحة العمل…" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Åpne mappe …" + "value": "Gi arbeidsområdet nytt navn …" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Abrir Pasta…" + "value": "Renomear Área de Trabalho…" } }, "th": { "stringUnit": { "state": "translated", - "value": "เปิดโฟลเดอร์..." + "value": "เปลี่ยนชื่อเวิร์กสเปซ..." } }, "tr": { "stringUnit": { "state": "translated", - "value": "Klasör Aç…" + "value": "Çalışma Alanını Yeniden Adlandır…" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Відкрити теку…" - } - } - } - }, - "command.openFolderInVSCodeInline.subtitle": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "VS Code Inline" - } - }, - "ja": { - "stringUnit": { - "state": "translated", - "value": "VS Code インライン" - } - }, - "ko": { - "stringUnit": { - "state": "translated", - "value": "VS Code 인라인" - } - } - } - }, - "command.openFolderInVSCodeInline.title": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Open Folder in VS Code (Inline)…" - } - }, - "ja": { - "stringUnit": { - "state": "translated", - "value": "フォルダを VS Code で開く(インライン)…" - } - }, - "ko": { - "stringUnit": { - "state": "translated", - "value": "VS Code에서 폴더 열기 (인라인)…" + "value": "Перейменувати робочу область…" } } } }, - "command.openSettings.subtitle": { + "command.reopenClosedBrowserTab.subtitle": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Global" + "value": "Browser" } }, "ja": { "stringUnit": { "state": "translated", - "value": "グローバル" + "value": "ブラウザ" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "全局" + "value": "浏览器" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "全域" + "value": "瀏覽器" } }, "ko": { "stringUnit": { "state": "translated", - "value": "전역" + "value": "브라우저" } }, "de": { "stringUnit": { "state": "translated", - "value": "Global" + "value": "Browser" } }, "es": { "stringUnit": { "state": "translated", - "value": "Global" + "value": "Navegador" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Général" + "value": "Navigateur" } }, "it": { "stringUnit": { "state": "translated", - "value": "Globale" + "value": "Browser" } }, "da": { "stringUnit": { "state": "translated", - "value": "Globalt" + "value": "Browser" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Globalne" + "value": "Przeglądarka" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Глобальные" + "value": "Браузер" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Globalno" + "value": "Preglednik" } }, "ar": { "stringUnit": { "state": "translated", - "value": "عام" + "value": "المتصفح" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Globalt" + "value": "Nettleser" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Global" + "value": "Navegador" } }, "th": { "stringUnit": { "state": "translated", - "value": "ทั่วไป" + "value": "เบราว์เซอร์" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Genel" + "value": "Tarayıcı" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Глобальна" + "value": "Браузер" } } } }, - "command.openSettings.title": { + "command.reopenClosedBrowserTab.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Open Settings" + "value": "Reopen Closed Browser Tab" } }, "ja": { "stringUnit": { "state": "translated", - "value": "設定を開く" + "value": "閉じたブラウザタブを再度開く" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "打开设置" + "value": "重新打开已关闭的浏览器标签页" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "開啟設定" + "value": "重新開啟已關閉的瀏覽器標籤頁" } }, "ko": { "stringUnit": { "state": "translated", - "value": "설정 열기" + "value": "닫은 브라우저 탭 다시 열기" } }, "de": { "stringUnit": { "state": "translated", - "value": "Einstellungen öffnen" + "value": "Geschlossenen Browser-Tab erneut öffnen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Abrir ajustes" + "value": "Reabrir pestaña del navegador cerrada" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Ouvrir les réglages" + "value": "Rouvrir l'onglet de navigateur fermé" } }, "it": { "stringUnit": { "state": "translated", - "value": "Apri impostazioni" + "value": "Riapri scheda browser chiusa" } }, "da": { "stringUnit": { "state": "translated", - "value": "Åbn indstillinger" + "value": "Genåbn lukket browserfane" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Otwórz ustawienia" + "value": "Otwórz ponownie zamkniętą kartę przeglądarki" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Открыть настройки" + "value": "Открыть закрытую вкладку браузера" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Otvori postavke" + "value": "Ponovo otvori zatvoreni tab preglednika" } }, "ar": { "stringUnit": { "state": "translated", - "value": "فتح الإعدادات" + "value": "إعادة فتح لسان المتصفح المغلق" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Åpne innstillinger" + "value": "Åpne lukket nettleserfane på nytt" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Abrir Ajustes" + "value": "Reabrir Aba do Navegador Fechada" } }, "th": { "stringUnit": { "state": "translated", - "value": "เปิดการตั้งค่า" + "value": "เปิดแท็บเบราว์เซอร์ที่ปิดไปอีกครั้ง" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Ayarları Aç" + "value": "Kapatılan Tarayıcı Sekmesini Yeniden Aç" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Відкрити налаштування" + "value": "Відновити закриту вкладку браузера" } } } }, - "command.openWorkspacePRLinks.title": { + "command.reopenPreviousSession.subtitle": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Open All Workspace PR Links" + "value": "Session" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ワークスペースのPRリンクをすべて開く" + "value": "セッション" + } + } + } + }, + "command.reopenPreviousSession.title": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Reopen Previous Session" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "前回のセッションを再度開く" + } + } + } + }, + "command.restartSocketListener.subtitle": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Global" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "グローバル" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "打开工作区所有 PR 链接" + "value": "全局" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "開啟所有工作區 PR 連結" + "value": "全域" } }, "ko": { "stringUnit": { "state": "translated", - "value": "작업 공간 PR 링크 모두 열기" + "value": "전역" } }, "de": { "stringUnit": { "state": "translated", - "value": "Alle PR-Links des Arbeitsbereichs öffnen" + "value": "Global" } }, "es": { "stringUnit": { "state": "translated", - "value": "Abrir todos los enlaces de PR del espacio de trabajo" + "value": "Global" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Ouvrir tous les liens PR de l'espace de travail" + "value": "Général" } }, "it": { "stringUnit": { "state": "translated", - "value": "Apri tutti i link PR dell'area di lavoro" + "value": "Globale" } }, "da": { "stringUnit": { "state": "translated", - "value": "Åbn alle PR-links for arbejdsområde" + "value": "Globalt" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Otwórz wszystkie linki PR przestrzeni roboczej" + "value": "Globalne" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Открыть все ссылки PR рабочего пространства" + "value": "Глобальные" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Otvori sve PR linkove radnog prostora" + "value": "Globalno" } }, "ar": { "stringUnit": { "state": "translated", - "value": "فتح جميع روابط طلبات السحب في مساحة العمل" + "value": "عام" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Åpne alle PR-lenker for arbeidsområdet" + "value": "Globalt" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Abrir Todos os Links de PR da Área de Trabalho" + "value": "Global" } }, "th": { "stringUnit": { "state": "translated", - "value": "เปิดลิงก์ PR ทั้งหมดของเวิร์กสเปซ" + "value": "ทั่วไป" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Tüm Çalışma Alanı PR Bağlantılarını Aç" + "value": "Genel" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Відкрити всі PR-посилання робочої області" + "value": "Глобальна" } } } }, - "command.pinTab.title": { + "command.restartSocketListener.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Pin Tab" + "value": "Restart CLI Listener" } }, "ja": { "stringUnit": { "state": "translated", - "value": "タブをピンで固定" + "value": "CLIリスナーを再起動" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "固定标签页" + "value": "重启 CLI 监听器" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "釘選標籤頁" + "value": "重新啟動 CLI 監聽器" } }, "ko": { "stringUnit": { "state": "translated", - "value": "탭 고정" + "value": "CLI 리스너 재시작" } }, "de": { "stringUnit": { "state": "translated", - "value": "Tab anheften" + "value": "CLI-Listener neu starten" } }, "es": { "stringUnit": { "state": "translated", - "value": "Fijar pestaña" + "value": "Reiniciar receptor de CLI" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Épingler l'onglet" + "value": "Redémarrer l'écouteur CLI" } }, "it": { "stringUnit": { "state": "translated", - "value": "Fissa scheda" + "value": "Riavvia listener CLI" } }, "da": { "stringUnit": { "state": "translated", - "value": "Fastgør fane" + "value": "Genstart CLI-lytter" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Przypnij kartę" + "value": "Uruchom ponownie nasłuchiwanie CLI" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Закрепить вкладку" + "value": "Перезапустить прослушиватель CLI" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Zakači tab" + "value": "Ponovo pokreni CLI osluškivač" } }, "ar": { "stringUnit": { "state": "translated", - "value": "تثبيت اللسان" + "value": "إعادة تشغيل مستمع واجهة الأوامر" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Fest fane" + "value": "Start CLI-lytteren på nytt" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Fixar Aba" + "value": "Reiniciar Listener do CLI" } }, "th": { "stringUnit": { "state": "translated", - "value": "ปักหมุดแท็บ" + "value": "รีสตาร์ตตัวรับฟัง CLI" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Sekmeyi Sabitle" + "value": "CLI Dinleyicisini Yeniden Başlat" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Закріпити вкладку" + "value": "Перезапустити слухач CLI" } } } }, - "command.pinWorkspace.title": { + "command.showNotifications.subtitle": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Pin Workspace" + "value": "Notifications" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ワークスペースをピンで固定" + "value": "通知" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "固定工作区" + "value": "通知" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "釘選工作區" + "value": "通知" } }, "ko": { "stringUnit": { "state": "translated", - "value": "작업 공간 고정" + "value": "알림" } }, "de": { "stringUnit": { "state": "translated", - "value": "Arbeitsbereich anheften" + "value": "Benachrichtigungen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Fijar espacio de trabajo" + "value": "Notificaciones" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Épingler l'espace de travail" + "value": "Notifications" } }, "it": { "stringUnit": { "state": "translated", - "value": "Fissa area di lavoro" + "value": "Notifiche" } }, "da": { "stringUnit": { "state": "translated", - "value": "Fastgør arbejdsområde" + "value": "Notifikationer" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Przypnij przestrzeń roboczą" + "value": "Powiadomienia" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Закрепить рабочее пространство" + "value": "Уведомления" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Zakači radni prostor" + "value": "Obavještenja" } }, "ar": { "stringUnit": { "state": "translated", - "value": "تثبيت مساحة العمل" + "value": "الإشعارات" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Fest arbeidsområde" + "value": "Varsler" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Fixar Área de Trabalho" + "value": "Notificações" } }, "th": { "stringUnit": { "state": "translated", - "value": "ปักหมุดเวิร์กสเปซ" + "value": "การแจ้งเตือน" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Çalışma Alanını Sabitle" + "value": "Bildirimler" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Закріпити робочу область" + "value": "Сповіщення" } } } }, - "command.previousTabInPane.subtitle": { + "command.showNotifications.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Tab Navigation" + "value": "Show Notifications" } }, "ja": { "stringUnit": { "state": "translated", - "value": "タブナビゲーション" + "value": "通知を表示" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "标签页导航" + "value": "显示通知" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "標籤頁導覽" + "value": "顯示通知" } }, "ko": { "stringUnit": { "state": "translated", - "value": "탭 탐색" + "value": "알림 표시" } }, "de": { "stringUnit": { "state": "translated", - "value": "Tab-Navigation" + "value": "Benachrichtigungen anzeigen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Navegación de pestañas" + "value": "Mostrar notificaciones" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Navigation par onglets" + "value": "Afficher les notifications" } }, "it": { "stringUnit": { "state": "translated", - "value": "Navigazione schede" + "value": "Mostra notifiche" } }, "da": { "stringUnit": { "state": "translated", - "value": "Fanenavigation" + "value": "Vis notifikationer" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Nawigacja po kartach" + "value": "Pokaż powiadomienia" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Навигация по вкладкам" + "value": "Показать уведомления" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Navigacija tabovima" + "value": "Prikaži obavještenja" } }, "ar": { "stringUnit": { "state": "translated", - "value": "التنقل بين الألسنة" + "value": "عرض الإشعارات" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Fanenavigering" + "value": "Vis varsler" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Navegação de Abas" + "value": "Mostrar Notificações" } }, "th": { "stringUnit": { "state": "translated", - "value": "การนำทางแท็บ" + "value": "แสดงการแจ้งเตือน" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Sekme Gezinme" + "value": "Bildirimleri Göster" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Навігація вкладками" + "value": "Показати сповіщення" } } } }, - "command.previousTabInPane.title": { + "command.terminalFind.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Previous Tab in Pane" + "value": "Find…" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ペイン内の前のタブ" + "value": "検索…" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "上一个面板标签页" + "value": "查找..." } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "面板中的上一個標籤頁" + "value": "尋找..." } }, "ko": { "stringUnit": { "state": "translated", - "value": "패널 내 이전 탭" + "value": "찾기…" } }, "de": { "stringUnit": { "state": "translated", - "value": "Vorheriger Tab im Bereich" + "value": "Suchen …" } }, "es": { "stringUnit": { "state": "translated", - "value": "Pestaña anterior en el panel" + "value": "Buscar…" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Onglet précédent dans le panneau" + "value": "Rechercher..." } }, "it": { "stringUnit": { "state": "translated", - "value": "Scheda precedente nel pannello" + "value": "Trova…" } }, "da": { "stringUnit": { "state": "translated", - "value": "Forrige fane i panel" + "value": "Søg…" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Poprzednia karta w panelu" + "value": "Znajdź…" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Предыдущая вкладка в панели" + "value": "Найти..." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Prethodni tab u panelu" + "value": "Pronađi…" } }, "ar": { "stringUnit": { "state": "translated", - "value": "اللسان السابق في اللوحة" + "value": "بحث…" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Forrige fane i panelet" + "value": "Finn …" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Aba Anterior no Painel" + "value": "Buscar…" } }, "th": { "stringUnit": { "state": "translated", - "value": "แท็บก่อนหน้าในบานหน้าต่าง" + "value": "ค้นหา..." } }, "tr": { "stringUnit": { "state": "translated", - "value": "Bölmedeki Önceki Sekme" + "value": "Bul…" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Попередня вкладка в панелі" + "value": "Знайти…" } } } }, - "command.previousWorkspace.subtitle": { + "command.terminalFindNext.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Workspace Navigation" + "value": "Find Next" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ワークスペースナビゲーション" + "value": "次を検索" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "工作区导航" + "value": "查找下一个" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "工作區導覽" + "value": "尋找下一個" } }, "ko": { "stringUnit": { "state": "translated", - "value": "작업 공간 탐색" + "value": "다음 찾기" } }, "de": { "stringUnit": { "state": "translated", - "value": "Arbeitsbereich-Navigation" + "value": "Weitersuchen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Navegación de espacios de trabajo" + "value": "Buscar siguiente" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Navigation par espaces de travail" + "value": "Résultat suivant" } }, "it": { "stringUnit": { "state": "translated", - "value": "Navigazione aree di lavoro" + "value": "Trova successivo" } }, "da": { "stringUnit": { "state": "translated", - "value": "Arbejdsområdenavigation" + "value": "Find næste" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Nawigacja po przestrzeniach roboczych" + "value": "Znajdź następny" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Навигация по рабочим пространствам" + "value": "Найти далее" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Navigacija radnim prostorima" + "value": "Pronađi sljedeće" } }, "ar": { "stringUnit": { "state": "translated", - "value": "التنقل بين مساحات العمل" + "value": "البحث عن التالي" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Arbeidsområdenavigering" + "value": "Finn neste" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Navegação de Áreas de Trabalho" + "value": "Buscar Próximo" } }, "th": { "stringUnit": { "state": "translated", - "value": "การนำทางเวิร์กสเปซ" + "value": "ค้นหาถัดไป" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Çalışma Alanı Gezinme" + "value": "Sonrakini Bul" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Навігація робочими областями" + "value": "Знайти наступне" } } } }, - "command.previousWorkspace.title": { + "command.terminalFindPrevious.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Previous Workspace" + "value": "Find Previous" } }, "ja": { "stringUnit": { "state": "translated", - "value": "前のワークスペース" + "value": "前を検索" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "上一个工作区" + "value": "查找上一个" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "上一個工作區" + "value": "尋找上一個" } }, "ko": { "stringUnit": { "state": "translated", - "value": "이전 작업 공간" + "value": "이전 찾기" } }, "de": { "stringUnit": { "state": "translated", - "value": "Vorheriger Arbeitsbereich" + "value": "Vorheriges suchen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Espacio de trabajo anterior" + "value": "Buscar anterior" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Espace de travail précédent" + "value": "Résultat précédent" } }, "it": { "stringUnit": { "state": "translated", - "value": "Area di lavoro precedente" + "value": "Trova precedente" } }, "da": { "stringUnit": { "state": "translated", - "value": "Forrige arbejdsområde" + "value": "Find forrige" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Poprzednia przestrzeń robocza" + "value": "Znajdź poprzedni" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Предыдущее рабочее пространство" + "value": "Найти ранее" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Prethodni radni prostor" + "value": "Pronađi prethodno" } }, "ar": { "stringUnit": { "state": "translated", - "value": "مساحة العمل السابقة" + "value": "البحث عن السابق" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Forrige arbeidsområde" + "value": "Finn forrige" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Área de Trabalho Anterior" + "value": "Buscar Anterior" } }, "th": { "stringUnit": { "state": "translated", - "value": "เวิร์กสเปซก่อนหน้า" + "value": "ค้นหาก่อนหน้า" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Önceki Çalışma Alanı" + "value": "Öncekini Bul" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Попередня робоча область" + "value": "Знайти попереднє" } } } }, - "command.renameTab.title": { + "command.terminalHideFind.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Rename Tab…" + "value": "Hide Find Bar" } }, "ja": { "stringUnit": { "state": "translated", - "value": "タブの名称変更…" + "value": "検索バーを非表示" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "重命名标签页..." + "value": "隐藏查找栏" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "重新命名標籤頁..." + "value": "隱藏尋找列" } }, "ko": { "stringUnit": { "state": "translated", - "value": "탭 이름 변경…" + "value": "찾기 막대 숨기기" } }, "de": { "stringUnit": { "state": "translated", - "value": "Tab umbenennen …" + "value": "Suchleiste ausblenden" } }, "es": { "stringUnit": { "state": "translated", - "value": "Renombrar pestaña…" + "value": "Ocultar barra de búsqueda" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Renommer l'onglet..." + "value": "Masquer la barre de recherche" } }, "it": { "stringUnit": { "state": "translated", - "value": "Rinomina scheda…" + "value": "Nascondi barra di ricerca" } }, "da": { "stringUnit": { "state": "translated", - "value": "Omdøb fane…" + "value": "Skjul søgelinje" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Zmień nazwę karty…" + "value": "Ukryj pasek wyszukiwania" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Переименовать вкладку..." + "value": "Скрыть панель поиска" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Preimenuj tab…" + "value": "Sakrij traku za pretragu" } }, "ar": { "stringUnit": { "state": "translated", - "value": "إعادة تسمية اللسان…" + "value": "إخفاء شريط البحث" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Gi fanen nytt navn …" + "value": "Skjul søkelinje" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Renomear Aba…" + "value": "Ocultar Barra de Busca" } }, "th": { "stringUnit": { "state": "translated", - "value": "เปลี่ยนชื่อแท็บ..." + "value": "ซ่อนแถบค้นหา" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Sekmeyi Yeniden Adlandır…" + "value": "Arama Çubuğunu Gizle" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Перейменувати вкладку…" + "value": "Сховати панель пошуку" } } } }, - "command.renameWorkspace.title": { + "command.terminalSplitBrowserDown.subtitle": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Rename Workspace…" + "value": "Terminal Layout" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ワークスペースの名称変更…" + "value": "ターミナルレイアウト" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "重命名工作区..." + "value": "终端布局" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "重新命名工作區..." + "value": "終端機版面" } }, "ko": { "stringUnit": { "state": "translated", - "value": "작업 공간 이름 변경…" + "value": "터미널 레이아웃" } }, "de": { "stringUnit": { "state": "translated", - "value": "Arbeitsbereich umbenennen …" + "value": "Terminal-Layout" } }, "es": { "stringUnit": { "state": "translated", - "value": "Renombrar espacio de trabajo…" + "value": "Disposición del terminal" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Renommer l'espace de travail..." + "value": "Disposition du terminal" } }, "it": { "stringUnit": { "state": "translated", - "value": "Rinomina area di lavoro…" + "value": "Layout terminale" } }, "da": { "stringUnit": { "state": "translated", - "value": "Omdøb arbejdsområde…" + "value": "Terminallayout" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Zmień nazwę przestrzeni roboczej…" + "value": "Układ terminala" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Переименовать рабочее пространство..." + "value": "Макет терминала" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Preimenuj radni prostor…" + "value": "Raspored terminala" } }, "ar": { "stringUnit": { "state": "translated", - "value": "إعادة تسمية مساحة العمل…" + "value": "تخطيط الطرفية" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Gi arbeidsområdet nytt navn …" + "value": "Terminaloppsett" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Renomear Área de Trabalho…" + "value": "Layout do Terminal" } }, "th": { "stringUnit": { "state": "translated", - "value": "เปลี่ยนชื่อเวิร์กสเปซ..." + "value": "เค้าโครงเทอร์มินัล" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Çalışma Alanını Yeniden Adlandır…" + "value": "Terminal Düzeni" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Перейменувати робочу область…" + "value": "Макет терміналу" } } } }, - "command.reopenClosedBrowserTab.subtitle": { + "command.terminalSplitBrowserDown.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Browser" + "value": "Split Browser Down" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ブラウザ" + "value": "ブラウザを下に分割" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "浏览器" + "value": "向下拆分浏览器" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "瀏覽器" + "value": "向下分割瀏覽器" } }, "ko": { "stringUnit": { "state": "translated", - "value": "브라우저" + "value": "브라우저를 아래로 분할" } }, "de": { "stringUnit": { "state": "translated", - "value": "Browser" + "value": "Browser nach unten teilen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Navegador" + "value": "Dividir navegador hacia abajo" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Navigateur" + "value": "Diviser le navigateur vers le bas" } }, "it": { "stringUnit": { "state": "translated", - "value": "Browser" + "value": "Dividi browser in basso" } }, "da": { "stringUnit": { "state": "translated", - "value": "Browser" + "value": "Opdel browser nedad" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Przeglądarka" + "value": "Podziel przeglądarkę w dół" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Браузер" + "value": "Разделить браузер вниз" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Preglednik" + "value": "Podijeli preglednik dolje" } }, "ar": { "stringUnit": { "state": "translated", - "value": "المتصفح" + "value": "تقسيم المتصفح للأسفل" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Nettleser" + "value": "Del nettleser ned" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Navegador" + "value": "Dividir Navegador para Baixo" } }, "th": { "stringUnit": { "state": "translated", - "value": "เบราว์เซอร์" + "value": "แยกเบราว์เซอร์ลงล่าง" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Tarayıcı" + "value": "Tarayıcıyı Aşağı Böl" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Браузер" + "value": "Розділити браузер вниз" } } } }, - "command.reopenClosedBrowserTab.title": { + "command.terminalSplitBrowserRight.subtitle": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Reopen Closed Browser Tab" + "value": "Terminal Layout" } }, "ja": { "stringUnit": { "state": "translated", - "value": "閉じたブラウザタブを再度開く" + "value": "ターミナルレイアウト" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "重新打开已关闭的浏览器标签页" + "value": "终端布局" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "重新開啟已關閉的瀏覽器標籤頁" + "value": "終端機版面" } }, "ko": { "stringUnit": { "state": "translated", - "value": "닫은 브라우저 탭 다시 열기" + "value": "터미널 레이아웃" } }, "de": { "stringUnit": { "state": "translated", - "value": "Geschlossenen Browser-Tab erneut öffnen" + "value": "Terminal-Layout" } }, "es": { "stringUnit": { "state": "translated", - "value": "Reabrir pestaña del navegador cerrada" + "value": "Disposición del terminal" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Rouvrir l'onglet de navigateur fermé" + "value": "Disposition du terminal" } }, "it": { "stringUnit": { "state": "translated", - "value": "Riapri scheda browser chiusa" + "value": "Layout terminale" } }, "da": { "stringUnit": { "state": "translated", - "value": "Genåbn lukket browserfane" + "value": "Terminallayout" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Otwórz ponownie zamkniętą kartę przeglądarki" + "value": "Układ terminala" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Открыть закрытую вкладку браузера" + "value": "Макет терминала" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Ponovo otvori zatvoreni tab preglednika" + "value": "Raspored terminala" } }, "ar": { "stringUnit": { "state": "translated", - "value": "إعادة فتح لسان المتصفح المغلق" + "value": "تخطيط الطرفية" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Åpne lukket nettleserfane på nytt" + "value": "Terminaloppsett" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Reabrir Aba do Navegador Fechada" + "value": "Layout do Terminal" } }, "th": { "stringUnit": { "state": "translated", - "value": "เปิดแท็บเบราว์เซอร์ที่ปิดไปอีกครั้ง" + "value": "เค้าโครงเทอร์มินัล" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Kapatılan Tarayıcı Sekmesini Yeniden Aç" + "value": "Terminal Düzeni" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Відновити закриту вкладку браузера" - } - } - } - }, - "command.reopenPreviousSession.subtitle": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Session" - } - }, - "ja": { - "stringUnit": { - "state": "translated", - "value": "セッション" - } - } - } - }, - "command.reopenPreviousSession.title": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Reopen Previous Session" - } - }, - "ja": { - "stringUnit": { - "state": "translated", - "value": "前回のセッションを再度開く" + "value": "Макет терміналу" } } } }, - "command.restartSocketListener.subtitle": { + "command.terminalSplitBrowserRight.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Global" + "value": "Split Browser Right" } }, "ja": { "stringUnit": { "state": "translated", - "value": "グローバル" + "value": "ブラウザを右に分割" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "全局" + "value": "向右拆分浏览器" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "全域" + "value": "向右分割瀏覽器" } }, "ko": { "stringUnit": { "state": "translated", - "value": "전역" + "value": "브라우저를 오른쪽으로 분할" } }, "de": { "stringUnit": { "state": "translated", - "value": "Global" + "value": "Browser nach rechts teilen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Global" + "value": "Dividir navegador a la derecha" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Général" + "value": "Diviser le navigateur à droite" } }, "it": { "stringUnit": { "state": "translated", - "value": "Globale" + "value": "Dividi browser a destra" } }, "da": { "stringUnit": { "state": "translated", - "value": "Globalt" + "value": "Opdel browser til højre" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Globalne" + "value": "Podziel przeglądarkę w prawo" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Глобальные" + "value": "Разделить браузер вправо" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Globalno" + "value": "Podijeli preglednik desno" } }, "ar": { "stringUnit": { "state": "translated", - "value": "عام" + "value": "تقسيم المتصفح لليمين" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Globalt" + "value": "Del nettleser til høyre" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Global" + "value": "Dividir Navegador à Direita" } }, "th": { "stringUnit": { "state": "translated", - "value": "ทั่วไป" + "value": "แยกเบราว์เซอร์ไปทางขวา" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Genel" + "value": "Tarayıcıyı Sağa Böl" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Глобальна" + "value": "Розділити браузер праворуч" } } } }, - "command.restartSocketListener.title": { + "command.forkAgentConversationRight.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Restart CLI Listener" + "value": "Fork Conversation to the Right" } }, "ja": { "stringUnit": { "state": "translated", - "value": "CLIリスナーを再起動" + "value": "会話を右にフォーク" + } + } + } + }, + "command.forkAgentConversationLeft.title": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Fork Conversation to the Left" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "会話を左にフォーク" + } + } + } + }, + "command.forkAgentConversationTop.title": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Fork Conversation to the Top" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "会話を上にフォーク" + } + } + } + }, + "command.forkAgentConversationBottom.title": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Fork Conversation to the Bottom" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "会話を下にフォーク" + } + } + } + }, + "command.forkAgentConversationNewWorkspace.title": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Fork Conversation to New Workspace" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "会話を新規ワークスペースにフォーク" + } + } + } + }, + "command.terminalSplitDown.subtitle": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Terminal Layout" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "ターミナルレイアウト" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "重启 CLI 监听器" + "value": "终端布局" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "重新啟動 CLI 監聽器" + "value": "終端機版面" } }, "ko": { "stringUnit": { "state": "translated", - "value": "CLI 리스너 재시작" + "value": "터미널 레이아웃" } }, "de": { "stringUnit": { "state": "translated", - "value": "CLI-Listener neu starten" + "value": "Terminal-Layout" } }, "es": { "stringUnit": { "state": "translated", - "value": "Reiniciar receptor de CLI" + "value": "Disposición del terminal" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Redémarrer l'écouteur CLI" + "value": "Disposition du terminal" } }, "it": { "stringUnit": { "state": "translated", - "value": "Riavvia listener CLI" + "value": "Layout terminale" } }, "da": { "stringUnit": { "state": "translated", - "value": "Genstart CLI-lytter" + "value": "Terminallayout" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Uruchom ponownie nasłuchiwanie CLI" + "value": "Układ terminala" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Перезапустить прослушиватель CLI" + "value": "Макет терминала" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Ponovo pokreni CLI osluškivač" + "value": "Raspored terminala" } }, "ar": { "stringUnit": { "state": "translated", - "value": "إعادة تشغيل مستمع واجهة الأوامر" + "value": "تخطيط الطرفية" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Start CLI-lytteren på nytt" + "value": "Terminaloppsett" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Reiniciar Listener do CLI" + "value": "Layout do Terminal" } }, "th": { "stringUnit": { "state": "translated", - "value": "รีสตาร์ตตัวรับฟัง CLI" + "value": "เค้าโครงเทอร์มินัล" } }, "tr": { "stringUnit": { "state": "translated", - "value": "CLI Dinleyicisini Yeniden Başlat" + "value": "Terminal Düzeni" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Перезапустити слухач CLI" + "value": "Макет терміналу" } } } }, - "command.showNotifications.subtitle": { + "command.terminalSplitDown.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Notifications" + "value": "Split Down" } }, "ja": { "stringUnit": { "state": "translated", - "value": "通知" + "value": "下に分割" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "通知" + "value": "向下拆分" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "通知" + "value": "向下分割" } }, "ko": { "stringUnit": { "state": "translated", - "value": "알림" + "value": "아래로 분할" } }, "de": { "stringUnit": { "state": "translated", - "value": "Benachrichtigungen" + "value": "Nach unten teilen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Notificaciones" + "value": "Dividir hacia abajo" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Notifications" + "value": "Diviser vers le bas" } }, "it": { "stringUnit": { "state": "translated", - "value": "Notifiche" + "value": "Dividi in basso" } }, "da": { "stringUnit": { "state": "translated", - "value": "Notifikationer" + "value": "Opdel nedad" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Powiadomienia" + "value": "Podziel w dół" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Уведомления" + "value": "Разделить вниз" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Obavještenja" + "value": "Podijeli dolje" } }, "ar": { "stringUnit": { "state": "translated", - "value": "الإشعارات" + "value": "تقسيم للأسفل" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Varsler" + "value": "Del ned" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Notificações" + "value": "Dividir para Baixo" } }, "th": { "stringUnit": { "state": "translated", - "value": "การแจ้งเตือน" + "value": "แยกลงล่าง" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Bildirimler" + "value": "Aşağı Böl" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Сповіщення" + "value": "Розділити вниз" } } } }, - "command.showNotifications.title": { + "command.terminalSplitRight.subtitle": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Show Notifications" + "value": "Terminal Layout" } }, "ja": { "stringUnit": { "state": "translated", - "value": "通知を表示" + "value": "ターミナルレイアウト" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "显示通知" + "value": "终端布局" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "顯示通知" + "value": "終端機版面" } }, "ko": { "stringUnit": { "state": "translated", - "value": "알림 표시" + "value": "터미널 레이아웃" } }, "de": { "stringUnit": { "state": "translated", - "value": "Benachrichtigungen anzeigen" + "value": "Terminal-Layout" } }, "es": { "stringUnit": { "state": "translated", - "value": "Mostrar notificaciones" + "value": "Disposición del terminal" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Afficher les notifications" + "value": "Disposition du terminal" } }, "it": { "stringUnit": { "state": "translated", - "value": "Mostra notifiche" + "value": "Layout terminale" } }, "da": { "stringUnit": { "state": "translated", - "value": "Vis notifikationer" + "value": "Terminallayout" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Pokaż powiadomienia" + "value": "Układ terminala" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Показать уведомления" + "value": "Макет терминала" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Prikaži obavještenja" + "value": "Raspored terminala" } }, "ar": { "stringUnit": { "state": "translated", - "value": "عرض الإشعارات" + "value": "تخطيط الطرفية" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Vis varsler" + "value": "Terminaloppsett" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Mostrar Notificações" + "value": "Layout do Terminal" } }, "th": { "stringUnit": { "state": "translated", - "value": "แสดงการแจ้งเตือน" + "value": "เค้าโครงเทอร์มินัล" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Bildirimleri Göster" + "value": "Terminal Düzeni" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Показати сповіщення" + "value": "Макет терміналу" } } } }, - "command.terminalFind.title": { + "command.terminalSplitRight.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Find…" + "value": "Split Right" } }, "ja": { "stringUnit": { "state": "translated", - "value": "検索…" + "value": "右に分割" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "查找..." + "value": "向右拆分" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "尋找..." + "value": "向右分割" } }, "ko": { "stringUnit": { "state": "translated", - "value": "찾기…" + "value": "오른쪽으로 분할" } }, "de": { "stringUnit": { "state": "translated", - "value": "Suchen …" + "value": "Nach rechts teilen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Buscar…" + "value": "Dividir a la derecha" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Rechercher..." + "value": "Diviser à droite" } }, "it": { "stringUnit": { "state": "translated", - "value": "Trova…" + "value": "Dividi a destra" } }, "da": { "stringUnit": { "state": "translated", - "value": "Søg…" + "value": "Opdel til højre" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Znajdź…" + "value": "Podziel w prawo" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Найти..." + "value": "Разделить вправо" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Pronađi…" + "value": "Podijeli desno" } }, "ar": { "stringUnit": { "state": "translated", - "value": "بحث…" + "value": "تقسيم لليمين" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Finn …" + "value": "Del til høyre" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Buscar…" + "value": "Dividir à Direita" } }, "th": { "stringUnit": { "state": "translated", - "value": "ค้นหา..." + "value": "แยกไปทางขวา" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Bul…" + "value": "Sağa Böl" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Знайти…" + "value": "Розділити праворуч" } } } }, - "command.terminalFindNext.title": { + "command.terminalUseSelectionForFind.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Find Next" + "value": "Use Selection for Find" } }, "ja": { "stringUnit": { "state": "translated", - "value": "次を検索" + "value": "選択範囲を検索に使用" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "查找下一个" + "value": "使用选中内容查找" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "尋找下一個" + "value": "使用所選範圍來尋找" } }, "ko": { "stringUnit": { "state": "translated", - "value": "다음 찾기" + "value": "선택 항목을 찾기에 사용" } }, "de": { "stringUnit": { "state": "translated", - "value": "Weitersuchen" + "value": "Auswahl für Suche verwenden" } }, "es": { "stringUnit": { "state": "translated", - "value": "Buscar siguiente" + "value": "Usar selección para buscar" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Résultat suivant" + "value": "Utiliser la sélection pour la recherche" } }, "it": { "stringUnit": { "state": "translated", - "value": "Trova successivo" + "value": "Usa selezione per la ricerca" } }, "da": { "stringUnit": { "state": "translated", - "value": "Find næste" + "value": "Brug markering til søgning" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Znajdź następny" + "value": "Użyj zaznaczenia do wyszukiwania" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Найти далее" + "value": "Использовать выделение для поиска" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Pronađi sljedeće" + "value": "Koristi odabrano za pretragu" } }, "ar": { "stringUnit": { "state": "translated", - "value": "البحث عن التالي" + "value": "استخدام التحديد للبحث" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Finn neste" + "value": "Bruk utvalg for søk" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Buscar Próximo" + "value": "Usar Seleção para Busca" } }, "th": { "stringUnit": { "state": "translated", - "value": "ค้นหาถัดไป" + "value": "ใช้ข้อความที่เลือกเพื่อค้นหา" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Sonrakini Bul" + "value": "Seçimi Bulmak İçin Kullan" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Знайти наступне" + "value": "Використати виділення для пошуку" } } } }, - "command.terminalFindPrevious.title": { + "command.toggleFullScreen.subtitle": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Find Previous" + "value": "Window" } }, "ja": { "stringUnit": { "state": "translated", - "value": "前を検索" + "value": "ウインドウ" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "查找上一个" + "value": "窗口" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "尋找上一個" + "value": "視窗" } }, "ko": { "stringUnit": { "state": "translated", - "value": "이전 찾기" + "value": "윈도우" } }, "de": { "stringUnit": { "state": "translated", - "value": "Vorheriges suchen" + "value": "Fenster" } }, "es": { "stringUnit": { "state": "translated", - "value": "Buscar anterior" + "value": "Ventana" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Résultat précédent" + "value": "Fenêtre" } }, "it": { "stringUnit": { "state": "translated", - "value": "Trova precedente" + "value": "Finestra" } }, "da": { "stringUnit": { "state": "translated", - "value": "Find forrige" + "value": "Vindue" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Znajdź poprzedni" + "value": "Okno" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Найти ранее" + "value": "Окно" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Pronađi prethodno" + "value": "Prozor" } }, "ar": { "stringUnit": { "state": "translated", - "value": "البحث عن السابق" + "value": "نافذة" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Finn forrige" + "value": "Vindu" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Buscar Anterior" + "value": "Janela" } }, "th": { "stringUnit": { "state": "translated", - "value": "ค้นหาก่อนหน้า" + "value": "หน้าต่าง" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Öncekini Bul" + "value": "Pencere" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Знайти попереднє" + "value": "Вікно" } } } }, - "command.terminalHideFind.title": { + "command.toggleFullScreen.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Hide Find Bar" + "value": "Toggle Full Screen" } }, "ja": { "stringUnit": { "state": "translated", - "value": "検索バーを非表示" + "value": "フルスクリーンの切り替え" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "隐藏查找栏" + "value": "切换全屏" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "隱藏尋找列" + "value": "切換全螢幕" } }, "ko": { "stringUnit": { "state": "translated", - "value": "찾기 막대 숨기기" + "value": "전체 화면 전환" } }, "de": { "stringUnit": { "state": "translated", - "value": "Suchleiste ausblenden" + "value": "Vollbild umschalten" } }, "es": { "stringUnit": { "state": "translated", - "value": "Ocultar barra de búsqueda" + "value": "Alternar pantalla completa" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Masquer la barre de recherche" + "value": "Activer/désactiver le plein écran" } }, "it": { "stringUnit": { "state": "translated", - "value": "Nascondi barra di ricerca" + "value": "Attiva/Disattiva schermo intero" } }, "da": { "stringUnit": { "state": "translated", - "value": "Skjul søgelinje" + "value": "Skift fuldskærm" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Ukryj pasek wyszukiwania" + "value": "Przełącz pełny ekran" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Скрыть панель поиска" + "value": "Полноэкранный режим" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Sakrij traku za pretragu" + "value": "Prebaci puni ekran" } }, "ar": { "stringUnit": { "state": "translated", - "value": "إخفاء شريط البحث" + "value": "تبديل ملء الشاشة" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Skjul søkelinje" + "value": "Slå fullskjerm av/på" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Ocultar Barra de Busca" + "value": "Alternar Tela Cheia" } }, "th": { "stringUnit": { "state": "translated", - "value": "ซ่อนแถบค้นหา" + "value": "สลับเต็มหน้าจอ" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Arama Çubuğunu Gizle" + "value": "Tam Ekranı Aç/Kapat" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Сховати панель пошуку" + "value": "Перемкнути повноекранний режим" } } } }, - "command.terminalSplitBrowserDown.subtitle": { + "command.toggleSidebar.subtitle": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Layout" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "レイアウト" + } + }, + "zh-Hans": { + "stringUnit": { + "state": "translated", + "value": "布局" + } + }, + "zh-Hant": { + "stringUnit": { + "state": "translated", + "value": "版面" + } + }, + "ko": { + "stringUnit": { + "state": "translated", + "value": "레이아웃" + } + }, + "de": { + "stringUnit": { + "state": "translated", + "value": "Layout" + } + }, + "es": { + "stringUnit": { + "state": "translated", + "value": "Disposición" + } + }, + "fr": { + "stringUnit": { + "state": "translated", + "value": "Disposition" + } + }, + "it": { + "stringUnit": { + "state": "translated", + "value": "Layout" + } + }, + "da": { + "stringUnit": { + "state": "translated", + "value": "Layout" + } + }, + "pl": { + "stringUnit": { + "state": "translated", + "value": "Układ" + } + }, + "ru": { + "stringUnit": { + "state": "translated", + "value": "Макет" + } + }, + "bs": { + "stringUnit": { + "state": "translated", + "value": "Raspored" + } + }, + "ar": { + "stringUnit": { + "state": "translated", + "value": "التخطيط" + } + }, + "nb": { + "stringUnit": { + "state": "translated", + "value": "Oppsett" + } + }, + "pt-BR": { + "stringUnit": { + "state": "translated", + "value": "Layout" + } + }, + "th": { + "stringUnit": { + "state": "translated", + "value": "เค้าโครง" + } + }, + "tr": { + "stringUnit": { + "state": "translated", + "value": "Düzen" + } + }, + "uk": { + "stringUnit": { + "state": "translated", + "value": "Макет" + } + } + } + }, + "command.toggleSplitZoom.subtitle": { "extractionState": "manual", "localizations": { "en": { @@ -28036,44413 +28514,42521 @@ } } }, - "command.terminalSplitBrowserDown.title": { + "command.toggleSplitZoom.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Split Browser Down" + "value": "Toggle Pane Zoom" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ブラウザを下に分割" + "value": "ペインズームの切り替え" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "向下拆分浏览器" + "value": "切换面板缩放" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "向下分割瀏覽器" + "value": "切換面板縮放" } }, "ko": { "stringUnit": { "state": "translated", - "value": "브라우저를 아래로 분할" + "value": "패널 확대/축소 전환" } }, "de": { "stringUnit": { "state": "translated", - "value": "Browser nach unten teilen" + "value": "Bereichszoom umschalten" } }, "es": { "stringUnit": { "state": "translated", - "value": "Dividir navegador hacia abajo" + "value": "Alternar zoom del panel" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Diviser le navigateur vers le bas" + "value": "Activer/désactiver le zoom du panneau" } }, "it": { "stringUnit": { "state": "translated", - "value": "Dividi browser in basso" + "value": "Attiva/Disattiva zoom pannello" } }, "da": { "stringUnit": { "state": "translated", - "value": "Opdel browser nedad" + "value": "Slå panelzoom til/fra" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Podziel przeglądarkę w dół" + "value": "Przełącz powiększenie panelu" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Разделить браузер вниз" + "value": "Масштаб панели" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Podijeli preglednik dolje" + "value": "Prebaci uvećanje panela" } }, "ar": { "stringUnit": { "state": "translated", - "value": "تقسيم المتصفح للأسفل" + "value": "تبديل تكبير اللوحة" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Del nettleser ned" + "value": "Slå panelzoom av/på" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Dividir Navegador para Baixo" + "value": "Alternar Zoom do Painel" } }, "th": { "stringUnit": { "state": "translated", - "value": "แยกเบราว์เซอร์ลงล่าง" + "value": "สลับการซูมบานหน้าต่าง" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Tarayıcıyı Aşağı Böl" + "value": "Bölme Yakınlaştırmasını Aç/Kapat" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Розділити браузер вниз" + "value": "Перемкнути масштаб панелі" } } } }, - "command.terminalSplitBrowserRight.subtitle": { + "command.triggerFlash.subtitle": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Terminal Layout" + "value": "View" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ターミナルレイアウト" + "value": "表示" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "终端布局" + "value": "视图" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "終端機版面" + "value": "顯示方式" } }, "ko": { "stringUnit": { "state": "translated", - "value": "터미널 레이아웃" + "value": "보기" } }, "de": { "stringUnit": { "state": "translated", - "value": "Terminal-Layout" + "value": "Ansicht" } }, "es": { "stringUnit": { "state": "translated", - "value": "Disposición del terminal" + "value": "Vista" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Disposition du terminal" + "value": "Présentation" } }, "it": { "stringUnit": { "state": "translated", - "value": "Layout terminale" + "value": "Vista" } }, "da": { "stringUnit": { "state": "translated", - "value": "Terminallayout" + "value": "Visning" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Układ terminala" + "value": "Widok" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Макет терминала" + "value": "Вид" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Raspored terminala" + "value": "Prikaz" } }, "ar": { "stringUnit": { "state": "translated", - "value": "تخطيط الطرفية" + "value": "العرض" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Terminaloppsett" + "value": "Vis" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Layout do Terminal" + "value": "Visualização" } }, "th": { "stringUnit": { "state": "translated", - "value": "เค้าโครงเทอร์มินัล" + "value": "มุมมอง" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Terminal Düzeni" + "value": "Görünüm" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Макет терміналу" + "value": "Перегляд" } } } }, - "command.terminalSplitBrowserRight.title": { + "command.triggerFlash.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Split Browser Right" + "value": "Flash Focused Panel" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ブラウザを右に分割" + "value": "フォーカスペインを強調" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "向右拆分浏览器" + "value": "闪烁聚焦面板" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "向右分割瀏覽器" + "value": "閃爍聚焦面板" } }, "ko": { "stringUnit": { "state": "translated", - "value": "브라우저를 오른쪽으로 분할" + "value": "포커스된 패널 깜빡이기" } }, "de": { "stringUnit": { "state": "translated", - "value": "Browser nach rechts teilen" + "value": "Fokussierten Bereich hervorheben" } }, "es": { "stringUnit": { "state": "translated", - "value": "Dividir navegador a la derecha" + "value": "Resaltar panel enfocado" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Diviser le navigateur à droite" + "value": "Flasher le panneau actif" } }, "it": { "stringUnit": { "state": "translated", - "value": "Dividi browser a destra" + "value": "Evidenzia pannello attivo" } }, "da": { "stringUnit": { "state": "translated", - "value": "Opdel browser til højre" + "value": "Fremhæv fokuseret panel" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Podziel przeglądarkę w prawo" + "value": "Podświetl aktywny panel" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Разделить браузер вправо" + "value": "Подсветить активную панель" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Podijeli preglednik desno" + "value": "Označi fokusirani panel" } }, "ar": { "stringUnit": { "state": "translated", - "value": "تقسيم المتصفح لليمين" + "value": "وميض اللوحة المركّزة" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Del nettleser til høyre" + "value": "Blink fokusert panel" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Dividir Navegador à Direita" + "value": "Piscar Painel em Foco" } }, "th": { "stringUnit": { "state": "translated", - "value": "แยกเบราว์เซอร์ไปทางขวา" + "value": "กะพริบแผงที่โฟกัส" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Tarayıcıyı Sağa Böl" + "value": "Odaklanılan Paneli Yanıp Söndür" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Розділити браузер праворуч" - } - } - } - }, - "command.forkAgentConversationRight.title": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Fork Conversation to the Right" - } - }, - "ja": { - "stringUnit": { - "state": "translated", - "value": "会話を右にフォーク" - } - } - } - }, - "command.forkAgentConversationLeft.title": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Fork Conversation to the Left" - } - }, - "ja": { - "stringUnit": { - "state": "translated", - "value": "会話を左にフォーク" - } - } - } - }, - "command.forkAgentConversationTop.title": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Fork Conversation to the Top" - } - }, - "ja": { - "stringUnit": { - "state": "translated", - "value": "会話を上にフォーク" - } - } - } - }, - "command.forkAgentConversationBottom.title": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Fork Conversation to the Bottom" - } - }, - "ja": { - "stringUnit": { - "state": "translated", - "value": "会話を下にフォーク" - } - } - } - }, - "command.forkAgentConversationNewWorkspace.title": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Fork Conversation to New Workspace" - } - }, - "ja": { - "stringUnit": { - "state": "translated", - "value": "会話を新規ワークスペースにフォーク" + "value": "Підсвітити активну панель" } } } }, - "command.terminalSplitDown.subtitle": { + "command.uninstallCLI.subtitle": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Terminal Layout" + "value": "CLI" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ターミナルレイアウト" + "value": "CLI" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "终端布局" + "value": "CLI" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "終端機版面" + "value": "CLI" } }, "ko": { "stringUnit": { "state": "translated", - "value": "터미널 레이아웃" + "value": "CLI" } }, "de": { "stringUnit": { "state": "translated", - "value": "Terminal-Layout" + "value": "CLI" } }, "es": { "stringUnit": { "state": "translated", - "value": "Disposición del terminal" + "value": "CLI" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Disposition du terminal" + "value": "CLI" } }, "it": { "stringUnit": { "state": "translated", - "value": "Layout terminale" + "value": "CLI" } }, "da": { "stringUnit": { "state": "translated", - "value": "Terminallayout" + "value": "CLI" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Układ terminala" + "value": "CLI" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Макет терминала" + "value": "CLI" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Raspored terminala" + "value": "CLI" } }, "ar": { "stringUnit": { "state": "translated", - "value": "تخطيط الطرفية" + "value": "واجهة الأوامر" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Terminaloppsett" + "value": "CLI" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Layout do Terminal" + "value": "CLI" } }, "th": { "stringUnit": { "state": "translated", - "value": "เค้าโครงเทอร์มินัล" + "value": "CLI" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Terminal Düzeni" + "value": "CLI" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Макет терміналу" + "value": "CLI" } } } }, - "command.terminalSplitDown.title": { + "command.uninstallCLI.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Split Down" + "value": "Shell Command: Uninstall 'cmux' from PATH" } }, "ja": { "stringUnit": { "state": "translated", - "value": "下に分割" + "value": "シェルコマンド: 'cmux'をPATHからアンインストール" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "向下拆分" + "value": "Shell 命令:从 PATH 卸载 'cmux'" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "向下分割" + "value": "Shell 指令:從 PATH 解除安裝「cmux」" } }, "ko": { "stringUnit": { "state": "translated", - "value": "아래로 분할" + "value": "셸 명령어: PATH에서 'cmux' 제거" } }, "de": { "stringUnit": { "state": "translated", - "value": "Nach unten teilen" + "value": "Shell-Befehl: 'cmux' aus PATH entfernen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Dividir hacia abajo" + "value": "Comando de shell: Desinstalar 'cmux' de PATH" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Diviser vers le bas" + "value": "Commande Shell : désinstaller « cmux » du PATH" } }, "it": { "stringUnit": { "state": "translated", - "value": "Dividi in basso" + "value": "Comando shell: disinstalla 'cmux' dal PATH" } }, "da": { "stringUnit": { "state": "translated", - "value": "Opdel nedad" + "value": "Skalkommando: Afinstaller 'cmux' fra PATH" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Podziel w dół" + "value": "Polecenie powłoki: Odinstaluj „cmux” z PATH" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Разделить вниз" + "value": "Команда оболочки: удалить «cmux» из PATH" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Podijeli dolje" + "value": "Shell naredba: Deinstaliraj 'cmux' iz PATH" } }, "ar": { "stringUnit": { "state": "translated", - "value": "تقسيم للأسفل" + "value": "أمر الصدفة: إلغاء تثبيت 'cmux' من PATH" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Del ned" + "value": "Skallkommando: Avinstaller «cmux» fra PATH" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Dividir para Baixo" + "value": "Comando Shell: Desinstalar 'cmux' do PATH" } }, "th": { "stringUnit": { "state": "translated", - "value": "แยกลงล่าง" + "value": "คำสั่ง Shell: ถอนการติดตั้ง 'cmux' จาก PATH" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Aşağı Böl" + "value": "Kabuk Komutu: 'cmux'u PATH'ten Kaldır" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Розділити вниз" + "value": "Команда оболонки: видалити 'cmux' з PATH" } } } }, - "command.terminalSplitRight.subtitle": { + "command.unpinTab.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Terminal Layout" + "value": "Unpin Tab" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ターミナルレイアウト" + "value": "タブのピンを外す" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "终端布局" + "value": "取消固定标签页" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "終端機版面" + "value": "取消釘選標籤頁" } }, "ko": { "stringUnit": { "state": "translated", - "value": "터미널 레이아웃" + "value": "탭 고정 해제" } }, "de": { "stringUnit": { "state": "translated", - "value": "Terminal-Layout" + "value": "Tab loslösen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Disposición del terminal" + "value": "Desfijar pestaña" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Disposition du terminal" + "value": "Désépingler l'onglet" } }, "it": { "stringUnit": { "state": "translated", - "value": "Layout terminale" + "value": "Sblocca scheda" } }, "da": { "stringUnit": { "state": "translated", - "value": "Terminallayout" + "value": "Frigør fane" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Układ terminala" + "value": "Odepnij kartę" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Макет терминала" + "value": "Открепить вкладку" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Raspored terminala" + "value": "Otkači tab" } }, "ar": { "stringUnit": { "state": "translated", - "value": "تخطيط الطرفية" + "value": "إلغاء تثبيت اللسان" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Terminaloppsett" + "value": "Løsne fane" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Layout do Terminal" + "value": "Desafixar Aba" } }, "th": { "stringUnit": { "state": "translated", - "value": "เค้าโครงเทอร์มินัล" + "value": "เลิกปักหมุดแท็บ" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Terminal Düzeni" + "value": "Sekme Sabitlemesini Kaldır" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Макет терміналу" + "value": "Відкріпити вкладку" } } } }, - "command.terminalSplitRight.title": { + "command.unpinWorkspace.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Split Right" + "value": "Unpin Workspace" } }, "ja": { "stringUnit": { "state": "translated", - "value": "右に分割" + "value": "ワークスペースのピンを外す" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "向右拆分" + "value": "取消固定工作区" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "向右分割" + "value": "取消釘選工作區" } }, "ko": { "stringUnit": { "state": "translated", - "value": "오른쪽으로 분할" + "value": "작업 공간 고정 해제" } }, "de": { "stringUnit": { "state": "translated", - "value": "Nach rechts teilen" + "value": "Arbeitsbereich loslösen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Dividir a la derecha" + "value": "Desfijar espacio de trabajo" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Diviser à droite" + "value": "Désépingler l'espace de travail" } }, "it": { "stringUnit": { "state": "translated", - "value": "Dividi a destra" + "value": "Sblocca area di lavoro" } }, "da": { "stringUnit": { "state": "translated", - "value": "Opdel til højre" + "value": "Frigør arbejdsområde" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Podziel w prawo" + "value": "Odepnij przestrzeń roboczą" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Разделить вправо" + "value": "Открепить рабочее пространство" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Podijeli desno" + "value": "Otkači radni prostor" } }, "ar": { "stringUnit": { "state": "translated", - "value": "تقسيم لليمين" + "value": "إلغاء تثبيت مساحة العمل" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Del til høyre" + "value": "Løsne arbeidsområde" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Dividir à Direita" + "value": "Desafixar Área de Trabalho" } }, "th": { "stringUnit": { "state": "translated", - "value": "แยกไปทางขวา" + "value": "เลิกปักหมุดเวิร์กสเปซ" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Sağa Böl" + "value": "Çalışma Alanı Sabitlemesini Kaldır" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Розділити праворуч" + "value": "Відкріпити робочу область" } } } }, - "command.terminalUseSelectionForFind.title": { + "command.vscodeServeWebRestart.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Use Selection for Find" + "value": "Restart VS Code Inline Server" } }, "ja": { "stringUnit": { "state": "translated", - "value": "選択範囲を検索に使用" + "value": "VS Codeインラインサーバーを再起動" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "使用选中内容查找" + "value": "重启 VS Code 内联服务器" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "使用所選範圍來尋找" + "value": "重新啟動 VS Code 內嵌伺服器" } }, "ko": { "stringUnit": { "state": "translated", - "value": "선택 항목을 찾기에 사용" + "value": "VS Code 인라인 서버 재시작" } }, "de": { "stringUnit": { "state": "translated", - "value": "Auswahl für Suche verwenden" + "value": "VS Code Inline-Server neu starten" } }, "es": { "stringUnit": { "state": "translated", - "value": "Usar selección para buscar" + "value": "Reiniciar servidor en línea de VS Code" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Utiliser la sélection pour la recherche" + "value": "Redémarrer le serveur VS Code intégré" } }, "it": { "stringUnit": { "state": "translated", - "value": "Usa selezione per la ricerca" + "value": "Riavvia server inline VS Code" } }, "da": { "stringUnit": { "state": "translated", - "value": "Brug markering til søgning" + "value": "Genstart VS Code Inline Server" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Użyj zaznaczenia do wyszukiwania" + "value": "Uruchom ponownie wbudowany serwer VS Code" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Использовать выделение для поиска" + "value": "Перезапустить встроенный сервер VS Code" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Koristi odabrano za pretragu" + "value": "Ponovo pokreni VS Code inline server" } }, "ar": { "stringUnit": { "state": "translated", - "value": "استخدام التحديد للبحث" + "value": "إعادة تشغيل خادم VS Code المضمّن" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Bruk utvalg for søk" + "value": "Start VS Code innebygd server på nytt" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Usar Seleção para Busca" + "value": "Reiniciar Servidor Inline do VS Code" } }, "th": { "stringUnit": { "state": "translated", - "value": "ใช้ข้อความที่เลือกเพื่อค้นหา" + "value": "รีสตาร์ตเซิร์ฟเวอร์ VS Code แบบอินไลน์" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Seçimi Bulmak İçin Kullan" + "value": "VS Code Satır İçi Sunucusunu Yeniden Başlat" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Використати виділення для пошуку" + "value": "Перезапустити вбудований сервер VS Code" } } } }, - "command.toggleFullScreen.subtitle": { + "command.vscodeServeWebStop.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Window" + "value": "Stop VS Code Inline Server" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ウインドウ" + "value": "VS Codeインラインサーバーを停止" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "窗口" + "value": "停止 VS Code 内联服务器" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "視窗" + "value": "停止 VS Code 內嵌伺服器" } }, "ko": { "stringUnit": { "state": "translated", - "value": "윈도우" + "value": "VS Code 인라인 서버 중지" } }, "de": { "stringUnit": { "state": "translated", - "value": "Fenster" + "value": "VS Code Inline-Server stoppen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Ventana" + "value": "Detener servidor en línea de VS Code" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Fenêtre" + "value": "Arrêter le serveur VS Code intégré" } }, "it": { "stringUnit": { "state": "translated", - "value": "Finestra" + "value": "Arresta server inline VS Code" } }, "da": { "stringUnit": { "state": "translated", - "value": "Vindue" + "value": "Stop VS Code Inline Server" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Okno" + "value": "Zatrzymaj wbudowany serwer VS Code" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Окно" + "value": "Остановить встроенный сервер VS Code" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Prozor" + "value": "Zaustavi VS Code inline server" } }, "ar": { "stringUnit": { "state": "translated", - "value": "نافذة" + "value": "إيقاف خادم VS Code المضمّن" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Vindu" + "value": "Stopp VS Code innebygd server" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Janela" + "value": "Parar Servidor Inline do VS Code" } }, "th": { "stringUnit": { "state": "translated", - "value": "หน้าต่าง" + "value": "หยุดเซิร์ฟเวอร์ VS Code แบบอินไลน์" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Pencere" + "value": "VS Code Satır İçi Sunucusunu Durdur" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Вікно" + "value": "Зупинити вбудований сервер VS Code" } } } }, - "command.toggleFullScreen.title": { + "commandPalette.kind.browser": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Toggle Full Screen" + "value": "Browser" } }, "ja": { "stringUnit": { "state": "translated", - "value": "フルスクリーンの切り替え" + "value": "ブラウザ" } }, - "zh-Hans": { + "uk": { "stringUnit": { "state": "translated", - "value": "切换全屏" + "value": "Браузер" } }, - "zh-Hant": { + "ko": { "stringUnit": { "state": "translated", - "value": "切換全螢幕" + "value": "브라우저" } - }, - "ko": { + } + } + }, + "commandPalette.kind.markdown": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "전체 화면 전환" + "value": "Markdown" } }, - "de": { + "ja": { "stringUnit": { "state": "translated", - "value": "Vollbild umschalten" + "value": "Markdown" } }, - "es": { + "uk": { "stringUnit": { "state": "translated", - "value": "Alternar pantalla completa" + "value": "Markdown" } }, - "fr": { + "ko": { "stringUnit": { "state": "translated", - "value": "Activer/désactiver le plein écran" + "value": "마크다운" } - }, - "it": { + } + } + }, + "commandPalette.kind.rightSidebarTool": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Attiva/Disattiva schermo intero" + "value": "Tool" } }, - "da": { + "ja": { "stringUnit": { "state": "translated", - "value": "Skift fuldskærm" + "value": "ツール" } - }, - "pl": { + } + } + }, + "commandPalette.kind.terminal": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Przełącz pełny ekran" + "value": "Terminal" } }, - "ru": { + "ja": { "stringUnit": { "state": "translated", - "value": "Полноэкранный режим" + "value": "ターミナル" } }, - "bs": { - "stringUnit": { - "state": "translated", - "value": "Prebaci puni ekran" - } - }, - "ar": { - "stringUnit": { - "state": "translated", - "value": "تبديل ملء الشاشة" - } - }, - "nb": { - "stringUnit": { - "state": "translated", - "value": "Slå fullskjerm av/på" - } - }, - "pt-BR": { - "stringUnit": { - "state": "translated", - "value": "Alternar Tela Cheia" - } - }, - "th": { - "stringUnit": { - "state": "translated", - "value": "สลับเต็มหน้าจอ" - } - }, - "tr": { + "uk": { "stringUnit": { "state": "translated", - "value": "Tam Ekranı Aç/Kapat" + "value": "Термінал" } }, - "uk": { + "ko": { "stringUnit": { "state": "translated", - "value": "Перемкнути повноекранний режим" + "value": "터미널" } } } }, - "command.toggleSidebar.subtitle": { + "commandPalette.kind.workspace": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Layout" + "value": "Workspace" } }, "ja": { "stringUnit": { "state": "translated", - "value": "レイアウト" + "value": "ワークスペース" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "布局" + "value": "工作区" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "版面" + "value": "工作區" } }, "ko": { "stringUnit": { "state": "translated", - "value": "레이아웃" + "value": "작업 공간" } }, "de": { "stringUnit": { "state": "translated", - "value": "Layout" + "value": "Arbeitsbereich" } }, "es": { "stringUnit": { "state": "translated", - "value": "Disposición" + "value": "Espacio de trabajo" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Disposition" + "value": "Espace de travail" } }, "it": { "stringUnit": { "state": "translated", - "value": "Layout" + "value": "Area di lavoro" } }, "da": { "stringUnit": { "state": "translated", - "value": "Layout" + "value": "Arbejdsområde" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Układ" + "value": "Przestrzeń robocza" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Макет" + "value": "Рабочее пространство" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Raspored" + "value": "Radni prostor" } }, "ar": { "stringUnit": { "state": "translated", - "value": "التخطيط" + "value": "مساحة العمل" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Oppsett" + "value": "Arbeidsområde" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Layout" + "value": "Área de Trabalho" } }, "th": { "stringUnit": { "state": "translated", - "value": "เค้าโครง" + "value": "เวิร์กสเปซ" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Düzen" + "value": "Çalışma Alanı" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Макет" + "value": "Робоча область" } } } }, - "command.toggleSplitZoom.subtitle": { + "commandPalette.rename.clearCustomName": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Terminal Layout" + "value": "(clear custom name)" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ターミナルレイアウト" + "value": "(カスタム名をクリア)" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "终端布局" + "value": "(清除自定义名称)" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "終端機版面" + "value": "(清除自訂名稱)" } }, "ko": { "stringUnit": { "state": "translated", - "value": "터미널 레이아웃" + "value": "(사용자 지정 이름 지우기)" } }, "de": { "stringUnit": { "state": "translated", - "value": "Terminal-Layout" + "value": "(Benutzerdefinierten Namen löschen)" } }, "es": { "stringUnit": { "state": "translated", - "value": "Disposición del terminal" + "value": "(borrar nombre personalizado)" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Disposition du terminal" + "value": "(effacer le nom personnalisé)" } }, "it": { "stringUnit": { "state": "translated", - "value": "Layout terminale" + "value": "(cancella nome personalizzato)" } }, "da": { "stringUnit": { "state": "translated", - "value": "Terminallayout" + "value": "(ryd brugerdefineret navn)" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Układ terminala" + "value": "(wyczyść własną nazwę)" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Макет терминала" + "value": "(очистить пользовательское имя)" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Raspored terminala" + "value": "(obriši prilagođeni naziv)" } }, "ar": { "stringUnit": { "state": "translated", - "value": "تخطيط الطرفية" + "value": "(مسح الاسم المخصص)" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Terminaloppsett" + "value": "(fjern egendefinert navn)" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Layout do Terminal" + "value": "(limpar nome personalizado)" } }, "th": { "stringUnit": { "state": "translated", - "value": "เค้าโครงเทอร์มินัล" + "value": "(ล้างชื่อที่กำหนดเอง)" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Terminal Düzeni" + "value": "(özel adı temizle)" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Макет терміналу" + "value": "(скинути власну назву)" } } } }, - "command.toggleSplitZoom.title": { + "commandPalette.rename.tabConfirmHint": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Toggle Pane Zoom" + "value": "Press Enter to apply this tab name, or Escape to cancel." } }, "ja": { "stringUnit": { "state": "translated", - "value": "ペインズームの切り替え" + "value": "Enterキーでタブ名を適用、Escapeキーでキャンセルします。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "切换面板缩放" + "value": "按 Enter 应用此标签页名称,或按 Escape 取消。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "切換面板縮放" + "value": "按 Enter 套用此標籤頁名稱,或按 Escape 取消。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "패널 확대/축소 전환" + "value": "Enter를 눌러 탭 이름을 적용하거나, Escape를 눌러 취소하세요." } }, "de": { "stringUnit": { "state": "translated", - "value": "Bereichszoom umschalten" + "value": "Drücken Sie die Eingabetaste, um den Tab-Namen zu übernehmen, oder Escape zum Abbrechen." } }, "es": { "stringUnit": { "state": "translated", - "value": "Alternar zoom del panel" + "value": "Pulsa Intro para aplicar este nombre de pestaña, o Escape para cancelar." } }, "fr": { "stringUnit": { "state": "translated", - "value": "Activer/désactiver le zoom du panneau" + "value": "Appuyez sur Entrée pour appliquer ce nom d'onglet, ou sur Échap pour annuler." } }, "it": { "stringUnit": { "state": "translated", - "value": "Attiva/Disattiva zoom pannello" + "value": "Premi Invio per applicare il nome della scheda, oppure Esc per annullare." } }, "da": { "stringUnit": { "state": "translated", - "value": "Slå panelzoom til/fra" + "value": "Tryk Enter for at anvende dette fanenavn, eller Escape for at annullere." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Przełącz powiększenie panelu" + "value": "Naciśnij Enter, aby zastosować nazwę karty, lub Escape, aby anulować." } }, "ru": { "stringUnit": { "state": "translated", - "value": "Масштаб панели" + "value": "Нажмите Enter, чтобы применить имя вкладки, или Escape для отмены." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Prebaci uvećanje panela" + "value": "Pritisnite Enter za primjenu naziva taba, ili Escape za otkazivanje." } }, "ar": { "stringUnit": { "state": "translated", - "value": "تبديل تكبير اللوحة" + "value": "اضغط Enter لتطبيق اسم اللسان، أو Escape للإلغاء." } }, "nb": { "stringUnit": { "state": "translated", - "value": "Slå panelzoom av/på" + "value": "Trykk Enter for å bruke dette fanenavnet, eller Escape for å avbryte." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Alternar Zoom do Painel" + "value": "Pressione Enter para aplicar este nome de aba ou Escape para cancelar." } }, "th": { "stringUnit": { "state": "translated", - "value": "สลับการซูมบานหน้าต่าง" + "value": "กด Enter เพื่อใช้ชื่อแท็บนี้ หรือ Escape เพื่อยกเลิก" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Bölme Yakınlaştırmasını Aç/Kapat" + "value": "Bu sekme adını uygulamak için Enter tuşuna basın veya iptal etmek için Escape tuşuna basın." } }, "uk": { "stringUnit": { "state": "translated", - "value": "Перемкнути масштаб панелі" + "value": "Натисніть Enter, щоб застосувати назву вкладки, або Escape для скасування." } } } }, - "command.triggerFlash.subtitle": { + "commandPalette.rename.tabDescription": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "View" + "value": "Choose a custom tab name." } }, "ja": { "stringUnit": { "state": "translated", - "value": "表示" + "value": "タブのカスタム名を選択してください。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "视图" + "value": "选择自定义标签页名称。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "顯示方式" + "value": "選擇自訂標籤頁名稱。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "보기" + "value": "사용자 지정 탭 이름을 선택하세요." } }, "de": { "stringUnit": { "state": "translated", - "value": "Ansicht" + "value": "Wählen Sie einen benutzerdefinierten Tab-Namen." } }, "es": { "stringUnit": { "state": "translated", - "value": "Vista" + "value": "Elige un nombre personalizado para la pestaña." } }, "fr": { "stringUnit": { "state": "translated", - "value": "Présentation" + "value": "Choisissez un nom personnalisé pour l'onglet." } }, "it": { "stringUnit": { "state": "translated", - "value": "Vista" + "value": "Scegli un nome personalizzato per la scheda." } }, "da": { "stringUnit": { "state": "translated", - "value": "Visning" + "value": "Vælg et brugerdefineret fanenavn." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Widok" + "value": "Wybierz własną nazwę karty." } }, "ru": { "stringUnit": { "state": "translated", - "value": "Вид" + "value": "Выберите пользовательское имя вкладки." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Prikaz" + "value": "Odaberite prilagođeni naziv taba." } }, "ar": { "stringUnit": { "state": "translated", - "value": "العرض" + "value": "اختر اسمًا مخصصًا للسان." } }, "nb": { "stringUnit": { "state": "translated", - "value": "Vis" + "value": "Velg et egendefinert fanenavn." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Visualização" + "value": "Escolha um nome personalizado para a aba." } }, "th": { "stringUnit": { "state": "translated", - "value": "มุมมอง" + "value": "เลือกชื่อแท็บที่กำหนดเอง" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Görünüm" + "value": "Özel bir sekme adı seçin." } }, "uk": { "stringUnit": { "state": "translated", - "value": "Перегляд" + "value": "Виберіть власну назву вкладки." } } } }, - "command.triggerFlash.title": { + "commandPalette.rename.tabInputHint": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Flash Focused Panel" + "value": "Enter a tab name. Press Enter to rename, Escape to cancel." } }, "ja": { "stringUnit": { "state": "translated", - "value": "フォーカスペインを強調" + "value": "タブ名を入力してください。Enterで名称変更、Escapeでキャンセルします。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "闪烁聚焦面板" + "value": "输入标签页名称。按 Enter 重命名,按 Escape 取消。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "閃爍聚焦面板" + "value": "輸入標籤頁名稱。按 Enter 重新命名,按 Escape 取消。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "포커스된 패널 깜빡이기" + "value": "탭 이름을 입력하세요. Enter로 이름 변경, Escape로 취소." } }, "de": { "stringUnit": { "state": "translated", - "value": "Fokussierten Bereich hervorheben" + "value": "Geben Sie einen Tab-Namen ein. Eingabetaste zum Umbenennen, Escape zum Abbrechen." } }, "es": { "stringUnit": { "state": "translated", - "value": "Resaltar panel enfocado" + "value": "Introduce un nombre de pestaña. Pulsa Intro para renombrar, Escape para cancelar." } }, "fr": { "stringUnit": { "state": "translated", - "value": "Flasher le panneau actif" + "value": "Saisissez un nom d'onglet. Appuyez sur Entrée pour renommer, Échap pour annuler." } }, "it": { "stringUnit": { "state": "translated", - "value": "Evidenzia pannello attivo" + "value": "Inserisci un nome per la scheda. Premi Invio per rinominare, Esc per annullare." } }, "da": { "stringUnit": { "state": "translated", - "value": "Fremhæv fokuseret panel" + "value": "Indtast et fanenavn. Tryk Enter for at omdøbe, Escape for at annullere." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Podświetl aktywny panel" + "value": "Wprowadź nazwę karty. Naciśnij Enter, aby zmienić nazwę, Escape, aby anulować." } }, "ru": { "stringUnit": { "state": "translated", - "value": "Подсветить активную панель" + "value": "Введите имя вкладки. Нажмите Enter для переименования, Escape для отмены." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Označi fokusirani panel" + "value": "Unesite naziv taba. Pritisnite Enter za preimenovanje, Escape za otkazivanje." } }, "ar": { "stringUnit": { "state": "translated", - "value": "وميض اللوحة المركّزة" + "value": "أدخل اسم اللسان. اضغط Enter لإعادة التسمية، Escape للإلغاء." } }, "nb": { "stringUnit": { "state": "translated", - "value": "Blink fokusert panel" + "value": "Skriv inn et fanenavn. Trykk Enter for å gi nytt navn, Escape for å avbryte." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Piscar Painel em Foco" + "value": "Insira um nome para a aba. Pressione Enter para renomear, Escape para cancelar." } }, "th": { "stringUnit": { "state": "translated", - "value": "กะพริบแผงที่โฟกัส" + "value": "ป้อนชื่อแท็บ กด Enter เพื่อเปลี่ยนชื่อ, Escape เพื่อยกเลิก" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Odaklanılan Paneli Yanıp Söndür" + "value": "Bir sekme adı girin. Yeniden adlandırmak için Enter, iptal etmek için Escape tuşuna basın." } }, "uk": { "stringUnit": { "state": "translated", - "value": "Підсвітити активну панель" + "value": "Введіть назву вкладки. Enter — перейменувати, Escape — скасувати." } } } }, - "command.uninstallCLI.subtitle": { + "commandPalette.rename.tabPlaceholder": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "CLI" + "value": "Tab name" } }, "ja": { "stringUnit": { "state": "translated", - "value": "CLI" + "value": "タブ名" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "CLI" + "value": "标签页名称" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "CLI" + "value": "標籤頁名稱" } }, "ko": { "stringUnit": { "state": "translated", - "value": "CLI" + "value": "탭 이름" } }, "de": { "stringUnit": { "state": "translated", - "value": "CLI" + "value": "Tab-Name" } }, "es": { "stringUnit": { "state": "translated", - "value": "CLI" + "value": "Nombre de pestaña" } }, "fr": { "stringUnit": { "state": "translated", - "value": "CLI" + "value": "Nom de l'onglet" } }, "it": { "stringUnit": { "state": "translated", - "value": "CLI" + "value": "Nome scheda" } }, "da": { "stringUnit": { "state": "translated", - "value": "CLI" + "value": "Fanenavn" } }, "pl": { "stringUnit": { "state": "translated", - "value": "CLI" + "value": "Nazwa karty" } }, "ru": { "stringUnit": { "state": "translated", - "value": "CLI" + "value": "Имя вкладки" } }, "bs": { "stringUnit": { "state": "translated", - "value": "CLI" + "value": "Naziv taba" } }, "ar": { "stringUnit": { "state": "translated", - "value": "واجهة الأوامر" + "value": "اسم اللسان" } }, "nb": { "stringUnit": { "state": "translated", - "value": "CLI" + "value": "Fanenavn" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "CLI" + "value": "Nome da aba" } }, "th": { "stringUnit": { "state": "translated", - "value": "CLI" + "value": "ชื่อแท็บ" } }, "tr": { "stringUnit": { "state": "translated", - "value": "CLI" + "value": "Sekme adı" } }, "uk": { "stringUnit": { "state": "translated", - "value": "CLI" + "value": "Назва вкладки" } } } }, - "command.uninstallCLI.title": { + "commandPalette.rename.tabTitle": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Shell Command: Uninstall 'cmux' from PATH" + "value": "Rename Tab" } }, "ja": { "stringUnit": { "state": "translated", - "value": "シェルコマンド: 'cmux'をPATHからアンインストール" + "value": "タブの名称変更" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "Shell 命令:从 PATH 卸载 'cmux'" + "value": "重命名标签页" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "Shell 指令:從 PATH 解除安裝「cmux」" + "value": "重新命名標籤頁" } }, "ko": { "stringUnit": { "state": "translated", - "value": "셸 명령어: PATH에서 'cmux' 제거" + "value": "탭 이름 변경" } }, "de": { "stringUnit": { "state": "translated", - "value": "Shell-Befehl: 'cmux' aus PATH entfernen" + "value": "Tab umbenennen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Comando de shell: Desinstalar 'cmux' de PATH" + "value": "Renombrar pestaña" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Commande Shell : désinstaller « cmux » du PATH" + "value": "Renommer l'onglet" } }, "it": { "stringUnit": { "state": "translated", - "value": "Comando shell: disinstalla 'cmux' dal PATH" + "value": "Rinomina scheda" } }, "da": { "stringUnit": { "state": "translated", - "value": "Skalkommando: Afinstaller 'cmux' fra PATH" + "value": "Omdøb fane" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Polecenie powłoki: Odinstaluj „cmux” z PATH" + "value": "Zmień nazwę karty" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Команда оболочки: удалить «cmux» из PATH" + "value": "Переименовать вкладку" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Shell naredba: Deinstaliraj 'cmux' iz PATH" + "value": "Preimenuj tab" } }, "ar": { "stringUnit": { "state": "translated", - "value": "أمر الصدفة: إلغاء تثبيت 'cmux' من PATH" + "value": "إعادة تسمية اللسان" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Skallkommando: Avinstaller «cmux» fra PATH" + "value": "Gi fanen nytt navn" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Comando Shell: Desinstalar 'cmux' do PATH" + "value": "Renomear Aba" } }, "th": { "stringUnit": { "state": "translated", - "value": "คำสั่ง Shell: ถอนการติดตั้ง 'cmux' จาก PATH" + "value": "เปลี่ยนชื่อแท็บ" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Kabuk Komutu: 'cmux'u PATH'ten Kaldır" + "value": "Sekmeyi Yeniden Adlandır" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Команда оболонки: видалити 'cmux' з PATH" + "value": "Перейменувати вкладку" } } } }, - "command.unpinTab.title": { + "commandPalette.rename.workspaceConfirmHint": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Unpin Tab" + "value": "Press Enter to apply this workspace name, or Escape to cancel." } }, "ja": { "stringUnit": { "state": "translated", - "value": "タブのピンを外す" + "value": "Enterキーでワークスペース名を適用、Escapeキーでキャンセルします。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "取消固定标签页" + "value": "按 Enter 应用此工作区名称,或按 Escape 取消。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "取消釘選標籤頁" + "value": "按 Enter 套用此工作區名稱,或按 Escape 取消。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "탭 고정 해제" + "value": "Enter를 눌러 작업 공간 이름을 적용하거나, Escape를 눌러 취소하세요." } }, "de": { "stringUnit": { "state": "translated", - "value": "Tab loslösen" + "value": "Drücken Sie die Eingabetaste, um den Arbeitsbereichsnamen zu übernehmen, oder Escape zum Abbrechen." } }, "es": { "stringUnit": { "state": "translated", - "value": "Desfijar pestaña" + "value": "Pulsa Intro para aplicar este nombre de espacio de trabajo, o Escape para cancelar." } }, "fr": { "stringUnit": { "state": "translated", - "value": "Désépingler l'onglet" + "value": "Appuyez sur Entrée pour appliquer ce nom d'espace de travail, ou sur Échap pour annuler." } }, "it": { "stringUnit": { "state": "translated", - "value": "Sblocca scheda" + "value": "Premi Invio per applicare il nome dell'area di lavoro, oppure Esc per annullare." } }, "da": { "stringUnit": { "state": "translated", - "value": "Frigør fane" + "value": "Tryk Enter for at anvende dette arbejdsområdenavn, eller Escape for at annullere." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Odepnij kartę" + "value": "Naciśnij Enter, aby zastosować nazwę przestrzeni roboczej, lub Escape, aby anulować." } }, "ru": { "stringUnit": { "state": "translated", - "value": "Открепить вкладку" + "value": "Нажмите Enter, чтобы применить имя рабочего пространства, или Escape для отмены." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Otkači tab" + "value": "Pritisnite Enter za primjenu naziva radnog prostora, ili Escape za otkazivanje." } }, "ar": { "stringUnit": { "state": "translated", - "value": "إلغاء تثبيت اللسان" + "value": "اضغط Enter لتطبيق اسم مساحة العمل، أو Escape للإلغاء." } }, "nb": { "stringUnit": { "state": "translated", - "value": "Løsne fane" + "value": "Trykk Enter for å bruke dette arbeidsområdenavnet, eller Escape for å avbryte." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Desafixar Aba" + "value": "Pressione Enter para aplicar este nome de área de trabalho ou Escape para cancelar." } }, "th": { "stringUnit": { "state": "translated", - "value": "เลิกปักหมุดแท็บ" + "value": "กด Enter เพื่อใช้ชื่อเวิร์กสเปซนี้ หรือ Escape เพื่อยกเลิก" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Sekme Sabitlemesini Kaldır" + "value": "Bu çalışma alanı adını uygulamak için Enter tuşuna basın veya iptal etmek için Escape tuşuna basın." } }, "uk": { "stringUnit": { "state": "translated", - "value": "Відкріпити вкладку" + "value": "Натисніть Enter, щоб застосувати назву робочої області, або Escape для скасування." } } } }, - "command.unpinWorkspace.title": { + "commandPalette.rename.workspaceDescription": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Unpin Workspace" + "value": "Choose a custom workspace name." } }, "ja": { "stringUnit": { "state": "translated", - "value": "ワークスペースのピンを外す" + "value": "ワークスペースのカスタム名を選択してください。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "取消固定工作区" + "value": "选择自定义工作区名称。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "取消釘選工作區" + "value": "選擇自訂工作區名稱。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "작업 공간 고정 해제" + "value": "사용자 지정 작업 공간 이름을 선택하세요." } }, "de": { "stringUnit": { "state": "translated", - "value": "Arbeitsbereich loslösen" + "value": "Wählen Sie einen benutzerdefinierten Arbeitsbereichsnamen." } }, "es": { "stringUnit": { "state": "translated", - "value": "Desfijar espacio de trabajo" + "value": "Elige un nombre personalizado para el espacio de trabajo." } }, "fr": { "stringUnit": { "state": "translated", - "value": "Désépingler l'espace de travail" + "value": "Choisissez un nom personnalisé pour l'espace de travail." } }, "it": { "stringUnit": { "state": "translated", - "value": "Sblocca area di lavoro" + "value": "Scegli un nome personalizzato per l'area di lavoro." } }, "da": { "stringUnit": { "state": "translated", - "value": "Frigør arbejdsområde" + "value": "Vælg et brugerdefineret arbejdsområdenavn." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Odepnij przestrzeń roboczą" + "value": "Wybierz własną nazwę przestrzeni roboczej." } }, "ru": { "stringUnit": { "state": "translated", - "value": "Открепить рабочее пространство" + "value": "Выберите пользовательское имя рабочего пространства." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Otkači radni prostor" + "value": "Odaberite prilagođeni naziv radnog prostora." } }, "ar": { "stringUnit": { "state": "translated", - "value": "إلغاء تثبيت مساحة العمل" + "value": "اختر اسمًا مخصصًا لمساحة العمل." } }, "nb": { "stringUnit": { "state": "translated", - "value": "Løsne arbeidsområde" + "value": "Velg et egendefinert arbeidsområdenavn." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Desafixar Área de Trabalho" + "value": "Escolha um nome personalizado para a área de trabalho." } }, "th": { "stringUnit": { "state": "translated", - "value": "เลิกปักหมุดเวิร์กสเปซ" + "value": "เลือกชื่อเวิร์กสเปซที่กำหนดเอง" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Çalışma Alanı Sabitlemesini Kaldır" + "value": "Özel bir çalışma alanı adı seçin." } }, "uk": { "stringUnit": { "state": "translated", - "value": "Відкріпити робочу область" + "value": "Виберіть власну назву робочої області." } } } }, - "command.vscodeServeWebRestart.title": { + "commandPalette.rename.workspaceInputHint": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Restart VS Code Inline Server" + "value": "Enter a workspace name. Press Enter to rename, Escape to cancel." } }, "ja": { "stringUnit": { "state": "translated", - "value": "VS Codeインラインサーバーを再起動" + "value": "ワークスペース名を入力してください。Enterで名称変更、Escapeでキャンセルします。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "重启 VS Code 内联服务器" + "value": "输入工作区名称。按 Enter 重命名,按 Escape 取消。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "重新啟動 VS Code 內嵌伺服器" + "value": "輸入工作區名稱。按 Enter 重新命名,按 Escape 取消。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "VS Code 인라인 서버 재시작" + "value": "작업 공간 이름을 입력하세요. Enter로 이름 변경, Escape로 취소." } }, "de": { "stringUnit": { "state": "translated", - "value": "VS Code Inline-Server neu starten" + "value": "Geben Sie einen Arbeitsbereichsnamen ein. Eingabetaste zum Umbenennen, Escape zum Abbrechen." } }, "es": { "stringUnit": { "state": "translated", - "value": "Reiniciar servidor en línea de VS Code" + "value": "Introduce un nombre de espacio de trabajo. Pulsa Intro para renombrar, Escape para cancelar." } }, "fr": { "stringUnit": { "state": "translated", - "value": "Redémarrer le serveur VS Code intégré" + "value": "Saisissez un nom d'espace de travail. Appuyez sur Entrée pour renommer, Échap pour annuler." } }, "it": { "stringUnit": { "state": "translated", - "value": "Riavvia server inline VS Code" + "value": "Inserisci un nome per l'area di lavoro. Premi Invio per rinominare, Esc per annullare." } }, "da": { "stringUnit": { "state": "translated", - "value": "Genstart VS Code Inline Server" + "value": "Indtast et arbejdsområdenavn. Tryk Enter for at omdøbe, Escape for at annullere." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Uruchom ponownie wbudowany serwer VS Code" + "value": "Wprowadź nazwę przestrzeni roboczej. Naciśnij Enter, aby zmienić nazwę, Escape, aby anulować." } }, "ru": { "stringUnit": { "state": "translated", - "value": "Перезапустить встроенный сервер VS Code" + "value": "Введите имя рабочего пространства. Нажмите Enter для переименования, Escape для отмены." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Ponovo pokreni VS Code inline server" + "value": "Unesite naziv radnog prostora. Pritisnite Enter za preimenovanje, Escape za otkazivanje." } }, "ar": { "stringUnit": { "state": "translated", - "value": "إعادة تشغيل خادم VS Code المضمّن" + "value": "أدخل اسم مساحة العمل. اضغط Enter لإعادة التسمية، Escape للإلغاء." } }, "nb": { "stringUnit": { "state": "translated", - "value": "Start VS Code innebygd server på nytt" + "value": "Skriv inn et arbeidsområdenavn. Trykk Enter for å gi nytt navn, Escape for å avbryte." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Reiniciar Servidor Inline do VS Code" + "value": "Insira um nome para a área de trabalho. Pressione Enter para renomear, Escape para cancelar." } }, "th": { "stringUnit": { "state": "translated", - "value": "รีสตาร์ตเซิร์ฟเวอร์ VS Code แบบอินไลน์" + "value": "ป้อนชื่อเวิร์กสเปซ กด Enter เพื่อเปลี่ยนชื่อ, Escape เพื่อยกเลิก" } }, "tr": { "stringUnit": { "state": "translated", - "value": "VS Code Satır İçi Sunucusunu Yeniden Başlat" + "value": "Bir çalışma alanı adı girin. Yeniden adlandırmak için Enter, iptal etmek için Escape tuşuna basın." } }, "uk": { "stringUnit": { "state": "translated", - "value": "Перезапустити вбудований сервер VS Code" + "value": "Введіть назву робочої області. Enter — перейменувати, Escape — скасувати." } } } }, - "command.vscodeServeWebStop.title": { + "commandPalette.rename.workspacePlaceholder": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Stop VS Code Inline Server" + "value": "Workspace name" } }, "ja": { "stringUnit": { "state": "translated", - "value": "VS Codeインラインサーバーを停止" + "value": "ワークスペース名" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "停止 VS Code 内联服务器" + "value": "工作区名称" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "停止 VS Code 內嵌伺服器" + "value": "工作區名稱" } }, "ko": { "stringUnit": { "state": "translated", - "value": "VS Code 인라인 서버 중지" + "value": "작업 공간 이름" } }, "de": { "stringUnit": { "state": "translated", - "value": "VS Code Inline-Server stoppen" + "value": "Name des Arbeitsbereichs" } }, "es": { "stringUnit": { "state": "translated", - "value": "Detener servidor en línea de VS Code" + "value": "Nombre del espacio de trabajo" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Arrêter le serveur VS Code intégré" + "value": "Nom de l'espace de travail" } }, "it": { "stringUnit": { "state": "translated", - "value": "Arresta server inline VS Code" + "value": "Nome area di lavoro" } }, "da": { "stringUnit": { "state": "translated", - "value": "Stop VS Code Inline Server" + "value": "Arbejdsområdenavn" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Zatrzymaj wbudowany serwer VS Code" + "value": "Nazwa przestrzeni roboczej" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Остановить встроенный сервер VS Code" + "value": "Имя рабочего пространства" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Zaustavi VS Code inline server" + "value": "Naziv radnog prostora" } }, "ar": { "stringUnit": { "state": "translated", - "value": "إيقاف خادم VS Code المضمّن" + "value": "اسم مساحة العمل" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Stopp VS Code innebygd server" + "value": "Arbeidsområdenavn" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Parar Servidor Inline do VS Code" + "value": "Nome da área de trabalho" } }, "th": { "stringUnit": { "state": "translated", - "value": "หยุดเซิร์ฟเวอร์ VS Code แบบอินไลน์" + "value": "ชื่อเวิร์กสเปซ" } }, "tr": { "stringUnit": { "state": "translated", - "value": "VS Code Satır İçi Sunucusunu Durdur" + "value": "Çalışma alanı adı" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Зупинити вбудований сервер VS Code" + "value": "Назва робочої області" } } } }, - "commandPalette.kind.browser": { + "commandPalette.rename.workspaceTitle": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Browser" + "value": "Rename Workspace" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ブラウザ" + "value": "ワークスペースの名称変更" } }, - "uk": { + "zh-Hans": { "stringUnit": { "state": "translated", - "value": "Браузер" + "value": "重命名工作区" } }, - "ko": { + "zh-Hant": { "stringUnit": { "state": "translated", - "value": "브라우저" + "value": "重新命名工作區" } - } - } - }, - "commandPalette.kind.markdown": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "ko": { "stringUnit": { "state": "translated", - "value": "Markdown" + "value": "작업 공간 이름 변경" } }, - "ja": { + "de": { "stringUnit": { "state": "translated", - "value": "Markdown" + "value": "Arbeitsbereich umbenennen" } }, - "uk": { + "es": { "stringUnit": { "state": "translated", - "value": "Markdown" + "value": "Renombrar espacio de trabajo" } }, - "ko": { + "fr": { "stringUnit": { "state": "translated", - "value": "마크다운" + "value": "Renommer l'espace de travail" } - } - } - }, - "commandPalette.kind.rightSidebarTool": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "it": { "stringUnit": { "state": "translated", - "value": "Tool" + "value": "Rinomina area di lavoro" } }, - "ja": { + "da": { "stringUnit": { "state": "translated", - "value": "ツール" + "value": "Omdøb arbejdsområde" } - } - } - }, - "commandPalette.kind.terminal": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "pl": { "stringUnit": { "state": "translated", - "value": "Terminal" + "value": "Zmień nazwę przestrzeni roboczej" } }, - "ja": { + "ru": { "stringUnit": { "state": "translated", - "value": "ターミナル" + "value": "Переименовать рабочее пространство" } }, - "uk": { + "bs": { "stringUnit": { "state": "translated", - "value": "Термінал" + "value": "Preimenuj radni prostor" } }, - "ko": { + "ar": { "stringUnit": { "state": "translated", - "value": "터미널" + "value": "إعادة تسمية مساحة العمل" + } + }, + "nb": { + "stringUnit": { + "state": "translated", + "value": "Gi arbeidsområdet nytt navn" + } + }, + "pt-BR": { + "stringUnit": { + "state": "translated", + "value": "Renomear Área de Trabalho" + } + }, + "th": { + "stringUnit": { + "state": "translated", + "value": "เปลี่ยนชื่อเวิร์กสเปซ" + } + }, + "tr": { + "stringUnit": { + "state": "translated", + "value": "Çalışma Alanını Yeniden Adlandır" + } + }, + "uk": { + "stringUnit": { + "state": "translated", + "value": "Перейменувати робочу область" } } } }, - "commandPalette.kind.workspace": { + "commandPalette.search.commandsEmpty": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Workspace" + "value": "No commands match your search." } }, "ja": { "stringUnit": { "state": "translated", - "value": "ワークスペース" + "value": "検索に一致するコマンドがありません。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "工作区" + "value": "没有匹配的命令。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "工作區" + "value": "沒有符合搜尋的指令。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "작업 공간" + "value": "검색과 일치하는 명령어가 없습니다." } }, "de": { "stringUnit": { "state": "translated", - "value": "Arbeitsbereich" + "value": "Keine Befehle entsprechen Ihrer Suche." } }, "es": { "stringUnit": { "state": "translated", - "value": "Espacio de trabajo" + "value": "Ningún comando coincide con tu búsqueda." } }, "fr": { "stringUnit": { "state": "translated", - "value": "Espace de travail" + "value": "Aucune commande ne correspond à votre recherche." } }, "it": { "stringUnit": { "state": "translated", - "value": "Area di lavoro" + "value": "Nessun comando corrisponde alla ricerca." } }, "da": { "stringUnit": { "state": "translated", - "value": "Arbejdsområde" + "value": "Ingen kommandoer matcher din søgning." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Przestrzeń robocza" + "value": "Brak poleceń pasujących do wyszukiwania." } }, "ru": { "stringUnit": { "state": "translated", - "value": "Рабочее пространство" + "value": "Нет команд, соответствующих запросу." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Radni prostor" + "value": "Nijedna naredba ne odgovara vašoj pretrazi." } }, "ar": { "stringUnit": { "state": "translated", - "value": "مساحة العمل" + "value": "لا توجد أوامر تطابق بحثك." } }, "nb": { "stringUnit": { "state": "translated", - "value": "Arbeidsområde" + "value": "Ingen kommandoer samsvarer med søket ditt." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Área de Trabalho" + "value": "Nenhum comando corresponde à sua pesquisa." } }, "th": { "stringUnit": { "state": "translated", - "value": "เวิร์กสเปซ" + "value": "ไม่มีคำสั่งที่ตรงกับการค้นหาของคุณ" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Çalışma Alanı" + "value": "Aramanızla eşleşen komut yok." } }, "uk": { "stringUnit": { "state": "translated", - "value": "Робоча область" + "value": "Команди, що відповідають пошуку, не знайдено." } } } }, - "commandPalette.rename.clearCustomName": { + "commandPalette.search.commandsPlaceholder": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "(clear custom name)" + "value": "Type a command" } }, "ja": { "stringUnit": { "state": "translated", - "value": "(カスタム名をクリア)" + "value": "コマンドを入力" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "(清除自定义名称)" + "value": "输入命令" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "(清除自訂名稱)" + "value": "輸入指令" } }, "ko": { "stringUnit": { "state": "translated", - "value": "(사용자 지정 이름 지우기)" + "value": "명령어를 입력하세요" } }, "de": { "stringUnit": { "state": "translated", - "value": "(Benutzerdefinierten Namen löschen)" + "value": "Befehl eingeben" } }, "es": { "stringUnit": { "state": "translated", - "value": "(borrar nombre personalizado)" + "value": "Escribe un comando" } }, "fr": { "stringUnit": { "state": "translated", - "value": "(effacer le nom personnalisé)" + "value": "Saisissez une commande" } }, "it": { "stringUnit": { "state": "translated", - "value": "(cancella nome personalizzato)" + "value": "Digita un comando" } }, "da": { "stringUnit": { "state": "translated", - "value": "(ryd brugerdefineret navn)" + "value": "Skriv en kommando" } }, "pl": { "stringUnit": { "state": "translated", - "value": "(wyczyść własną nazwę)" + "value": "Wpisz polecenie" } }, "ru": { "stringUnit": { "state": "translated", - "value": "(очистить пользовательское имя)" + "value": "Введите команду" } }, "bs": { "stringUnit": { "state": "translated", - "value": "(obriši prilagođeni naziv)" + "value": "Unesite naredbu" } }, "ar": { "stringUnit": { "state": "translated", - "value": "(مسح الاسم المخصص)" + "value": "اكتب أمرًا" } }, "nb": { "stringUnit": { "state": "translated", - "value": "(fjern egendefinert navn)" + "value": "Skriv en kommando" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "(limpar nome personalizado)" + "value": "Digite um comando" } }, "th": { "stringUnit": { "state": "translated", - "value": "(ล้างชื่อที่กำหนดเอง)" + "value": "พิมพ์คำสั่ง" } }, "tr": { "stringUnit": { "state": "translated", - "value": "(özel adı temizle)" + "value": "Bir komut yazın" } }, "uk": { "stringUnit": { "state": "translated", - "value": "(скинути власну назву)" + "value": "Введіть команду" } } } }, - "commandPalette.rename.tabConfirmHint": { + "commandPalette.search.switcherEmpty": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Press Enter to apply this tab name, or Escape to cancel." + "value": "No workspaces match your search." } }, "ja": { "stringUnit": { "state": "translated", - "value": "Enterキーでタブ名を適用、Escapeキーでキャンセルします。" + "value": "検索に一致するワークスペースがありません。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "按 Enter 应用此标签页名称,或按 Escape 取消。" + "value": "没有匹配的工作区。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "按 Enter 套用此標籤頁名稱,或按 Escape 取消。" + "value": "沒有符合搜尋的工作區。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "Enter를 눌러 탭 이름을 적용하거나, Escape를 눌러 취소하세요." + "value": "검색과 일치하는 작업 공간이 없습니다." } }, "de": { "stringUnit": { "state": "translated", - "value": "Drücken Sie die Eingabetaste, um den Tab-Namen zu übernehmen, oder Escape zum Abbrechen." + "value": "Keine Arbeitsbereiche entsprechen Ihrer Suche." } }, "es": { "stringUnit": { "state": "translated", - "value": "Pulsa Intro para aplicar este nombre de pestaña, o Escape para cancelar." + "value": "Ningún espacio de trabajo coincide con tu búsqueda." } }, "fr": { "stringUnit": { "state": "translated", - "value": "Appuyez sur Entrée pour appliquer ce nom d'onglet, ou sur Échap pour annuler." + "value": "Aucun espace de travail ne correspond à votre recherche." } }, "it": { "stringUnit": { "state": "translated", - "value": "Premi Invio per applicare il nome della scheda, oppure Esc per annullare." + "value": "Nessuna area di lavoro corrisponde alla ricerca." } }, "da": { "stringUnit": { "state": "translated", - "value": "Tryk Enter for at anvende dette fanenavn, eller Escape for at annullere." + "value": "Ingen arbejdsområder matcher din søgning." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Naciśnij Enter, aby zastosować nazwę karty, lub Escape, aby anulować." + "value": "Brak przestrzeni roboczych pasujących do wyszukiwania." } }, "ru": { "stringUnit": { "state": "translated", - "value": "Нажмите Enter, чтобы применить имя вкладки, или Escape для отмены." + "value": "Нет рабочих пространств, соответствующих запросу." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Pritisnite Enter za primjenu naziva taba, ili Escape za otkazivanje." + "value": "Nijedan radni prostor ne odgovara vašoj pretrazi." } }, "ar": { "stringUnit": { "state": "translated", - "value": "اضغط Enter لتطبيق اسم اللسان، أو Escape للإلغاء." + "value": "لا توجد مساحات عمل تطابق بحثك." } }, "nb": { "stringUnit": { "state": "translated", - "value": "Trykk Enter for å bruke dette fanenavnet, eller Escape for å avbryte." + "value": "Ingen arbeidsområder samsvarer med søket ditt." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Pressione Enter para aplicar este nome de aba ou Escape para cancelar." + "value": "Nenhuma área de trabalho corresponde à sua pesquisa." } }, "th": { "stringUnit": { "state": "translated", - "value": "กด Enter เพื่อใช้ชื่อแท็บนี้ หรือ Escape เพื่อยกเลิก" + "value": "ไม่มีเวิร์กสเปซที่ตรงกับการค้นหาของคุณ" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Bu sekme adını uygulamak için Enter tuşuna basın veya iptal etmek için Escape tuşuna basın." + "value": "Aramanızla eşleşen çalışma alanı yok." } }, "uk": { "stringUnit": { "state": "translated", - "value": "Натисніть Enter, щоб застосувати назву вкладки, або Escape для скасування." + "value": "Робочі області, що відповідають пошуку, не знайдено." } } } }, - "commandPalette.rename.tabDescription": { + "commandPalette.search.switcherEmptyAllSurfaces": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Choose a custom tab name." + "value": "No workspaces or surfaces match your search." } }, "ja": { "stringUnit": { "state": "translated", - "value": "タブのカスタム名を選択してください。" + "value": "検索に一致するワークスペースまたはサーフェスはありません。" + } + }, + "uk": { + "stringUnit": { + "state": "translated", + "value": "Робочі області чи поверхні, що відповідають пошуку, не знайдено." + } + }, + "ko": { + "stringUnit": { + "state": "translated", + "value": "검색과 일치하는 워크스페이스 또는 서피스가 없습니다." + } + } + } + }, + "commandPalette.search.switcherPlaceholder": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Search workspaces" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "ワークスペースを検索" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "选择自定义标签页名称。" + "value": "搜索工作区" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "選擇自訂標籤頁名稱。" + "value": "搜尋工作區" } }, "ko": { "stringUnit": { "state": "translated", - "value": "사용자 지정 탭 이름을 선택하세요." + "value": "작업 공간 검색" } }, "de": { "stringUnit": { "state": "translated", - "value": "Wählen Sie einen benutzerdefinierten Tab-Namen." + "value": "Arbeitsbereiche durchsuchen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Elige un nombre personalizado para la pestaña." + "value": "Buscar espacios de trabajo" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Choisissez un nom personnalisé pour l'onglet." + "value": "Rechercher des espaces de travail" } }, "it": { "stringUnit": { "state": "translated", - "value": "Scegli un nome personalizzato per la scheda." + "value": "Cerca aree di lavoro" } }, "da": { "stringUnit": { "state": "translated", - "value": "Vælg et brugerdefineret fanenavn." + "value": "Søg i arbejdsområder" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Wybierz własną nazwę karty." + "value": "Szukaj przestrzeni roboczych" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Выберите пользовательское имя вкладки." + "value": "Поиск рабочих пространств" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Odaberite prilagođeni naziv taba." + "value": "Pretraži radne prostore" } }, "ar": { "stringUnit": { "state": "translated", - "value": "اختر اسمًا مخصصًا للسان." + "value": "البحث في مساحات العمل" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Velg et egendefinert fanenavn." + "value": "Søk i arbeidsområder" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Escolha um nome personalizado para a aba." + "value": "Pesquisar áreas de trabalho" } }, "th": { "stringUnit": { "state": "translated", - "value": "เลือกชื่อแท็บที่กำหนดเอง" + "value": "ค้นหาเวิร์กสเปซ" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Özel bir sekme adı seçin." + "value": "Çalışma alanlarını ara" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Виберіть власну назву вкладки." + "value": "Пошук робочих областей" } } } }, - "commandPalette.rename.tabInputHint": { + "commandPalette.search.switcherPlaceholderAllSurfaces": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Enter a tab name. Press Enter to rename, Escape to cancel." + "value": "Search workspaces and surfaces" } }, "ja": { "stringUnit": { "state": "translated", - "value": "タブ名を入力してください。Enterで名称変更、Escapeでキャンセルします。" + "value": "ワークスペースとサーフェスを検索" + } + }, + "uk": { + "stringUnit": { + "state": "translated", + "value": "Пошук робочих областей і поверхонь" + } + }, + "ko": { + "stringUnit": { + "state": "translated", + "value": "워크스페이스 및 서피스 검색" + } + } + } + }, + "commandPalette.subtitle.browserWithName": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Browser • %@" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "ブラウザ • %@" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "输入标签页名称。按 Enter 重命名,按 Escape 取消。" + "value": "浏览器 • %@" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "輸入標籤頁名稱。按 Enter 重新命名,按 Escape 取消。" + "value": "瀏覽器 • %@" } }, "ko": { "stringUnit": { "state": "translated", - "value": "탭 이름을 입력하세요. Enter로 이름 변경, Escape로 취소." + "value": "브라우저 • %@" } }, "de": { "stringUnit": { "state": "translated", - "value": "Geben Sie einen Tab-Namen ein. Eingabetaste zum Umbenennen, Escape zum Abbrechen." + "value": "Browser • %@" } }, "es": { "stringUnit": { "state": "translated", - "value": "Introduce un nombre de pestaña. Pulsa Intro para renombrar, Escape para cancelar." + "value": "Navegador • %@" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Saisissez un nom d'onglet. Appuyez sur Entrée pour renommer, Échap pour annuler." + "value": "Navigateur • %@" } }, "it": { "stringUnit": { "state": "translated", - "value": "Inserisci un nome per la scheda. Premi Invio per rinominare, Esc per annullare." + "value": "Browser • %@" } }, "da": { "stringUnit": { "state": "translated", - "value": "Indtast et fanenavn. Tryk Enter for at omdøbe, Escape for at annullere." + "value": "Browser • %@" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Wprowadź nazwę karty. Naciśnij Enter, aby zmienić nazwę, Escape, aby anulować." + "value": "Przeglądarka • %@" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Введите имя вкладки. Нажмите Enter для переименования, Escape для отмены." + "value": "Браузер • %@" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Unesite naziv taba. Pritisnite Enter za preimenovanje, Escape za otkazivanje." + "value": "Preglednik • %@" } }, "ar": { "stringUnit": { "state": "translated", - "value": "أدخل اسم اللسان. اضغط Enter لإعادة التسمية، Escape للإلغاء." + "value": "المتصفح • %@" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Skriv inn et fanenavn. Trykk Enter for å gi nytt navn, Escape for å avbryte." + "value": "Nettleser • %@" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Insira um nome para a aba. Pressione Enter para renomear, Escape para cancelar." + "value": "Navegador • %@" } }, "th": { "stringUnit": { "state": "translated", - "value": "ป้อนชื่อแท็บ กด Enter เพื่อเปลี่ยนชื่อ, Escape เพื่อยกเลิก" + "value": "เบราว์เซอร์ • %@" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Bir sekme adı girin. Yeniden adlandırmak için Enter, iptal etmek için Escape tuşuna basın." + "value": "Tarayıcı • %@" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Введіть назву вкладки. Enter — перейменувати, Escape — скасувати." + "value": "Браузер • %@" } } } }, - "commandPalette.rename.tabPlaceholder": { + "commandPalette.subtitle.tabFallback": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Tab name" + "value": "Tab" } }, "ja": { "stringUnit": { "state": "translated", - "value": "タブ名" + "value": "タブ" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "标签页名称" + "value": "标签页" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "標籤頁名稱" + "value": "標籤頁" } }, "ko": { "stringUnit": { "state": "translated", - "value": "탭 이름" + "value": "탭" } }, "de": { "stringUnit": { "state": "translated", - "value": "Tab-Name" + "value": "Tab" } }, "es": { "stringUnit": { "state": "translated", - "value": "Nombre de pestaña" + "value": "Pestaña" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Nom de l'onglet" + "value": "Onglet" } }, "it": { "stringUnit": { "state": "translated", - "value": "Nome scheda" + "value": "Scheda" } }, "da": { "stringUnit": { "state": "translated", - "value": "Fanenavn" + "value": "Fane" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Nazwa karty" + "value": "Karta" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Имя вкладки" + "value": "Вкладка" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Naziv taba" + "value": "Tab" } }, "ar": { "stringUnit": { "state": "translated", - "value": "اسم اللسان" + "value": "لسان" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Fanenavn" + "value": "Fane" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Nome da aba" + "value": "Aba" } }, "th": { "stringUnit": { "state": "translated", - "value": "ชื่อแท็บ" + "value": "แท็บ" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Sekme adı" + "value": "Sekme" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Назва вкладки" + "value": "Вкладка" } } } }, - "commandPalette.rename.tabTitle": { + "commandPalette.subtitle.tabWithName": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Rename Tab" + "value": "Tab • %@" } }, "ja": { "stringUnit": { "state": "translated", - "value": "タブの名称変更" + "value": "タブ • %@" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "重命名标签页" + "value": "标签页 • %@" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "重新命名標籤頁" + "value": "標籤頁 • %@" } }, "ko": { "stringUnit": { "state": "translated", - "value": "탭 이름 변경" + "value": "탭 • %@" } }, "de": { "stringUnit": { "state": "translated", - "value": "Tab umbenennen" + "value": "Tab • %@" } }, "es": { "stringUnit": { "state": "translated", - "value": "Renombrar pestaña" + "value": "Pestaña • %@" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Renommer l'onglet" + "value": "Onglet • %@" } }, "it": { "stringUnit": { "state": "translated", - "value": "Rinomina scheda" + "value": "Scheda • %@" } }, "da": { "stringUnit": { "state": "translated", - "value": "Omdøb fane" + "value": "Fane • %@" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Zmień nazwę karty" + "value": "Karta • %@" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Переименовать вкладку" + "value": "Вкладка • %@" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Preimenuj tab" + "value": "Tab • %@" } }, "ar": { "stringUnit": { "state": "translated", - "value": "إعادة تسمية اللسان" + "value": "لسان • %@" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Gi fanen nytt navn" + "value": "Fane • %@" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Renomear Aba" + "value": "Aba • %@" } }, "th": { "stringUnit": { "state": "translated", - "value": "เปลี่ยนชื่อแท็บ" + "value": "แท็บ • %@" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Sekmeyi Yeniden Adlandır" + "value": "Sekme • %@" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Перейменувати вкладку" + "value": "Вкладка • %@" } } } }, - "commandPalette.rename.workspaceConfirmHint": { + "commandPalette.subtitle.terminalWithName": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Press Enter to apply this workspace name, or Escape to cancel." + "value": "Terminal • %@" } }, "ja": { "stringUnit": { "state": "translated", - "value": "Enterキーでワークスペース名を適用、Escapeキーでキャンセルします。" + "value": "ターミナル • %@" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "按 Enter 应用此工作区名称,或按 Escape 取消。" + "value": "终端 • %@" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "按 Enter 套用此工作區名稱,或按 Escape 取消。" + "value": "終端機 • %@" } }, "ko": { "stringUnit": { "state": "translated", - "value": "Enter를 눌러 작업 공간 이름을 적용하거나, Escape를 눌러 취소하세요." + "value": "터미널 • %@" } }, "de": { "stringUnit": { "state": "translated", - "value": "Drücken Sie die Eingabetaste, um den Arbeitsbereichsnamen zu übernehmen, oder Escape zum Abbrechen." + "value": "Terminal • %@" } }, "es": { "stringUnit": { "state": "translated", - "value": "Pulsa Intro para aplicar este nombre de espacio de trabajo, o Escape para cancelar." + "value": "Terminal • %@" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Appuyez sur Entrée pour appliquer ce nom d'espace de travail, ou sur Échap pour annuler." + "value": "Terminal • %@" } }, "it": { "stringUnit": { "state": "translated", - "value": "Premi Invio per applicare il nome dell'area di lavoro, oppure Esc per annullare." + "value": "Terminale • %@" } }, "da": { "stringUnit": { "state": "translated", - "value": "Tryk Enter for at anvende dette arbejdsområdenavn, eller Escape for at annullere." + "value": "Terminal • %@" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Naciśnij Enter, aby zastosować nazwę przestrzeni roboczej, lub Escape, aby anulować." + "value": "Terminal • %@" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Нажмите Enter, чтобы применить имя рабочего пространства, или Escape для отмены." + "value": "Терминал • %@" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Pritisnite Enter za primjenu naziva radnog prostora, ili Escape za otkazivanje." + "value": "Terminal • %@" } }, "ar": { "stringUnit": { "state": "translated", - "value": "اضغط Enter لتطبيق اسم مساحة العمل، أو Escape للإلغاء." + "value": "الطرفية • %@" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Trykk Enter for å bruke dette arbeidsområdenavnet, eller Escape for å avbryte." + "value": "Terminal • %@" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Pressione Enter para aplicar este nome de área de trabalho ou Escape para cancelar." + "value": "Terminal • %@" } }, "th": { "stringUnit": { "state": "translated", - "value": "กด Enter เพื่อใช้ชื่อเวิร์กสเปซนี้ หรือ Escape เพื่อยกเลิก" + "value": "เทอร์มินัล • %@" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Bu çalışma alanı adını uygulamak için Enter tuşuna basın veya iptal etmek için Escape tuşuna basın." + "value": "Terminal • %@" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Натисніть Enter, щоб застосувати назву робочої області, або Escape для скасування." + "value": "Термінал • %@" } } } }, - "commandPalette.rename.workspaceDescription": { + "commandPalette.subtitle.workspaceFallback": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Choose a custom workspace name." + "value": "Workspace" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ワークスペースのカスタム名を選択してください。" + "value": "ワークスペース" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "选择自定义工作区名称。" + "value": "工作区" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "選擇自訂工作區名稱。" + "value": "工作區" } }, "ko": { "stringUnit": { "state": "translated", - "value": "사용자 지정 작업 공간 이름을 선택하세요." + "value": "작업 공간" } }, "de": { "stringUnit": { "state": "translated", - "value": "Wählen Sie einen benutzerdefinierten Arbeitsbereichsnamen." + "value": "Arbeitsbereich" } }, "es": { "stringUnit": { "state": "translated", - "value": "Elige un nombre personalizado para el espacio de trabajo." + "value": "Espacio de trabajo" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Choisissez un nom personnalisé pour l'espace de travail." + "value": "Espace de travail" } }, "it": { "stringUnit": { "state": "translated", - "value": "Scegli un nome personalizzato per l'area di lavoro." + "value": "Area di lavoro" } }, "da": { "stringUnit": { "state": "translated", - "value": "Vælg et brugerdefineret arbejdsområdenavn." + "value": "Arbejdsområde" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Wybierz własną nazwę przestrzeni roboczej." + "value": "Przestrzeń robocza" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Выберите пользовательское имя рабочего пространства." + "value": "Рабочее пространство" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Odaberite prilagođeni naziv radnog prostora." + "value": "Radni prostor" } }, "ar": { "stringUnit": { "state": "translated", - "value": "اختر اسمًا مخصصًا لمساحة العمل." + "value": "مساحة العمل" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Velg et egendefinert arbeidsområdenavn." + "value": "Arbeidsområde" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Escolha um nome personalizado para a área de trabalho." + "value": "Área de Trabalho" } }, "th": { "stringUnit": { "state": "translated", - "value": "เลือกชื่อเวิร์กสเปซที่กำหนดเอง" + "value": "เวิร์กสเปซ" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Özel bir çalışma alanı adı seçin." + "value": "Çalışma Alanı" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Виберіть власну назву робочої області." + "value": "Робоча область" } } } }, - "commandPalette.rename.workspaceInputHint": { + "commandPalette.subtitle.workspaceWithName": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Enter a workspace name. Press Enter to rename, Escape to cancel." + "value": "Workspace • %@" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ワークスペース名を入力してください。Enterで名称変更、Escapeでキャンセルします。" + "value": "ワークスペース • %@" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "输入工作区名称。按 Enter 重命名,按 Escape 取消。" + "value": "工作区 • %@" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "輸入工作區名稱。按 Enter 重新命名,按 Escape 取消。" + "value": "工作區 • %@" } }, "ko": { "stringUnit": { "state": "translated", - "value": "작업 공간 이름을 입력하세요. Enter로 이름 변경, Escape로 취소." + "value": "작업 공간 • %@" } }, "de": { "stringUnit": { "state": "translated", - "value": "Geben Sie einen Arbeitsbereichsnamen ein. Eingabetaste zum Umbenennen, Escape zum Abbrechen." + "value": "Arbeitsbereich • %@" } }, "es": { "stringUnit": { "state": "translated", - "value": "Introduce un nombre de espacio de trabajo. Pulsa Intro para renombrar, Escape para cancelar." + "value": "Espacio de trabajo • %@" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Saisissez un nom d'espace de travail. Appuyez sur Entrée pour renommer, Échap pour annuler." + "value": "Espace de travail • %@" } }, "it": { "stringUnit": { "state": "translated", - "value": "Inserisci un nome per l'area di lavoro. Premi Invio per rinominare, Esc per annullare." + "value": "Area di lavoro • %@" } }, "da": { "stringUnit": { "state": "translated", - "value": "Indtast et arbejdsområdenavn. Tryk Enter for at omdøbe, Escape for at annullere." + "value": "Arbejdsområde • %@" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Wprowadź nazwę przestrzeni roboczej. Naciśnij Enter, aby zmienić nazwę, Escape, aby anulować." + "value": "Przestrzeń robocza • %@" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Введите имя рабочего пространства. Нажмите Enter для переименования, Escape для отмены." + "value": "Рабочее пространство • %@" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Unesite naziv radnog prostora. Pritisnite Enter za preimenovanje, Escape za otkazivanje." + "value": "Radni prostor • %@" } }, "ar": { "stringUnit": { "state": "translated", - "value": "أدخل اسم مساحة العمل. اضغط Enter لإعادة التسمية، Escape للإلغاء." + "value": "مساحة العمل • %@" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Skriv inn et arbeidsområdenavn. Trykk Enter for å gi nytt navn, Escape for å avbryte." + "value": "Arbeidsområde • %@" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Insira um nome para a área de trabalho. Pressione Enter para renomear, Escape para cancelar." + "value": "Área de Trabalho • %@" } }, "th": { "stringUnit": { "state": "translated", - "value": "ป้อนชื่อเวิร์กสเปซ กด Enter เพื่อเปลี่ยนชื่อ, Escape เพื่อยกเลิก" + "value": "เวิร์กสเปซ • %@" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Bir çalışma alanı adı girin. Yeniden adlandırmak için Enter, iptal etmek için Escape tuşuna basın." + "value": "Çalışma Alanı • %@" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Введіть назву робочої області. Enter — перейменувати, Escape — скасувати." + "value": "Робоча область • %@" } } } }, - "commandPalette.rename.workspacePlaceholder": { + "commandPalette.switcher.windowLabel": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Workspace name" + "value": "Window %lld" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ワークスペース名" + "value": "ウインドウ %lld" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "工作区名称" + "value": "窗口 %lld" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "工作區名稱" + "value": "視窗 %lld" } }, "ko": { "stringUnit": { "state": "translated", - "value": "작업 공간 이름" + "value": "윈도우 %lld" } }, "de": { "stringUnit": { "state": "translated", - "value": "Name des Arbeitsbereichs" + "value": "Fenster %lld" } }, "es": { "stringUnit": { "state": "translated", - "value": "Nombre del espacio de trabajo" + "value": "Ventana %lld" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Nom de l'espace de travail" + "value": "Fenêtre %lld" } }, "it": { "stringUnit": { "state": "translated", - "value": "Nome area di lavoro" + "value": "Finestra %lld" } }, "da": { "stringUnit": { "state": "translated", - "value": "Arbejdsområdenavn" + "value": "Vindue %lld" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Nazwa przestrzeni roboczej" + "value": "Okno %lld" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Имя рабочего пространства" + "value": "Окно %lld" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Naziv radnog prostora" + "value": "Prozor %lld" } }, "ar": { "stringUnit": { "state": "translated", - "value": "اسم مساحة العمل" + "value": "النافذة %lld" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Arbeidsområdenavn" + "value": "Vindu %lld" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Nome da área de trabalho" + "value": "Janela %lld" } }, "th": { "stringUnit": { "state": "translated", - "value": "ชื่อเวิร์กสเปซ" + "value": "หน้าต่าง %lld" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Çalışma alanı adı" + "value": "Pencere %lld" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Назва робочої області" + "value": "Вікно %lld" } } } }, - "commandPalette.rename.workspaceTitle": { + "commandPalette.switcher.workspaceLabel": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Rename Workspace" + "value": "Workspace" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ワークスペースの名称変更" + "value": "ワークスペース" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "重命名工作区" + "value": "工作区" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "重新命名工作區" + "value": "工作區" } }, "ko": { "stringUnit": { "state": "translated", - "value": "작업 공간 이름 변경" + "value": "작업 공간" } }, "de": { "stringUnit": { "state": "translated", - "value": "Arbeitsbereich umbenennen" + "value": "Arbeitsbereich" } }, "es": { "stringUnit": { "state": "translated", - "value": "Renombrar espacio de trabajo" + "value": "Espacio de trabajo" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Renommer l'espace de travail" + "value": "Espace de travail" } }, "it": { "stringUnit": { "state": "translated", - "value": "Rinomina area di lavoro" + "value": "Area di lavoro" } }, "da": { "stringUnit": { "state": "translated", - "value": "Omdøb arbejdsområde" + "value": "Arbejdsområde" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Zmień nazwę przestrzeni roboczej" + "value": "Przestrzeń robocza" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Переименовать рабочее пространство" + "value": "Рабочее пространство" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Preimenuj radni prostor" + "value": "Radni prostor" } }, "ar": { "stringUnit": { "state": "translated", - "value": "إعادة تسمية مساحة العمل" + "value": "مساحة العمل" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Gi arbeidsområdet nytt navn" + "value": "Arbeidsområde" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Renomear Área de Trabalho" + "value": "Área de Trabalho" } }, "th": { "stringUnit": { "state": "translated", - "value": "เปลี่ยนชื่อเวิร์กสเปซ" + "value": "เวิร์กสเปซ" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Çalışma Alanını Yeniden Adlandır" + "value": "Çalışma Alanı" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Перейменувати робочу область" + "value": "Робоча область" } } } }, - "commandPalette.search.commandsEmpty": { + "common.allow": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "No commands match your search." + "value": "Allow" } }, "ja": { "stringUnit": { "state": "translated", - "value": "検索に一致するコマンドがありません。" + "value": "許可" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "没有匹配的命令。" + "value": "允许" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "沒有符合搜尋的指令。" + "value": "允許" } }, "ko": { "stringUnit": { "state": "translated", - "value": "검색과 일치하는 명령어가 없습니다." + "value": "허용" } }, "de": { "stringUnit": { "state": "translated", - "value": "Keine Befehle entsprechen Ihrer Suche." + "value": "Erlauben" } }, "es": { "stringUnit": { "state": "translated", - "value": "Ningún comando coincide con tu búsqueda." + "value": "Permitir" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Aucune commande ne correspond à votre recherche." + "value": "Autoriser" } }, "it": { "stringUnit": { "state": "translated", - "value": "Nessun comando corrisponde alla ricerca." + "value": "Consenti" } }, "da": { "stringUnit": { "state": "translated", - "value": "Ingen kommandoer matcher din søgning." + "value": "Tillad" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Brak poleceń pasujących do wyszukiwania." + "value": "Zezwól" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Нет команд, соответствующих запросу." + "value": "Разрешить" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Nijedna naredba ne odgovara vašoj pretrazi." + "value": "Dozvoli" } }, "ar": { "stringUnit": { "state": "translated", - "value": "لا توجد أوامر تطابق بحثك." + "value": "سماح" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Ingen kommandoer samsvarer med søket ditt." + "value": "Tillat" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Nenhum comando corresponde à sua pesquisa." + "value": "Permitir" } }, "th": { "stringUnit": { "state": "translated", - "value": "ไม่มีคำสั่งที่ตรงกับการค้นหาของคุณ" + "value": "อนุญาต" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Aramanızla eşleşen komut yok." + "value": "İzin Ver" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Команди, що відповідають пошуку, не знайдено." + "value": "Дозволити" } } } }, - "commandPalette.search.commandsPlaceholder": { + "common.cancel": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Type a command" + "value": "Cancel" } }, "ja": { "stringUnit": { "state": "translated", - "value": "コマンドを入力" + "value": "キャンセル" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "输入命令" + "value": "取消" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "輸入指令" + "value": "取消" } }, "ko": { "stringUnit": { "state": "translated", - "value": "명령어를 입력하세요" + "value": "취소" } }, "de": { "stringUnit": { "state": "translated", - "value": "Befehl eingeben" + "value": "Abbrechen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Escribe un comando" + "value": "Cancelar" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Saisissez une commande" + "value": "Annuler" } }, "it": { "stringUnit": { "state": "translated", - "value": "Digita un comando" + "value": "Annulla" } }, "da": { "stringUnit": { "state": "translated", - "value": "Skriv en kommando" + "value": "Annuller" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Wpisz polecenie" + "value": "Anuluj" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Введите команду" + "value": "Отменить" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Unesite naredbu" + "value": "Otkaži" } }, "ar": { "stringUnit": { "state": "translated", - "value": "اكتب أمرًا" + "value": "إلغاء" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Skriv en kommando" + "value": "Avbryt" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Digite um comando" + "value": "Cancelar" } }, "th": { "stringUnit": { "state": "translated", - "value": "พิมพ์คำสั่ง" + "value": "ยกเลิก" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Bir komut yazın" + "value": "Vazgeç" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Введіть команду" + "value": "Скасувати" } } } }, - "commandPalette.search.switcherEmpty": { + "common.create": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "No workspaces match your search." + "value": "Create" } }, "ja": { "stringUnit": { "state": "translated", - "value": "検索に一致するワークスペースがありません。" + "value": "作成" + } + }, + "uk": { + "stringUnit": { + "state": "translated", + "value": "Створити" + } + }, + "ko": { + "stringUnit": { + "state": "translated", + "value": "생성" + } + } + } + }, + "common.close": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Close" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "閉じる" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "没有匹配的工作区。" + "value": "关闭" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "沒有符合搜尋的工作區。" + "value": "關閉" } }, "ko": { "stringUnit": { "state": "translated", - "value": "검색과 일치하는 작업 공간이 없습니다." + "value": "닫기" } }, "de": { "stringUnit": { "state": "translated", - "value": "Keine Arbeitsbereiche entsprechen Ihrer Suche." + "value": "Schließen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Ningún espacio de trabajo coincide con tu búsqueda." + "value": "Cerrar" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Aucun espace de travail ne correspond à votre recherche." + "value": "Fermer" } }, "it": { "stringUnit": { "state": "translated", - "value": "Nessuna area di lavoro corrisponde alla ricerca." + "value": "Chiudi" } }, "da": { "stringUnit": { "state": "translated", - "value": "Ingen arbejdsområder matcher din søgning." + "value": "Luk" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Brak przestrzeni roboczych pasujących do wyszukiwania." + "value": "Zamknij" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Нет рабочих пространств, соответствующих запросу." + "value": "Закрыть" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Nijedan radni prostor ne odgovara vašoj pretrazi." + "value": "Zatvori" } }, "ar": { "stringUnit": { "state": "translated", - "value": "لا توجد مساحات عمل تطابق بحثك." + "value": "إغلاق" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Ingen arbeidsområder samsvarer med søket ditt." + "value": "Lukk" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Nenhuma área de trabalho corresponde à sua pesquisa." + "value": "Fechar" } }, "th": { "stringUnit": { "state": "translated", - "value": "ไม่มีเวิร์กสเปซที่ตรงกับการค้นหาของคุณ" + "value": "ปิด" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Aramanızla eşleşen çalışma alanı yok." - } - }, - "uk": { - "stringUnit": { - "state": "translated", - "value": "Робочі області, що відповідають пошуку, не знайдено." - } - } - } - }, - "commandPalette.search.switcherEmptyAllSurfaces": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "No workspaces or surfaces match your search." - } - }, - "ja": { - "stringUnit": { - "state": "translated", - "value": "検索に一致するワークスペースまたはサーフェスはありません。" + "value": "Kapat" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Робочі області чи поверхні, що відповідають пошуку, не знайдено." - } - }, - "ko": { - "stringUnit": { - "state": "translated", - "value": "검색과 일치하는 워크스페이스 또는 서피스가 없습니다." + "value": "Закрити" } } } }, - "commandPalette.search.switcherPlaceholder": { + "common.copyDetails": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Search workspaces" + "value": "Copy Details" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ワークスペースを検索" + "value": "詳細をコピー" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "搜索工作区" + "value": "拷贝详细信息" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "搜尋工作區" + "value": "拷貝詳細資訊" } }, "ko": { "stringUnit": { "state": "translated", - "value": "작업 공간 검색" + "value": "세부 정보 복사" } }, "de": { "stringUnit": { "state": "translated", - "value": "Arbeitsbereiche durchsuchen" + "value": "Details kopieren" } }, "es": { "stringUnit": { "state": "translated", - "value": "Buscar espacios de trabajo" + "value": "Copiar detalles" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Rechercher des espaces de travail" + "value": "Copier les détails" } }, "it": { "stringUnit": { "state": "translated", - "value": "Cerca aree di lavoro" + "value": "Copia dettagli" } }, "da": { "stringUnit": { "state": "translated", - "value": "Søg i arbejdsområder" + "value": "Kopier detaljer" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Szukaj przestrzeni roboczych" + "value": "Kopiuj szczegóły" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Поиск рабочих пространств" + "value": "Скопировать подробности" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Pretraži radne prostore" + "value": "Kopiraj detalje" } }, "ar": { "stringUnit": { "state": "translated", - "value": "البحث في مساحات العمل" + "value": "نسخ التفاصيل" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Søk i arbeidsområder" + "value": "Kopier detaljer" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Pesquisar áreas de trabalho" + "value": "Copiar Detalhes" } }, "th": { "stringUnit": { "state": "translated", - "value": "ค้นหาเวิร์กสเปซ" + "value": "คัดลอกรายละเอียด" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Çalışma alanlarını ara" - } - }, - "uk": { - "stringUnit": { - "state": "translated", - "value": "Пошук робочих областей" - } - } - } - }, - "commandPalette.search.switcherPlaceholderAllSurfaces": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Search workspaces and surfaces" - } - }, - "ja": { - "stringUnit": { - "state": "translated", - "value": "ワークスペースとサーフェスを検索" + "value": "Ayrıntıları Kopyala" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Пошук робочих областей і поверхонь" - } - }, - "ko": { - "stringUnit": { - "state": "translated", - "value": "워크스페이스 및 서피스 검색" + "value": "Копіювати деталі" } } } }, - "commandPalette.subtitle.browserWithName": { + "common.dontSave": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Browser • %@" + "value": "Don't Save" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ブラウザ • %@" + "value": "保存しない" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "浏览器 • %@" + "value": "不存储" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "瀏覽器 • %@" + "value": "不儲存" } }, "ko": { "stringUnit": { "state": "translated", - "value": "브라우저 • %@" + "value": "저장 안 함" } }, "de": { "stringUnit": { "state": "translated", - "value": "Browser • %@" + "value": "Nicht sichern" } }, "es": { "stringUnit": { "state": "translated", - "value": "Navegador • %@" + "value": "No guardar" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Navigateur • %@" + "value": "Ne pas enregistrer" } }, "it": { "stringUnit": { "state": "translated", - "value": "Browser • %@" + "value": "Non salvare" } }, "da": { "stringUnit": { "state": "translated", - "value": "Browser • %@" + "value": "Gem ikke" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Przeglądarka • %@" + "value": "Nie zachowuj" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Браузер • %@" + "value": "Не сохранять" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Preglednik • %@" + "value": "Ne spremi" } }, "ar": { "stringUnit": { "state": "translated", - "value": "المتصفح • %@" + "value": "عدم الحفظ" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Nettleser • %@" + "value": "Ikke arkiver" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Navegador • %@" + "value": "Não Salvar" } }, "th": { "stringUnit": { "state": "translated", - "value": "เบราว์เซอร์ • %@" + "value": "ไม่บันทึก" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Tarayıcı • %@" + "value": "Kaydetme" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Браузер • %@" + "value": "Не зберігати" } } } }, - "commandPalette.subtitle.tabFallback": { + "common.installAndRelaunch": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Tab" + "value": "Install and Relaunch" } }, "ja": { "stringUnit": { "state": "translated", - "value": "タブ" + "value": "インストールして再起動" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "标签页" + "value": "安装并重新启动" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "標籤頁" + "value": "安裝並重新啟動" } }, "ko": { "stringUnit": { "state": "translated", - "value": "탭" + "value": "설치 후 재실행" } }, "de": { "stringUnit": { "state": "translated", - "value": "Tab" + "value": "Installieren und neu starten" } }, "es": { "stringUnit": { "state": "translated", - "value": "Pestaña" + "value": "Instalar y reiniciar" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Onglet" + "value": "Installer et relancer" } }, "it": { "stringUnit": { "state": "translated", - "value": "Scheda" + "value": "Installa e riavvia" } }, "da": { "stringUnit": { "state": "translated", - "value": "Fane" + "value": "Installer og genstart" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Karta" + "value": "Zainstaluj i uruchom ponownie" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Вкладка" + "value": "Установить и перезапустить" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Tab" + "value": "Instaliraj i ponovo pokreni" } }, "ar": { "stringUnit": { "state": "translated", - "value": "لسان" + "value": "تثبيت وإعادة التشغيل" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Fane" + "value": "Installer og start på nytt" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Aba" + "value": "Instalar e Reiniciar" } }, "th": { "stringUnit": { "state": "translated", - "value": "แท็บ" + "value": "ติดตั้งและเปิดใหม่" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Sekme" + "value": "Yükle ve Yeniden Başlat" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Вкладка" + "value": "Встановити та перезапустити" } } } }, - "commandPalette.subtitle.tabWithName": { + "common.later": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Tab • %@" + "value": "Later" } }, "ja": { "stringUnit": { "state": "translated", - "value": "タブ • %@" + "value": "後で" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "标签页 • %@" + "value": "稍后" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "標籤頁 • %@" + "value": "稍後" } }, "ko": { "stringUnit": { "state": "translated", - "value": "탭 • %@" + "value": "나중에" } }, "de": { "stringUnit": { "state": "translated", - "value": "Tab • %@" + "value": "Später" } }, "es": { "stringUnit": { "state": "translated", - "value": "Pestaña • %@" + "value": "Más tarde" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Onglet • %@" + "value": "Plus tard" } }, "it": { "stringUnit": { "state": "translated", - "value": "Scheda • %@" + "value": "Più tardi" } }, "da": { "stringUnit": { "state": "translated", - "value": "Fane • %@" + "value": "Senere" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Karta • %@" + "value": "Później" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Вкладка • %@" + "value": "Позже" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Tab • %@" + "value": "Kasnije" } }, "ar": { "stringUnit": { "state": "translated", - "value": "لسان • %@" + "value": "لاحقًا" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Fane • %@" + "value": "Senere" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Aba • %@" + "value": "Depois" } }, "th": { "stringUnit": { "state": "translated", - "value": "แท็บ • %@" + "value": "ภายหลัง" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Sekme • %@" + "value": "Daha Sonra" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Вкладка • %@" + "value": "Пізніше" } } } }, - "commandPalette.subtitle.terminalWithName": { + "common.notNow": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Terminal • %@" + "value": "Not Now" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ターミナル • %@" + "value": "今はしない" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "终端 • %@" + "value": "以后再说" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "終端機 • %@" + "value": "現在不要" } }, "ko": { "stringUnit": { "state": "translated", - "value": "터미널 • %@" + "value": "나중에" } }, "de": { "stringUnit": { "state": "translated", - "value": "Terminal • %@" + "value": "Nicht jetzt" } }, "es": { "stringUnit": { "state": "translated", - "value": "Terminal • %@" + "value": "Ahora no" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Terminal • %@" + "value": "Pas maintenant" } }, "it": { "stringUnit": { "state": "translated", - "value": "Terminale • %@" + "value": "Non ora" } }, "da": { "stringUnit": { "state": "translated", - "value": "Terminal • %@" + "value": "Ikke nu" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Terminal • %@" + "value": "Nie teraz" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Терминал • %@" + "value": "Не сейчас" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Terminal • %@" + "value": "Ne sada" } }, "ar": { "stringUnit": { "state": "translated", - "value": "الطرفية • %@" + "value": "ليس الآن" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Terminal • %@" + "value": "Ikke nå" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Terminal • %@" + "value": "Agora Não" } }, "th": { "stringUnit": { "state": "translated", - "value": "เทอร์มินัล • %@" + "value": "ไม่ใช่ตอนนี้" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Terminal • %@" + "value": "Şimdi Değil" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Термінал • %@" + "value": "Не зараз" } } } }, - "commandPalette.subtitle.workspaceFallback": { + "common.ok": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Workspace" + "value": "OK" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ワークスペース" + "value": "OK" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "工作区" + "value": "OK" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "工作區" + "value": "OK" } }, "ko": { "stringUnit": { "state": "translated", - "value": "작업 공간" + "value": "OK" } }, "de": { "stringUnit": { "state": "translated", - "value": "Arbeitsbereich" + "value": "OK" } }, "es": { "stringUnit": { "state": "translated", - "value": "Espacio de trabajo" + "value": "OK" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Espace de travail" + "value": "OK" } }, "it": { "stringUnit": { "state": "translated", - "value": "Area di lavoro" + "value": "OK" } }, "da": { "stringUnit": { "state": "translated", - "value": "Arbejdsområde" + "value": "OK" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Przestrzeń robocza" + "value": "OK" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Рабочее пространство" + "value": "OK" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Radni prostor" + "value": "OK" } }, "ar": { "stringUnit": { "state": "translated", - "value": "مساحة العمل" + "value": "OK" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Arbeidsområde" + "value": "OK" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Área de Trabalho" + "value": "OK" } }, "th": { "stringUnit": { "state": "translated", - "value": "เวิร์กสเปซ" + "value": "OK" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Çalışma Alanı" + "value": "Tamam" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Робоча область" + "value": "OK" } } } }, - "commandPalette.subtitle.workspaceWithName": { + "common.rename": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Workspace • %@" + "value": "Rename" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ワークスペース • %@" + "value": "名前を変更" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "工作区 • %@" + "value": "重命名" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "工作區 • %@" + "value": "重新命名" } }, "ko": { "stringUnit": { "state": "translated", - "value": "작업 공간 • %@" + "value": "이름 변경" } }, "de": { "stringUnit": { "state": "translated", - "value": "Arbeitsbereich • %@" + "value": "Umbenennen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Espacio de trabajo • %@" + "value": "Renombrar" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Espace de travail • %@" + "value": "Renommer" } }, "it": { "stringUnit": { "state": "translated", - "value": "Area di lavoro • %@" + "value": "Rinomina" } }, "da": { "stringUnit": { "state": "translated", - "value": "Arbejdsområde • %@" + "value": "Omdøb" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Przestrzeń robocza • %@" + "value": "Zmień nazwę" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Рабочее пространство • %@" + "value": "Переименовать" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Radni prostor • %@" + "value": "Preimenuj" } }, "ar": { "stringUnit": { "state": "translated", - "value": "مساحة العمل • %@" + "value": "إعادة تسمية" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Arbeidsområde • %@" + "value": "Gi nytt navn" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Área de Trabalho • %@" + "value": "Renomear" } }, "th": { "stringUnit": { "state": "translated", - "value": "เวิร์กสเปซ • %@" + "value": "เปลี่ยนชื่อ" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Çalışma Alanı • %@" + "value": "Yeniden Adlandır" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Робоча область • %@" + "value": "Перейменувати" } } } }, - "commandPalette.switcher.windowLabel": { + "common.restartLater": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Window %lld" + "value": "Restart Later" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ウインドウ %lld" + "value": "後で再起動" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "窗口 %lld" + "value": "稍后重启" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "視窗 %lld" + "value": "稍後重新啟動" } }, "ko": { "stringUnit": { "state": "translated", - "value": "윈도우 %lld" + "value": "나중에 재시작" } }, "de": { "stringUnit": { "state": "translated", - "value": "Fenster %lld" + "value": "Später neu starten" } }, "es": { "stringUnit": { "state": "translated", - "value": "Ventana %lld" + "value": "Reiniciar más tarde" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Fenêtre %lld" + "value": "Redémarrer plus tard" } }, "it": { "stringUnit": { "state": "translated", - "value": "Finestra %lld" + "value": "Riavvia più tardi" } }, "da": { "stringUnit": { "state": "translated", - "value": "Vindue %lld" + "value": "Genstart senere" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Okno %lld" + "value": "Uruchom ponownie później" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Окно %lld" + "value": "Перезапустить позже" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Prozor %lld" + "value": "Ponovo pokreni kasnije" } }, "ar": { "stringUnit": { "state": "translated", - "value": "النافذة %lld" + "value": "إعادة التشغيل لاحقًا" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Vindu %lld" + "value": "Start på nytt senere" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Janela %lld" + "value": "Reiniciar Depois" } }, "th": { "stringUnit": { "state": "translated", - "value": "หน้าต่าง %lld" + "value": "รีสตาร์ตภายหลัง" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Pencere %lld" + "value": "Daha Sonra Yeniden Başlat" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Вікно %lld" + "value": "Перезапустити пізніше" } } } }, - "commandPalette.switcher.workspaceLabel": { + "common.restartNow": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Workspace" + "value": "Restart Now" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ワークスペース" + "value": "今すぐ再起動" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "工作区" + "value": "立即重启" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "工作區" + "value": "立即重新啟動" } }, "ko": { "stringUnit": { "state": "translated", - "value": "작업 공간" + "value": "지금 재시작" } }, "de": { "stringUnit": { "state": "translated", - "value": "Arbeitsbereich" + "value": "Jetzt neu starten" } }, "es": { "stringUnit": { "state": "translated", - "value": "Espacio de trabajo" + "value": "Reiniciar ahora" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Espace de travail" + "value": "Redémarrer maintenant" } }, "it": { "stringUnit": { "state": "translated", - "value": "Area di lavoro" + "value": "Riavvia ora" } }, "da": { "stringUnit": { "state": "translated", - "value": "Arbejdsområde" + "value": "Genstart nu" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Przestrzeń robocza" + "value": "Uruchom ponownie teraz" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Рабочее пространство" + "value": "Перезапустить сейчас" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Radni prostor" + "value": "Ponovo pokreni sada" } }, "ar": { "stringUnit": { "state": "translated", - "value": "مساحة العمل" + "value": "إعادة التشغيل الآن" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Arbeidsområde" + "value": "Start på nytt nå" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Área de Trabalho" + "value": "Reiniciar Agora" } }, "th": { "stringUnit": { "state": "translated", - "value": "เวิร์กสเปซ" + "value": "รีสตาร์ตเดี๋ยวนี้" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Çalışma Alanı" + "value": "Şimdi Yeniden Başlat" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Робоча область" + "value": "Перезапустити зараз" } } } }, - "common.allow": { + "common.retry": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Allow" + "value": "Retry" } }, "ja": { "stringUnit": { "state": "translated", - "value": "許可" + "value": "再試行" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "允许" + "value": "重试" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "允許" + "value": "重試" } }, "ko": { "stringUnit": { "state": "translated", - "value": "허용" + "value": "재시도" } }, "de": { "stringUnit": { "state": "translated", - "value": "Erlauben" + "value": "Erneut versuchen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Permitir" + "value": "Reintentar" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Autoriser" + "value": "Réessayer" } }, "it": { "stringUnit": { "state": "translated", - "value": "Consenti" + "value": "Riprova" } }, "da": { "stringUnit": { "state": "translated", - "value": "Tillad" + "value": "Prøv igen" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Zezwól" + "value": "Ponów" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Разрешить" + "value": "Повторить" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Dozvoli" + "value": "Pokušaj ponovo" } }, "ar": { "stringUnit": { "state": "translated", - "value": "سماح" + "value": "إعادة المحاولة" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Tillat" + "value": "Prøv igjen" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Permitir" + "value": "Tentar Novamente" } }, "th": { "stringUnit": { "state": "translated", - "value": "อนุญาต" + "value": "ลองใหม่" } }, "tr": { "stringUnit": { "state": "translated", - "value": "İzin Ver" + "value": "Tekrar Dene" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Дозволити" + "value": "Повторити" } } } }, - "common.cancel": { + "common.skip": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Cancel" + "value": "Skip" } }, "ja": { "stringUnit": { "state": "translated", - "value": "キャンセル" + "value": "スキップ" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "取消" + "value": "跳过" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "取消" + "value": "略過" } }, "ko": { "stringUnit": { "state": "translated", - "value": "취소" + "value": "건너뛰기" } }, "de": { "stringUnit": { "state": "translated", - "value": "Abbrechen" + "value": "Überspringen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Cancelar" + "value": "Omitir" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Annuler" + "value": "Ignorer" } }, "it": { "stringUnit": { "state": "translated", - "value": "Annulla" + "value": "Salta" } }, "da": { "stringUnit": { "state": "translated", - "value": "Annuller" + "value": "Spring over" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Anuluj" + "value": "Pomiń" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Отменить" + "value": "Пропустить" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Otkaži" + "value": "Preskoči" } }, "ar": { "stringUnit": { "state": "translated", - "value": "إلغاء" + "value": "تخطي" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Avbryt" + "value": "Hopp over" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Cancelar" + "value": "Pular" } }, "th": { "stringUnit": { "state": "translated", - "value": "ยกเลิก" + "value": "ข้าม" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Vazgeç" - } - }, - "uk": { - "stringUnit": { - "state": "translated", - "value": "Скасувати" - } - } - } - }, - "common.create": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Create" - } - }, - "ja": { - "stringUnit": { - "state": "translated", - "value": "作成" + "value": "Atla" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Створити" - } - }, - "ko": { - "stringUnit": { - "state": "translated", - "value": "생성" + "value": "Пропустити" } } } }, - "common.close": { + "contextMenu.chooseCustomColor": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Close" + "value": "Choose Custom Color…" } }, "ja": { "stringUnit": { "state": "translated", - "value": "閉じる" + "value": "カスタムカラーを選択…" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "关闭" + "value": "选取自定义颜色..." } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "關閉" + "value": "選擇自訂顏色..." } }, "ko": { "stringUnit": { "state": "translated", - "value": "닫기" + "value": "사용자 지정 색상 선택…" } }, "de": { "stringUnit": { "state": "translated", - "value": "Schließen" + "value": "Eigene Farbe wählen …" } }, "es": { "stringUnit": { "state": "translated", - "value": "Cerrar" + "value": "Elegir color personalizado…" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Fermer" + "value": "Choisir une couleur personnalisée..." } }, "it": { "stringUnit": { "state": "translated", - "value": "Chiudi" + "value": "Scegli colore personalizzato…" } }, "da": { "stringUnit": { "state": "translated", - "value": "Luk" + "value": "Vælg brugerdefineret farve…" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Zamknij" + "value": "Wybierz własny kolor…" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Закрыть" + "value": "Выбрать пользовательский цвет..." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Zatvori" + "value": "Odaberi prilagođenu boju…" } }, "ar": { "stringUnit": { "state": "translated", - "value": "إغلاق" + "value": "اختيار لون مخصص…" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Lukk" + "value": "Velg egendefinert farge …" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Fechar" + "value": "Escolher Cor Personalizada…" } }, "th": { "stringUnit": { "state": "translated", - "value": "ปิด" + "value": "เลือกสีที่กำหนดเอง..." } }, "tr": { "stringUnit": { "state": "translated", - "value": "Kapat" + "value": "Özel Renk Seç…" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Закрити" + "value": "Вибрати власний колір…" } } } }, - "common.copyDetails": { + "contextMenu.clearColor": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Copy Details" + "value": "Clear Color" } }, "ja": { "stringUnit": { "state": "translated", - "value": "詳細をコピー" + "value": "カラーをクリア" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "拷贝详细信息" + "value": "清除颜色" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "拷貝詳細資訊" + "value": "清除顏色" } }, "ko": { "stringUnit": { "state": "translated", - "value": "세부 정보 복사" + "value": "색상 지우기" } }, "de": { "stringUnit": { "state": "translated", - "value": "Details kopieren" + "value": "Farbe entfernen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Copiar detalles" + "value": "Borrar color" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Copier les détails" + "value": "Effacer la couleur" } }, "it": { "stringUnit": { "state": "translated", - "value": "Copia dettagli" + "value": "Rimuovi colore" } }, "da": { "stringUnit": { "state": "translated", - "value": "Kopier detaljer" + "value": "Ryd farve" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Kopiuj szczegóły" + "value": "Wyczyść kolor" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Скопировать подробности" + "value": "Убрать цвет" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Kopiraj detalje" + "value": "Obriši boju" } }, "ar": { "stringUnit": { "state": "translated", - "value": "نسخ التفاصيل" + "value": "مسح اللون" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Kopier detaljer" + "value": "Fjern farge" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Copiar Detalhes" + "value": "Limpar Cor" } }, "th": { "stringUnit": { "state": "translated", - "value": "คัดลอกรายละเอียด" + "value": "ล้างสี" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Ayrıntıları Kopyala" + "value": "Rengi Temizle" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Копіювати деталі" + "value": "Скинути колір" } } } }, - "common.dontSave": { + "contextMenu.clearLatestNotification": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Don't Save" + "value": "Clear Latest Notification" } }, "ja": { "stringUnit": { "state": "translated", - "value": "保存しない" + "value": "最新の通知をクリア" + } + }, + "ko": { + "stringUnit": { + "state": "translated", + "value": "최근 알림 지우기" + } + } + } + }, + "contextMenu.clearLatestNotifications": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Clear Latest Notifications" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "最新の通知をクリア" + } + }, + "ko": { + "stringUnit": { + "state": "translated", + "value": "최근 알림 모두 지우기" + } + } + } + }, + "contextMenu.closeOtherWorkspaces": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Close Other Workspaces" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "他のワークスペースを閉じる" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "不存储" + "value": "关闭其他工作区" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "不儲存" + "value": "關閉其他工作區" } }, "ko": { "stringUnit": { "state": "translated", - "value": "저장 안 함" + "value": "다른 작업 공간 닫기" } }, "de": { "stringUnit": { "state": "translated", - "value": "Nicht sichern" + "value": "Andere Arbeitsbereiche schließen" } }, "es": { "stringUnit": { "state": "translated", - "value": "No guardar" + "value": "Cerrar otros espacios de trabajo" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Ne pas enregistrer" + "value": "Fermer les autres espaces de travail" } }, "it": { "stringUnit": { "state": "translated", - "value": "Non salvare" + "value": "Chiudi altre aree di lavoro" } }, "da": { "stringUnit": { "state": "translated", - "value": "Gem ikke" + "value": "Luk andre arbejdsområder" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Nie zachowuj" + "value": "Zamknij inne przestrzenie robocze" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Не сохранять" + "value": "Закрыть другие рабочие пространства" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Ne spremi" + "value": "Zatvori ostale radne prostore" } }, "ar": { "stringUnit": { "state": "translated", - "value": "عدم الحفظ" + "value": "إغلاق مساحات العمل الأخرى" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Ikke arkiver" + "value": "Lukk andre arbeidsområder" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Não Salvar" + "value": "Fechar Outras Áreas de Trabalho" } }, "th": { "stringUnit": { "state": "translated", - "value": "ไม่บันทึก" + "value": "ปิดเวิร์กสเปซอื่น" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Kaydetme" + "value": "Diğer Çalışma Alanlarını Kapat" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Не зберігати" + "value": "Закрити інші робочі області" } } } }, - "common.installAndRelaunch": { + "contextMenu.closeWorkspace": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Install and Relaunch" + "value": "Close Workspace" } }, "ja": { "stringUnit": { "state": "translated", - "value": "インストールして再起動" + "value": "ワークスペースを閉じる" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "安装并重新启动" + "value": "关闭工作区" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "安裝並重新啟動" + "value": "關閉工作區" } }, "ko": { "stringUnit": { "state": "translated", - "value": "설치 후 재실행" + "value": "작업 공간 닫기" } }, "de": { "stringUnit": { "state": "translated", - "value": "Installieren und neu starten" + "value": "Arbeitsbereich schließen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Instalar y reiniciar" + "value": "Cerrar espacio de trabajo" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Installer et relancer" + "value": "Fermer l'espace de travail" } }, "it": { "stringUnit": { "state": "translated", - "value": "Installa e riavvia" + "value": "Chiudi area di lavoro" } }, "da": { "stringUnit": { "state": "translated", - "value": "Installer og genstart" + "value": "Luk arbejdsområde" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Zainstaluj i uruchom ponownie" + "value": "Zamknij przestrzeń roboczą" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Установить и перезапустить" + "value": "Закрыть рабочее пространство" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Instaliraj i ponovo pokreni" + "value": "Zatvori radni prostor" } }, "ar": { "stringUnit": { "state": "translated", - "value": "تثبيت وإعادة التشغيل" + "value": "إغلاق مساحة العمل" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Installer og start på nytt" + "value": "Lukk arbeidsområde" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Instalar e Reiniciar" + "value": "Fechar Área de Trabalho" } }, "th": { "stringUnit": { "state": "translated", - "value": "ติดตั้งและเปิดใหม่" + "value": "ปิดเวิร์กสเปซ" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Yükle ve Yeniden Başlat" + "value": "Çalışma Alanını Kapat" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Встановити та перезапустити" + "value": "Закрити робочу область" } } } }, - "common.later": { + "contextMenu.closeWorkspaces": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Later" + "value": "Close Workspaces" } }, "ja": { "stringUnit": { "state": "translated", - "value": "後で" + "value": "ワークスペースを閉じる" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "稍后" + "value": "关闭工作区" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "稍後" + "value": "關閉工作區" } }, "ko": { "stringUnit": { "state": "translated", - "value": "나중에" + "value": "작업 공간 닫기" } }, "de": { "stringUnit": { "state": "translated", - "value": "Später" + "value": "Arbeitsbereiche schließen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Más tarde" + "value": "Cerrar espacios de trabajo" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Plus tard" + "value": "Fermer les espaces de travail" } }, "it": { "stringUnit": { "state": "translated", - "value": "Più tardi" + "value": "Chiudi aree di lavoro" } }, "da": { "stringUnit": { "state": "translated", - "value": "Senere" + "value": "Luk arbejdsområder" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Później" + "value": "Zamknij przestrzenie robocze" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Позже" + "value": "Закрыть рабочие пространства" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Kasnije" + "value": "Zatvori radne prostore" } }, "ar": { "stringUnit": { "state": "translated", - "value": "لاحقًا" + "value": "إغلاق مساحات العمل" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Senere" + "value": "Lukk arbeidsområder" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Depois" + "value": "Fechar Áreas de Trabalho" } }, "th": { "stringUnit": { "state": "translated", - "value": "ภายหลัง" + "value": "ปิดเวิร์กสเปซ" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Daha Sonra" + "value": "Çalışma Alanlarını Kapat" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Пізніше" + "value": "Закрити робочі області" } } } }, - "common.notNow": { + "contextMenu.closeWorkspacesAbove": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Not Now" + "value": "Close Workspaces Above" } }, "ja": { "stringUnit": { "state": "translated", - "value": "今はしない" + "value": "上のワークスペースを閉じる" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "以后再说" + "value": "关闭上方工作区" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "現在不要" + "value": "關閉上方的工作區" } }, "ko": { "stringUnit": { "state": "translated", - "value": "나중에" + "value": "위쪽 작업 공간 닫기" } }, "de": { "stringUnit": { "state": "translated", - "value": "Nicht jetzt" + "value": "Arbeitsbereiche darüber schließen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Ahora no" + "value": "Cerrar espacios de trabajo superiores" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Pas maintenant" + "value": "Fermer les espaces de travail au-dessus" } }, "it": { "stringUnit": { "state": "translated", - "value": "Non ora" + "value": "Chiudi aree di lavoro sopra" } }, "da": { "stringUnit": { "state": "translated", - "value": "Ikke nu" + "value": "Luk arbejdsområder ovenfor" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Nie teraz" + "value": "Zamknij przestrzenie robocze powyżej" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Не сейчас" + "value": "Закрыть рабочие пространства выше" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Ne sada" + "value": "Zatvori radne prostore iznad" } }, "ar": { "stringUnit": { "state": "translated", - "value": "ليس الآن" + "value": "إغلاق مساحات العمل أعلاه" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Ikke nå" + "value": "Lukk arbeidsområder over" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Agora Não" + "value": "Fechar Áreas de Trabalho Acima" } }, "th": { "stringUnit": { "state": "translated", - "value": "ไม่ใช่ตอนนี้" + "value": "ปิดเวิร์กสเปซด้านบน" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Şimdi Değil" + "value": "Yukarıdaki Çalışma Alanlarını Kapat" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Не зараз" + "value": "Закрити робочі області вище" } } } }, - "common.ok": { + "contextMenu.closeWorkspacesBelow": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "OK" + "value": "Close Workspaces Below" } }, "ja": { "stringUnit": { "state": "translated", - "value": "OK" + "value": "下のワークスペースを閉じる" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "OK" + "value": "关闭下方工作区" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "OK" + "value": "關閉下方的工作區" } }, "ko": { "stringUnit": { "state": "translated", - "value": "OK" + "value": "아래쪽 작업 공간 닫기" } }, "de": { "stringUnit": { "state": "translated", - "value": "OK" + "value": "Arbeitsbereiche darunter schließen" } }, "es": { "stringUnit": { "state": "translated", - "value": "OK" + "value": "Cerrar espacios de trabajo inferiores" } }, "fr": { "stringUnit": { "state": "translated", - "value": "OK" + "value": "Fermer les espaces de travail en dessous" } }, "it": { "stringUnit": { "state": "translated", - "value": "OK" + "value": "Chiudi aree di lavoro sotto" } }, "da": { "stringUnit": { "state": "translated", - "value": "OK" + "value": "Luk arbejdsområder nedenfor" } }, "pl": { "stringUnit": { "state": "translated", - "value": "OK" + "value": "Zamknij przestrzenie robocze poniżej" } }, "ru": { "stringUnit": { "state": "translated", - "value": "OK" + "value": "Закрыть рабочие пространства ниже" } }, "bs": { "stringUnit": { "state": "translated", - "value": "OK" + "value": "Zatvori radne prostore ispod" } }, "ar": { "stringUnit": { "state": "translated", - "value": "OK" + "value": "إغلاق مساحات العمل أدناه" } }, "nb": { "stringUnit": { "state": "translated", - "value": "OK" + "value": "Lukk arbeidsområder under" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "OK" + "value": "Fechar Áreas de Trabalho Abaixo" } }, "th": { "stringUnit": { "state": "translated", - "value": "OK" + "value": "ปิดเวิร์กสเปซด้านล่าง" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Tamam" + "value": "Aşağıdaki Çalışma Alanlarını Kapat" } }, "uk": { "stringUnit": { "state": "translated", - "value": "OK" + "value": "Закрити робочі області нижче" } } } }, - "common.rename": { + "contextMenu.markWorkspaceRead": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Rename" + "value": "Mark Workspace as Read" } }, "ja": { "stringUnit": { "state": "translated", - "value": "名前を変更" + "value": "ワークスペースを既読にする" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "重命名" + "value": "将工作区标记为已读" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "重新命名" + "value": "將工作區標為已讀" } }, "ko": { "stringUnit": { "state": "translated", - "value": "이름 변경" + "value": "작업 공간을 읽음으로 표시" } }, "de": { "stringUnit": { "state": "translated", - "value": "Umbenennen" + "value": "Arbeitsbereich als gelesen markieren" } }, "es": { "stringUnit": { "state": "translated", - "value": "Renombrar" + "value": "Marcar espacio de trabajo como leído" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Renommer" + "value": "Marquer l'espace de travail comme lu" } }, "it": { "stringUnit": { "state": "translated", - "value": "Rinomina" + "value": "Segna area di lavoro come letta" } }, "da": { "stringUnit": { "state": "translated", - "value": "Omdøb" + "value": "Marker arbejdsområde som læst" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Zmień nazwę" + "value": "Oznacz przestrzeń roboczą jako przeczytaną" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Переименовать" + "value": "Отметить рабочее пространство как прочитанное" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Preimenuj" + "value": "Označi radni prostor kao pročitan" } }, "ar": { "stringUnit": { "state": "translated", - "value": "إعادة تسمية" + "value": "تعليم مساحة العمل كمقروءة" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Gi nytt navn" + "value": "Merk arbeidsområde som lest" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Renomear" + "value": "Marcar Área de Trabalho como Lida" } }, "th": { "stringUnit": { "state": "translated", - "value": "เปลี่ยนชื่อ" + "value": "ทำเครื่องหมายเวิร์กสเปซว่าอ่านแล้ว" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Yeniden Adlandır" + "value": "Çalışma Alanını Okundu Olarak İşaretle" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Перейменувати" + "value": "Позначити робочу область як прочитану" } } } }, - "common.restartLater": { + "contextMenu.markWorkspaceUnread": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Restart Later" + "value": "Mark Workspace as Unread" } }, "ja": { "stringUnit": { "state": "translated", - "value": "後で再起動" + "value": "ワークスペースを未読にする" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "稍后重启" + "value": "将工作区标记为未读" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "稍後重新啟動" + "value": "將工作區標為未讀" } }, "ko": { "stringUnit": { "state": "translated", - "value": "나중에 재시작" + "value": "작업 공간을 읽지 않음으로 표시" } }, "de": { "stringUnit": { "state": "translated", - "value": "Später neu starten" + "value": "Arbeitsbereich als ungelesen markieren" } }, "es": { "stringUnit": { "state": "translated", - "value": "Reiniciar más tarde" + "value": "Marcar espacio de trabajo como no leído" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Redémarrer plus tard" + "value": "Marquer l'espace de travail comme non lu" } }, "it": { "stringUnit": { "state": "translated", - "value": "Riavvia più tardi" + "value": "Segna area di lavoro come non letta" } }, "da": { "stringUnit": { "state": "translated", - "value": "Genstart senere" + "value": "Marker arbejdsområde som ulæst" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Uruchom ponownie później" + "value": "Oznacz przestrzeń roboczą jako nieprzeczytaną" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Перезапустить позже" + "value": "Отметить рабочее пространство как непрочитанное" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Ponovo pokreni kasnije" + "value": "Označi radni prostor kao nepročitan" } }, "ar": { "stringUnit": { "state": "translated", - "value": "إعادة التشغيل لاحقًا" + "value": "تعليم مساحة العمل كغير مقروءة" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Start på nytt senere" + "value": "Merk arbeidsområde som ulest" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Reiniciar Depois" + "value": "Marcar Área de Trabalho como Não Lida" } }, "th": { "stringUnit": { "state": "translated", - "value": "รีสตาร์ตภายหลัง" + "value": "ทำเครื่องหมายเวิร์กสเปซว่ายังไม่อ่าน" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Daha Sonra Yeniden Başlat" + "value": "Çalışma Alanını Okunmadı Olarak İşaretle" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Перезапустити пізніше" + "value": "Позначити робочу область як непрочитану" } } } }, - "common.restartNow": { + "contextMenu.markWorkspacesRead": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Restart Now" + "value": "Mark Workspaces as Read" } }, "ja": { "stringUnit": { "state": "translated", - "value": "今すぐ再起動" + "value": "ワークスペースを既読にする" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "立即重启" + "value": "将工作区标记为已读" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "立即重新啟動" + "value": "將工作區標為已讀" } }, "ko": { "stringUnit": { "state": "translated", - "value": "지금 재시작" + "value": "작업 공간을 읽음으로 표시" } }, "de": { "stringUnit": { "state": "translated", - "value": "Jetzt neu starten" + "value": "Arbeitsbereiche als gelesen markieren" } }, "es": { "stringUnit": { "state": "translated", - "value": "Reiniciar ahora" + "value": "Marcar espacios de trabajo como leídos" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Redémarrer maintenant" + "value": "Marquer les espaces de travail comme lus" } }, "it": { "stringUnit": { "state": "translated", - "value": "Riavvia ora" + "value": "Segna aree di lavoro come lette" } }, "da": { "stringUnit": { "state": "translated", - "value": "Genstart nu" + "value": "Marker arbejdsområder som læste" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Uruchom ponownie teraz" + "value": "Oznacz przestrzenie robocze jako przeczytane" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Перезапустить сейчас" + "value": "Отметить рабочие пространства как прочитанные" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Ponovo pokreni sada" + "value": "Označi radne prostore kao pročitane" } }, "ar": { "stringUnit": { "state": "translated", - "value": "إعادة التشغيل الآن" + "value": "تعليم مساحات العمل كمقروءة" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Start på nytt nå" + "value": "Merk arbeidsområder som lest" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Reiniciar Agora" + "value": "Marcar Áreas de Trabalho como Lidas" } }, "th": { "stringUnit": { "state": "translated", - "value": "รีสตาร์ตเดี๋ยวนี้" + "value": "ทำเครื่องหมายเวิร์กสเปซว่าอ่านแล้ว" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Şimdi Yeniden Başlat" + "value": "Çalışma Alanlarını Okundu Olarak İşaretle" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Перезапустити зараз" + "value": "Позначити робочі області як прочитані" } } } }, - "common.retry": { + "contextMenu.markWorkspacesUnread": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Retry" + "value": "Mark Workspaces as Unread" } }, "ja": { "stringUnit": { "state": "translated", - "value": "再試行" + "value": "ワークスペースを未読にする" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "重试" + "value": "将工作区标记为未读" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "重試" + "value": "將工作區標為未讀" } }, "ko": { "stringUnit": { "state": "translated", - "value": "재시도" + "value": "작업 공간을 읽지 않음으로 표시" } }, "de": { "stringUnit": { "state": "translated", - "value": "Erneut versuchen" + "value": "Arbeitsbereiche als ungelesen markieren" } }, "es": { "stringUnit": { "state": "translated", - "value": "Reintentar" + "value": "Marcar espacios de trabajo como no leídos" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Réessayer" + "value": "Marquer les espaces de travail comme non lus" } }, "it": { "stringUnit": { "state": "translated", - "value": "Riprova" + "value": "Segna aree di lavoro come non lette" } }, "da": { "stringUnit": { "state": "translated", - "value": "Prøv igen" + "value": "Marker arbejdsområder som ulæste" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Ponów" + "value": "Oznacz przestrzenie robocze jako nieprzeczytane" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Повторить" + "value": "Отметить рабочие пространства как непрочитанные" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Pokušaj ponovo" + "value": "Označi radne prostore kao nepročitane" } }, "ar": { "stringUnit": { "state": "translated", - "value": "إعادة المحاولة" + "value": "تعليم مساحات العمل كغير مقروءة" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Prøv igjen" + "value": "Merk arbeidsområder som ulest" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Tentar Novamente" + "value": "Marcar Áreas de Trabalho como Não Lidas" } }, "th": { "stringUnit": { "state": "translated", - "value": "ลองใหม่" + "value": "ทำเครื่องหมายเวิร์กสเปซว่ายังไม่อ่าน" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Tekrar Dene" + "value": "Çalışma Alanlarını Okunmadı Olarak İşaretle" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Повторити" + "value": "Позначити робочі області як непрочитані" } } } }, - "common.skip": { + "contextMenu.copyError": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Skip" + "value": "Copy Error" } }, "ja": { "stringUnit": { "state": "translated", - "value": "スキップ" + "value": "エラーをコピー" } }, - "zh-Hans": { + "uk": { "stringUnit": { "state": "translated", - "value": "跳过" + "value": "Копіювати помилку" } }, - "zh-Hant": { + "ko": { "stringUnit": { "state": "translated", - "value": "略過" + "value": "오류 복사" + } + } + } + }, + "contextMenu.copyErrors": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Copy Errors" } }, - "ko": { + "ja": { "stringUnit": { "state": "translated", - "value": "건너뛰기" + "value": "エラーをコピー" } }, - "de": { + "uk": { "stringUnit": { "state": "translated", - "value": "Überspringen" + "value": "Копіювати помилки" } }, - "es": { + "ko": { "stringUnit": { "state": "translated", - "value": "Omitir" + "value": "오류 모두 복사" + } + } + } + }, + "clipboard.sshError.item": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "%lld. %@ (%@): %@" } }, - "fr": { + "ja": { "stringUnit": { "state": "translated", - "value": "Ignorer" + "value": "%lld. %@ (%@): %@" } }, - "it": { + "uk": { "stringUnit": { "state": "translated", - "value": "Salta" + "value": "%lld. %@ (%@): %@" } }, - "da": { + "ko": { "stringUnit": { "state": "translated", - "value": "Spring over" + "value": "%lld. %@ (%@): %@" + } + } + } + }, + "clipboard.sshError.single": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "SSH error (%@): %@" } }, - "pl": { + "ja": { "stringUnit": { "state": "translated", - "value": "Pomiń" + "value": "SSH エラー (%@): %@" } }, - "ru": { + "uk": { "stringUnit": { "state": "translated", - "value": "Пропустить" + "value": "Помилка SSH (%@): %@" } }, - "bs": { + "ko": { "stringUnit": { "state": "translated", - "value": "Preskoči" + "value": "SSH 오류 (%@): %@" + } + } + } + }, + "contextMenu.copySshError": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Copy SSH Error" } }, - "ar": { + "ja": { "stringUnit": { "state": "translated", - "value": "تخطي" + "value": "SSHエラーをコピー" } }, - "nb": { + "uk": { "stringUnit": { "state": "translated", - "value": "Hopp over" + "value": "Копіювати помилку SSH" } }, - "pt-BR": { + "ko": { "stringUnit": { "state": "translated", - "value": "Pular" + "value": "SSH 오류 복사" + } + } + } + }, + "contextMenu.copyWorkspaceID": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Copy Workspace ID" } }, - "th": { + "ja": { "stringUnit": { "state": "translated", - "value": "ข้าม" + "value": "ワークスペースIDをコピー" } }, - "tr": { + "ko": { "stringUnit": { "state": "translated", - "value": "Atla" + "value": "워크스페이스 ID 복사" + } + } + } + }, + "contextMenu.copyWorkspaceIDs": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Copy Workspace IDs" } }, - "uk": { + "ja": { "stringUnit": { "state": "translated", - "value": "Пропустити" + "value": "ワークスペースIDをコピー" + } + }, + "ko": { + "stringUnit": { + "state": "translated", + "value": "워크스페이스 ID 복사" } } } }, - "contextMenu.chooseCustomColor": { + "contextMenu.moveDown": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Choose Custom Color…" + "value": "Move Down" } }, "ja": { "stringUnit": { "state": "translated", - "value": "カスタムカラーを選択…" + "value": "下に移動" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "选取自定义颜色..." + "value": "下移" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "選擇自訂顏色..." + "value": "下移" } }, "ko": { "stringUnit": { "state": "translated", - "value": "사용자 지정 색상 선택…" + "value": "아래로 이동" } }, "de": { "stringUnit": { "state": "translated", - "value": "Eigene Farbe wählen …" + "value": "Nach unten bewegen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Elegir color personalizado…" + "value": "Mover hacia abajo" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Choisir une couleur personnalisée..." + "value": "Déplacer vers le bas" } }, "it": { "stringUnit": { "state": "translated", - "value": "Scegli colore personalizzato…" + "value": "Sposta in basso" } }, "da": { "stringUnit": { "state": "translated", - "value": "Vælg brugerdefineret farve…" + "value": "Flyt ned" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Wybierz własny kolor…" + "value": "Przenieś w dół" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Выбрать пользовательский цвет..." + "value": "Переместить вниз" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Odaberi prilagođenu boju…" + "value": "Pomjeri dolje" } }, "ar": { "stringUnit": { "state": "translated", - "value": "اختيار لون مخصص…" + "value": "نقل للأسفل" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Velg egendefinert farge …" + "value": "Flytt ned" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Escolher Cor Personalizada…" + "value": "Mover para Baixo" } }, "th": { "stringUnit": { "state": "translated", - "value": "เลือกสีที่กำหนดเอง..." + "value": "เลื่อนลง" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Özel Renk Seç…" + "value": "Aşağı Taşı" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Вибрати власний колір…" + "value": "Перемістити вниз" } } } }, - "contextMenu.clearColor": { + "contextMenu.moveToTop": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Clear Color" + "value": "Move to Top" } }, "ja": { "stringUnit": { "state": "translated", - "value": "カラーをクリア" + "value": "一番上に移動" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "清除颜色" + "value": "移到顶部" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "清除顏色" + "value": "移至最上方" } }, "ko": { "stringUnit": { "state": "translated", - "value": "색상 지우기" + "value": "맨 위로 이동" } }, "de": { "stringUnit": { "state": "translated", - "value": "Farbe entfernen" + "value": "Nach oben bewegen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Borrar color" + "value": "Mover al inicio" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Effacer la couleur" + "value": "Déplacer en haut" } }, "it": { "stringUnit": { "state": "translated", - "value": "Rimuovi colore" + "value": "Sposta in cima" } }, "da": { "stringUnit": { "state": "translated", - "value": "Ryd farve" + "value": "Flyt til toppen" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Wyczyść kolor" + "value": "Przenieś na górę" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Убрать цвет" + "value": "Переместить наверх" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Obriši boju" + "value": "Pomjeri na vrh" } }, "ar": { "stringUnit": { "state": "translated", - "value": "مسح اللون" + "value": "نقل إلى الأعلى" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Fjern farge" + "value": "Flytt til toppen" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Limpar Cor" + "value": "Mover para o Topo" } }, "th": { "stringUnit": { "state": "translated", - "value": "ล้างสี" + "value": "ย้ายไปด้านบน" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Rengi Temizle" + "value": "En Üste Taşı" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Скинути колір" + "value": "Перемістити на початок" } } } }, - "contextMenu.clearLatestNotification": { + "contextMenu.moveUp": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Clear Latest Notification" + "value": "Move Up" } }, "ja": { "stringUnit": { "state": "translated", - "value": "最新の通知をクリア" + "value": "上に移動" } }, - "ko": { - "stringUnit": { - "state": "translated", - "value": "최근 알림 지우기" - } - } - } - }, - "contextMenu.clearLatestNotifications": { - "extractionState": "manual", - "localizations": { - "en": { + "zh-Hans": { "stringUnit": { "state": "translated", - "value": "Clear Latest Notifications" + "value": "上移" } }, - "ja": { + "zh-Hant": { "stringUnit": { "state": "translated", - "value": "最新の通知をクリア" + "value": "上移" } }, "ko": { "stringUnit": { "state": "translated", - "value": "최근 알림 모두 지우기" + "value": "위로 이동" } - } - } - }, - "contextMenu.closeOtherWorkspaces": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "de": { "stringUnit": { "state": "translated", - "value": "Close Other Workspaces" + "value": "Nach oben bewegen" } }, - "ja": { + "es": { "stringUnit": { "state": "translated", - "value": "他のワークスペースを閉じる" + "value": "Mover hacia arriba" } }, - "zh-Hans": { + "fr": { "stringUnit": { "state": "translated", - "value": "关闭其他工作区" + "value": "Déplacer vers le haut" } }, - "zh-Hant": { + "it": { "stringUnit": { "state": "translated", - "value": "關閉其他工作區" - } - }, - "ko": { - "stringUnit": { - "state": "translated", - "value": "다른 작업 공간 닫기" - } - }, - "de": { - "stringUnit": { - "state": "translated", - "value": "Andere Arbeitsbereiche schließen" - } - }, - "es": { - "stringUnit": { - "state": "translated", - "value": "Cerrar otros espacios de trabajo" - } - }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "Fermer les autres espaces de travail" - } - }, - "it": { - "stringUnit": { - "state": "translated", - "value": "Chiudi altre aree di lavoro" + "value": "Sposta in alto" } }, "da": { "stringUnit": { "state": "translated", - "value": "Luk andre arbejdsområder" + "value": "Flyt op" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Zamknij inne przestrzenie robocze" + "value": "Przenieś w górę" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Закрыть другие рабочие пространства" + "value": "Переместить вверх" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Zatvori ostale radne prostore" + "value": "Pomjeri gore" } }, "ar": { "stringUnit": { "state": "translated", - "value": "إغلاق مساحات العمل الأخرى" + "value": "نقل للأعلى" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Lukk andre arbeidsområder" + "value": "Flytt opp" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Fechar Outras Áreas de Trabalho" + "value": "Mover para Cima" } }, "th": { "stringUnit": { "state": "translated", - "value": "ปิดเวิร์กสเปซอื่น" + "value": "เลื่อนขึ้น" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Diğer Çalışma Alanlarını Kapat" + "value": "Yukarı Taşı" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Закрити інші робочі області" + "value": "Перемістити вгору" } } } }, - "contextMenu.closeWorkspace": { + "contextMenu.moveWorkspaceToWindow": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Close Workspace" + "value": "Move Workspace to Window" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ワークスペースを閉じる" + "value": "ワークスペースをウインドウに移動" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "关闭工作区" + "value": "将工作区移到窗口" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "關閉工作區" + "value": "將工作區移至視窗" } }, "ko": { "stringUnit": { "state": "translated", - "value": "작업 공간 닫기" + "value": "작업 공간을 윈도우로 이동" } }, "de": { "stringUnit": { "state": "translated", - "value": "Arbeitsbereich schließen" + "value": "Arbeitsbereich in Fenster bewegen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Cerrar espacio de trabajo" + "value": "Mover espacio de trabajo a ventana" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Fermer l'espace de travail" + "value": "Déplacer l'espace de travail vers une fenêtre" } }, "it": { "stringUnit": { "state": "translated", - "value": "Chiudi area di lavoro" + "value": "Sposta area di lavoro in una finestra" } }, "da": { "stringUnit": { "state": "translated", - "value": "Luk arbejdsområde" + "value": "Flyt arbejdsområde til vindue" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Zamknij przestrzeń roboczą" + "value": "Przenieś przestrzeń roboczą do okna" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Закрыть рабочее пространство" + "value": "Переместить рабочее пространство в окно" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Zatvori radni prostor" + "value": "Premjesti radni prostor u prozor" } }, "ar": { "stringUnit": { "state": "translated", - "value": "إغلاق مساحة العمل" + "value": "نقل مساحة العمل إلى نافذة" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Lukk arbeidsområde" + "value": "Flytt arbeidsområde til vindu" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Fechar Área de Trabalho" + "value": "Mover Área de Trabalho para Janela" } }, "th": { "stringUnit": { "state": "translated", - "value": "ปิดเวิร์กสเปซ" + "value": "ย้ายเวิร์กสเปซไปยังหน้าต่าง" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Çalışma Alanını Kapat" + "value": "Çalışma Alanını Pencereye Taşı" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Закрити робочу область" + "value": "Перемістити робочу область у вікно" } } } }, - "contextMenu.closeWorkspaces": { + "contextMenu.moveWorkspacesToWindow": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Close Workspaces" + "value": "Move Workspaces to Window" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ワークスペースを閉じる" + "value": "ワークスペースをウインドウに移動" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "关闭工作区" + "value": "将工作区移到窗口" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "關閉工作區" + "value": "將工作區移至視窗" } }, "ko": { "stringUnit": { "state": "translated", - "value": "작업 공간 닫기" + "value": "작업 공간을 윈도우로 이동" } }, "de": { "stringUnit": { "state": "translated", - "value": "Arbeitsbereiche schließen" + "value": "Arbeitsbereiche in Fenster bewegen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Cerrar espacios de trabajo" + "value": "Mover espacios de trabajo a ventana" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Fermer les espaces de travail" + "value": "Déplacer les espaces de travail vers une fenêtre" } }, "it": { "stringUnit": { "state": "translated", - "value": "Chiudi aree di lavoro" + "value": "Sposta aree di lavoro in una finestra" } }, "da": { "stringUnit": { "state": "translated", - "value": "Luk arbejdsområder" + "value": "Flyt arbejdsområder til vindue" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Zamknij przestrzenie robocze" + "value": "Przenieś przestrzenie robocze do okna" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Закрыть рабочие пространства" + "value": "Переместить рабочие пространства в окно" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Zatvori radne prostore" + "value": "Premjesti radne prostore u prozor" } }, "ar": { "stringUnit": { "state": "translated", - "value": "إغلاق مساحات العمل" + "value": "نقل مساحات العمل إلى نافذة" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Lukk arbeidsområder" + "value": "Flytt arbeidsområder til vindu" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Fechar Áreas de Trabalho" + "value": "Mover Áreas de Trabalho para Janela" } }, "th": { "stringUnit": { "state": "translated", - "value": "ปิดเวิร์กสเปซ" + "value": "ย้ายเวิร์กสเปซไปยังหน้าต่าง" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Çalışma Alanlarını Kapat" + "value": "Çalışma Alanlarını Pencereye Taşı" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Закрити робочі області" + "value": "Перемістити робочі області у вікно" } } } }, - "contextMenu.closeWorkspacesAbove": { + "contextMenu.newWindow": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Close Workspaces Above" + "value": "New Window" } }, "ja": { "stringUnit": { "state": "translated", - "value": "上のワークスペースを閉じる" + "value": "新規ウインドウ" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "关闭上方工作区" + "value": "新建窗口" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "關閉上方的工作區" + "value": "新增視窗" } }, "ko": { "stringUnit": { "state": "translated", - "value": "위쪽 작업 공간 닫기" + "value": "새 윈도우" } }, "de": { "stringUnit": { "state": "translated", - "value": "Arbeitsbereiche darüber schließen" + "value": "Neues Fenster" } }, "es": { "stringUnit": { "state": "translated", - "value": "Cerrar espacios de trabajo superiores" + "value": "Nueva ventana" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Fermer les espaces de travail au-dessus" + "value": "Nouvelle fenêtre" } }, "it": { "stringUnit": { "state": "translated", - "value": "Chiudi aree di lavoro sopra" + "value": "Nuova finestra" } }, "da": { "stringUnit": { "state": "translated", - "value": "Luk arbejdsområder ovenfor" + "value": "Nyt vindue" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Zamknij przestrzenie robocze powyżej" + "value": "Nowe okno" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Закрыть рабочие пространства выше" + "value": "Новое окно" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Zatvori radne prostore iznad" + "value": "Novi prozor" } }, "ar": { "stringUnit": { "state": "translated", - "value": "إغلاق مساحات العمل أعلاه" + "value": "نافذة جديدة" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Lukk arbeidsområder over" + "value": "Nytt vindu" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Fechar Áreas de Trabalho Acima" + "value": "Nova Janela" } }, "th": { "stringUnit": { "state": "translated", - "value": "ปิดเวิร์กสเปซด้านบน" + "value": "หน้าต่างใหม่" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Yukarıdaki Çalışma Alanlarını Kapat" + "value": "Yeni Pencere" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Закрити робочі області вище" + "value": "Нове вікно" } } } }, - "contextMenu.closeWorkspacesBelow": { + "contextMenu.pinWorkspace": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Close Workspaces Below" + "value": "Pin Workspace" } }, "ja": { "stringUnit": { "state": "translated", - "value": "下のワークスペースを閉じる" + "value": "ワークスペースをピンで固定" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "关闭下方工作区" + "value": "固定工作区" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "關閉下方的工作區" + "value": "釘選工作區" } }, "ko": { "stringUnit": { "state": "translated", - "value": "아래쪽 작업 공간 닫기" + "value": "작업 공간 고정" } }, "de": { "stringUnit": { "state": "translated", - "value": "Arbeitsbereiche darunter schließen" + "value": "Arbeitsbereich anheften" } }, "es": { "stringUnit": { "state": "translated", - "value": "Cerrar espacios de trabajo inferiores" + "value": "Fijar espacio de trabajo" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Fermer les espaces de travail en dessous" + "value": "Épingler l'espace de travail" } }, "it": { "stringUnit": { "state": "translated", - "value": "Chiudi aree di lavoro sotto" + "value": "Fissa area di lavoro" } }, "da": { "stringUnit": { "state": "translated", - "value": "Luk arbejdsområder nedenfor" + "value": "Fastgør arbejdsområde" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Zamknij przestrzenie robocze poniżej" + "value": "Przypnij przestrzeń roboczą" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Закрыть рабочие пространства ниже" + "value": "Закрепить рабочее пространство" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Zatvori radne prostore ispod" + "value": "Zakači radni prostor" } }, "ar": { "stringUnit": { "state": "translated", - "value": "إغلاق مساحات العمل أدناه" + "value": "تثبيت مساحة العمل" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Lukk arbeidsområder under" + "value": "Fest arbeidsområde" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Fechar Áreas de Trabalho Abaixo" + "value": "Fixar Área de Trabalho" } }, "th": { "stringUnit": { "state": "translated", - "value": "ปิดเวิร์กสเปซด้านล่าง" + "value": "ปักหมุดเวิร์กสเปซ" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Aşağıdaki Çalışma Alanlarını Kapat" + "value": "Çalışma Alanını Sabitle" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Закрити робочі області нижче" + "value": "Закріпити робочу область" } } } }, - "contextMenu.markWorkspaceRead": { + "contextMenu.pinWorkspaces": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Mark Workspace as Read" + "value": "Pin Workspaces" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ワークスペースを既読にする" + "value": "ワークスペースをピンで固定" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "将工作区标记为已读" + "value": "固定工作区" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "將工作區標為已讀" + "value": "釘選工作區" } }, "ko": { "stringUnit": { "state": "translated", - "value": "작업 공간을 읽음으로 표시" + "value": "작업 공간 고정" } }, "de": { "stringUnit": { "state": "translated", - "value": "Arbeitsbereich als gelesen markieren" + "value": "Arbeitsbereiche anheften" } }, "es": { "stringUnit": { "state": "translated", - "value": "Marcar espacio de trabajo como leído" + "value": "Fijar espacios de trabajo" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Marquer l'espace de travail comme lu" + "value": "Épingler les espaces de travail" } }, "it": { "stringUnit": { "state": "translated", - "value": "Segna area di lavoro come letta" + "value": "Fissa aree di lavoro" } }, "da": { "stringUnit": { "state": "translated", - "value": "Marker arbejdsområde som læst" + "value": "Fastgør arbejdsområder" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Oznacz przestrzeń roboczą jako przeczytaną" + "value": "Przypnij przestrzenie robocze" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Отметить рабочее пространство как прочитанное" + "value": "Закрепить рабочие пространства" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Označi radni prostor kao pročitan" + "value": "Zakači radne prostore" } }, "ar": { "stringUnit": { "state": "translated", - "value": "تعليم مساحة العمل كمقروءة" + "value": "تثبيت مساحات العمل" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Merk arbeidsområde som lest" + "value": "Fest arbeidsområder" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Marcar Área de Trabalho como Lida" + "value": "Fixar Áreas de Trabalho" } }, "th": { "stringUnit": { "state": "translated", - "value": "ทำเครื่องหมายเวิร์กสเปซว่าอ่านแล้ว" + "value": "ปักหมุดเวิร์กสเปซ" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Çalışma Alanını Okundu Olarak İşaretle" + "value": "Çalışma Alanlarını Sabitle" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Позначити робочу область як прочитану" + "value": "Закріпити робочі області" } } } }, - "contextMenu.markWorkspaceUnread": { + "contextMenu.removeCustomWorkspaceName": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Mark Workspace as Unread" + "value": "Remove Custom Workspace Name" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ワークスペースを未読にする" + "value": "カスタムワークスペース名を削除" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "将工作区标记为未读" + "value": "移除自定义工作区名称" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "將工作區標為未讀" + "value": "移除自訂工作區名稱" } }, "ko": { "stringUnit": { "state": "translated", - "value": "작업 공간을 읽지 않음으로 표시" + "value": "사용자 지정 작업 공간 이름 제거" } }, "de": { "stringUnit": { "state": "translated", - "value": "Arbeitsbereich als ungelesen markieren" + "value": "Benutzerdefinierten Arbeitsbereichsnamen entfernen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Marcar espacio de trabajo como no leído" + "value": "Eliminar nombre personalizado del espacio de trabajo" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Marquer l'espace de travail comme non lu" + "value": "Supprimer le nom personnalisé de l'espace de travail" } }, "it": { "stringUnit": { "state": "translated", - "value": "Segna area di lavoro come non letta" + "value": "Rimuovi nome personalizzato area di lavoro" } }, "da": { "stringUnit": { "state": "translated", - "value": "Marker arbejdsområde som ulæst" + "value": "Fjern brugerdefineret arbejdsområdenavn" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Oznacz przestrzeń roboczą jako nieprzeczytaną" + "value": "Usuń własną nazwę przestrzeni roboczej" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Отметить рабочее пространство как непрочитанное" + "value": "Удалить пользовательское имя рабочего пространства" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Označi radni prostor kao nepročitan" + "value": "Ukloni prilagođeni naziv radnog prostora" } }, "ar": { "stringUnit": { "state": "translated", - "value": "تعليم مساحة العمل كغير مقروءة" + "value": "إزالة اسم مساحة العمل المخصص" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Merk arbeidsområde som ulest" + "value": "Fjern egendefinert arbeidsområdenavn" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Marcar Área de Trabalho como Não Lida" + "value": "Remover Nome Personalizado da Área de Trabalho" } }, "th": { "stringUnit": { "state": "translated", - "value": "ทำเครื่องหมายเวิร์กสเปซว่ายังไม่อ่าน" + "value": "ลบชื่อเวิร์กสเปซที่กำหนดเอง" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Çalışma Alanını Okunmadı Olarak İşaretle" + "value": "Özel Çalışma Alanı Adını Kaldır" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Позначити робочу область як непрочитану" + "value": "Видалити власну назву робочої області" } } } }, - "contextMenu.markWorkspacesRead": { + "contextMenu.renameWorkspace": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Mark Workspaces as Read" + "value": "Rename Workspace…" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ワークスペースを既読にする" + "value": "ワークスペースの名称変更…" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "将工作区标记为已读" + "value": "重命名工作区..." } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "將工作區標為已讀" + "value": "重新命名工作區..." } }, "ko": { "stringUnit": { "state": "translated", - "value": "작업 공간을 읽음으로 표시" + "value": "작업 공간 이름 변경…" } }, "de": { "stringUnit": { "state": "translated", - "value": "Arbeitsbereiche als gelesen markieren" + "value": "Arbeitsbereich umbenennen …" } }, "es": { "stringUnit": { "state": "translated", - "value": "Marcar espacios de trabajo como leídos" + "value": "Renombrar espacio de trabajo…" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Marquer les espaces de travail comme lus" + "value": "Renommer l'espace de travail..." } }, "it": { "stringUnit": { "state": "translated", - "value": "Segna aree di lavoro come lette" + "value": "Rinomina area di lavoro…" } }, "da": { "stringUnit": { "state": "translated", - "value": "Marker arbejdsområder som læste" + "value": "Omdøb arbejdsområde…" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Oznacz przestrzenie robocze jako przeczytane" + "value": "Zmień nazwę przestrzeni roboczej…" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Отметить рабочие пространства как прочитанные" + "value": "Переименовать рабочее пространство..." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Označi radne prostore kao pročitane" + "value": "Preimenuj radni prostor…" } }, "ar": { "stringUnit": { "state": "translated", - "value": "تعليم مساحات العمل كمقروءة" + "value": "إعادة تسمية مساحة العمل…" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Merk arbeidsområder som lest" + "value": "Gi arbeidsområdet nytt navn …" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Marcar Áreas de Trabalho como Lidas" + "value": "Renomear Área de Trabalho…" } }, "th": { "stringUnit": { "state": "translated", - "value": "ทำเครื่องหมายเวิร์กสเปซว่าอ่านแล้ว" + "value": "เปลี่ยนชื่อเวิร์กสเปซ..." } }, "tr": { "stringUnit": { "state": "translated", - "value": "Çalışma Alanlarını Okundu Olarak İşaretle" + "value": "Çalışma Alanını Yeniden Adlandır…" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Позначити робочі області як прочитані" + "value": "Перейменувати робочу область…" } } } }, - "contextMenu.markWorkspacesUnread": { + "contextMenu.unpinWorkspace": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Mark Workspaces as Unread" + "value": "Unpin Workspace" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ワークスペースを未読にする" + "value": "ワークスペースのピンを外す" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "将工作区标记为未读" + "value": "取消固定工作区" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "將工作區標為未讀" + "value": "取消釘選工作區" } }, "ko": { "stringUnit": { "state": "translated", - "value": "작업 공간을 읽지 않음으로 표시" + "value": "작업 공간 고정 해제" } }, "de": { "stringUnit": { "state": "translated", - "value": "Arbeitsbereiche als ungelesen markieren" + "value": "Arbeitsbereich loslösen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Marcar espacios de trabajo como no leídos" + "value": "Desfijar espacio de trabajo" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Marquer les espaces de travail comme non lus" + "value": "Désépingler l'espace de travail" } }, "it": { "stringUnit": { "state": "translated", - "value": "Segna aree di lavoro come non lette" + "value": "Sblocca area di lavoro" } }, "da": { "stringUnit": { "state": "translated", - "value": "Marker arbejdsområder som ulæste" + "value": "Frigør arbejdsområde" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Oznacz przestrzenie robocze jako nieprzeczytane" + "value": "Odepnij przestrzeń roboczą" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Отметить рабочие пространства как непрочитанные" + "value": "Открепить рабочее пространство" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Označi radne prostore kao nepročitane" + "value": "Otkači radni prostor" } }, "ar": { "stringUnit": { "state": "translated", - "value": "تعليم مساحات العمل كغير مقروءة" + "value": "إلغاء تثبيت مساحة العمل" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Merk arbeidsområder som ulest" + "value": "Løsne arbeidsområde" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Marcar Áreas de Trabalho como Não Lidas" + "value": "Desafixar Área de Trabalho" } }, "th": { "stringUnit": { "state": "translated", - "value": "ทำเครื่องหมายเวิร์กสเปซว่ายังไม่อ่าน" + "value": "เลิกปักหมุดเวิร์กสเปซ" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Çalışma Alanlarını Okunmadı Olarak İşaretle" + "value": "Çalışma Alanı Sabitlemesini Kaldır" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Позначити робочі області як непрочитані" + "value": "Відкріпити робочу область" } } } }, - "contextMenu.copyError": { + "contextMenu.unpinWorkspaces": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Copy Error" + "value": "Unpin Workspaces" } }, "ja": { "stringUnit": { "state": "translated", - "value": "エラーをコピー" + "value": "ワークスペースのピンを外す" } }, - "uk": { + "zh-Hans": { "stringUnit": { "state": "translated", - "value": "Копіювати помилку" + "value": "取消固定工作区" } }, - "ko": { - "stringUnit": { - "state": "translated", - "value": "오류 복사" - } - } - } - }, - "contextMenu.copyErrors": { - "extractionState": "manual", - "localizations": { - "en": { + "zh-Hant": { "stringUnit": { "state": "translated", - "value": "Copy Errors" + "value": "取消釘選工作區" } }, - "ja": { + "ko": { "stringUnit": { "state": "translated", - "value": "エラーをコピー" + "value": "작업 공간 고정 해제" } }, - "uk": { + "de": { "stringUnit": { "state": "translated", - "value": "Копіювати помилки" + "value": "Arbeitsbereiche loslösen" } }, - "ko": { + "es": { "stringUnit": { "state": "translated", - "value": "오류 모두 복사" + "value": "Desfijar espacios de trabajo" } - } - } - }, - "clipboard.sshError.item": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "fr": { "stringUnit": { "state": "translated", - "value": "%lld. %@ (%@): %@" + "value": "Désépingler les espaces de travail" } }, - "ja": { + "it": { "stringUnit": { "state": "translated", - "value": "%lld. %@ (%@): %@" + "value": "Sblocca aree di lavoro" } }, - "uk": { + "da": { "stringUnit": { "state": "translated", - "value": "%lld. %@ (%@): %@" + "value": "Frigør arbejdsområder" } }, - "ko": { + "pl": { "stringUnit": { "state": "translated", - "value": "%lld. %@ (%@): %@" + "value": "Odepnij przestrzenie robocze" } - } - } - }, - "clipboard.sshError.single": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "ru": { "stringUnit": { "state": "translated", - "value": "SSH error (%@): %@" + "value": "Открепить рабочие пространства" } }, - "ja": { + "bs": { "stringUnit": { "state": "translated", - "value": "SSH エラー (%@): %@" + "value": "Otkači radne prostore" } }, - "uk": { + "ar": { "stringUnit": { "state": "translated", - "value": "Помилка SSH (%@): %@" + "value": "إلغاء تثبيت مساحات العمل" } }, - "ko": { + "nb": { "stringUnit": { "state": "translated", - "value": "SSH 오류 (%@): %@" + "value": "Løsne arbeidsområder" } - } - } - }, - "contextMenu.copySshError": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "pt-BR": { "stringUnit": { "state": "translated", - "value": "Copy SSH Error" + "value": "Desafixar Áreas de Trabalho" } }, - "ja": { + "th": { "stringUnit": { "state": "translated", - "value": "SSHエラーをコピー" + "value": "เลิกปักหมุดเวิร์กสเปซ" } }, - "uk": { + "tr": { "stringUnit": { "state": "translated", - "value": "Копіювати помилку SSH" + "value": "Çalışma Alanları Sabitlemesini Kaldır" } }, - "ko": { + "uk": { "stringUnit": { "state": "translated", - "value": "SSH 오류 복사" + "value": "Відкріпити робочі області" } } } }, - "contextMenu.copyWorkspaceID": { + "contextMenu.workspaceColor": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Copy Workspace ID" + "value": "Workspace Color" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ワークスペースIDをコピー" + "value": "ワークスペースカラー" } }, - "ko": { - "stringUnit": { - "state": "translated", - "value": "워크스페이스 ID 복사" - } - } - } - }, - "contextMenu.copyWorkspaceIDs": { - "extractionState": "manual", - "localizations": { - "en": { + "zh-Hans": { "stringUnit": { "state": "translated", - "value": "Copy Workspace IDs" + "value": "工作区颜色" } }, - "ja": { + "zh-Hant": { "stringUnit": { "state": "translated", - "value": "ワークスペースIDをコピー" + "value": "工作區顏色" } }, "ko": { "stringUnit": { "state": "translated", - "value": "워크스페이스 ID 복사" + "value": "작업 공간 색상" } - } - } - }, - "contextMenu.moveDown": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "de": { "stringUnit": { "state": "translated", - "value": "Move Down" - } - }, - "ja": { - "stringUnit": { - "state": "translated", - "value": "下に移動" - } - }, - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "下移" - } - }, - "zh-Hant": { - "stringUnit": { - "state": "translated", - "value": "下移" - } - }, - "ko": { - "stringUnit": { - "state": "translated", - "value": "아래로 이동" - } - }, - "de": { - "stringUnit": { - "state": "translated", - "value": "Nach unten bewegen" + "value": "Arbeitsbereichsfarbe" } }, "es": { "stringUnit": { "state": "translated", - "value": "Mover hacia abajo" + "value": "Color del espacio de trabajo" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Déplacer vers le bas" + "value": "Couleur de l'espace de travail" } }, "it": { "stringUnit": { "state": "translated", - "value": "Sposta in basso" + "value": "Colore area di lavoro" } }, "da": { "stringUnit": { "state": "translated", - "value": "Flyt ned" + "value": "Arbejdsområdefarve" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Przenieś w dół" + "value": "Kolor przestrzeni roboczej" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Переместить вниз" + "value": "Цвет рабочего пространства" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Pomjeri dolje" + "value": "Boja radnog prostora" } }, "ar": { "stringUnit": { "state": "translated", - "value": "نقل للأسفل" + "value": "لون مساحة العمل" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Flytt ned" + "value": "Arbeidsområdefarge" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Mover para Baixo" + "value": "Cor da Área de Trabalho" } }, "th": { "stringUnit": { "state": "translated", - "value": "เลื่อนลง" + "value": "สีเวิร์กสเปซ" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Aşağı Taşı" + "value": "Çalışma Alanı Rengi" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Перемістити вниз" + "value": "Колір робочої області" } } } }, - "contextMenu.moveToTop": { + "dialog.closeLastTabWindow.message": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Move to Top" + "value": "This will close the last tab and close the window." } }, "ja": { "stringUnit": { "state": "translated", - "value": "一番上に移動" + "value": "最後のタブを閉じ、ウインドウを閉じます。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "移到顶部" + "value": "这将关闭最后一个标签页并关闭窗口。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "移至最上方" + "value": "這將關閉最後一個標籤頁並關閉視窗。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "맨 위로 이동" + "value": "마지막 탭이 닫히면 윈도우도 닫힙니다." } }, "de": { "stringUnit": { "state": "translated", - "value": "Nach oben bewegen" + "value": "Dadurch wird der letzte Tab geschlossen und das Fenster geschlossen." } }, "es": { "stringUnit": { "state": "translated", - "value": "Mover al inicio" + "value": "Esto cerrará la última pestaña y cerrará la ventana." } }, "fr": { "stringUnit": { "state": "translated", - "value": "Déplacer en haut" + "value": "Cela fermera le dernier onglet et fermera la fenêtre." } }, "it": { "stringUnit": { "state": "translated", - "value": "Sposta in cima" + "value": "Questa operazione chiuderà l'ultima scheda e la finestra." } }, "da": { "stringUnit": { "state": "translated", - "value": "Flyt til toppen" + "value": "Dette lukker den sidste fane og lukker vinduet." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Przenieś na górę" + "value": "Spowoduje to zamknięcie ostatniej karty i zamknięcie okna." } }, "ru": { "stringUnit": { "state": "translated", - "value": "Переместить наверх" + "value": "Это закроет последнюю вкладку и окно." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Pomjeri na vrh" + "value": "Ovo će zatvoriti posljednji tab i zatvoriti prozor." } }, "ar": { "stringUnit": { "state": "translated", - "value": "نقل إلى الأعلى" + "value": "سيؤدي هذا إلى إغلاق آخر لسان وإغلاق النافذة." } }, "nb": { "stringUnit": { "state": "translated", - "value": "Flytt til toppen" + "value": "Dette vil lukke den siste fanen og lukke vinduet." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Mover para o Topo" + "value": "Isto fechará a última aba e fechará a janela." } }, "th": { "stringUnit": { "state": "translated", - "value": "ย้ายไปด้านบน" + "value": "การดำเนินการนี้จะปิดแท็บสุดท้ายและปิดหน้าต่าง" } }, "tr": { "stringUnit": { "state": "translated", - "value": "En Üste Taşı" + "value": "Bu, son sekmeyi kapatacak ve pencereyi kapatacak." } }, "uk": { "stringUnit": { "state": "translated", - "value": "Перемістити на початок" + "value": "Це закриє останню вкладку та закриє вікно." } } } }, - "contextMenu.moveUp": { + "dialog.closeLastTabWorkspace.message": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Move Up" + "value": "This will close the last tab and close its workspace." } }, "ja": { "stringUnit": { "state": "translated", - "value": "上に移動" + "value": "最後のタブを閉じ、ワークスペースを閉じます。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "上移" + "value": "这将关闭最后一个标签页并关闭其工作区。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "上移" + "value": "這將關閉最後一個標籤頁並關閉其工作區。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "위로 이동" + "value": "마지막 탭이 닫히면 해당 작업 공간도 닫힙니다." } }, "de": { "stringUnit": { "state": "translated", - "value": "Nach oben bewegen" + "value": "Dadurch wird der letzte Tab geschlossen und der Arbeitsbereich geschlossen." } }, "es": { "stringUnit": { "state": "translated", - "value": "Mover hacia arriba" + "value": "Esto cerrará la última pestaña y cerrará su espacio de trabajo." } }, "fr": { "stringUnit": { "state": "translated", - "value": "Déplacer vers le haut" + "value": "Cela fermera le dernier onglet et fermera son espace de travail." } }, "it": { "stringUnit": { "state": "translated", - "value": "Sposta in alto" + "value": "Questa operazione chiuderà l'ultima scheda e la sua area di lavoro." } }, "da": { "stringUnit": { "state": "translated", - "value": "Flyt op" + "value": "Dette lukker den sidste fane og lukker dets arbejdsområde." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Przenieś w górę" + "value": "Spowoduje to zamknięcie ostatniej karty i zamknięcie jej przestrzeni roboczej." } }, "ru": { "stringUnit": { "state": "translated", - "value": "Переместить вверх" + "value": "Это закроет последнюю вкладку и её рабочее пространство." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Pomjeri gore" + "value": "Ovo će zatvoriti posljednji tab i zatvoriti njegov radni prostor." } }, "ar": { "stringUnit": { "state": "translated", - "value": "نقل للأعلى" + "value": "سيؤدي هذا إلى إغلاق آخر لسان وإغلاق مساحة العمل." } }, "nb": { "stringUnit": { "state": "translated", - "value": "Flytt opp" + "value": "Dette vil lukke den siste fanen og lukke arbeidsområdet." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Mover para Cima" + "value": "Isto fechará a última aba e fechará sua área de trabalho." } }, "th": { "stringUnit": { "state": "translated", - "value": "เลื่อนขึ้น" + "value": "การดำเนินการนี้จะปิดแท็บสุดท้ายและปิดเวิร์กสเปซ" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Yukarı Taşı" + "value": "Bu, son sekmeyi kapatacak ve çalışma alanını kapatacak." } }, "uk": { "stringUnit": { "state": "translated", - "value": "Перемістити вгору" + "value": "Це закриє останню вкладку та її робочу область." } } } }, - "contextMenu.moveWorkspaceToWindow": { + "dialog.closeOtherTabs.message.one": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Move Workspace to Window" + "value": "This will close 1 tab in this pane:\n%@" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ワークスペースをウインドウに移動" + "value": "このペインの 1 個のタブを閉じます:\n%@" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "将工作区移到窗口" + "value": "这将关闭此面板中的 1 个标签页:\n%@" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "將工作區移至視窗" + "value": "這將關閉此面板中的 1 個標籤頁:\n%@" } }, "ko": { "stringUnit": { "state": "translated", - "value": "작업 공간을 윈도우로 이동" + "value": "이 패널에서 탭 1개를 닫습니다:\n%@" } }, "de": { "stringUnit": { "state": "translated", - "value": "Arbeitsbereich in Fenster bewegen" + "value": "Dadurch wird 1 Tab in diesem Bereich geschlossen:\n%@" } }, "es": { "stringUnit": { "state": "translated", - "value": "Mover espacio de trabajo a ventana" + "value": "Esto cerrará 1 pestaña en este panel:\n%@" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Déplacer l'espace de travail vers une fenêtre" + "value": "Cela fermera 1 onglet dans ce panneau :\n%@" } }, "it": { "stringUnit": { "state": "translated", - "value": "Sposta area di lavoro in una finestra" + "value": "Questa operazione chiuderà 1 scheda in questo pannello:\n%@" } }, "da": { "stringUnit": { "state": "translated", - "value": "Flyt arbejdsområde til vindue" + "value": "Dette lukker 1 fane i dette panel:\n%@" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Przenieś przestrzeń roboczą do okna" + "value": "Spowoduje to zamknięcie 1 karty w tym panelu:\n%@" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Переместить рабочее пространство в окно" + "value": "Будет закрыта 1 вкладка в этой панели:\n%@" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Premjesti radni prostor u prozor" + "value": "Ovo će zatvoriti 1 tab u ovom panelu:\n%@" } }, "ar": { "stringUnit": { "state": "translated", - "value": "نقل مساحة العمل إلى نافذة" + "value": "سيؤدي هذا إلى إغلاق لسان واحد في هذه اللوحة:\n%@" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Flytt arbeidsområde til vindu" + "value": "Dette vil lukke 1 fane i dette panelet:\n%@" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Mover Área de Trabalho para Janela" + "value": "Isto fechará 1 aba neste painel:\n%@" } }, "th": { "stringUnit": { "state": "translated", - "value": "ย้ายเวิร์กสเปซไปยังหน้าต่าง" + "value": "การดำเนินการนี้จะปิด 1 แท็บในบานหน้าต่างนี้:\n%@" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Çalışma Alanını Pencereye Taşı" + "value": "Bu bölmedeki 1 sekme kapatılacak:\n%@" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Перемістити робочу область у вікно" + "value": "Це закриє 1 вкладку в цій панелі:\n%@" } } } }, - "contextMenu.moveWorkspacesToWindow": { + "dialog.closeOtherTabs.message.other": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Move Workspaces to Window" + "value": "This will close %1$lld tabs in this pane:\n%2$@" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ワークスペースをウインドウに移動" + "value": "このペインの %1$lld 個のタブを閉じます:\n%2$@" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "将工作区移到窗口" + "value": "这将关闭此面板中的 %1$lld 个标签页:\n%2$@" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "將工作區移至視窗" + "value": "這將關閉此面板中的 %1$lld 個標籤頁:\n%2$@" } }, "ko": { "stringUnit": { "state": "translated", - "value": "작업 공간을 윈도우로 이동" + "value": "이 패널에서 탭 %1$lld개를 닫습니다:\n%2$@" } }, "de": { "stringUnit": { "state": "translated", - "value": "Arbeitsbereiche in Fenster bewegen" + "value": "Dadurch werden %1$lld Tabs in diesem Bereich geschlossen:\n%2$@" } }, "es": { "stringUnit": { "state": "translated", - "value": "Mover espacios de trabajo a ventana" + "value": "Esto cerrará %1$lld pestañas en este panel:\n%2$@" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Déplacer les espaces de travail vers une fenêtre" + "value": "Cela fermera %1$lld onglets dans ce panneau :\n%2$@" } }, "it": { "stringUnit": { "state": "translated", - "value": "Sposta aree di lavoro in una finestra" + "value": "Questa operazione chiuderà %1$lld schede in questo pannello:\n%2$@" } }, "da": { "stringUnit": { "state": "translated", - "value": "Flyt arbejdsområder til vindue" + "value": "Dette lukker %1$lld faner i dette panel:\n%2$@" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Przenieś przestrzenie robocze do okna" + "value": "Spowoduje to zamknięcie %1$lld kart w tym panelu:\n%2$@" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Переместить рабочие пространства в окно" + "value": "Будет закрыто вкладок в этой панели: %1$lld\n%2$@" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Premjesti radne prostore u prozor" + "value": "Ovo će zatvoriti %1$lld tabova u ovom panelu:\n%2$@" } }, "ar": { "stringUnit": { "state": "translated", - "value": "نقل مساحات العمل إلى نافذة" + "value": "سيؤدي هذا إلى إغلاق %1$lld لسان في هذه اللوحة:\n%2$@" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Flytt arbeidsområder til vindu" + "value": "Dette vil lukke %1$lld faner i dette panelet:\n%2$@" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Mover Áreas de Trabalho para Janela" + "value": "Isto fechará %1$lld abas neste painel:\n%2$@" } }, "th": { "stringUnit": { "state": "translated", - "value": "ย้ายเวิร์กสเปซไปยังหน้าต่าง" + "value": "การดำเนินการนี้จะปิด %1$lld แท็บในบานหน้าต่างนี้:\n%2$@" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Çalışma Alanlarını Pencereye Taşı" + "value": "Bu bölmedeki %1$lld sekme kapatılacak:\n%2$@" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Перемістити робочі області у вікно" + "value": "Це закриє %1$lld вкладок у цій панелі:\n%2$@" } } } }, - "contextMenu.newWindow": { + "dialog.closeOtherTabs.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "New Window" + "value": "Close other tabs?" } }, "ja": { "stringUnit": { "state": "translated", - "value": "新規ウインドウ" + "value": "他のタブを閉じますか?" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "新建窗口" + "value": "关闭其他标签页?" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "新增視窗" + "value": "要關閉其他標籤頁嗎?" } }, "ko": { "stringUnit": { "state": "translated", - "value": "새 윈도우" + "value": "다른 탭을 닫으시겠습니까?" } }, "de": { "stringUnit": { "state": "translated", - "value": "Neues Fenster" + "value": "Andere Tabs schließen?" } }, "es": { "stringUnit": { "state": "translated", - "value": "Nueva ventana" + "value": "¿Cerrar otras pestañas?" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Nouvelle fenêtre" + "value": "Fermer les autres onglets ?" } }, "it": { "stringUnit": { "state": "translated", - "value": "Nuova finestra" + "value": "Chiudere le altre schede?" } }, "da": { "stringUnit": { "state": "translated", - "value": "Nyt vindue" + "value": "Luk andre faner?" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Nowe okno" + "value": "Zamknąć inne karty?" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Новое окно" + "value": "Закрыть другие вкладки?" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Novi prozor" + "value": "Zatvoriti ostale tabove?" } }, "ar": { "stringUnit": { "state": "translated", - "value": "نافذة جديدة" + "value": "إغلاق الألسنة الأخرى؟" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Nytt vindu" + "value": "Lukke andre faner?" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Nova Janela" + "value": "Fechar outras abas?" } }, "th": { "stringUnit": { "state": "translated", - "value": "หน้าต่างใหม่" + "value": "ปิดแท็บอื่นหรือไม่?" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Yeni Pencere" + "value": "Diğer sekmeler kapatılsın mı?" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Нове вікно" + "value": "Закрити інші вкладки?" } } } }, - "contextMenu.pinWorkspace": { + "dialog.closeTab.close": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Pin Workspace" + "value": "Close" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ワークスペースをピンで固定" + "value": "閉じる" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "固定工作区" + "value": "关闭" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "釘選工作區" + "value": "關閉" } }, "ko": { "stringUnit": { "state": "translated", - "value": "작업 공간 고정" + "value": "닫기" } }, "de": { "stringUnit": { "state": "translated", - "value": "Arbeitsbereich anheften" + "value": "Schließen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Fijar espacio de trabajo" + "value": "Cerrar" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Épingler l'espace de travail" + "value": "Fermer" } }, "it": { "stringUnit": { "state": "translated", - "value": "Fissa area di lavoro" + "value": "Chiudi" } }, "da": { "stringUnit": { "state": "translated", - "value": "Fastgør arbejdsområde" + "value": "Luk" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Przypnij przestrzeń roboczą" + "value": "Zamknij" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Закрепить рабочее пространство" + "value": "Закрыть" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Zakači radni prostor" + "value": "Zatvori" } }, "ar": { "stringUnit": { "state": "translated", - "value": "تثبيت مساحة العمل" + "value": "إغلاق" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Fest arbeidsområde" + "value": "Lukk" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Fixar Área de Trabalho" + "value": "Fechar" } }, "th": { "stringUnit": { "state": "translated", - "value": "ปักหมุดเวิร์กสเปซ" + "value": "ปิด" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Çalışma Alanını Sabitle" + "value": "Kapat" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Закріпити робочу область" + "value": "Закрити" } } } }, - "contextMenu.pinWorkspaces": { + "dialog.closeTab.cancel": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Pin Workspaces" + "value": "Cancel" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ワークスペースをピンで固定" + "value": "キャンセル" + } + }, + "uk": { + "stringUnit": { + "state": "translated", + "value": "Скасувати" + } + }, + "ko": { + "stringUnit": { + "state": "translated", + "value": "취소" + } + } + } + }, + "dialog.closeTab.message": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "This will close the current tab." + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "現在のタブを閉じます。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "固定工作区" + "value": "这将关闭当前标签页。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "釘選工作區" + "value": "這將關閉目前的標籤頁。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "작업 공간 고정" + "value": "현재 탭을 닫습니다." } }, "de": { "stringUnit": { "state": "translated", - "value": "Arbeitsbereiche anheften" + "value": "Dadurch wird der aktuelle Tab geschlossen." } }, "es": { "stringUnit": { "state": "translated", - "value": "Fijar espacios de trabajo" + "value": "Esto cerrará la pestaña actual." } }, "fr": { "stringUnit": { "state": "translated", - "value": "Épingler les espaces de travail" + "value": "Cela fermera l'onglet actuel." } }, "it": { "stringUnit": { "state": "translated", - "value": "Fissa aree di lavoro" + "value": "Questa operazione chiuderà la scheda corrente." } }, "da": { "stringUnit": { "state": "translated", - "value": "Fastgør arbejdsområder" + "value": "Dette lukker den aktuelle fane." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Przypnij przestrzenie robocze" + "value": "Spowoduje to zamknięcie bieżącej karty." } }, "ru": { "stringUnit": { "state": "translated", - "value": "Закрепить рабочие пространства" + "value": "Текущая вкладка будет закрыта." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Zakači radne prostore" + "value": "Ovo će zatvoriti trenutni tab." } }, "ar": { "stringUnit": { "state": "translated", - "value": "تثبيت مساحات العمل" + "value": "سيؤدي هذا إلى إغلاق اللسان الحالي." } }, "nb": { "stringUnit": { "state": "translated", - "value": "Fest arbeidsområder" + "value": "Dette vil lukke den gjeldende fanen." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Fixar Áreas de Trabalho" + "value": "Isto fechará a aba atual." } }, "th": { "stringUnit": { "state": "translated", - "value": "ปักหมุดเวิร์กสเปซ" + "value": "การดำเนินการนี้จะปิดแท็บปัจจุบัน" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Çalışma Alanlarını Sabitle" + "value": "Bu, geçerli sekmeyi kapatacak." } }, "uk": { "stringUnit": { "state": "translated", - "value": "Закріпити робочі області" + "value": "Це закриє поточну вкладку." } } } }, - "contextMenu.removeCustomWorkspaceName": { + "dialog.closeTab.messageNamed": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Remove Custom Workspace Name" + "value": "This will close \"%@\"." } }, "ja": { "stringUnit": { "state": "translated", - "value": "カスタムワークスペース名を削除" + "value": "「%@」を閉じます。" + } + }, + "uk": { + "stringUnit": { + "state": "translated", + "value": "Це закриє \"%@\"." + } + }, + "ko": { + "stringUnit": { + "state": "translated", + "value": "\"%@\"을(를) 닫습니다." + } + } + } + }, + "dialog.closeTab.title": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Close tab?" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "タブを閉じますか?" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "移除自定义工作区名称" + "value": "关闭标签页?" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "移除自訂工作區名稱" + "value": "要關閉標籤頁嗎?" } }, "ko": { "stringUnit": { "state": "translated", - "value": "사용자 지정 작업 공간 이름 제거" + "value": "탭을 닫으시겠습니까?" } }, "de": { "stringUnit": { "state": "translated", - "value": "Benutzerdefinierten Arbeitsbereichsnamen entfernen" + "value": "Tab schließen?" } }, "es": { "stringUnit": { "state": "translated", - "value": "Eliminar nombre personalizado del espacio de trabajo" + "value": "¿Cerrar pestaña?" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Supprimer le nom personnalisé de l'espace de travail" + "value": "Fermer l'onglet ?" } }, "it": { "stringUnit": { "state": "translated", - "value": "Rimuovi nome personalizzato area di lavoro" + "value": "Chiudere la scheda?" } }, "da": { "stringUnit": { "state": "translated", - "value": "Fjern brugerdefineret arbejdsområdenavn" + "value": "Luk fane?" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Usuń własną nazwę przestrzeni roboczej" + "value": "Zamknąć kartę?" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Удалить пользовательское имя рабочего пространства" + "value": "Закрыть вкладку?" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Ukloni prilagođeni naziv radnog prostora" + "value": "Zatvoriti tab?" } }, "ar": { "stringUnit": { "state": "translated", - "value": "إزالة اسم مساحة العمل المخصص" + "value": "إغلاق اللسان؟" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Fjern egendefinert arbeidsområdenavn" + "value": "Lukke fane?" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Remover Nome Personalizado da Área de Trabalho" + "value": "Fechar aba?" } }, "th": { "stringUnit": { "state": "translated", - "value": "ลบชื่อเวิร์กสเปซที่กำหนดเอง" + "value": "ปิดแท็บหรือไม่?" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Özel Çalışma Alanı Adını Kaldır" + "value": "Sekme kapatılsın mı?" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Видалити власну назву робочої області" + "value": "Закрити вкладку?" } } } }, - "contextMenu.renameWorkspace": { + "dialog.closeWindow.message": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Rename Workspace…" + "value": "This will close the current window and all of its workspaces." } }, "ja": { "stringUnit": { "state": "translated", - "value": "ワークスペースの名称変更…" + "value": "現在のウィンドウとそのすべてのワークスペースを閉じます。" } }, - "zh-Hans": { + "uk": { "stringUnit": { "state": "translated", - "value": "重命名工作区..." + "value": "Це закриє поточне вікно та всі його робочі області." } }, - "zh-Hant": { + "ko": { "stringUnit": { "state": "translated", - "value": "重新命名工作區..." + "value": "현재 윈도우와 모든 워크스페이스가 닫힙니다." } - }, - "ko": { + } + } + }, + "dialog.closeWindow.title": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "작업 공간 이름 변경…" + "value": "Close window?" } }, - "de": { + "ja": { "stringUnit": { "state": "translated", - "value": "Arbeitsbereich umbenennen …" + "value": "ウィンドウを閉じますか?" } }, - "es": { + "uk": { "stringUnit": { "state": "translated", - "value": "Renombrar espacio de trabajo…" + "value": "Закрити вікно?" } }, - "fr": { + "ko": { "stringUnit": { "state": "translated", - "value": "Renommer l'espace de travail..." + "value": "윈도우를 닫으시겠습니까?" } - }, - "it": { + } + } + }, + "dialog.closeWorkspaces.message": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Rinomina area di lavoro…" + "value": "This will close %1$lld workspaces and all of their panels:\n%2$@" } }, - "da": { + "ja": { "stringUnit": { "state": "translated", - "value": "Omdøb arbejdsområde…" + "value": "%1$lld 個のワークスペースと、それぞれのすべてのパネルを閉じます:\n%2$@" } }, - "pl": { + "uk": { "stringUnit": { "state": "translated", - "value": "Zmień nazwę przestrzeni roboczej…" + "value": "Це закриє %1$lld робочих областей та всі їхні панелі:\n%2$@" } }, - "ru": { + "ko": { "stringUnit": { "state": "translated", - "value": "Переименовать рабочее пространство..." + "value": "%1$lld개의 워크스페이스와 모든 패널이 닫힙니다:\n%2$@" } - }, - "bs": { + } + } + }, + "dialog.closeWorkspaces.title": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Preimenuj radni prostor…" + "value": "Close workspaces?" } }, - "ar": { + "ja": { "stringUnit": { "state": "translated", - "value": "إعادة تسمية مساحة العمل…" + "value": "ワークスペースを閉じますか?" } }, - "nb": { + "uk": { "stringUnit": { "state": "translated", - "value": "Gi arbeidsområdet nytt navn …" + "value": "Закрити робочі області?" } }, - "pt-BR": { + "ko": { "stringUnit": { "state": "translated", - "value": "Renomear Área de Trabalho…" + "value": "워크스페이스를 닫으시겠습니까?" + } + } + } + }, + "dialog.closeWorkspacesWindow.message": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "This will close the current window, its %1$lld workspaces, and all of their panels:\n%2$@" } }, - "th": { + "ja": { "stringUnit": { "state": "translated", - "value": "เปลี่ยนชื่อเวิร์กสเปซ..." + "value": "現在のウィンドウと、その %1$lld 個のワークスペースと、それぞれのすべてのパネルを閉じます:\n%2$@" } }, - "tr": { + "uk": { "stringUnit": { "state": "translated", - "value": "Çalışma Alanını Yeniden Adlandır…" + "value": "Це закриє поточне вікно, його %1$lld робочих областей та всі їхні панелі:\n%2$@" + } + }, + "ko": { + "stringUnit": { + "state": "translated", + "value": "현재 윈도우, %1$lld개의 워크스페이스 및 모든 패널이 닫힙니다:\n%2$@" + } + } + } + }, + "dialog.closePinnedWorkspace.message": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "This workspace is pinned. Closing it will close the workspace and all of its panels." + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "このワークスペースはピン留めされています。閉じると、このワークスペースとその中のすべてのパネルが閉じます。" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Перейменувати робочу область…" + "value": "Ця робоча область закріплена. Закриття видалить робочу область та всі її панелі." + } + }, + "ko": { + "stringUnit": { + "state": "translated", + "value": "이 워크스페이스는 고정되어 있습니다. 닫으면 워크스페이스와 모든 패널이 닫힙니다." } } } }, - "contextMenu.unpinWorkspace": { + "dialog.closePinnedWorkspace.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Unpin Workspace" + "value": "Close pinned workspace?" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ワークスペースのピンを外す" + "value": "ピン留めされたワークスペースを閉じますか?" + } + }, + "uk": { + "stringUnit": { + "state": "translated", + "value": "Закрити закріплену робочу область?" + } + }, + "ko": { + "stringUnit": { + "state": "translated", + "value": "고정된 워크스페이스를 닫으시겠습니까?" + } + } + } + }, + "dialog.closeWorkspace.message": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "This will close the workspace and all of its panels." + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "ワークスペースとそのすべてのパネルを閉じます。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "取消固定工作区" + "value": "这将关闭工作区及其所有面板。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "取消釘選工作區" + "value": "這將關閉工作區及其所有面板。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "작업 공간 고정 해제" + "value": "작업 공간과 모든 패널을 닫습니다." } }, "de": { "stringUnit": { "state": "translated", - "value": "Arbeitsbereich loslösen" + "value": "Dadurch werden der Arbeitsbereich und alle zugehörigen Bereiche geschlossen." } }, "es": { "stringUnit": { "state": "translated", - "value": "Desfijar espacio de trabajo" + "value": "Esto cerrará el espacio de trabajo y todos sus paneles." } }, "fr": { "stringUnit": { "state": "translated", - "value": "Désépingler l'espace de travail" + "value": "Cela fermera l'espace de travail et tous ses panneaux." } }, "it": { "stringUnit": { "state": "translated", - "value": "Sblocca area di lavoro" + "value": "Questa operazione chiuderà l'area di lavoro e tutti i suoi pannelli." } }, "da": { "stringUnit": { "state": "translated", - "value": "Frigør arbejdsområde" + "value": "Dette lukker arbejdsområdet og alle dets paneler." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Odepnij przestrzeń roboczą" + "value": "Spowoduje to zamknięcie przestrzeni roboczej i wszystkich jej paneli." } }, "ru": { "stringUnit": { "state": "translated", - "value": "Открепить рабочее пространство" + "value": "Рабочее пространство и все его панели будут закрыты." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Otkači radni prostor" + "value": "Ovo će zatvoriti radni prostor i sve njegove panele." } }, "ar": { "stringUnit": { "state": "translated", - "value": "إلغاء تثبيت مساحة العمل" + "value": "سيؤدي هذا إلى إغلاق مساحة العمل وجميع لوحاتها." } }, "nb": { "stringUnit": { "state": "translated", - "value": "Løsne arbeidsområde" + "value": "Dette vil lukke arbeidsområdet og alle panelene." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Desafixar Área de Trabalho" + "value": "Isto fechará a área de trabalho e todos os seus painéis." } }, "th": { "stringUnit": { "state": "translated", - "value": "เลิกปักหมุดเวิร์กสเปซ" + "value": "การดำเนินการนี้จะปิดเวิร์กสเปซและแผงทั้งหมด" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Çalışma Alanı Sabitlemesini Kaldır" + "value": "Bu, çalışma alanını ve tüm panellerini kapatacak." } }, "uk": { "stringUnit": { "state": "translated", - "value": "Відкріпити робочу область" + "value": "Це закриє робочу область та всі її панелі." } } } }, - "contextMenu.unpinWorkspaces": { + "dialog.closeWorkspace.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Unpin Workspaces" + "value": "Close workspace?" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ワークスペースのピンを外す" + "value": "ワークスペースを閉じますか?" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "取消固定工作区" + "value": "关闭工作区?" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "取消釘選工作區" + "value": "要關閉工作區嗎?" } }, "ko": { "stringUnit": { "state": "translated", - "value": "작업 공간 고정 해제" + "value": "작업 공간을 닫으시겠습니까?" } }, "de": { "stringUnit": { "state": "translated", - "value": "Arbeitsbereiche loslösen" + "value": "Arbeitsbereich schließen?" } }, "es": { "stringUnit": { "state": "translated", - "value": "Desfijar espacios de trabajo" + "value": "¿Cerrar espacio de trabajo?" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Désépingler les espaces de travail" + "value": "Fermer l'espace de travail ?" } }, "it": { "stringUnit": { "state": "translated", - "value": "Sblocca aree di lavoro" + "value": "Chiudere l'area di lavoro?" } }, "da": { "stringUnit": { "state": "translated", - "value": "Frigør arbejdsområder" + "value": "Luk arbejdsområde?" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Odepnij przestrzenie robocze" + "value": "Zamknąć przestrzeń roboczą?" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Открепить рабочие пространства" + "value": "Закрыть рабочее пространство?" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Otkači radne prostore" + "value": "Zatvoriti radni prostor?" } }, "ar": { "stringUnit": { "state": "translated", - "value": "إلغاء تثبيت مساحات العمل" + "value": "إغلاق مساحة العمل؟" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Løsne arbeidsområder" + "value": "Lukke arbeidsområde?" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Desafixar Áreas de Trabalho" + "value": "Fechar área de trabalho?" } }, "th": { "stringUnit": { "state": "translated", - "value": "เลิกปักหมุดเวิร์กสเปซ" + "value": "ปิดเวิร์กสเปซหรือไม่?" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Çalışma Alanları Sabitlemesini Kaldır" + "value": "Çalışma alanı kapatılsın mı?" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Відкріпити робочі області" + "value": "Закрити робочу область?" } } } }, - "contextMenu.workspaceColor": { + "dialog.dontWarnCmdQ": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Workspace Color" + "value": "Don't warn again for Cmd+Q" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ワークスペースカラー" + "value": "Cmd+Q の警告を表示しない" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "工作区颜色" + "value": "不再提示 Cmd+Q 警告" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "工作區顏色" + "value": "不再顯示 Cmd+Q 警告" } }, "ko": { "stringUnit": { "state": "translated", - "value": "작업 공간 색상" + "value": "Cmd+Q에 대해 다시 경고하지 않기" } }, "de": { "stringUnit": { "state": "translated", - "value": "Arbeitsbereichsfarbe" + "value": "Nicht erneut bei Cmd+Q warnen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Color del espacio de trabajo" + "value": "No volver a advertir para Cmd+Q" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Couleur de l'espace de travail" + "value": "Ne plus avertir pour Cmd+Q" } }, "it": { "stringUnit": { "state": "translated", - "value": "Colore area di lavoro" + "value": "Non avvisare più per Cmd+Q" } }, "da": { "stringUnit": { "state": "translated", - "value": "Arbejdsområdefarve" + "value": "Advar ikke igen for Cmd+Q" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Kolor przestrzeni roboczej" + "value": "Nie ostrzegaj ponownie przy Cmd+Q" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Цвет рабочего пространства" + "value": "Больше не предупреждать при Cmd+Q" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Boja radnog prostora" + "value": "Ne upozoravaj ponovo za Cmd+Q" } }, "ar": { "stringUnit": { "state": "translated", - "value": "لون مساحة العمل" + "value": "عدم التحذير مجددًا عند Cmd+Q" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Arbeidsområdefarge" + "value": "Ikke advar igjen for Cmd+Q" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Cor da Área de Trabalho" + "value": "Não avisar novamente para Cmd+Q" } }, "th": { "stringUnit": { "state": "translated", - "value": "สีเวิร์กสเปซ" + "value": "ไม่ต้องเตือนอีกสำหรับ Cmd+Q" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Çalışma Alanı Rengi" + "value": "Cmd+Q için bir daha uyarma" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Колір робочої області" + "value": "Більше не попереджувати про Cmd+Q" } } } }, - "dialog.closeLastTabWindow.message": { + "dialog.enableNotifications.message": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "This will close the last tab and close the window." + "value": "Notifications are disabled for cmux. Enable them in System Settings to see alerts." } }, "ja": { "stringUnit": { "state": "translated", - "value": "最後のタブを閉じ、ウインドウを閉じます。" + "value": "cmuxの通知が無効になっています。アラートを表示するにはシステム設定で有効にしてください。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "这将关闭最后一个标签页并关闭窗口。" + "value": "cmux 的通知已被禁用。请在系统设置中启用通知以接收提醒。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "這將關閉最後一個標籤頁並關閉視窗。" + "value": "cmux 的通知已停用。請在「系統設定」中啟用,以接收提示。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "마지막 탭이 닫히면 윈도우도 닫힙니다." + "value": "cmux에 대한 알림이 비활성화되어 있습니다. 알림을 보려면 시스템 설정에서 활성화하세요." } }, "de": { "stringUnit": { "state": "translated", - "value": "Dadurch wird der letzte Tab geschlossen und das Fenster geschlossen." + "value": "Benachrichtigungen sind für cmux deaktiviert. Aktivieren Sie sie in den Systemeinstellungen, um Hinweise zu sehen." } }, "es": { "stringUnit": { "state": "translated", - "value": "Esto cerrará la última pestaña y cerrará la ventana." + "value": "Las notificaciones están desactivadas para cmux. Actívalas en Ajustes del Sistema para ver alertas." } }, "fr": { "stringUnit": { "state": "translated", - "value": "Cela fermera le dernier onglet et fermera la fenêtre." + "value": "Les notifications sont désactivées pour cmux. Activez-les dans les Réglages Système pour voir les alertes." } }, "it": { "stringUnit": { "state": "translated", - "value": "Questa operazione chiuderà l'ultima scheda e la finestra." + "value": "Le notifiche sono disabilitate per cmux. Abilitale nelle Impostazioni di Sistema per visualizzare gli avvisi." } }, "da": { "stringUnit": { "state": "translated", - "value": "Dette lukker den sidste fane og lukker vinduet." + "value": "Notifikationer er deaktiveret for cmux. Aktiver dem i Systemindstillinger for at se advarsler." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Spowoduje to zamknięcie ostatniej karty i zamknięcie okna." + "value": "Powiadomienia są wyłączone dla cmux. Włącz je w Ustawieniach systemowych, aby widzieć alerty." } }, "ru": { "stringUnit": { "state": "translated", - "value": "Это закроет последнюю вкладку и окно." + "value": "Уведомления для cmux отключены. Включите их в Системных настройках, чтобы видеть оповещения." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Ovo će zatvoriti posljednji tab i zatvoriti prozor." + "value": "Obavještenja su onemogućena za cmux. Omogućite ih u Postavkama sistema da biste vidjeli upozorenja." } }, "ar": { "stringUnit": { "state": "translated", - "value": "سيؤدي هذا إلى إغلاق آخر لسان وإغلاق النافذة." + "value": "الإشعارات معطلة لـ cmux. قم بتفعيلها في إعدادات النظام لرؤية التنبيهات." } }, "nb": { "stringUnit": { "state": "translated", - "value": "Dette vil lukke den siste fanen og lukke vinduet." + "value": "Varsler er deaktivert for cmux. Aktiver dem i Systeminnstillinger for å se varsler." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Isto fechará a última aba e fechará a janela." + "value": "As notificações estão desativadas para o cmux. Ative-as nos Ajustes do Sistema para ver os alertas." } }, "th": { "stringUnit": { "state": "translated", - "value": "การดำเนินการนี้จะปิดแท็บสุดท้ายและปิดหน้าต่าง" + "value": "การแจ้งเตือนถูกปิดใช้งานสำหรับ cmux เปิดใช้งานในการตั้งค่าระบบเพื่อดูการแจ้งเตือน" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Bu, son sekmeyi kapatacak ve pencereyi kapatacak." + "value": "cmux için bildirimler devre dışı. Uyarıları görmek için Sistem Ayarları'nda etkinleştirin." } }, "uk": { "stringUnit": { "state": "translated", - "value": "Це закриє останню вкладку та закриє вікно." + "value": "Сповіщення для cmux вимкнено. Увімкніть їх у Системних налаштуваннях, щоб бачити повідомлення." } } } }, - "dialog.closeLastTabWorkspace.message": { + "dialog.enableNotifications.notNow": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "This will close the last tab and close its workspace." + "value": "Not Now" } }, "ja": { "stringUnit": { "state": "translated", - "value": "最後のタブを閉じ、ワークスペースを閉じます。" + "value": "今はしない" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "这将关闭最后一个标签页并关闭其工作区。" + "value": "以后再说" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "這將關閉最後一個標籤頁並關閉其工作區。" + "value": "現在不要" } }, "ko": { "stringUnit": { "state": "translated", - "value": "마지막 탭이 닫히면 해당 작업 공간도 닫힙니다." + "value": "나중에" } }, "de": { "stringUnit": { "state": "translated", - "value": "Dadurch wird der letzte Tab geschlossen und der Arbeitsbereich geschlossen." + "value": "Nicht jetzt" } }, "es": { "stringUnit": { "state": "translated", - "value": "Esto cerrará la última pestaña y cerrará su espacio de trabajo." + "value": "Ahora no" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Cela fermera le dernier onglet et fermera son espace de travail." + "value": "Pas maintenant" } }, "it": { "stringUnit": { "state": "translated", - "value": "Questa operazione chiuderà l'ultima scheda e la sua area di lavoro." + "value": "Non ora" } }, "da": { "stringUnit": { "state": "translated", - "value": "Dette lukker den sidste fane og lukker dets arbejdsområde." + "value": "Ikke nu" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Spowoduje to zamknięcie ostatniej karty i zamknięcie jej przestrzeni roboczej." + "value": "Nie teraz" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Это закроет последнюю вкладку и её рабочее пространство." + "value": "Не сейчас" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Ovo će zatvoriti posljednji tab i zatvoriti njegov radni prostor." + "value": "Ne sada" } }, "ar": { "stringUnit": { "state": "translated", - "value": "سيؤدي هذا إلى إغلاق آخر لسان وإغلاق مساحة العمل." + "value": "ليس الآن" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Dette vil lukke den siste fanen og lukke arbeidsområdet." + "value": "Ikke nå" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Isto fechará a última aba e fechará sua área de trabalho." + "value": "Agora Não" } }, "th": { "stringUnit": { "state": "translated", - "value": "การดำเนินการนี้จะปิดแท็บสุดท้ายและปิดเวิร์กสเปซ" + "value": "ไม่ใช่ตอนนี้" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Bu, son sekmeyi kapatacak ve çalışma alanını kapatacak." + "value": "Şimdi Değil" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Це закриє останню вкладку та її робочу область." + "value": "Не зараз" } } } }, - "dialog.closeOtherTabs.message.one": { + "dialog.enableNotifications.openSettings": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "This will close 1 tab in this pane:\n%@" + "value": "Open Settings" } }, "ja": { "stringUnit": { "state": "translated", - "value": "このペインの 1 個のタブを閉じます:\n%@" + "value": "設定を開く" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "这将关闭此面板中的 1 个标签页:\n%@" + "value": "打开设置" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "這將關閉此面板中的 1 個標籤頁:\n%@" + "value": "開啟設定" } }, "ko": { "stringUnit": { "state": "translated", - "value": "이 패널에서 탭 1개를 닫습니다:\n%@" + "value": "설정 열기" } }, "de": { "stringUnit": { "state": "translated", - "value": "Dadurch wird 1 Tab in diesem Bereich geschlossen:\n%@" + "value": "Einstellungen öffnen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Esto cerrará 1 pestaña en este panel:\n%@" + "value": "Abrir Ajustes" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Cela fermera 1 onglet dans ce panneau :\n%@" + "value": "Ouvrir les réglages" } }, "it": { "stringUnit": { "state": "translated", - "value": "Questa operazione chiuderà 1 scheda in questo pannello:\n%@" + "value": "Apri impostazioni" } }, "da": { "stringUnit": { "state": "translated", - "value": "Dette lukker 1 fane i dette panel:\n%@" + "value": "Åbn indstillinger" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Spowoduje to zamknięcie 1 karty w tym panelu:\n%@" + "value": "Otwórz ustawienia" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Будет закрыта 1 вкладка в этой панели:\n%@" + "value": "Открыть настройки" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Ovo će zatvoriti 1 tab u ovom panelu:\n%@" + "value": "Otvori postavke" } }, "ar": { "stringUnit": { "state": "translated", - "value": "سيؤدي هذا إلى إغلاق لسان واحد في هذه اللوحة:\n%@" + "value": "فتح الإعدادات" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Dette vil lukke 1 fane i dette panelet:\n%@" + "value": "Åpne innstillinger" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Isto fechará 1 aba neste painel:\n%@" + "value": "Abrir Ajustes" } }, "th": { "stringUnit": { "state": "translated", - "value": "การดำเนินการนี้จะปิด 1 แท็บในบานหน้าต่างนี้:\n%@" + "value": "เปิดการตั้งค่า" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Bu bölmedeki 1 sekme kapatılacak:\n%@" + "value": "Ayarları Aç" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Це закриє 1 вкладку в цій панелі:\n%@" + "value": "Відкрити налаштування" } } } }, - "dialog.closeOtherTabs.message.other": { + "dialog.enableNotifications.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "This will close %1$lld tabs in this pane:\n%2$@" + "value": "Enable Notifications for cmux" } }, "ja": { "stringUnit": { "state": "translated", - "value": "このペインの %1$lld 個のタブを閉じます:\n%2$@" + "value": "cmuxの通知を有効にする" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "这将关闭此面板中的 %1$lld 个标签页:\n%2$@" + "value": "启用 cmux 通知" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "這將關閉此面板中的 %1$lld 個標籤頁:\n%2$@" + "value": "為 cmux 啟用通知" } }, "ko": { "stringUnit": { "state": "translated", - "value": "이 패널에서 탭 %1$lld개를 닫습니다:\n%2$@" + "value": "cmux 알림 활성화" } }, "de": { "stringUnit": { "state": "translated", - "value": "Dadurch werden %1$lld Tabs in diesem Bereich geschlossen:\n%2$@" + "value": "Benachrichtigungen für cmux aktivieren" } }, "es": { "stringUnit": { "state": "translated", - "value": "Esto cerrará %1$lld pestañas en este panel:\n%2$@" + "value": "Activar notificaciones para cmux" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Cela fermera %1$lld onglets dans ce panneau :\n%2$@" + "value": "Activer les notifications pour cmux" } }, "it": { "stringUnit": { "state": "translated", - "value": "Questa operazione chiuderà %1$lld schede in questo pannello:\n%2$@" + "value": "Abilita notifiche per cmux" } }, "da": { "stringUnit": { "state": "translated", - "value": "Dette lukker %1$lld faner i dette panel:\n%2$@" + "value": "Aktiver notifikationer for cmux" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Spowoduje to zamknięcie %1$lld kart w tym panelu:\n%2$@" + "value": "Włącz powiadomienia dla cmux" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Будет закрыто вкладок в этой панели: %1$lld\n%2$@" + "value": "Включить уведомления для cmux" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Ovo će zatvoriti %1$lld tabova u ovom panelu:\n%2$@" + "value": "Omogući obavještenja za cmux" } }, "ar": { "stringUnit": { "state": "translated", - "value": "سيؤدي هذا إلى إغلاق %1$lld لسان في هذه اللوحة:\n%2$@" + "value": "تفعيل الإشعارات لـ cmux" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Dette vil lukke %1$lld faner i dette panelet:\n%2$@" + "value": "Aktiver varsler for cmux" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Isto fechará %1$lld abas neste painel:\n%2$@" + "value": "Ativar Notificações para o cmux" } }, "th": { "stringUnit": { "state": "translated", - "value": "การดำเนินการนี้จะปิด %1$lld แท็บในบานหน้าต่างนี้:\n%2$@" + "value": "เปิดใช้งานการแจ้งเตือนสำหรับ cmux" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Bu bölmedeki %1$lld sekme kapatılacak:\n%2$@" + "value": "cmux İçin Bildirimleri Etkinleştir" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Це закриє %1$lld вкладок у цій панелі:\n%2$@" + "value": "Увімкнути сповіщення для cmux" } } } }, - "dialog.closeOtherTabs.title": { + "dialog.moveFailed.message": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Close other tabs?" + "value": "cmux could not move this tab to the selected destination." } }, "ja": { "stringUnit": { "state": "translated", - "value": "他のタブを閉じますか?" + "value": "cmuxはこのタブを選択した移動先に移動できませんでした。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "关闭其他标签页?" + "value": "cmux 无法将此标签页移动到所选目标。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "要關閉其他標籤頁嗎?" + "value": "cmux 無法將此標籤頁移至所選的目的地。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "다른 탭을 닫으시겠습니까?" + "value": "cmux에서 이 탭을 선택한 대상으로 이동할 수 없습니다." } }, "de": { "stringUnit": { "state": "translated", - "value": "Andere Tabs schließen?" + "value": "cmux konnte diesen Tab nicht zum ausgewählten Ziel verschieben." } }, "es": { "stringUnit": { "state": "translated", - "value": "¿Cerrar otras pestañas?" + "value": "cmux no pudo mover esta pestaña al destino seleccionado." } }, "fr": { "stringUnit": { "state": "translated", - "value": "Fermer les autres onglets ?" + "value": "cmux n'a pas pu déplacer cet onglet vers la destination sélectionnée." } }, "it": { "stringUnit": { "state": "translated", - "value": "Chiudere le altre schede?" + "value": "cmux non è riuscito a spostare questa scheda nella destinazione selezionata." } }, "da": { "stringUnit": { "state": "translated", - "value": "Luk andre faner?" + "value": "cmux kunne ikke flytte denne fane til den valgte destination." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Zamknąć inne karty?" + "value": "cmux nie mógł przenieść tej karty do wybranego miejsca docelowego." } }, "ru": { "stringUnit": { "state": "translated", - "value": "Закрыть другие вкладки?" + "value": "cmux не удалось переместить эту вкладку в выбранное место назначения." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Zatvoriti ostale tabove?" + "value": "cmux nije mogao premjestiti ovaj tab na odabrano odredište." } }, "ar": { "stringUnit": { "state": "translated", - "value": "إغلاق الألسنة الأخرى؟" + "value": "لم يتمكن cmux من نقل هذا اللسان إلى الوجهة المحددة." } }, "nb": { "stringUnit": { "state": "translated", - "value": "Lukke andre faner?" + "value": "cmux kunne ikke flytte denne fanen til den valgte destinasjonen." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Fechar outras abas?" + "value": "O cmux não conseguiu mover esta aba para o destino selecionado." } }, "th": { "stringUnit": { "state": "translated", - "value": "ปิดแท็บอื่นหรือไม่?" + "value": "cmux ไม่สามารถย้ายแท็บนี้ไปยังปลายทางที่เลือกได้" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Diğer sekmeler kapatılsın mı?" + "value": "cmux bu sekmeyi seçilen hedefe taşıyamadı." } }, "uk": { "stringUnit": { "state": "translated", - "value": "Закрити інші вкладки?" + "value": "cmux не зміг перемістити цю вкладку до вибраного місця призначення." } } } }, - "dialog.closeTab.close": { + "dialog.moveFailed.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Close" + "value": "Move Failed" } }, "ja": { "stringUnit": { "state": "translated", - "value": "閉じる" + "value": "移動失敗" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "关闭" + "value": "移动失败" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "關閉" + "value": "移動失敗" } }, "ko": { "stringUnit": { "state": "translated", - "value": "닫기" + "value": "이동 실패" } }, "de": { "stringUnit": { "state": "translated", - "value": "Schließen" + "value": "Verschieben fehlgeschlagen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Cerrar" + "value": "Error al mover" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Fermer" + "value": "Échec du déplacement" } }, "it": { "stringUnit": { "state": "translated", - "value": "Chiudi" + "value": "Spostamento non riuscito" } }, "da": { "stringUnit": { "state": "translated", - "value": "Luk" + "value": "Flytning mislykkedes" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Zamknij" + "value": "Przenoszenie nie powiodło się" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Закрыть" + "value": "Ошибка перемещения" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Zatvori" + "value": "Premještanje nije uspjelo" } }, "ar": { "stringUnit": { "state": "translated", - "value": "إغلاق" + "value": "فشل النقل" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Lukk" + "value": "Flytting mislyktes" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Fechar" + "value": "Falha ao Mover" } }, "th": { "stringUnit": { "state": "translated", - "value": "ปิด" + "value": "การย้ายล้มเหลว" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Kapat" - } - }, - "uk": { - "stringUnit": { - "state": "translated", - "value": "Закрити" - } - } - } - }, - "dialog.closeTab.cancel": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Cancel" - } - }, - "ja": { - "stringUnit": { - "state": "translated", - "value": "キャンセル" + "value": "Taşıma Başarısız" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Скасувати" - } - }, - "ko": { - "stringUnit": { - "state": "translated", - "value": "취소" + "value": "Помилка переміщення" } } } }, - "dialog.closeTab.message": { + "dialog.moveTab.message": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "This will close the current tab." + "value": "Choose a destination for this tab." } }, "ja": { "stringUnit": { "state": "translated", - "value": "現在のタブを閉じます。" + "value": "このタブの移動先を選択してください。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "这将关闭当前标签页。" + "value": "请为此标签页选择目标位置。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "這將關閉目前的標籤頁。" + "value": "選擇此標籤頁的目的地。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "현재 탭을 닫습니다." + "value": "이 탭의 대상을 선택하세요." } }, "de": { "stringUnit": { "state": "translated", - "value": "Dadurch wird der aktuelle Tab geschlossen." + "value": "Wählen Sie ein Ziel für diesen Tab." } }, "es": { "stringUnit": { "state": "translated", - "value": "Esto cerrará la pestaña actual." + "value": "Elige un destino para esta pestaña." } }, "fr": { "stringUnit": { "state": "translated", - "value": "Cela fermera l'onglet actuel." + "value": "Choisissez une destination pour cet onglet." } }, "it": { "stringUnit": { "state": "translated", - "value": "Questa operazione chiuderà la scheda corrente." + "value": "Scegli una destinazione per questa scheda." } }, "da": { "stringUnit": { "state": "translated", - "value": "Dette lukker den aktuelle fane." + "value": "Vælg en destination for denne fane." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Spowoduje to zamknięcie bieżącej karty." + "value": "Wybierz miejsce docelowe dla tej karty." } }, "ru": { "stringUnit": { "state": "translated", - "value": "Текущая вкладка будет закрыта." + "value": "Выберите место назначения для этой вкладки." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Ovo će zatvoriti trenutni tab." + "value": "Odaberite odredište za ovaj tab." } }, "ar": { "stringUnit": { "state": "translated", - "value": "سيؤدي هذا إلى إغلاق اللسان الحالي." + "value": "اختر وجهة لهذا اللسان." } }, "nb": { "stringUnit": { "state": "translated", - "value": "Dette vil lukke den gjeldende fanen." + "value": "Velg en destinasjon for denne fanen." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Isto fechará a aba atual." + "value": "Escolha um destino para esta aba." } }, "th": { "stringUnit": { "state": "translated", - "value": "การดำเนินการนี้จะปิดแท็บปัจจุบัน" + "value": "เลือกปลายทางสำหรับแท็บนี้" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Bu, geçerli sekmeyi kapatacak." + "value": "Bu sekme için bir hedef seçin." } }, "uk": { "stringUnit": { "state": "translated", - "value": "Це закриє поточну вкладку." - } - } - } - }, - "dialog.closeTab.messageNamed": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "This will close \"%@\"." - } - }, - "ja": { - "stringUnit": { - "state": "translated", - "value": "「%@」を閉じます。" - } - }, - "uk": { - "stringUnit": { - "state": "translated", - "value": "Це закриє \"%@\"." - } - }, - "ko": { - "stringUnit": { - "state": "translated", - "value": "\"%@\"을(를) 닫습니다." + "value": "Виберіть місце призначення для цієї вкладки." } } } }, - "dialog.closeTab.title": { + "dialog.moveTab.move": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Close tab?" + "value": "Move" } }, "ja": { "stringUnit": { "state": "translated", - "value": "タブを閉じますか?" + "value": "移動" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "关闭标签页?" + "value": "移动" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "要關閉標籤頁嗎?" + "value": "移動" } }, "ko": { "stringUnit": { "state": "translated", - "value": "탭을 닫으시겠습니까?" + "value": "이동" } }, "de": { "stringUnit": { "state": "translated", - "value": "Tab schließen?" + "value": "Verschieben" } }, "es": { "stringUnit": { "state": "translated", - "value": "¿Cerrar pestaña?" + "value": "Mover" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Fermer l'onglet ?" + "value": "Déplacer" } }, "it": { "stringUnit": { "state": "translated", - "value": "Chiudere la scheda?" + "value": "Sposta" } }, "da": { "stringUnit": { "state": "translated", - "value": "Luk fane?" + "value": "Flyt" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Zamknąć kartę?" + "value": "Przenieś" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Закрыть вкладку?" + "value": "Переместить" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Zatvoriti tab?" + "value": "Premjesti" } }, "ar": { "stringUnit": { "state": "translated", - "value": "إغلاق اللسان؟" + "value": "نقل" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Lukke fane?" + "value": "Flytt" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Fechar aba?" + "value": "Mover" } }, "th": { "stringUnit": { "state": "translated", - "value": "ปิดแท็บหรือไม่?" + "value": "ย้าย" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Sekme kapatılsın mı?" + "value": "Taşı" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Закрити вкладку?" + "value": "Перемістити" } } } }, - "dialog.closeWindow.message": { + "dialog.moveTab.newWorkspaceCurrentWindow": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "This will close the current window and all of its workspaces." + "value": "New Workspace in Current Window" } }, "ja": { "stringUnit": { "state": "translated", - "value": "現在のウィンドウとそのすべてのワークスペースを閉じます。" - } - }, - "uk": { - "stringUnit": { - "state": "translated", - "value": "Це закриє поточне вікно та всі його робочі області." - } - }, - "ko": { - "stringUnit": { - "state": "translated", - "value": "현재 윈도우와 모든 워크스페이스가 닫힙니다." - } - } - } - }, - "dialog.closeWindow.title": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Close window?" + "value": "現在のウインドウの新規ワークスペース" } }, - "ja": { + "zh-Hans": { "stringUnit": { "state": "translated", - "value": "ウィンドウを閉じますか?" + "value": "当前窗口的新工作区" } }, - "uk": { + "zh-Hant": { "stringUnit": { "state": "translated", - "value": "Закрити вікно?" + "value": "目前視窗的新工作區" } }, "ko": { "stringUnit": { "state": "translated", - "value": "윈도우를 닫으시겠습니까?" - } - } - } - }, - "dialog.closeWorkspaces.message": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "This will close %1$lld workspaces and all of their panels:\n%2$@" + "value": "현재 윈도우의 새 작업 공간" } }, - "ja": { + "de": { "stringUnit": { "state": "translated", - "value": "%1$lld 個のワークスペースと、それぞれのすべてのパネルを閉じます:\n%2$@" + "value": "Neuer Arbeitsbereich im aktuellen Fenster" } }, - "uk": { + "es": { "stringUnit": { "state": "translated", - "value": "Це закриє %1$lld робочих областей та всі їхні панелі:\n%2$@" + "value": "Nuevo espacio de trabajo en la ventana actual" } }, - "ko": { - "stringUnit": { - "state": "translated", - "value": "%1$lld개의 워크스페이스와 모든 패널이 닫힙니다:\n%2$@" - } - } - } - }, - "dialog.closeWorkspaces.title": { - "extractionState": "manual", - "localizations": { - "en": { + "fr": { "stringUnit": { "state": "translated", - "value": "Close workspaces?" + "value": "Nouvel espace de travail dans la fenêtre actuelle" } }, - "ja": { + "it": { "stringUnit": { "state": "translated", - "value": "ワークスペースを閉じますか?" + "value": "Nuova area di lavoro nella finestra corrente" } }, - "uk": { + "da": { "stringUnit": { "state": "translated", - "value": "Закрити робочі області?" + "value": "Nyt arbejdsområde i nuværende vindue" } }, - "ko": { - "stringUnit": { - "state": "translated", - "value": "워크스페이스를 닫으시겠습니까?" - } - } - } - }, - "dialog.closeWorkspacesWindow.message": { - "extractionState": "manual", - "localizations": { - "en": { + "pl": { "stringUnit": { "state": "translated", - "value": "This will close the current window, its %1$lld workspaces, and all of their panels:\n%2$@" + "value": "Nowa przestrzeń robocza w bieżącym oknie" } }, - "ja": { + "ru": { "stringUnit": { "state": "translated", - "value": "現在のウィンドウと、その %1$lld 個のワークスペースと、それぞれのすべてのパネルを閉じます:\n%2$@" + "value": "Новое рабочее пространство в текущем окне" } }, - "uk": { + "bs": { "stringUnit": { "state": "translated", - "value": "Це закриє поточне вікно, його %1$lld робочих областей та всі їхні панелі:\n%2$@" + "value": "Novi radni prostor u trenutnom prozoru" } }, - "ko": { - "stringUnit": { - "state": "translated", - "value": "현재 윈도우, %1$lld개의 워크스페이스 및 모든 패널이 닫힙니다:\n%2$@" - } - } - } - }, - "dialog.closePinnedWorkspace.message": { - "extractionState": "manual", - "localizations": { - "en": { + "ar": { "stringUnit": { "state": "translated", - "value": "This workspace is pinned. Closing it will close the workspace and all of its panels." + "value": "مساحة عمل جديدة في النافذة الحالية" } }, - "ja": { + "nb": { "stringUnit": { "state": "translated", - "value": "このワークスペースはピン留めされています。閉じると、このワークスペースとその中のすべてのパネルが閉じます。" + "value": "Nytt arbeidsområde i gjeldende vindu" } }, - "uk": { + "pt-BR": { "stringUnit": { "state": "translated", - "value": "Ця робоча область закріплена. Закриття видалить робочу область та всі її панелі." + "value": "Nova Área de Trabalho na Janela Atual" } }, - "ko": { - "stringUnit": { - "state": "translated", - "value": "이 워크스페이스는 고정되어 있습니다. 닫으면 워크스페이스와 모든 패널이 닫힙니다." - } - } - } - }, - "dialog.closePinnedWorkspace.title": { - "extractionState": "manual", - "localizations": { - "en": { + "th": { "stringUnit": { "state": "translated", - "value": "Close pinned workspace?" + "value": "เวิร์กสเปซใหม่ในหน้าต่างปัจจุบัน" } }, - "ja": { + "tr": { "stringUnit": { "state": "translated", - "value": "ピン留めされたワークスペースを閉じますか?" + "value": "Geçerli Pencerede Yeni Çalışma Alanı" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Закрити закріплену робочу область?" - } - }, - "ko": { - "stringUnit": { - "state": "translated", - "value": "고정된 워크스페이스를 닫으시겠습니까?" + "value": "Нова робоча область у поточному вікні" } } } }, - "dialog.closeWorkspace.message": { + "dialog.moveTab.selectedWorkspaceNewWindow": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "This will close the workspace and all of its panels." + "value": "Selected Workspace in New Window" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ワークスペースとそのすべてのパネルを閉じます。" + "value": "選択したワークスペースを新規ウインドウに" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "这将关闭工作区及其所有面板。" + "value": "新窗口中的所选工作区" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "這將關閉工作區及其所有面板。" + "value": "所選工作區至新視窗" } }, "ko": { "stringUnit": { "state": "translated", - "value": "작업 공간과 모든 패널을 닫습니다." + "value": "선택한 작업 공간을 새 윈도우로" } }, "de": { "stringUnit": { "state": "translated", - "value": "Dadurch werden der Arbeitsbereich und alle zugehörigen Bereiche geschlossen." + "value": "Ausgewählter Arbeitsbereich in neuem Fenster" } }, "es": { "stringUnit": { "state": "translated", - "value": "Esto cerrará el espacio de trabajo y todos sus paneles." + "value": "Espacio de trabajo seleccionado en nueva ventana" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Cela fermera l'espace de travail et tous ses panneaux." + "value": "Espace de travail sélectionné dans une nouvelle fenêtre" } }, "it": { "stringUnit": { "state": "translated", - "value": "Questa operazione chiuderà l'area di lavoro e tutti i suoi pannelli." + "value": "Area di lavoro selezionata in una nuova finestra" } }, "da": { "stringUnit": { "state": "translated", - "value": "Dette lukker arbejdsområdet og alle dets paneler." + "value": "Valgt arbejdsområde i nyt vindue" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Spowoduje to zamknięcie przestrzeni roboczej i wszystkich jej paneli." + "value": "Wybrana przestrzeń robocza w nowym oknie" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Рабочее пространство и все его панели будут закрыты." + "value": "Выбранное рабочее пространство в новом окне" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Ovo će zatvoriti radni prostor i sve njegove panele." + "value": "Odabrani radni prostor u novom prozoru" } }, "ar": { "stringUnit": { "state": "translated", - "value": "سيؤدي هذا إلى إغلاق مساحة العمل وجميع لوحاتها." + "value": "مساحة العمل المحددة في نافذة جديدة" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Dette vil lukke arbeidsområdet og alle panelene." + "value": "Valgt arbeidsområde i nytt vindu" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Isto fechará a área de trabalho e todos os seus painéis." + "value": "Área de Trabalho Selecionada em Nova Janela" } }, "th": { "stringUnit": { "state": "translated", - "value": "การดำเนินการนี้จะปิดเวิร์กสเปซและแผงทั้งหมด" + "value": "เวิร์กสเปซที่เลือกในหน้าต่างใหม่" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Bu, çalışma alanını ve tüm panellerini kapatacak." + "value": "Yeni Pencerede Seçili Çalışma Alanı" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Це закриє робочу область та всі її панелі." + "value": "Вибрана робоча область у новому вікні" } } } }, - "dialog.closeWorkspace.title": { + "dialog.moveTab.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Close workspace?" + "value": "Move Tab" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ワークスペースを閉じますか?" + "value": "タブの移動" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "关闭工作区?" + "value": "移动标签页" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "要關閉工作區嗎?" + "value": "移動標籤頁" } }, "ko": { "stringUnit": { "state": "translated", - "value": "작업 공간을 닫으시겠습니까?" + "value": "탭 이동" } }, "de": { "stringUnit": { "state": "translated", - "value": "Arbeitsbereich schließen?" + "value": "Tab verschieben" } }, "es": { "stringUnit": { "state": "translated", - "value": "¿Cerrar espacio de trabajo?" + "value": "Mover pestaña" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Fermer l'espace de travail ?" + "value": "Déplacer l'onglet" } }, "it": { "stringUnit": { "state": "translated", - "value": "Chiudere l'area di lavoro?" + "value": "Sposta scheda" } }, "da": { "stringUnit": { "state": "translated", - "value": "Luk arbejdsområde?" + "value": "Flyt fane" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Zamknąć przestrzeń roboczą?" + "value": "Przenieś kartę" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Закрыть рабочее пространство?" + "value": "Переместить вкладку" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Zatvoriti radni prostor?" + "value": "Premjesti tab" } }, "ar": { "stringUnit": { "state": "translated", - "value": "إغلاق مساحة العمل؟" + "value": "نقل اللسان" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Lukke arbeidsområde?" + "value": "Flytt fane" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Fechar área de trabalho?" + "value": "Mover Aba" } }, "th": { "stringUnit": { "state": "translated", - "value": "ปิดเวิร์กสเปซหรือไม่?" + "value": "ย้ายแท็บ" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Çalışma alanı kapatılsın mı?" + "value": "Sekmeyi Taşı" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Закрити робочу область?" + "value": "Перемістити вкладку" } } } }, - "dialog.dontWarnCmdQ": { + "dialog.quitCmux.message": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Don't warn again for Cmd+Q" + "value": "This will close all windows and workspaces." } }, "ja": { "stringUnit": { "state": "translated", - "value": "Cmd+Q の警告を表示しない" + "value": "すべてのウインドウとワークスペースを閉じます。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "不再提示 Cmd+Q 警告" + "value": "这将关闭所有窗口和工作区。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "不再顯示 Cmd+Q 警告" + "value": "這將關閉所有視窗和工作區。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "Cmd+Q에 대해 다시 경고하지 않기" + "value": "모든 윈도우와 작업 공간을 닫습니다." } }, "de": { "stringUnit": { "state": "translated", - "value": "Nicht erneut bei Cmd+Q warnen" + "value": "Dadurch werden alle Fenster und Arbeitsbereiche geschlossen." } }, "es": { "stringUnit": { "state": "translated", - "value": "No volver a advertir para Cmd+Q" + "value": "Esto cerrará todas las ventanas y espacios de trabajo." } }, "fr": { "stringUnit": { "state": "translated", - "value": "Ne plus avertir pour Cmd+Q" + "value": "Cela fermera toutes les fenêtres et tous les espaces de travail." } }, "it": { "stringUnit": { "state": "translated", - "value": "Non avvisare più per Cmd+Q" + "value": "Questa operazione chiuderà tutte le finestre e le aree di lavoro." } }, "da": { "stringUnit": { "state": "translated", - "value": "Advar ikke igen for Cmd+Q" + "value": "Dette lukker alle vinduer og arbejdsområder." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Nie ostrzegaj ponownie przy Cmd+Q" + "value": "Spowoduje to zamknięcie wszystkich okien i przestrzeni roboczych." } }, "ru": { "stringUnit": { "state": "translated", - "value": "Больше не предупреждать при Cmd+Q" + "value": "Все окна и рабочие пространства будут закрыты." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Ne upozoravaj ponovo za Cmd+Q" + "value": "Ovo će zatvoriti sve prozore i radne prostore." } }, "ar": { "stringUnit": { "state": "translated", - "value": "عدم التحذير مجددًا عند Cmd+Q" + "value": "سيؤدي هذا إلى إغلاق جميع النوافذ ومساحات العمل." } }, "nb": { "stringUnit": { "state": "translated", - "value": "Ikke advar igjen for Cmd+Q" + "value": "Dette vil lukke alle vinduer og arbeidsområder." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Não avisar novamente para Cmd+Q" + "value": "Isto fechará todas as janelas e áreas de trabalho." } }, "th": { "stringUnit": { "state": "translated", - "value": "ไม่ต้องเตือนอีกสำหรับ Cmd+Q" + "value": "การดำเนินการนี้จะปิดหน้าต่างและเวิร์กสเปซทั้งหมด" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Cmd+Q için bir daha uyarma" + "value": "Bu, tüm pencereleri ve çalışma alanlarını kapatacak." } }, "uk": { "stringUnit": { "state": "translated", - "value": "Більше не попереджувати про Cmd+Q" + "value": "Це закриє всі вікна та робочі області." } } } }, - "dialog.enableNotifications.message": { + "dialog.quitCmux.quit": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Notifications are disabled for cmux. Enable them in System Settings to see alerts." + "value": "Quit" } }, "ja": { "stringUnit": { "state": "translated", - "value": "cmuxの通知が無効になっています。アラートを表示するにはシステム設定で有効にしてください。" + "value": "終了" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "cmux 的通知已被禁用。请在系统设置中启用通知以接收提醒。" + "value": "退出" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "cmux 的通知已停用。請在「系統設定」中啟用,以接收提示。" + "value": "結束" } }, "ko": { "stringUnit": { "state": "translated", - "value": "cmux에 대한 알림이 비활성화되어 있습니다. 알림을 보려면 시스템 설정에서 활성화하세요." + "value": "종료" } }, "de": { "stringUnit": { "state": "translated", - "value": "Benachrichtigungen sind für cmux deaktiviert. Aktivieren Sie sie in den Systemeinstellungen, um Hinweise zu sehen." + "value": "Beenden" } }, "es": { "stringUnit": { "state": "translated", - "value": "Las notificaciones están desactivadas para cmux. Actívalas en Ajustes del Sistema para ver alertas." + "value": "Salir" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Les notifications sont désactivées pour cmux. Activez-les dans les Réglages Système pour voir les alertes." + "value": "Quitter" } }, "it": { "stringUnit": { "state": "translated", - "value": "Le notifiche sono disabilitate per cmux. Abilitale nelle Impostazioni di Sistema per visualizzare gli avvisi." + "value": "Esci" } }, "da": { "stringUnit": { "state": "translated", - "value": "Notifikationer er deaktiveret for cmux. Aktiver dem i Systemindstillinger for at se advarsler." + "value": "Afslut" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Powiadomienia są wyłączone dla cmux. Włącz je w Ustawieniach systemowych, aby widzieć alerty." + "value": "Zakończ" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Уведомления для cmux отключены. Включите их в Системных настройках, чтобы видеть оповещения." + "value": "Завершить" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Obavještenja su onemogućena za cmux. Omogućite ih u Postavkama sistema da biste vidjeli upozorenja." + "value": "Zatvori" } }, "ar": { "stringUnit": { "state": "translated", - "value": "الإشعارات معطلة لـ cmux. قم بتفعيلها في إعدادات النظام لرؤية التنبيهات." + "value": "إنهاء" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Varsler er deaktivert for cmux. Aktiver dem i Systeminnstillinger for å se varsler." + "value": "Avslutt" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "As notificações estão desativadas para o cmux. Ative-as nos Ajustes do Sistema para ver os alertas." + "value": "Encerrar" } }, "th": { "stringUnit": { "state": "translated", - "value": "การแจ้งเตือนถูกปิดใช้งานสำหรับ cmux เปิดใช้งานในการตั้งค่าระบบเพื่อดูการแจ้งเตือน" + "value": "ออก" } }, "tr": { "stringUnit": { "state": "translated", - "value": "cmux için bildirimler devre dışı. Uyarıları görmek için Sistem Ayarları'nda etkinleştirin." + "value": "Çık" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Сповіщення для cmux вимкнено. Увімкніть їх у Системних налаштуваннях, щоб бачити повідомлення." + "value": "Завершити" } } } }, - "dialog.enableNotifications.notNow": { + "dialog.quitCmux.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Not Now" + "value": "Quit cmux?" } }, "ja": { "stringUnit": { "state": "translated", - "value": "今はしない" + "value": "cmux を終了しますか?" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "以后再说" + "value": "退出 cmux?" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "現在不要" + "value": "要結束 cmux 嗎?" } }, "ko": { "stringUnit": { "state": "translated", - "value": "나중에" + "value": "cmux를 종료하시겠습니까?" } }, "de": { "stringUnit": { "state": "translated", - "value": "Nicht jetzt" + "value": "cmux beenden?" } }, "es": { "stringUnit": { "state": "translated", - "value": "Ahora no" + "value": "¿Salir de cmux?" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Pas maintenant" + "value": "Quitter cmux ?" } }, "it": { "stringUnit": { "state": "translated", - "value": "Non ora" + "value": "Uscire da cmux?" } }, "da": { "stringUnit": { "state": "translated", - "value": "Ikke nu" + "value": "Afslut cmux?" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Nie teraz" + "value": "Zakończyć cmux?" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Не сейчас" + "value": "Завершить cmux?" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Ne sada" + "value": "Zatvoriti cmux?" } }, "ar": { "stringUnit": { "state": "translated", - "value": "ليس الآن" + "value": "إنهاء cmux؟" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Ikke nå" + "value": "Avslutte cmux?" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Agora Não" + "value": "Encerrar o cmux?" } }, "th": { "stringUnit": { "state": "translated", - "value": "ไม่ใช่ตอนนี้" + "value": "ออกจาก cmux หรือไม่?" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Şimdi Değil" + "value": "cmux'tan çıkılsın mı?" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Не зараз" + "value": "Завершити cmux?" } } } }, - "dialog.enableNotifications.openSettings": { + "dialog.renameTab.message": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Open Settings" + "value": "Enter a custom name for this tab." } }, "ja": { "stringUnit": { "state": "translated", - "value": "設定を開く" + "value": "このタブのカスタム名を入力してください。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "打开设置" + "value": "请为此标签页输入自定义名称。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "開啟設定" + "value": "為此標籤頁輸入自訂名稱。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "설정 열기" + "value": "이 탭의 사용자 지정 이름을 입력하세요." } }, "de": { "stringUnit": { "state": "translated", - "value": "Einstellungen öffnen" + "value": "Geben Sie einen benutzerdefinierten Namen für diesen Tab ein." } }, "es": { "stringUnit": { "state": "translated", - "value": "Abrir Ajustes" + "value": "Introduce un nombre personalizado para esta pestaña." } }, "fr": { "stringUnit": { "state": "translated", - "value": "Ouvrir les réglages" + "value": "Saisissez un nom personnalisé pour cet onglet." } }, "it": { "stringUnit": { "state": "translated", - "value": "Apri impostazioni" + "value": "Inserisci un nome personalizzato per questa scheda." } }, "da": { "stringUnit": { "state": "translated", - "value": "Åbn indstillinger" + "value": "Indtast et brugerdefineret navn til denne fane." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Otwórz ustawienia" + "value": "Wprowadź własną nazwę dla tej karty." } }, "ru": { "stringUnit": { "state": "translated", - "value": "Открыть настройки" + "value": "Введите пользовательское имя для этой вкладки." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Otvori postavke" + "value": "Unesite prilagođeni naziv za ovaj tab." } }, "ar": { "stringUnit": { "state": "translated", - "value": "فتح الإعدادات" + "value": "أدخل اسمًا مخصصًا لهذا اللسان." } }, "nb": { "stringUnit": { "state": "translated", - "value": "Åpne innstillinger" + "value": "Skriv inn et egendefinert navn for denne fanen." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Abrir Ajustes" + "value": "Insira um nome personalizado para esta aba." } }, "th": { "stringUnit": { "state": "translated", - "value": "เปิดการตั้งค่า" + "value": "ป้อนชื่อที่กำหนดเองสำหรับแท็บนี้" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Ayarları Aç" + "value": "Bu sekme için özel bir ad girin." } }, "uk": { "stringUnit": { "state": "translated", - "value": "Відкрити налаштування" + "value": "Введіть власну назву для цієї вкладки." } } } }, - "dialog.enableNotifications.title": { + "dialog.renameTab.placeholder": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Enable Notifications for cmux" + "value": "Tab name" } }, "ja": { "stringUnit": { "state": "translated", - "value": "cmuxの通知を有効にする" + "value": "タブ名" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "启用 cmux 通知" + "value": "标签页名称" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "為 cmux 啟用通知" + "value": "標籤頁名稱" } }, "ko": { "stringUnit": { "state": "translated", - "value": "cmux 알림 활성화" + "value": "탭 이름" } }, "de": { "stringUnit": { "state": "translated", - "value": "Benachrichtigungen für cmux aktivieren" + "value": "Tab-Name" } }, "es": { "stringUnit": { "state": "translated", - "value": "Activar notificaciones para cmux" + "value": "Nombre de pestaña" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Activer les notifications pour cmux" + "value": "Nom de l'onglet" } }, "it": { "stringUnit": { "state": "translated", - "value": "Abilita notifiche per cmux" + "value": "Nome scheda" } }, "da": { "stringUnit": { "state": "translated", - "value": "Aktiver notifikationer for cmux" + "value": "Fanenavn" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Włącz powiadomienia dla cmux" + "value": "Nazwa karty" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Включить уведомления для cmux" + "value": "Имя вкладки" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Omogući obavještenja za cmux" + "value": "Naziv taba" } }, "ar": { "stringUnit": { "state": "translated", - "value": "تفعيل الإشعارات لـ cmux" + "value": "اسم اللسان" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Aktiver varsler for cmux" + "value": "Fanenavn" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Ativar Notificações para o cmux" + "value": "Nome da aba" } }, "th": { "stringUnit": { "state": "translated", - "value": "เปิดใช้งานการแจ้งเตือนสำหรับ cmux" + "value": "ชื่อแท็บ" } }, "tr": { "stringUnit": { "state": "translated", - "value": "cmux İçin Bildirimleri Etkinleştir" + "value": "Sekme adı" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Увімкнути сповіщення для cmux" + "value": "Назва вкладки" } } } }, - "dialog.moveFailed.message": { + "dialog.renameTab.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "cmux could not move this tab to the selected destination." + "value": "Rename Tab" } }, "ja": { "stringUnit": { "state": "translated", - "value": "cmuxはこのタブを選択した移動先に移動できませんでした。" + "value": "タブの名称変更" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "cmux 无法将此标签页移动到所选目标。" + "value": "重命名标签页" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "cmux 無法將此標籤頁移至所選的目的地。" + "value": "重新命名標籤頁" } }, "ko": { "stringUnit": { "state": "translated", - "value": "cmux에서 이 탭을 선택한 대상으로 이동할 수 없습니다." + "value": "탭 이름 변경" } }, "de": { "stringUnit": { "state": "translated", - "value": "cmux konnte diesen Tab nicht zum ausgewählten Ziel verschieben." + "value": "Tab umbenennen" } }, "es": { "stringUnit": { "state": "translated", - "value": "cmux no pudo mover esta pestaña al destino seleccionado." + "value": "Renombrar pestaña" } }, "fr": { "stringUnit": { "state": "translated", - "value": "cmux n'a pas pu déplacer cet onglet vers la destination sélectionnée." + "value": "Renommer l'onglet" } }, "it": { "stringUnit": { "state": "translated", - "value": "cmux non è riuscito a spostare questa scheda nella destinazione selezionata." + "value": "Rinomina scheda" } }, "da": { "stringUnit": { "state": "translated", - "value": "cmux kunne ikke flytte denne fane til den valgte destination." + "value": "Omdøb fane" } }, "pl": { "stringUnit": { "state": "translated", - "value": "cmux nie mógł przenieść tej karty do wybranego miejsca docelowego." + "value": "Zmień nazwę karty" } }, "ru": { "stringUnit": { "state": "translated", - "value": "cmux не удалось переместить эту вкладку в выбранное место назначения." + "value": "Переименовать вкладку" } }, "bs": { "stringUnit": { "state": "translated", - "value": "cmux nije mogao premjestiti ovaj tab na odabrano odredište." + "value": "Preimenuj tab" } }, "ar": { "stringUnit": { "state": "translated", - "value": "لم يتمكن cmux من نقل هذا اللسان إلى الوجهة المحددة." + "value": "إعادة تسمية اللسان" } }, "nb": { "stringUnit": { "state": "translated", - "value": "cmux kunne ikke flytte denne fanen til den valgte destinasjonen." + "value": "Gi fanen nytt navn" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "O cmux não conseguiu mover esta aba para o destino selecionado." + "value": "Renomear Aba" } }, "th": { "stringUnit": { "state": "translated", - "value": "cmux ไม่สามารถย้ายแท็บนี้ไปยังปลายทางที่เลือกได้" + "value": "เปลี่ยนชื่อแท็บ" } }, "tr": { "stringUnit": { "state": "translated", - "value": "cmux bu sekmeyi seçilen hedefe taşıyamadı." + "value": "Sekmeyi Yeniden Adlandır" } }, "uk": { "stringUnit": { "state": "translated", - "value": "cmux не зміг перемістити цю вкладку до вибраного місця призначення." + "value": "Перейменувати вкладку" } } } }, - "dialog.moveFailed.title": { + "dialog.renameWorkspace.message": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Move Failed" + "value": "Enter a custom name for this workspace." } }, "ja": { "stringUnit": { "state": "translated", - "value": "移動失敗" + "value": "このワークスペースのカスタム名を入力してください。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "移动失败" + "value": "请为此工作区输入自定义名称。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "移動失敗" + "value": "為此工作區輸入自訂名稱。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "이동 실패" + "value": "이 작업 공간의 사용자 지정 이름을 입력하세요." } }, "de": { "stringUnit": { "state": "translated", - "value": "Verschieben fehlgeschlagen" + "value": "Geben Sie einen benutzerdefinierten Namen für diesen Arbeitsbereich ein." } }, "es": { "stringUnit": { "state": "translated", - "value": "Error al mover" + "value": "Introduce un nombre personalizado para este espacio de trabajo." } }, "fr": { "stringUnit": { "state": "translated", - "value": "Échec du déplacement" + "value": "Saisissez un nom personnalisé pour cet espace de travail." } }, "it": { "stringUnit": { "state": "translated", - "value": "Spostamento non riuscito" + "value": "Inserisci un nome personalizzato per questa area di lavoro." } }, "da": { "stringUnit": { "state": "translated", - "value": "Flytning mislykkedes" + "value": "Indtast et brugerdefineret navn til dette arbejdsområde." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Przenoszenie nie powiodło się" + "value": "Wprowadź własną nazwę dla tej przestrzeni roboczej." } }, "ru": { "stringUnit": { "state": "translated", - "value": "Ошибка перемещения" + "value": "Введите пользовательское имя для этого рабочего пространства." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Premještanje nije uspjelo" + "value": "Unesite prilagođeni naziv za ovaj radni prostor." } }, "ar": { "stringUnit": { "state": "translated", - "value": "فشل النقل" + "value": "أدخل اسمًا مخصصًا لمساحة العمل هذه." } }, "nb": { "stringUnit": { "state": "translated", - "value": "Flytting mislyktes" + "value": "Skriv inn et egendefinert navn for dette arbeidsområdet." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Falha ao Mover" + "value": "Insira um nome personalizado para esta área de trabalho." } }, "th": { "stringUnit": { "state": "translated", - "value": "การย้ายล้มเหลว" + "value": "ป้อนชื่อที่กำหนดเองสำหรับเวิร์กสเปซนี้" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Taşıma Başarısız" + "value": "Bu çalışma alanı için özel bir ad girin." } }, "uk": { "stringUnit": { "state": "translated", - "value": "Помилка переміщення" + "value": "Введіть власну назву для цієї робочої області." } } } }, - "dialog.moveTab.message": { + "dialog.renameWorkspace.placeholder": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Choose a destination for this tab." + "value": "Workspace name" } }, "ja": { "stringUnit": { "state": "translated", - "value": "このタブの移動先を選択してください。" + "value": "ワークスペース名" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "请为此标签页选择目标位置。" + "value": "工作区名称" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "選擇此標籤頁的目的地。" + "value": "工作區名稱" } }, "ko": { "stringUnit": { "state": "translated", - "value": "이 탭의 대상을 선택하세요." + "value": "작업 공간 이름" } }, "de": { "stringUnit": { "state": "translated", - "value": "Wählen Sie ein Ziel für diesen Tab." + "value": "Name des Arbeitsbereichs" } }, "es": { "stringUnit": { "state": "translated", - "value": "Elige un destino para esta pestaña." + "value": "Nombre del espacio de trabajo" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Choisissez une destination pour cet onglet." + "value": "Nom de l'espace de travail" } }, "it": { "stringUnit": { "state": "translated", - "value": "Scegli una destinazione per questa scheda." + "value": "Nome area di lavoro" } }, "da": { "stringUnit": { "state": "translated", - "value": "Vælg en destination for denne fane." + "value": "Arbejdsområdenavn" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Wybierz miejsce docelowe dla tej karty." + "value": "Nazwa przestrzeni roboczej" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Выберите место назначения для этой вкладки." + "value": "Имя рабочего пространства" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Odaberite odredište za ovaj tab." + "value": "Naziv radnog prostora" } }, "ar": { "stringUnit": { "state": "translated", - "value": "اختر وجهة لهذا اللسان." + "value": "اسم مساحة العمل" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Velg en destinasjon for denne fanen." + "value": "Arbeidsområdenavn" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Escolha um destino para esta aba." + "value": "Nome da área de trabalho" } }, "th": { "stringUnit": { "state": "translated", - "value": "เลือกปลายทางสำหรับแท็บนี้" + "value": "ชื่อเวิร์กสเปซ" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Bu sekme için bir hedef seçin." + "value": "Çalışma alanı adı" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Виберіть місце призначення для цієї вкладки." + "value": "Назва робочої області" } } } }, - "dialog.moveTab.move": { + "dialog.renameWorkspace.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Move" + "value": "Rename Workspace" } }, "ja": { "stringUnit": { "state": "translated", - "value": "移動" + "value": "ワークスペースの名称変更" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "移动" + "value": "重命名工作区" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "移動" + "value": "重新命名工作區" } }, "ko": { "stringUnit": { "state": "translated", - "value": "이동" + "value": "작업 공간 이름 변경" } }, "de": { "stringUnit": { "state": "translated", - "value": "Verschieben" + "value": "Arbeitsbereich umbenennen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Mover" + "value": "Renombrar espacio de trabajo" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Déplacer" + "value": "Renommer l'espace de travail" } }, "it": { "stringUnit": { "state": "translated", - "value": "Sposta" + "value": "Rinomina area di lavoro" } }, "da": { "stringUnit": { "state": "translated", - "value": "Flyt" + "value": "Omdøb arbejdsområde" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Przenieś" + "value": "Zmień nazwę przestrzeni roboczej" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Переместить" + "value": "Переименовать рабочее пространство" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Premjesti" + "value": "Preimenuj radni prostor" } }, "ar": { "stringUnit": { "state": "translated", - "value": "نقل" + "value": "إعادة تسمية مساحة العمل" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Flytt" + "value": "Gi arbeidsområdet nytt navn" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Mover" + "value": "Renomear Área de Trabalho" } }, "th": { "stringUnit": { "state": "translated", - "value": "ย้าย" + "value": "เปลี่ยนชื่อเวิร์กสเปซ" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Taşı" + "value": "Çalışma Alanını Yeniden Adlandır" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Перемістити" + "value": "Перейменувати робочу область" } } } }, - "dialog.moveTab.newWorkspaceCurrentWindow": { + "error.clipboardFolderPath": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "New Workspace in Current Window" + "value": "Could not load any folder path from the clipboard." } }, "ja": { "stringUnit": { "state": "translated", - "value": "現在のウインドウの新規ワークスペース" + "value": "クリップボードからフォルダパスを読み込めませんでした。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "当前窗口的新工作区" + "value": "无法从剪贴板加载文件夹路径。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "目前視窗的新工作區" + "value": "無法從剪貼簿載入資料夾路徑。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "현재 윈도우의 새 작업 공간" + "value": "클립보드에서 폴더 경로를 불러올 수 없습니다." } }, "de": { "stringUnit": { "state": "translated", - "value": "Neuer Arbeitsbereich im aktuellen Fenster" + "value": "Es konnte kein Ordnerpfad aus der Zwischenablage geladen werden." } }, "es": { "stringUnit": { "state": "translated", - "value": "Nuevo espacio de trabajo en la ventana actual" + "value": "No se pudo cargar ninguna ruta de carpeta desde el portapapeles." } }, "fr": { "stringUnit": { "state": "translated", - "value": "Nouvel espace de travail dans la fenêtre actuelle" + "value": "Impossible de charger un chemin de dossier depuis le presse-papiers." } }, "it": { "stringUnit": { "state": "translated", - "value": "Nuova area di lavoro nella finestra corrente" + "value": "Impossibile caricare un percorso cartella dagli appunti." } }, "da": { "stringUnit": { "state": "translated", - "value": "Nyt arbejdsområde i nuværende vindue" + "value": "Kunne ikke indlæse nogen mappesti fra udklipsholderen." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Nowa przestrzeń robocza w bieżącym oknie" + "value": "Nie udało się wczytać ścieżki folderu ze schowka." } }, "ru": { "stringUnit": { "state": "translated", - "value": "Новое рабочее пространство в текущем окне" + "value": "Не удалось загрузить путь к папке из буфера обмена." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Novi radni prostor u trenutnom prozoru" + "value": "Nije moguće učitati putanju foldera iz međuspremnika." } }, "ar": { "stringUnit": { "state": "translated", - "value": "مساحة عمل جديدة في النافذة الحالية" + "value": "تعذر تحميل أي مسار مجلد من الحافظة." } }, "nb": { "stringUnit": { "state": "translated", - "value": "Nytt arbeidsområde i gjeldende vindu" + "value": "Kunne ikke laste inn noen mappesti fra utklippstavlen." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Nova Área de Trabalho na Janela Atual" + "value": "Não foi possível carregar nenhum caminho de pasta da área de transferência." } }, "th": { "stringUnit": { "state": "translated", - "value": "เวิร์กสเปซใหม่ในหน้าต่างปัจจุบัน" + "value": "ไม่สามารถโหลดเส้นทางโฟลเดอร์จากคลิปบอร์ดได้" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Geçerli Pencerede Yeni Çalışma Alanı" + "value": "Panodan herhangi bir klasör yolu yüklenemedi." } }, "uk": { "stringUnit": { "state": "translated", - "value": "Нова робоча область у поточному вікні" + "value": "Не вдалося завантажити шлях до теки з буфера обміну." } } } }, - "dialog.moveTab.selectedWorkspaceNewWindow": { + "language.system": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Selected Workspace in New Window" + "value": "System" } }, "ja": { "stringUnit": { "state": "translated", - "value": "選択したワークスペースを新規ウインドウに" + "value": "システム" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "新窗口中的所选工作区" + "value": "系统" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "所選工作區至新視窗" + "value": "系統" } }, "ko": { "stringUnit": { "state": "translated", - "value": "선택한 작업 공간을 새 윈도우로" + "value": "시스템" } }, "de": { "stringUnit": { "state": "translated", - "value": "Ausgewählter Arbeitsbereich in neuem Fenster" + "value": "System" } }, "es": { "stringUnit": { "state": "translated", - "value": "Espacio de trabajo seleccionado en nueva ventana" + "value": "Sistema" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Espace de travail sélectionné dans une nouvelle fenêtre" + "value": "Système" } }, "it": { "stringUnit": { "state": "translated", - "value": "Area di lavoro selezionata in una nuova finestra" + "value": "Sistema" } }, "da": { "stringUnit": { "state": "translated", - "value": "Valgt arbejdsområde i nyt vindue" + "value": "System" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Wybrana przestrzeń robocza w nowym oknie" + "value": "Systemowy" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Выбранное рабочее пространство в новом окне" + "value": "Системный" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Odabrani radni prostor u novom prozoru" + "value": "Sistemski" } }, "ar": { "stringUnit": { "state": "translated", - "value": "مساحة العمل المحددة في نافذة جديدة" + "value": "النظام" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Valgt arbeidsområde i nytt vindu" + "value": "System" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Área de Trabalho Selecionada em Nova Janela" + "value": "Sistema" } }, "th": { "stringUnit": { "state": "translated", - "value": "เวิร์กสเปซที่เลือกในหน้าต่างใหม่" + "value": "ระบบ" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Yeni Pencerede Seçili Çalışma Alanı" + "value": "Sistem" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Вибрана робоча область у новому вікні" + "value": "Системна" } } } }, - "dialog.moveTab.title": { + "menu.help.agentIntegrations": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Move Tab" + "value": "Agent Integrations" } }, "ja": { "stringUnit": { "state": "translated", - "value": "タブの移動" - } - }, - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "移动标签页" - } - }, - "zh-Hant": { - "stringUnit": { - "state": "translated", - "value": "移動標籤頁" - } - }, - "ko": { - "stringUnit": { - "state": "translated", - "value": "탭 이동" + "value": "エージェント連携" } - }, - "de": { + } + } + }, + "menu.help.apiReference": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Tab verschieben" + "value": "API Reference" } }, - "es": { + "ja": { "stringUnit": { "state": "translated", - "value": "Mover pestaña" + "value": "APIリファレンス" } - }, - "fr": { + } + } + }, + "menu.help.browserAutomation": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Déplacer l'onglet" + "value": "Browser Automation" } }, - "it": { + "ja": { "stringUnit": { "state": "translated", - "value": "Sposta scheda" + "value": "ブラウザ自動化" } - }, - "da": { + } + } + }, + "menu.help.changelog": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Flyt fane" + "value": "Changelog" } }, - "pl": { + "ja": { "stringUnit": { "state": "translated", - "value": "Przenieś kartę" + "value": "変更履歴" } - }, - "ru": { + } + } + }, + "menu.help.claudeCodeTeams": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Переместить вкладку" + "value": "Claude Code Teams" } }, - "bs": { + "ja": { "stringUnit": { "state": "translated", - "value": "Premjesti tab" + "value": "Claude Code Teams" } - }, - "ar": { + } + } + }, + "menu.help.concepts": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "نقل اللسان" + "value": "Concepts" } }, - "nb": { + "ja": { "stringUnit": { "state": "translated", - "value": "Flytt fane" + "value": "コンセプト" } - }, - "pt-BR": { + } + } + }, + "menu.help.configuration": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Mover Aba" + "value": "Configuration" } }, - "th": { + "ja": { "stringUnit": { "state": "translated", - "value": "ย้ายแท็บ" + "value": "設定ガイド" } - }, - "tr": { + } + } + }, + "menu.help.customCommands": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Sekmeyi Taşı" + "value": "Custom Commands" } }, - "uk": { + "ja": { "stringUnit": { "state": "translated", - "value": "Перемістити вкладку" + "value": "カスタムコマンド" } } } }, - "dialog.quitCmux.message": { + "menu.help.dock": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "This will close all windows and workspaces." + "value": "Dock" } }, "ja": { "stringUnit": { "state": "translated", - "value": "すべてのウインドウとワークスペースを閉じます。" - } - }, - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "这将关闭所有窗口和工作区。" + "value": "Dock" } - }, - "zh-Hant": { + } + } + }, + "menu.help.gettingStarted": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "這將關閉所有視窗和工作區。" + "value": "Getting Started" } }, - "ko": { + "ja": { "stringUnit": { "state": "translated", - "value": "모든 윈도우와 작업 공간을 닫습니다." + "value": "はじめに" } - }, - "de": { + } + } + }, + "menu.help.keyboardShortcutsSettings": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Dadurch werden alle Fenster und Arbeitsbereiche geschlossen." + "value": "Keyboard Shortcuts Settings…" } }, - "es": { + "ja": { "stringUnit": { "state": "translated", - "value": "Esto cerrará todas las ventanas y espacios de trabajo." + "value": "キーボードショートカット設定…" } - }, - "fr": { + } + } + }, + "menu.help.notifications": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Cela fermera toutes les fenêtres et tous les espaces de travail." + "value": "Notifications" } }, - "it": { + "ja": { "stringUnit": { "state": "translated", - "value": "Questa operazione chiuderà tutte le finestre e le aree di lavoro." + "value": "通知" } - }, - "da": { + } + } + }, + "menu.help.ohMyClaudeCode": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Dette lukker alle vinduer og arbejdsområder." + "value": "oh-my-claudecode" } }, - "pl": { + "ja": { "stringUnit": { "state": "translated", - "value": "Spowoduje to zamknięcie wszystkich okien i przestrzeni roboczych." + "value": "oh-my-claudecode" } - }, - "ru": { + } + } + }, + "menu.help.ohMyCodex": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Все окна и рабочие пространства будут закрыты." + "value": "oh-my-codex" } }, - "bs": { + "ja": { "stringUnit": { "state": "translated", - "value": "Ovo će zatvoriti sve prozore i radne prostore." + "value": "oh-my-codex" } - }, - "ar": { + } + } + }, + "menu.help.ohMyOpenCode": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "سيؤدي هذا إلى إغلاق جميع النوافذ ومساحات العمل." + "value": "oh-my-opencode" } }, - "nb": { + "ja": { "stringUnit": { "state": "translated", - "value": "Dette vil lukke alle vinduer og arbeidsområder." + "value": "oh-my-opencode" } - }, - "pt-BR": { + } + } + }, + "menu.help.skills": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Isto fechará todas as janelas e áreas de trabalho." + "value": "Skills" } }, - "th": { + "ja": { "stringUnit": { "state": "translated", - "value": "การดำเนินการนี้จะปิดหน้าต่างและเวิร์กสเปซทั้งหมด" + "value": "スキル" } - }, - "tr": { + } + } + }, + "menu.help.ssh": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Bu, tüm pencereleri ve çalışma alanlarını kapatacak." + "value": "SSH" } }, - "uk": { + "ja": { "stringUnit": { "state": "translated", - "value": "Це закриє всі вікна та робочі області." + "value": "SSH" } } } }, - "dialog.quitCmux.quit": { + "menu.app.about": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Quit" + "value": "About cmux" } }, "ja": { "stringUnit": { "state": "translated", - "value": "終了" + "value": "cmuxについて" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "退出" + "value": "关于 cmux" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "結束" + "value": "關於 cmux" } }, "ko": { "stringUnit": { "state": "translated", - "value": "종료" + "value": "cmux에 관하여" } }, "de": { "stringUnit": { "state": "translated", - "value": "Beenden" + "value": "Über cmux" } }, "es": { "stringUnit": { "state": "translated", - "value": "Salir" + "value": "Acerca de cmux" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Quitter" + "value": "À propos de cmux" } }, "it": { "stringUnit": { "state": "translated", - "value": "Esci" + "value": "Informazioni su cmux" } }, "da": { "stringUnit": { "state": "translated", - "value": "Afslut" + "value": "Om cmux" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Zakończ" + "value": "O cmux" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Завершить" + "value": "О программе cmux" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Zatvori" + "value": "O programu cmux" } }, "ar": { "stringUnit": { "state": "translated", - "value": "إنهاء" + "value": "حول cmux" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Avslutt" + "value": "Om cmux" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Encerrar" + "value": "Sobre o cmux" } }, "th": { "stringUnit": { "state": "translated", - "value": "ออก" + "value": "เกี่ยวกับ cmux" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Çık" + "value": "cmux Hakkında" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Завершити" + "value": "Про cmux" } } } }, - "dialog.quitCmux.title": { + "menu.app.checkForUpdates": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Quit cmux?" + "value": "Check for Updates…" } }, "ja": { "stringUnit": { "state": "translated", - "value": "cmux を終了しますか?" + "value": "アップデートを確認…" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "退出 cmux?" + "value": "检查更新..." } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "要結束 cmux 嗎?" + "value": "檢查更新..." } }, "ko": { "stringUnit": { "state": "translated", - "value": "cmux를 종료하시겠습니까?" + "value": "업데이트 확인…" } }, "de": { "stringUnit": { "state": "translated", - "value": "cmux beenden?" + "value": "Nach Updates suchen …" } }, "es": { "stringUnit": { "state": "translated", - "value": "¿Salir de cmux?" + "value": "Buscar actualizaciones…" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Quitter cmux ?" + "value": "Rechercher des mises à jour..." } }, "it": { "stringUnit": { "state": "translated", - "value": "Uscire da cmux?" + "value": "Verifica aggiornamenti…" } }, "da": { "stringUnit": { "state": "translated", - "value": "Afslut cmux?" + "value": "Søg efter opdateringer…" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Zakończyć cmux?" + "value": "Sprawdź aktualizacje…" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Завершить cmux?" + "value": "Проверить обновления..." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Zatvoriti cmux?" + "value": "Provjeri ažuriranja…" } }, "ar": { "stringUnit": { "state": "translated", - "value": "إنهاء cmux؟" + "value": "التحقق من التحديثات…" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Avslutte cmux?" + "value": "Se etter oppdateringer …" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Encerrar o cmux?" + "value": "Buscar Atualizações…" } }, "th": { "stringUnit": { "state": "translated", - "value": "ออกจาก cmux หรือไม่?" + "value": "ตรวจหาอัปเดต..." } }, "tr": { "stringUnit": { "state": "translated", - "value": "cmux'tan çıkılsın mı?" + "value": "Güncellemeleri Denetle…" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Завершити cmux?" + "value": "Перевірити оновлення…" } } } }, - "dialog.renameTab.message": { + "menu.app.ghosttySettings": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Enter a custom name for this tab." + "value": "Ghostty Settings…" } }, "ja": { "stringUnit": { "state": "translated", - "value": "このタブのカスタム名を入力してください。" + "value": "Ghostty設定…" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "请为此标签页输入自定义名称。" + "value": "Ghostty 设置..." } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "為此標籤頁輸入自訂名稱。" + "value": "Ghostty 設定..." } }, "ko": { "stringUnit": { "state": "translated", - "value": "이 탭의 사용자 지정 이름을 입력하세요." + "value": "Ghostty 설정…" } }, "de": { "stringUnit": { "state": "translated", - "value": "Geben Sie einen benutzerdefinierten Namen für diesen Tab ein." + "value": "Ghostty-Einstellungen …" } }, "es": { "stringUnit": { "state": "translated", - "value": "Introduce un nombre personalizado para esta pestaña." + "value": "Ajustes de Ghostty…" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Saisissez un nom personnalisé pour cet onglet." + "value": "Réglages Ghostty..." } }, "it": { "stringUnit": { "state": "translated", - "value": "Inserisci un nome personalizzato per questa scheda." + "value": "Impostazioni Ghostty…" } }, "da": { "stringUnit": { "state": "translated", - "value": "Indtast et brugerdefineret navn til denne fane." + "value": "Ghostty-indstillinger…" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Wprowadź własną nazwę dla tej karty." + "value": "Ustawienia Ghostty…" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Введите пользовательское имя для этой вкладки." + "value": "Настройки Ghostty..." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Unesite prilagođeni naziv za ovaj tab." + "value": "Ghostty postavke…" } }, "ar": { "stringUnit": { "state": "translated", - "value": "أدخل اسمًا مخصصًا لهذا اللسان." + "value": "إعدادات Ghostty…" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Skriv inn et egendefinert navn for denne fanen." + "value": "Ghostty-innstillinger …" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Insira um nome personalizado para esta aba." + "value": "Ajustes do Ghostty…" } }, "th": { "stringUnit": { "state": "translated", - "value": "ป้อนชื่อที่กำหนดเองสำหรับแท็บนี้" + "value": "การตั้งค่า Ghostty..." } }, "tr": { "stringUnit": { "state": "translated", - "value": "Bu sekme için özel bir ad girin." + "value": "Ghostty Ayarları…" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Введіть власну назву для цієї вкладки." + "value": "Налаштування Ghostty…" } } } }, - "dialog.renameTab.placeholder": { + "menu.app.reloadConfiguration": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Tab name" + "value": "Reload Configuration" } }, "ja": { "stringUnit": { "state": "translated", - "value": "タブ名" + "value": "構成を再読み込み" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "标签页名称" + "value": "重新加载配置" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "標籤頁名稱" + "value": "重新載入設定" } }, "ko": { "stringUnit": { "state": "translated", - "value": "탭 이름" + "value": "구성 다시 불러오기" } }, "de": { "stringUnit": { "state": "translated", - "value": "Tab-Name" + "value": "Konfiguration neu laden" } }, "es": { "stringUnit": { "state": "translated", - "value": "Nombre de pestaña" + "value": "Recargar configuración" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Nom de l'onglet" + "value": "Recharger la configuration" } }, "it": { "stringUnit": { "state": "translated", - "value": "Nome scheda" + "value": "Ricarica configurazione" } }, "da": { "stringUnit": { "state": "translated", - "value": "Fanenavn" + "value": "Genindlæs konfiguration" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Nazwa karty" + "value": "Odśwież konfigurację" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Имя вкладки" + "value": "Перезагрузить конфигурацию" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Naziv taba" + "value": "Ponovo učitaj konfiguraciju" } }, "ar": { "stringUnit": { "state": "translated", - "value": "اسم اللسان" + "value": "إعادة تحميل الإعدادات" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Fanenavn" + "value": "Last inn konfigurasjon på nytt" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Nome da aba" + "value": "Recarregar Configuração" } }, "th": { "stringUnit": { "state": "translated", - "value": "ชื่อแท็บ" + "value": "โหลดการกำหนดค่าใหม่" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Sekme adı" + "value": "Yapılandırmayı Yeniden Yükle" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Назва вкладки" + "value": "Перезавантажити конфігурацію" } } } }, - "dialog.renameTab.title": { + "menu.app.settings": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Rename Tab" + "value": "Settings…" } }, "ja": { "stringUnit": { "state": "translated", - "value": "タブの名称変更" + "value": "設定…" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "重命名标签页" + "value": "设置..." } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "重新命名標籤頁" + "value": "設定..." } }, "ko": { "stringUnit": { "state": "translated", - "value": "탭 이름 변경" + "value": "설정…" } }, "de": { "stringUnit": { "state": "translated", - "value": "Tab umbenennen" + "value": "Einstellungen …" } }, "es": { "stringUnit": { "state": "translated", - "value": "Renombrar pestaña" + "value": "Ajustes…" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Renommer l'onglet" + "value": "Réglages..." } }, "it": { "stringUnit": { "state": "translated", - "value": "Rinomina scheda" + "value": "Impostazioni…" } }, "da": { "stringUnit": { "state": "translated", - "value": "Omdøb fane" + "value": "Indstillinger…" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Zmień nazwę karty" + "value": "Ustawienia…" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Переименовать вкладку" + "value": "Настройки..." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Preimenuj tab" + "value": "Postavke…" } }, "ar": { "stringUnit": { "state": "translated", - "value": "إعادة تسمية اللسان" + "value": "الإعدادات…" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Gi fanen nytt navn" + "value": "Innstillinger …" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Renomear Aba" + "value": "Ajustes…" } }, "th": { "stringUnit": { "state": "translated", - "value": "เปลี่ยนชื่อแท็บ" + "value": "การตั้งค่า..." } }, "tr": { "stringUnit": { "state": "translated", - "value": "Sekmeyi Yeniden Adlandır" + "value": "Ayarlar…" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Перейменувати вкладку" + "value": "Налаштування…" } } } }, - "dialog.renameWorkspace.message": { + "menu.app.openCmuxSettingsFile": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Enter a custom name for this workspace." + "value": "Open cmux.json" } }, "ja": { "stringUnit": { "state": "translated", - "value": "このワークスペースのカスタム名を入力してください。" + "value": "cmux.jsonを開く" + } + }, + "ko": { + "stringUnit": { + "state": "translated", + "value": "cmux.json 열기" + } + } + } + }, + "menu.checkForUpdates": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Check for Updates…" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "アップデートを確認…" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "请为此工作区输入自定义名称。" + "value": "检查更新..." } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "為此工作區輸入自訂名稱。" + "value": "檢查更新..." } }, "ko": { "stringUnit": { "state": "translated", - "value": "이 작업 공간의 사용자 지정 이름을 입력하세요." + "value": "업데이트 확인…" } }, "de": { "stringUnit": { "state": "translated", - "value": "Geben Sie einen benutzerdefinierten Namen für diesen Arbeitsbereich ein." + "value": "Nach Updates suchen …" } }, "es": { "stringUnit": { "state": "translated", - "value": "Introduce un nombre personalizado para este espacio de trabajo." + "value": "Buscar actualizaciones…" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Saisissez un nom personnalisé pour cet espace de travail." + "value": "Rechercher des mises à jour..." } }, "it": { "stringUnit": { "state": "translated", - "value": "Inserisci un nome personalizzato per questa area di lavoro." + "value": "Verifica aggiornamenti…" } }, "da": { "stringUnit": { "state": "translated", - "value": "Indtast et brugerdefineret navn til dette arbejdsområde." + "value": "Søg efter opdateringer…" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Wprowadź własną nazwę dla tej przestrzeni roboczej." + "value": "Sprawdź aktualizacje…" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Введите пользовательское имя для этого рабочего пространства." + "value": "Проверить обновления..." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Unesite prilagođeni naziv za ovaj radni prostor." + "value": "Provjeri ažuriranja…" } }, "ar": { "stringUnit": { "state": "translated", - "value": "أدخل اسمًا مخصصًا لمساحة العمل هذه." + "value": "التحقق من التحديثات…" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Skriv inn et egendefinert navn for dette arbeidsområdet." + "value": "Se etter oppdateringer …" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Insira um nome personalizado para esta área de trabalho." + "value": "Buscar Atualizações…" } }, "th": { "stringUnit": { "state": "translated", - "value": "ป้อนชื่อที่กำหนดเองสำหรับเวิร์กสเปซนี้" + "value": "ตรวจหาอัปเดต..." } }, "tr": { "stringUnit": { "state": "translated", - "value": "Bu çalışma alanı için özel bir ad girin." + "value": "Güncellemeleri Denetle…" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Введіть власну назву для цієї робочої області." + "value": "Перевірити оновлення…" } } } }, - "dialog.renameWorkspace.placeholder": { + "menu.currentWindow": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Workspace name" + "value": "Current Window" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ワークスペース名" + "value": "現在のウインドウ" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "工作区名称" + "value": "当前窗口" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "工作區名稱" + "value": "目前視窗" } }, "ko": { "stringUnit": { "state": "translated", - "value": "작업 공간 이름" + "value": "현재 윈도우" } }, "de": { "stringUnit": { "state": "translated", - "value": "Name des Arbeitsbereichs" + "value": "Aktuelles Fenster" } }, "es": { "stringUnit": { "state": "translated", - "value": "Nombre del espacio de trabajo" + "value": "Ventana actual" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Nom de l'espace de travail" + "value": "Fenêtre actuelle" } }, "it": { "stringUnit": { "state": "translated", - "value": "Nome area di lavoro" + "value": "Finestra corrente" } }, "da": { "stringUnit": { "state": "translated", - "value": "Arbejdsområdenavn" + "value": "Nuværende vindue" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Nazwa przestrzeni roboczej" + "value": "Bieżące okno" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Имя рабочего пространства" + "value": "Текущее окно" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Naziv radnog prostora" + "value": "Trenutni prozor" } }, "ar": { "stringUnit": { "state": "translated", - "value": "اسم مساحة العمل" + "value": "النافذة الحالية" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Arbeidsområdenavn" + "value": "Gjeldende vindu" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Nome da área de trabalho" + "value": "Janela Atual" } }, "th": { "stringUnit": { "state": "translated", - "value": "ชื่อเวิร์กสเปซ" + "value": "หน้าต่างปัจจุบัน" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Çalışma alanı adı" + "value": "Geçerli Pencere" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Назва робочої області" + "value": "Поточне вікно" } } } }, - "dialog.renameWorkspace.title": { + "menu.file.closeOtherTabs": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Rename Workspace" + "value": "Close Other Tabs in Pane" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ワークスペースの名称変更" + "value": "ペイン内の他のタブを閉じる" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "重命名工作区" + "value": "关闭面板中的其他标签页" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "重新命名工作區" + "value": "關閉面板中的其他標籤頁" } }, "ko": { "stringUnit": { "state": "translated", - "value": "작업 공간 이름 변경" + "value": "패널의 다른 탭 닫기" } }, "de": { "stringUnit": { "state": "translated", - "value": "Arbeitsbereich umbenennen" + "value": "Andere Tabs im Bereich schließen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Renombrar espacio de trabajo" + "value": "Cerrar otras pestañas del panel" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Renommer l'espace de travail" + "value": "Fermer les autres onglets du panneau" } }, "it": { "stringUnit": { "state": "translated", - "value": "Rinomina area di lavoro" + "value": "Chiudi altre schede nel pannello" } }, "da": { "stringUnit": { "state": "translated", - "value": "Omdøb arbejdsområde" + "value": "Luk andre faner i panel" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Zmień nazwę przestrzeni roboczej" + "value": "Zamknij inne karty w panelu" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Переименовать рабочее пространство" + "value": "Закрыть другие вкладки в панели" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Preimenuj radni prostor" + "value": "Zatvori ostale tabove u panelu" } }, "ar": { "stringUnit": { "state": "translated", - "value": "إعادة تسمية مساحة العمل" + "value": "إغلاق الألسنة الأخرى في اللوحة" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Gi arbeidsområdet nytt navn" + "value": "Lukk andre faner i panelet" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Renomear Área de Trabalho" + "value": "Fechar Outras Abas no Painel" } }, "th": { "stringUnit": { "state": "translated", - "value": "เปลี่ยนชื่อเวิร์กสเปซ" + "value": "ปิดแท็บอื่นในบานหน้าต่าง" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Çalışma Alanını Yeniden Adlandır" + "value": "Bölmedeki Diğer Sekmeleri Kapat" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Перейменувати робочу область" + "value": "Закрити інші вкладки в панелі" } } } }, - "error.clipboardFolderPath": { + "menu.file.closeTab": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Could not load any folder path from the clipboard." + "value": "Close Tab" } }, "ja": { "stringUnit": { "state": "translated", - "value": "クリップボードからフォルダパスを読み込めませんでした。" + "value": "タブを閉じる" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "无法从剪贴板加载文件夹路径。" + "value": "关闭标签页" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "無法從剪貼簿載入資料夾路徑。" + "value": "關閉標籤頁" } }, "ko": { "stringUnit": { "state": "translated", - "value": "클립보드에서 폴더 경로를 불러올 수 없습니다." + "value": "탭 닫기" } }, "de": { "stringUnit": { "state": "translated", - "value": "Es konnte kein Ordnerpfad aus der Zwischenablage geladen werden." + "value": "Tab schließen" } }, "es": { "stringUnit": { "state": "translated", - "value": "No se pudo cargar ninguna ruta de carpeta desde el portapapeles." + "value": "Cerrar pestaña" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Impossible de charger un chemin de dossier depuis le presse-papiers." + "value": "Fermer l'onglet" } }, "it": { "stringUnit": { "state": "translated", - "value": "Impossibile caricare un percorso cartella dagli appunti." + "value": "Chiudi scheda" } }, "da": { "stringUnit": { "state": "translated", - "value": "Kunne ikke indlæse nogen mappesti fra udklipsholderen." + "value": "Luk fane" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Nie udało się wczytać ścieżki folderu ze schowka." + "value": "Zamknij kartę" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Не удалось загрузить путь к папке из буфера обмена." + "value": "Закрыть вкладку" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Nije moguće učitati putanju foldera iz međuspremnika." + "value": "Zatvori tab" } }, "ar": { "stringUnit": { "state": "translated", - "value": "تعذر تحميل أي مسار مجلد من الحافظة." + "value": "إغلاق اللسان" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Kunne ikke laste inn noen mappesti fra utklippstavlen." + "value": "Lukk fane" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Não foi possível carregar nenhum caminho de pasta da área de transferência." + "value": "Fechar Aba" } }, "th": { "stringUnit": { "state": "translated", - "value": "ไม่สามารถโหลดเส้นทางโฟลเดอร์จากคลิปบอร์ดได้" + "value": "ปิดแท็บ" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Panodan herhangi bir klasör yolu yüklenemedi." + "value": "Sekmeyi Kapat" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Не вдалося завантажити шлях до теки з буфера обміну." + "value": "Закрити вкладку" } } } }, - "language.system": { + "menu.file.closeWorkspace": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "System" + "value": "Close Workspace" } }, "ja": { "stringUnit": { "state": "translated", - "value": "システム" + "value": "ワークスペースを閉じる" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "系统" + "value": "关闭工作区" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "系統" + "value": "關閉工作區" } }, "ko": { "stringUnit": { "state": "translated", - "value": "시스템" + "value": "작업 공간 닫기" } }, "de": { "stringUnit": { "state": "translated", - "value": "System" + "value": "Arbeitsbereich schließen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Sistema" + "value": "Cerrar espacio de trabajo" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Système" + "value": "Fermer l'espace de travail" } }, "it": { "stringUnit": { "state": "translated", - "value": "Sistema" + "value": "Chiudi area di lavoro" } }, "da": { "stringUnit": { "state": "translated", - "value": "System" + "value": "Luk arbejdsområde" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Systemowy" + "value": "Zamknij przestrzeń roboczą" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Системный" + "value": "Закрыть рабочее пространство" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Sistemski" + "value": "Zatvori radni prostor" } }, "ar": { "stringUnit": { "state": "translated", - "value": "النظام" + "value": "إغلاق مساحة العمل" } }, "nb": { "stringUnit": { "state": "translated", - "value": "System" + "value": "Lukk arbeidsområde" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Sistema" + "value": "Fechar Área de Trabalho" } }, "th": { "stringUnit": { "state": "translated", - "value": "ระบบ" + "value": "ปิดเวิร์กสเปซ" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Sistem" + "value": "Çalışma Alanını Kapat" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Системна" + "value": "Закрити робочу область" } } } }, - "menu.help.agentIntegrations": { + "menu.file.commandPalette": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Agent Integrations" + "value": "Command Palette…" } }, "ja": { "stringUnit": { "state": "translated", - "value": "エージェント連携" + "value": "コマンドパレット…" } - } - } - }, - "menu.help.apiReference": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "zh-Hans": { "stringUnit": { "state": "translated", - "value": "API Reference" + "value": "命令面板..." } }, - "ja": { + "zh-Hant": { "stringUnit": { "state": "translated", - "value": "APIリファレンス" + "value": "指令面板..." } - } - } - }, - "menu.help.browserAutomation": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "ko": { "stringUnit": { "state": "translated", - "value": "Browser Automation" + "value": "명령어 팔레트…" } }, - "ja": { + "de": { "stringUnit": { "state": "translated", - "value": "ブラウザ自動化" + "value": "Befehlspalette …" } - } - } - }, - "menu.help.changelog": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "es": { "stringUnit": { "state": "translated", - "value": "Changelog" + "value": "Paleta de comandos…" } }, - "ja": { + "fr": { "stringUnit": { "state": "translated", - "value": "変更履歴" + "value": "Palette de commandes..." } - } - } - }, - "menu.help.claudeCodeTeams": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "it": { "stringUnit": { "state": "translated", - "value": "Claude Code Teams" + "value": "Tavolozza comandi…" } }, - "ja": { + "da": { "stringUnit": { "state": "translated", - "value": "Claude Code Teams" + "value": "Kommandopalette…" } - } - } - }, - "menu.help.concepts": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "pl": { "stringUnit": { "state": "translated", - "value": "Concepts" + "value": "Paleta poleceń…" } }, - "ja": { + "ru": { "stringUnit": { "state": "translated", - "value": "コンセプト" + "value": "Палитра команд..." } - } - } - }, - "menu.help.configuration": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "bs": { "stringUnit": { "state": "translated", - "value": "Configuration" + "value": "Paleta naredbi…" } }, - "ja": { + "ar": { "stringUnit": { "state": "translated", - "value": "設定ガイド" + "value": "لوحة الأوامر…" } - } - } - }, - "menu.help.customCommands": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "nb": { "stringUnit": { "state": "translated", - "value": "Custom Commands" + "value": "Kommandopalett …" } }, - "ja": { + "pt-BR": { "stringUnit": { "state": "translated", - "value": "カスタムコマンド" + "value": "Paleta de Comandos…" } - } - } - }, - "menu.help.dock": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "th": { "stringUnit": { "state": "translated", - "value": "Dock" + "value": "แถบคำสั่ง..." } }, - "ja": { + "tr": { "stringUnit": { "state": "translated", - "value": "Dock" + "value": "Komut Paleti…" + } + }, + "uk": { + "stringUnit": { + "state": "translated", + "value": "Палітра команд…" } } } }, - "menu.help.gettingStarted": { + "menu.file.goToWorkspace": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Getting Started" + "value": "Go to Workspace…" } }, "ja": { "stringUnit": { "state": "translated", - "value": "はじめに" + "value": "ワークスペースに移動…" } - } - } - }, - "menu.help.keyboardShortcutsSettings": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "zh-Hans": { "stringUnit": { "state": "translated", - "value": "Keyboard Shortcuts Settings…" + "value": "前往工作区..." } }, - "ja": { + "zh-Hant": { "stringUnit": { "state": "translated", - "value": "キーボードショートカット設定…" + "value": "前往工作區..." } - } - } - }, - "menu.help.notifications": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "ko": { "stringUnit": { "state": "translated", - "value": "Notifications" + "value": "작업 공간으로 이동…" } }, - "ja": { + "de": { "stringUnit": { "state": "translated", - "value": "通知" + "value": "Zum Arbeitsbereich wechseln …" } - } - } - }, - "menu.help.ohMyClaudeCode": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "es": { "stringUnit": { "state": "translated", - "value": "oh-my-claudecode" + "value": "Ir al espacio de trabajo…" } }, - "ja": { + "fr": { "stringUnit": { "state": "translated", - "value": "oh-my-claudecode" + "value": "Aller à l'espace de travail..." } - } - } - }, - "menu.help.ohMyCodex": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "it": { "stringUnit": { "state": "translated", - "value": "oh-my-codex" + "value": "Vai all'area di lavoro…" } }, - "ja": { + "da": { "stringUnit": { "state": "translated", - "value": "oh-my-codex" + "value": "Gå til arbejdsområde…" } - } - } - }, - "menu.help.ohMyOpenCode": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "pl": { "stringUnit": { "state": "translated", - "value": "oh-my-opencode" + "value": "Przejdź do przestrzeni roboczej…" } }, - "ja": { + "ru": { "stringUnit": { "state": "translated", - "value": "oh-my-opencode" + "value": "Перейти к рабочему пространству..." } - } - } - }, - "menu.help.skills": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "bs": { "stringUnit": { "state": "translated", - "value": "Skills" + "value": "Idi na radni prostor…" } }, - "ja": { + "ar": { "stringUnit": { "state": "translated", - "value": "スキル" + "value": "الانتقال إلى مساحة العمل…" } - } - } - }, - "menu.help.ssh": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "nb": { "stringUnit": { "state": "translated", - "value": "SSH" + "value": "Gå til arbeidsområde …" } }, - "ja": { + "pt-BR": { "stringUnit": { "state": "translated", - "value": "SSH" + "value": "Ir para Área de Trabalho…" + } + }, + "th": { + "stringUnit": { + "state": "translated", + "value": "ไปที่เวิร์กสเปซ..." + } + }, + "tr": { + "stringUnit": { + "state": "translated", + "value": "Çalışma Alanına Git…" + } + }, + "uk": { + "stringUnit": { + "state": "translated", + "value": "Перейти до робочої області…" } } } }, - "menu.app.about": { + "menu.file.newWindow": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "About cmux" + "value": "New Window" } }, "ja": { "stringUnit": { "state": "translated", - "value": "cmuxについて" + "value": "新規ウインドウ" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "关于 cmux" + "value": "新建窗口" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "關於 cmux" + "value": "新增視窗" } }, "ko": { "stringUnit": { "state": "translated", - "value": "cmux에 관하여" + "value": "새 윈도우" } }, "de": { "stringUnit": { "state": "translated", - "value": "Über cmux" + "value": "Neues Fenster" } }, "es": { "stringUnit": { "state": "translated", - "value": "Acerca de cmux" + "value": "Nueva ventana" } }, "fr": { "stringUnit": { "state": "translated", - "value": "À propos de cmux" + "value": "Nouvelle fenêtre" } }, "it": { "stringUnit": { "state": "translated", - "value": "Informazioni su cmux" + "value": "Nuova finestra" } }, "da": { "stringUnit": { "state": "translated", - "value": "Om cmux" + "value": "Nyt vindue" } }, "pl": { "stringUnit": { "state": "translated", - "value": "O cmux" + "value": "Nowe okno" } }, "ru": { "stringUnit": { "state": "translated", - "value": "О программе cmux" + "value": "Новое окно" } }, "bs": { "stringUnit": { "state": "translated", - "value": "O programu cmux" + "value": "Novi prozor" } }, "ar": { "stringUnit": { "state": "translated", - "value": "حول cmux" + "value": "نافذة جديدة" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Om cmux" + "value": "Nytt vindu" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Sobre o cmux" + "value": "Nova Janela" } }, "th": { "stringUnit": { "state": "translated", - "value": "เกี่ยวกับ cmux" + "value": "หน้าต่างใหม่" } }, "tr": { "stringUnit": { "state": "translated", - "value": "cmux Hakkında" + "value": "Yeni Pencere" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Про cmux" + "value": "Нове вікно" } } } }, - "menu.app.checkForUpdates": { + "menu.file.newWorkspace": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Check for Updates…" + "value": "New Workspace" } }, "ja": { "stringUnit": { "state": "translated", - "value": "アップデートを確認…" + "value": "新規ワークスペース" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "检查更新..." + "value": "新建工作区" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "檢查更新..." + "value": "新增工作區" } }, "ko": { "stringUnit": { "state": "translated", - "value": "업데이트 확인…" + "value": "새 작업 공간" } }, "de": { "stringUnit": { "state": "translated", - "value": "Nach Updates suchen …" + "value": "Neuer Arbeitsbereich" } }, "es": { "stringUnit": { "state": "translated", - "value": "Buscar actualizaciones…" + "value": "Nuevo espacio de trabajo" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Rechercher des mises à jour..." + "value": "Nouvel espace de travail" } }, "it": { "stringUnit": { "state": "translated", - "value": "Verifica aggiornamenti…" + "value": "Nuova area di lavoro" } }, "da": { "stringUnit": { "state": "translated", - "value": "Søg efter opdateringer…" + "value": "Nyt arbejdsområde" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Sprawdź aktualizacje…" + "value": "Nowa przestrzeń robocza" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Проверить обновления..." + "value": "Новое рабочее пространство" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Provjeri ažuriranja…" + "value": "Novi radni prostor" } }, "ar": { "stringUnit": { "state": "translated", - "value": "التحقق من التحديثات…" + "value": "مساحة عمل جديدة" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Se etter oppdateringer …" + "value": "Nytt arbeidsområde" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Buscar Atualizações…" + "value": "Nova Área de Trabalho" } }, "th": { "stringUnit": { "state": "translated", - "value": "ตรวจหาอัปเดต..." + "value": "เวิร์กสเปซใหม่" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Güncellemeleri Denetle…" + "value": "Yeni Çalışma Alanı" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Перевірити оновлення…" + "value": "Нова робоча область" } } } }, - "menu.app.ghosttySettings": { + "menu.file.openFolder": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Ghostty Settings…" + "value": "Open Folder…" } }, "ja": { "stringUnit": { "state": "translated", - "value": "Ghostty設定…" + "value": "フォルダを開く…" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "Ghostty 设置..." + "value": "打开文件夹..." } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "Ghostty 設定..." + "value": "開啟資料夾..." } }, "ko": { "stringUnit": { "state": "translated", - "value": "Ghostty 설정…" + "value": "폴더 열기…" } }, "de": { "stringUnit": { "state": "translated", - "value": "Ghostty-Einstellungen …" + "value": "Ordner öffnen …" } }, "es": { "stringUnit": { "state": "translated", - "value": "Ajustes de Ghostty…" + "value": "Abrir carpeta…" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Réglages Ghostty..." + "value": "Ouvrir un dossier..." } }, "it": { "stringUnit": { "state": "translated", - "value": "Impostazioni Ghostty…" + "value": "Apri cartella…" } }, "da": { "stringUnit": { "state": "translated", - "value": "Ghostty-indstillinger…" + "value": "Åbn mappe…" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Ustawienia Ghostty…" + "value": "Otwórz folder…" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Настройки Ghostty..." + "value": "Открыть папку..." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Ghostty postavke…" + "value": "Otvori folder…" } }, "ar": { "stringUnit": { "state": "translated", - "value": "إعدادات Ghostty…" + "value": "فتح مجلد…" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Ghostty-innstillinger …" + "value": "Åpne mappe …" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Ajustes do Ghostty…" + "value": "Abrir Pasta…" } }, "th": { "stringUnit": { "state": "translated", - "value": "การตั้งค่า Ghostty..." + "value": "เปิดโฟลเดอร์..." } }, "tr": { "stringUnit": { "state": "translated", - "value": "Ghostty Ayarları…" + "value": "Klasör Aç…" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Налаштування Ghostty…" + "value": "Відкрити теку…" } } } }, - "menu.app.reloadConfiguration": { + "menu.file.openFolder.panelPrompt": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Reload Configuration" + "value": "Open" } }, "ja": { "stringUnit": { "state": "translated", - "value": "構成を再読み込み" + "value": "開く" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "重新加载配置" + "value": "打开" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "重新載入設定" + "value": "開啟" } }, "ko": { "stringUnit": { "state": "translated", - "value": "구성 다시 불러오기" + "value": "열기" } }, "de": { "stringUnit": { "state": "translated", - "value": "Konfiguration neu laden" + "value": "Öffnen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Recargar configuración" + "value": "Abrir" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Recharger la configuration" + "value": "Ouvrir" } }, "it": { "stringUnit": { "state": "translated", - "value": "Ricarica configurazione" + "value": "Apri" } }, "da": { "stringUnit": { "state": "translated", - "value": "Genindlæs konfiguration" + "value": "Åbn" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Odśwież konfigurację" + "value": "Otwórz" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Перезагрузить конфигурацию" + "value": "Открыть" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Ponovo učitaj konfiguraciju" + "value": "Otvori" } }, "ar": { "stringUnit": { "state": "translated", - "value": "إعادة تحميل الإعدادات" + "value": "فتح" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Last inn konfigurasjon på nytt" + "value": "Åpne" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Recarregar Configuração" + "value": "Abrir" } }, "th": { "stringUnit": { "state": "translated", - "value": "โหลดการกำหนดค่าใหม่" + "value": "เปิด" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Yapılandırmayı Yeniden Yükle" + "value": "Aç" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Перезавантажити конфігурацію" + "value": "Відкрити" } } } }, - "menu.app.settings": { + "menu.file.openFolder.panelTitle": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Settings…" + "value": "Open Folder" } }, "ja": { "stringUnit": { "state": "translated", - "value": "設定…" + "value": "フォルダを開く" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "设置..." + "value": "打开文件夹" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "設定..." + "value": "開啟資料夾" } }, "ko": { "stringUnit": { "state": "translated", - "value": "설정…" + "value": "폴더 열기" } }, "de": { "stringUnit": { "state": "translated", - "value": "Einstellungen …" + "value": "Ordner öffnen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Ajustes…" + "value": "Abrir carpeta" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Réglages..." + "value": "Ouvrir un dossier" } }, "it": { "stringUnit": { "state": "translated", - "value": "Impostazioni…" + "value": "Apri cartella" } }, "da": { "stringUnit": { "state": "translated", - "value": "Indstillinger…" + "value": "Åbn mappe" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Ustawienia…" + "value": "Otwórz folder" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Настройки..." + "value": "Открыть папку" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Postavke…" + "value": "Otvori folder" } }, "ar": { "stringUnit": { "state": "translated", - "value": "الإعدادات…" + "value": "فتح مجلد" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Innstillinger …" + "value": "Åpne mappe" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Ajustes…" + "value": "Abrir Pasta" } }, "th": { "stringUnit": { "state": "translated", - "value": "การตั้งค่า..." + "value": "เปิดโฟลเดอร์" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Ayarlar…" + "value": "Klasör Aç" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Налаштування…" + "value": "Відкрити теку" } } } }, - "menu.app.openCmuxSettingsFile": { + "menu.file.openFolderInVSCodeInline": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Open cmux.json" + "value": "Open Folder in VS Code (Inline)…" } }, "ja": { "stringUnit": { "state": "translated", - "value": "cmux.jsonを開く" + "value": "フォルダを VS Code で開く(インライン)…" } }, "ko": { "stringUnit": { "state": "translated", - "value": "cmux.json 열기" + "value": "VS Code에서 폴더 열기 (인라인)…" } } } }, - "menu.checkForUpdates": { + "menu.file.openFolderInVSCodeInline.panelPrompt": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Check for Updates…" + "value": "Open in VS Code" } }, "ja": { "stringUnit": { "state": "translated", - "value": "アップデートを確認…" + "value": "VS Code で開く" + } + }, + "ko": { + "stringUnit": { + "state": "translated", + "value": "VS Code에서 열기" + } + } + } + }, + "menu.file.openFolderInVSCodeInline.panelTitle": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Open Folder in VS Code (Inline)" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "フォルダを VS Code で開く(インライン)" + } + }, + "ko": { + "stringUnit": { + "state": "translated", + "value": "VS Code에서 폴더 열기 (인라인)" + } + } + } + }, + "menu.file.reopenClosedBrowserPanel": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Reopen Closed Browser Panel" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "閉じたブラウザパネルを再度開く" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "检查更新..." + "value": "重新打开已关闭的浏览器面板" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "檢查更新..." + "value": "重新開啟已關閉的瀏覽器面板" } }, "ko": { "stringUnit": { "state": "translated", - "value": "업데이트 확인…" + "value": "닫은 브라우저 패널 다시 열기" } }, "de": { "stringUnit": { "state": "translated", - "value": "Nach Updates suchen …" + "value": "Geschlossenes Browserfenster erneut öffnen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Buscar actualizaciones…" + "value": "Reabrir panel del navegador cerrado" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Rechercher des mises à jour..." + "value": "Rouvrir le panneau de navigateur fermé" } }, "it": { "stringUnit": { "state": "translated", - "value": "Verifica aggiornamenti…" + "value": "Riapri pannello browser chiuso" } }, "da": { "stringUnit": { "state": "translated", - "value": "Søg efter opdateringer…" + "value": "Genåbn lukket browserpanel" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Sprawdź aktualizacje…" + "value": "Otwórz ponownie zamknięty panel przeglądarki" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Проверить обновления..." + "value": "Открыть закрытую панель браузера" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Provjeri ažuriranja…" + "value": "Ponovo otvori zatvoreni panel preglednika" } }, "ar": { "stringUnit": { "state": "translated", - "value": "التحقق من التحديثات…" + "value": "إعادة فتح لوحة المتصفح المغلقة" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Se etter oppdateringer …" + "value": "Åpne lukket nettleserpanel på nytt" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Buscar Atualizações…" + "value": "Reabrir Painel do Navegador Fechado" } }, "th": { "stringUnit": { "state": "translated", - "value": "ตรวจหาอัปเดต..." + "value": "เปิดแผงเบราว์เซอร์ที่ปิดไปอีกครั้ง" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Güncellemeleri Denetle…" + "value": "Kapatılan Tarayıcı Panelini Yeniden Aç" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Перевірити оновлення…" + "value": "Відновити закриту панель браузера" } } } }, - "menu.currentWindow": { + "menu.file.reopenPreviousSession": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Current Window" + "value": "Reopen Previous Session" } }, "ja": { "stringUnit": { "state": "translated", - "value": "現在のウインドウ" + "value": "前回のセッションを再度開く" + } + } + } + }, + "menu.find.find": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Find…" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "検索…" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "当前窗口" + "value": "查找…" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "目前視窗" + "value": "尋找…" } }, "ko": { "stringUnit": { "state": "translated", - "value": "현재 윈도우" + "value": "찾기…" } }, "de": { "stringUnit": { "state": "translated", - "value": "Aktuelles Fenster" + "value": "Suchen…" } }, "es": { "stringUnit": { "state": "translated", - "value": "Ventana actual" + "value": "Buscar…" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Fenêtre actuelle" + "value": "Rechercher…" } }, "it": { "stringUnit": { "state": "translated", - "value": "Finestra corrente" + "value": "Cerca…" } }, "da": { "stringUnit": { "state": "translated", - "value": "Nuværende vindue" + "value": "Find…" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Bieżące okno" + "value": "Znajdź…" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Текущее окно" + "value": "Найти…" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Trenutni prozor" + "value": "Pronađi…" } }, "ar": { "stringUnit": { "state": "translated", - "value": "النافذة الحالية" + "value": "بحث…" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Gjeldende vindu" + "value": "Finn…" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Janela Atual" + "value": "Buscar…" } }, "th": { "stringUnit": { "state": "translated", - "value": "หน้าต่างปัจจุบัน" + "value": "ค้นหา…" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Geçerli Pencere" + "value": "Bul…" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Поточне вікно" + "value": "Знайти…" } } } }, - "menu.file.closeOtherTabs": { + "menu.find.findNext": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Close Other Tabs in Pane" + "value": "Find Next" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ペイン内の他のタブを閉じる" + "value": "次を検索" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "关闭面板中的其他标签页" + "value": "查找下一个" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "關閉面板中的其他標籤頁" + "value": "尋找下一個" } }, "ko": { "stringUnit": { "state": "translated", - "value": "패널의 다른 탭 닫기" + "value": "다음 찾기" } }, "de": { "stringUnit": { "state": "translated", - "value": "Andere Tabs im Bereich schließen" + "value": "Weitersuchen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Cerrar otras pestañas del panel" + "value": "Buscar siguiente" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Fermer les autres onglets du panneau" + "value": "Résultat suivant" } }, "it": { "stringUnit": { "state": "translated", - "value": "Chiudi altre schede nel pannello" + "value": "Trova successivo" } }, "da": { "stringUnit": { "state": "translated", - "value": "Luk andre faner i panel" + "value": "Find næste" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Zamknij inne karty w panelu" + "value": "Znajdź następny" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Закрыть другие вкладки в панели" + "value": "Найти далее" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Zatvori ostale tabove u panelu" + "value": "Pronađi sljedeće" } }, "ar": { "stringUnit": { "state": "translated", - "value": "إغلاق الألسنة الأخرى في اللوحة" + "value": "البحث عن التالي" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Lukk andre faner i panelet" + "value": "Finn neste" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Fechar Outras Abas no Painel" + "value": "Buscar Próximo" } }, "th": { "stringUnit": { "state": "translated", - "value": "ปิดแท็บอื่นในบานหน้าต่าง" + "value": "ค้นหาถัดไป" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Bölmedeki Diğer Sekmeleri Kapat" + "value": "Sonrakini Bul" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Закрити інші вкладки в панелі" + "value": "Знайти наступне" } } } }, - "menu.file.closeTab": { + "menu.find.findInDirectory": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Close Tab" + "value": "Find in Directory…" } }, "ja": { "stringUnit": { "state": "translated", - "value": "タブを閉じる" + "value": "ディレクトリ内を検索…" + } + } + } + }, + "menu.find.findPrevious": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Find Previous" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "前を検索" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "关闭标签页" + "value": "查找上一个" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "關閉標籤頁" + "value": "尋找上一個" } }, "ko": { "stringUnit": { "state": "translated", - "value": "탭 닫기" + "value": "이전 찾기" } }, "de": { "stringUnit": { "state": "translated", - "value": "Tab schließen" + "value": "Vorheriges suchen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Cerrar pestaña" + "value": "Buscar anterior" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Fermer l'onglet" + "value": "Résultat précédent" } }, "it": { "stringUnit": { "state": "translated", - "value": "Chiudi scheda" + "value": "Trova precedente" } }, "da": { "stringUnit": { "state": "translated", - "value": "Luk fane" + "value": "Find forrige" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Zamknij kartę" + "value": "Znajdź poprzedni" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Закрыть вкладку" + "value": "Найти ранее" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Zatvori tab" + "value": "Pronađi prethodno" } }, "ar": { "stringUnit": { "state": "translated", - "value": "إغلاق اللسان" + "value": "البحث عن السابق" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Lukk fane" + "value": "Finn forrige" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Fechar Aba" + "value": "Buscar Anterior" } }, "th": { "stringUnit": { "state": "translated", - "value": "ปิดแท็บ" + "value": "ค้นหาก่อนหน้า" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Sekmeyi Kapat" + "value": "Öncekini Bul" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Закрити вкладку" + "value": "Знайти попереднє" } } } }, - "menu.file.closeWorkspace": { + "menu.find.hideFindBar": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Close Workspace" + "value": "Hide Find Bar" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ワークスペースを閉じる" + "value": "検索バーを非表示" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "关闭工作区" + "value": "隐藏查找栏" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "關閉工作區" + "value": "隱藏尋找列" } }, "ko": { "stringUnit": { "state": "translated", - "value": "작업 공간 닫기" + "value": "찾기 막대 숨기기" } }, "de": { "stringUnit": { "state": "translated", - "value": "Arbeitsbereich schließen" + "value": "Suchleiste ausblenden" } }, "es": { "stringUnit": { "state": "translated", - "value": "Cerrar espacio de trabajo" + "value": "Ocultar barra de búsqueda" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Fermer l'espace de travail" + "value": "Masquer la barre de recherche" } }, "it": { "stringUnit": { "state": "translated", - "value": "Chiudi area di lavoro" + "value": "Nascondi barra di ricerca" } }, "da": { "stringUnit": { "state": "translated", - "value": "Luk arbejdsområde" + "value": "Skjul søgelinje" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Zamknij przestrzeń roboczą" + "value": "Ukryj pasek wyszukiwania" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Закрыть рабочее пространство" + "value": "Скрыть панель поиска" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Zatvori radni prostor" + "value": "Sakrij traku za pretragu" } }, "ar": { "stringUnit": { "state": "translated", - "value": "إغلاق مساحة العمل" + "value": "إخفاء شريط البحث" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Lukk arbeidsområde" + "value": "Skjul søkelinje" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Fechar Área de Trabalho" + "value": "Ocultar Barra de Busca" } }, "th": { "stringUnit": { "state": "translated", - "value": "ปิดเวิร์กสเปซ" + "value": "ซ่อนแถบค้นหา" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Çalışma Alanını Kapat" + "value": "Arama Çubuğunu Gizle" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Закрити робочу область" + "value": "Сховати панель пошуку" } } } }, - "menu.file.commandPalette": { + "menu.find.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Command Palette…" + "value": "Find" } }, "ja": { "stringUnit": { "state": "translated", - "value": "コマンドパレット…" + "value": "検索" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "命令面板..." + "value": "查找" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "指令面板..." + "value": "尋找" } }, "ko": { "stringUnit": { "state": "translated", - "value": "명령어 팔레트…" + "value": "찾기" } }, "de": { "stringUnit": { "state": "translated", - "value": "Befehlspalette …" + "value": "Suchen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Paleta de comandos…" + "value": "Buscar" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Palette de commandes..." + "value": "Rechercher" } }, "it": { "stringUnit": { "state": "translated", - "value": "Tavolozza comandi…" + "value": "Trova" } }, "da": { "stringUnit": { "state": "translated", - "value": "Kommandopalette…" + "value": "Søg" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Paleta poleceń…" + "value": "Znajdź" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Палитра команд..." + "value": "Поиск" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Paleta naredbi…" + "value": "Pronađi" } }, "ar": { "stringUnit": { "state": "translated", - "value": "لوحة الأوامر…" + "value": "بحث" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Kommandopalett …" + "value": "Finn" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Paleta de Comandos…" + "value": "Buscar" } }, "th": { "stringUnit": { "state": "translated", - "value": "แถบคำสั่ง..." + "value": "ค้นหา" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Komut Paleti…" + "value": "Bul" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Палітра команд…" + "value": "Пошук" } } } }, - "menu.file.goToWorkspace": { + "menu.find.useSelectionForFind": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Go to Workspace…" + "value": "Use Selection for Find" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ワークスペースに移動…" + "value": "選択範囲を検索に使用" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "前往工作区..." + "value": "使用选中内容查找" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "前往工作區..." + "value": "使用所選範圍來尋找" } }, "ko": { "stringUnit": { "state": "translated", - "value": "작업 공간으로 이동…" + "value": "선택 항목을 찾기에 사용" } }, "de": { "stringUnit": { "state": "translated", - "value": "Zum Arbeitsbereich wechseln …" + "value": "Auswahl für Suche verwenden" } }, "es": { "stringUnit": { "state": "translated", - "value": "Ir al espacio de trabajo…" + "value": "Usar selección para buscar" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Aller à l'espace de travail..." + "value": "Utiliser la sélection pour la recherche" } }, "it": { "stringUnit": { "state": "translated", - "value": "Vai all'area di lavoro…" + "value": "Usa selezione per la ricerca" } }, "da": { "stringUnit": { "state": "translated", - "value": "Gå til arbejdsområde…" + "value": "Brug markering til søgning" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Przejdź do przestrzeni roboczej…" + "value": "Użyj zaznaczenia do wyszukiwania" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Перейти к рабочему пространству..." + "value": "Использовать выделение для поиска" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Idi na radni prostor…" + "value": "Koristi odabrano za pretragu" } }, "ar": { "stringUnit": { "state": "translated", - "value": "الانتقال إلى مساحة العمل…" + "value": "استخدام التحديد للبحث" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Gå til arbeidsområde …" + "value": "Bruk utvalg for søk" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Ir para Área de Trabalho…" + "value": "Usar Seleção para Busca" } }, "th": { "stringUnit": { "state": "translated", - "value": "ไปที่เวิร์กสเปซ..." + "value": "ใช้ข้อความที่เลือกเพื่อค้นหา" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Çalışma Alanına Git…" + "value": "Seçimi Bulmak İçin Kullan" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Перейти до робочої області…" + "value": "Використати виділення для пошуку" } } } }, - "menu.file.newWindow": { + "menu.notifications.clearAll": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "New Window" + "value": "Clear All" } }, "ja": { "stringUnit": { "state": "translated", - "value": "新規ウインドウ" + "value": "すべてクリア" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "新建窗口" + "value": "全部清除" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "新增視窗" + "value": "清除全部" } }, "ko": { "stringUnit": { "state": "translated", - "value": "새 윈도우" + "value": "모두 지우기" } }, "de": { "stringUnit": { "state": "translated", - "value": "Neues Fenster" + "value": "Alle löschen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Nueva ventana" + "value": "Borrar todo" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Nouvelle fenêtre" + "value": "Tout effacer" } }, "it": { "stringUnit": { "state": "translated", - "value": "Nuova finestra" + "value": "Cancella tutto" } }, "da": { "stringUnit": { "state": "translated", - "value": "Nyt vindue" + "value": "Ryd alle" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Nowe okno" + "value": "Wyczyść wszystko" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Новое окно" + "value": "Очистить все" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Novi prozor" + "value": "Obriši sve" } }, "ar": { "stringUnit": { "state": "translated", - "value": "نافذة جديدة" + "value": "مسح الكل" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Nytt vindu" + "value": "Fjern alle" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Nova Janela" + "value": "Limpar Tudo" } }, "th": { "stringUnit": { "state": "translated", - "value": "หน้าต่างใหม่" + "value": "ล้างทั้งหมด" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Yeni Pencere" + "value": "Tümünü Temizle" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Нове вікно" + "value": "Очистити все" } } } }, - "menu.file.newWorkspace": { + "menu.notifications.jumpToUnread": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "New Workspace" + "value": "Jump to Latest Unread" } }, "ja": { "stringUnit": { "state": "translated", - "value": "新規ワークスペース" + "value": "最新の未読にジャンプ" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "新建工作区" + "value": "跳转到最新未读" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "新增工作區" + "value": "跳至最新未讀" } }, "ko": { "stringUnit": { "state": "translated", - "value": "새 작업 공간" + "value": "최신 읽지 않은 항목으로 이동" } }, "de": { "stringUnit": { "state": "translated", - "value": "Neuer Arbeitsbereich" + "value": "Zur letzten ungelesenen springen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Nuevo espacio de trabajo" + "value": "Ir a la última no leída" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Nouvel espace de travail" + "value": "Aller au dernier message non lu" } }, "it": { "stringUnit": { "state": "translated", - "value": "Nuova area di lavoro" + "value": "Vai all'ultimo non letto" } }, "da": { "stringUnit": { "state": "translated", - "value": "Nyt arbejdsområde" + "value": "Gå til seneste ulæste" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Nowa przestrzeń robocza" + "value": "Przejdź do najnowszego nieprzeczytanego" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Новое рабочее пространство" + "value": "Перейти к последнему непрочитанному" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Novi radni prostor" + "value": "Skoči na najnovije nepročitano" } }, "ar": { "stringUnit": { "state": "translated", - "value": "مساحة عمل جديدة" + "value": "الانتقال إلى أحدث غير مقروء" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Nytt arbeidsområde" + "value": "Gå til siste uleste" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Nova Área de Trabalho" + "value": "Ir para Última Não Lida" } }, "th": { "stringUnit": { "state": "translated", - "value": "เวิร์กสเปซใหม่" + "value": "ข้ามไปยังรายการยังไม่อ่านล่าสุด" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Yeni Çalışma Alanı" + "value": "Son Okunmamışa Atla" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Нова робоча область" + "value": "Перейти до останнього непрочитаного" } } } }, - "menu.file.openFolder": { + "menu.notifications.toggleUnread": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Open Folder…" + "value": "Toggle Unread" } }, "ja": { "stringUnit": { "state": "translated", - "value": "フォルダを開く…" + "value": "未読を切り替え" + } + } + } + }, + "menu.notifications.markAllRead": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Mark All Read" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "すべて既読にする" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "打开文件夹..." + "value": "全部标记为已读" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "開啟資料夾..." + "value": "全部標為已讀" } }, "ko": { "stringUnit": { "state": "translated", - "value": "폴더 열기…" + "value": "모두 읽음으로 표시" } }, "de": { "stringUnit": { "state": "translated", - "value": "Ordner öffnen …" + "value": "Alle als gelesen markieren" } }, "es": { "stringUnit": { "state": "translated", - "value": "Abrir carpeta…" + "value": "Marcar todo como leído" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Ouvrir un dossier..." + "value": "Tout marquer comme lu" } }, "it": { "stringUnit": { "state": "translated", - "value": "Apri cartella…" + "value": "Segna tutto come letto" } }, "da": { "stringUnit": { "state": "translated", - "value": "Åbn mappe…" + "value": "Marker alle som læste" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Otwórz folder…" + "value": "Oznacz wszystko jako przeczytane" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Открыть папку..." + "value": "Отметить все как прочитанные" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Otvori folder…" + "value": "Označi sve kao pročitano" } }, "ar": { "stringUnit": { "state": "translated", - "value": "فتح مجلد…" + "value": "تعليم الكل كمقروء" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Åpne mappe …" + "value": "Merk alle som lest" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Abrir Pasta…" + "value": "Marcar Tudo como Lido" } }, "th": { "stringUnit": { "state": "translated", - "value": "เปิดโฟลเดอร์..." + "value": "ทำเครื่องหมายว่าอ่านทั้งหมดแล้ว" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Klasör Aç…" + "value": "Tümünü Okundu İşaretle" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Відкрити теку…" + "value": "Позначити все як прочитане" } } } }, - "menu.file.openFolder.panelPrompt": { + "menu.notifications.show": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Open" + "value": "Show Notifications" } }, "ja": { "stringUnit": { "state": "translated", - "value": "開く" + "value": "通知を表示" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "打开" + "value": "显示通知" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "開啟" + "value": "顯示通知" } }, "ko": { "stringUnit": { "state": "translated", - "value": "열기" + "value": "알림 표시" } }, "de": { "stringUnit": { "state": "translated", - "value": "Öffnen" + "value": "Benachrichtigungen anzeigen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Abrir" + "value": "Mostrar notificaciones" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Ouvrir" + "value": "Afficher les notifications" } }, "it": { "stringUnit": { "state": "translated", - "value": "Apri" + "value": "Mostra notifiche" } }, "da": { "stringUnit": { "state": "translated", - "value": "Åbn" + "value": "Vis notifikationer" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Otwórz" + "value": "Pokaż powiadomienia" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Открыть" + "value": "Показать уведомления" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Otvori" + "value": "Prikaži obavještenja" } }, "ar": { "stringUnit": { "state": "translated", - "value": "فتح" + "value": "عرض الإشعارات" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Åpne" + "value": "Vis varsler" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Abrir" + "value": "Mostrar Notificações" } }, "th": { "stringUnit": { "state": "translated", - "value": "เปิด" + "value": "แสดงการแจ้งเตือน" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Aç" + "value": "Bildirimleri Göster" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Відкрити" + "value": "Показати сповіщення" } } } }, - "menu.file.openFolder.panelTitle": { + "menu.notifications.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Open Folder" + "value": "Notifications" } }, "ja": { "stringUnit": { "state": "translated", - "value": "フォルダを開く" + "value": "通知" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "打开文件夹" + "value": "通知" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "開啟資料夾" + "value": "通知" } }, "ko": { "stringUnit": { "state": "translated", - "value": "폴더 열기" + "value": "알림" } }, "de": { "stringUnit": { "state": "translated", - "value": "Ordner öffnen" + "value": "Benachrichtigungen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Abrir carpeta" + "value": "Notificaciones" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Ouvrir un dossier" + "value": "Notifications" } }, "it": { "stringUnit": { "state": "translated", - "value": "Apri cartella" + "value": "Notifiche" } }, "da": { "stringUnit": { "state": "translated", - "value": "Åbn mappe" + "value": "Notifikationer" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Otwórz folder" + "value": "Powiadomienia" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Открыть папку" + "value": "Уведомления" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Otvori folder" + "value": "Obavještenja" } }, "ar": { "stringUnit": { "state": "translated", - "value": "فتح مجلد" + "value": "الإشعارات" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Åpne mappe" + "value": "Varsler" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Abrir Pasta" + "value": "Notificações" } }, "th": { "stringUnit": { "state": "translated", - "value": "เปิดโฟลเดอร์" + "value": "การแจ้งเตือน" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Klasör Aç" + "value": "Bildirimler" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Відкрити теку" + "value": "Сповіщення" } } } }, - "menu.file.openFolderInVSCodeInline": { + "menu.openInAndroidStudio": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Open Folder in VS Code (Inline)…" + "value": "Open Current Directory in Android Studio" } }, "ja": { "stringUnit": { "state": "translated", - "value": "フォルダを VS Code で開く(インライン)…" + "value": "現在のディレクトリを Android Studio で開く" } }, - "ko": { - "stringUnit": { - "state": "translated", - "value": "VS Code에서 폴더 열기 (인라인)…" - } - } - } - }, - "menu.file.openFolderInVSCodeInline.panelPrompt": { - "extractionState": "manual", - "localizations": { - "en": { + "zh-Hans": { "stringUnit": { "state": "translated", - "value": "Open in VS Code" + "value": "在 Android Studio 中打开当前目录" } }, - "ja": { + "zh-Hant": { "stringUnit": { "state": "translated", - "value": "VS Code で開く" + "value": "在 Android Studio 中開啟目前目錄" } }, "ko": { "stringUnit": { "state": "translated", - "value": "VS Code에서 열기" + "value": "현재 디렉토리를 Android Studio에서 열기" } - } - } - }, - "menu.file.openFolderInVSCodeInline.panelTitle": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "de": { "stringUnit": { "state": "translated", - "value": "Open Folder in VS Code (Inline)" + "value": "Aktuelles Verzeichnis in Android Studio öffnen" } }, - "ja": { + "es": { "stringUnit": { "state": "translated", - "value": "フォルダを VS Code で開く(インライン)" + "value": "Abrir directorio actual en Android Studio" } }, - "ko": { + "fr": { "stringUnit": { "state": "translated", - "value": "VS Code에서 폴더 열기 (인라인)" + "value": "Ouvrir le répertoire courant dans Android Studio" } - } - } - }, - "menu.file.reopenClosedBrowserPanel": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "it": { "stringUnit": { "state": "translated", - "value": "Reopen Closed Browser Panel" + "value": "Apri la directory corrente in Android Studio" } }, - "ja": { + "da": { "stringUnit": { "state": "translated", - "value": "閉じたブラウザパネルを再度開く" + "value": "Åbn nuværende mappe i Android Studio" } }, - "zh-Hans": { + "pl": { "stringUnit": { "state": "translated", - "value": "重新打开已关闭的浏览器面板" + "value": "Otwórz bieżący katalog w Android Studio" } }, - "zh-Hant": { + "ru": { "stringUnit": { "state": "translated", - "value": "重新開啟已關閉的瀏覽器面板" + "value": "Открыть текущий каталог в Android Studio" } }, - "ko": { + "bs": { "stringUnit": { "state": "translated", - "value": "닫은 브라우저 패널 다시 열기" + "value": "Otvori trenutni direktorij u Android Studio" } }, - "de": { + "ar": { "stringUnit": { "state": "translated", - "value": "Geschlossenes Browserfenster erneut öffnen" + "value": "فتح الدليل الحالي في Android Studio" } }, - "es": { + "nb": { "stringUnit": { "state": "translated", - "value": "Reabrir panel del navegador cerrado" + "value": "Åpne gjeldende katalog i Android Studio" } }, - "fr": { + "pt-BR": { "stringUnit": { "state": "translated", - "value": "Rouvrir le panneau de navigateur fermé" - } - }, - "it": { - "stringUnit": { - "state": "translated", - "value": "Riapri pannello browser chiuso" - } - }, - "da": { - "stringUnit": { - "state": "translated", - "value": "Genåbn lukket browserpanel" - } - }, - "pl": { - "stringUnit": { - "state": "translated", - "value": "Otwórz ponownie zamknięty panel przeglądarki" - } - }, - "ru": { - "stringUnit": { - "state": "translated", - "value": "Открыть закрытую панель браузера" - } - }, - "bs": { - "stringUnit": { - "state": "translated", - "value": "Ponovo otvori zatvoreni panel preglednika" - } - }, - "ar": { - "stringUnit": { - "state": "translated", - "value": "إعادة فتح لوحة المتصفح المغلقة" - } - }, - "nb": { - "stringUnit": { - "state": "translated", - "value": "Åpne lukket nettleserpanel på nytt" - } - }, - "pt-BR": { - "stringUnit": { - "state": "translated", - "value": "Reabrir Painel do Navegador Fechado" + "value": "Abrir Diretório Atual no Android Studio" } }, "th": { "stringUnit": { "state": "translated", - "value": "เปิดแผงเบราว์เซอร์ที่ปิดไปอีกครั้ง" + "value": "เปิดไดเรกทอรีปัจจุบันใน Android Studio" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Kapatılan Tarayıcı Panelini Yeniden Aç" + "value": "Geçerli Dizini Android Studio'da Aç" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Відновити закриту панель браузера" - } - } - } - }, - "menu.file.reopenPreviousSession": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Reopen Previous Session" - } - }, - "ja": { - "stringUnit": { - "state": "translated", - "value": "前回のセッションを再度開く" + "value": "Відкрити поточну теку в Android Studio" } } } }, - "menu.find.find": { + "menu.openInAntigravity": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Find…" + "value": "Open Current Directory in Antigravity" } }, "ja": { "stringUnit": { "state": "translated", - "value": "検索…" + "value": "現在のディレクトリを Antigravity で開く" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "查找…" + "value": "在 Antigravity 中打开当前目录" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "尋找…" + "value": "在 Antigravity 中開啟目前目錄" } }, "ko": { "stringUnit": { "state": "translated", - "value": "찾기…" + "value": "현재 디렉토리를 Antigravity에서 열기" } }, "de": { "stringUnit": { "state": "translated", - "value": "Suchen…" + "value": "Aktuelles Verzeichnis in Antigravity öffnen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Buscar…" + "value": "Abrir directorio actual en Antigravity" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Rechercher…" + "value": "Ouvrir le répertoire courant dans Antigravity" } }, "it": { "stringUnit": { "state": "translated", - "value": "Cerca…" + "value": "Apri la directory corrente in Antigravity" } }, "da": { "stringUnit": { "state": "translated", - "value": "Find…" + "value": "Åbn nuværende mappe i Antigravity" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Znajdź…" + "value": "Otwórz bieżący katalog w Antigravity" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Найти…" + "value": "Открыть текущий каталог в Antigravity" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Pronađi…" + "value": "Otvori trenutni direktorij u Antigravity" } }, "ar": { "stringUnit": { "state": "translated", - "value": "بحث…" + "value": "فتح الدليل الحالي في Antigravity" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Finn…" + "value": "Åpne gjeldende katalog i Antigravity" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Buscar…" + "value": "Abrir Diretório Atual no Antigravity" } }, "th": { "stringUnit": { "state": "translated", - "value": "ค้นหา…" + "value": "เปิดไดเรกทอรีปัจจุบันใน Antigravity" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Bul…" + "value": "Geçerli Dizini Antigravity'de Aç" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Знайти…" + "value": "Відкрити поточну теку в Antigravity" } } } }, - "menu.find.findNext": { + "menu.openInCursor": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Find Next" + "value": "Open Current Directory in Cursor" } }, "ja": { "stringUnit": { "state": "translated", - "value": "次を検索" + "value": "現在のディレクトリを Cursor で開く" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "查找下一个" + "value": "在 Cursor 中打开当前目录" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "尋找下一個" + "value": "在 Cursor 中開啟目前目錄" } }, "ko": { "stringUnit": { "state": "translated", - "value": "다음 찾기" + "value": "현재 디렉토리를 Cursor에서 열기" } }, "de": { "stringUnit": { "state": "translated", - "value": "Weitersuchen" + "value": "Aktuelles Verzeichnis in Cursor öffnen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Buscar siguiente" + "value": "Abrir directorio actual en Cursor" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Résultat suivant" + "value": "Ouvrir le répertoire courant dans Cursor" } }, "it": { "stringUnit": { "state": "translated", - "value": "Trova successivo" + "value": "Apri la directory corrente in Cursor" } }, "da": { "stringUnit": { "state": "translated", - "value": "Find næste" + "value": "Åbn nuværende mappe i Cursor" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Znajdź następny" + "value": "Otwórz bieżący katalog w Cursor" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Найти далее" + "value": "Открыть текущий каталог в Cursor" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Pronađi sljedeće" + "value": "Otvori trenutni direktorij u Cursor" } }, "ar": { "stringUnit": { "state": "translated", - "value": "البحث عن التالي" + "value": "فتح الدليل الحالي في Cursor" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Finn neste" + "value": "Åpne gjeldende katalog i Cursor" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Buscar Próximo" + "value": "Abrir Diretório Atual no Cursor" } }, "th": { "stringUnit": { "state": "translated", - "value": "ค้นหาถัดไป" + "value": "เปิดไดเรกทอรีปัจจุบันใน Cursor" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Sonrakini Bul" + "value": "Geçerli Dizini Cursor'da Aç" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Знайти наступне" - } - } - } - }, - "menu.find.findInDirectory": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Find in Directory…" - } - }, - "ja": { - "stringUnit": { - "state": "translated", - "value": "ディレクトリ内を検索…" + "value": "Відкрити поточну теку в Cursor" } } } }, - "menu.find.findPrevious": { + "menu.openInFinder": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Find Previous" + "value": "Open Current Directory in Finder" } }, "ja": { "stringUnit": { "state": "translated", - "value": "前を検索" + "value": "現在のディレクトリを Finder で開く" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "查找上一个" + "value": "在访达中打开当前目录" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "尋找上一個" + "value": "在 Finder 中開啟目前目錄" } }, "ko": { "stringUnit": { "state": "translated", - "value": "이전 찾기" + "value": "현재 디렉토리를 Finder에서 열기" } }, "de": { "stringUnit": { "state": "translated", - "value": "Vorheriges suchen" + "value": "Aktuelles Verzeichnis im Finder öffnen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Buscar anterior" + "value": "Abrir directorio actual en Finder" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Résultat précédent" + "value": "Ouvrir le répertoire courant dans le Finder" } }, "it": { "stringUnit": { "state": "translated", - "value": "Trova precedente" + "value": "Apri la directory corrente nel Finder" } }, "da": { "stringUnit": { "state": "translated", - "value": "Find forrige" + "value": "Åbn nuværende mappe i Finder" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Znajdź poprzedni" + "value": "Otwórz bieżący katalog w Finderze" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Найти ранее" + "value": "Открыть текущий каталог в Finder" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Pronađi prethodno" + "value": "Otvori trenutni direktorij u Finder" } }, "ar": { "stringUnit": { "state": "translated", - "value": "البحث عن السابق" + "value": "فتح الدليل الحالي في Finder" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Finn forrige" + "value": "Åpne gjeldende katalog i Finder" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Buscar Anterior" + "value": "Abrir Diretório Atual no Finder" } }, "th": { "stringUnit": { "state": "translated", - "value": "ค้นหาก่อนหน้า" + "value": "เปิดไดเรกทอรีปัจจุบันใน Finder" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Öncekini Bul" + "value": "Geçerli Dizini Finder'da Aç" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Знайти попереднє" + "value": "Відкрити поточну теку у Finder" } } } }, - "menu.find.hideFindBar": { + "menu.openInGhostty": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Hide Find Bar" + "value": "Open Current Directory in Ghostty" } }, "ja": { "stringUnit": { "state": "translated", - "value": "検索バーを非表示" + "value": "現在のディレクトリを Ghostty で開く" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "隐藏查找栏" + "value": "在 Ghostty 中打开当前目录" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "隱藏尋找列" + "value": "在 Ghostty 中開啟目前目錄" } }, "ko": { "stringUnit": { "state": "translated", - "value": "찾기 막대 숨기기" + "value": "현재 디렉토리를 Ghostty에서 열기" } }, "de": { "stringUnit": { "state": "translated", - "value": "Suchleiste ausblenden" + "value": "Aktuelles Verzeichnis in Ghostty öffnen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Ocultar barra de búsqueda" + "value": "Abrir directorio actual en Ghostty" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Masquer la barre de recherche" + "value": "Ouvrir le répertoire courant dans Ghostty" } }, "it": { "stringUnit": { "state": "translated", - "value": "Nascondi barra di ricerca" + "value": "Apri la directory corrente in Ghostty" } }, "da": { "stringUnit": { "state": "translated", - "value": "Skjul søgelinje" + "value": "Åbn nuværende mappe i Ghostty" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Ukryj pasek wyszukiwania" + "value": "Otwórz bieżący katalog w Ghostty" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Скрыть панель поиска" + "value": "Открыть текущий каталог в Ghostty" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Sakrij traku za pretragu" + "value": "Otvori trenutni direktorij u Ghostty" } }, "ar": { "stringUnit": { "state": "translated", - "value": "إخفاء شريط البحث" + "value": "فتح الدليل الحالي في Ghostty" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Skjul søkelinje" + "value": "Åpne gjeldende katalog i Ghostty" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Ocultar Barra de Busca" + "value": "Abrir Diretório Atual no Ghostty" } }, "th": { "stringUnit": { "state": "translated", - "value": "ซ่อนแถบค้นหา" + "value": "เปิดไดเรกทอรีปัจจุบันใน Ghostty" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Arama Çubuğunu Gizle" + "value": "Geçerli Dizini Ghostty'de Aç" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Сховати панель пошуку" + "value": "Відкрити поточну теку в Ghostty" } } } }, - "menu.find.title": { + "menu.openInITerm2": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Find" + "value": "Open Current Directory in iTerm2" } }, "ja": { "stringUnit": { "state": "translated", - "value": "検索" + "value": "現在のディレクトリを iTerm2 で開く" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "查找" + "value": "在 iTerm2 中打开当前目录" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "尋找" + "value": "在 iTerm2 中開啟目前目錄" } }, "ko": { "stringUnit": { "state": "translated", - "value": "찾기" + "value": "현재 디렉토리를 iTerm2에서 열기" } }, "de": { "stringUnit": { "state": "translated", - "value": "Suchen" + "value": "Aktuelles Verzeichnis in iTerm2 öffnen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Buscar" + "value": "Abrir directorio actual en iTerm2" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Rechercher" + "value": "Ouvrir le répertoire courant dans iTerm2" } }, "it": { "stringUnit": { "state": "translated", - "value": "Trova" + "value": "Apri la directory corrente in iTerm2" } }, "da": { "stringUnit": { "state": "translated", - "value": "Søg" + "value": "Åbn nuværende mappe i iTerm2" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Znajdź" + "value": "Otwórz bieżący katalog w iTerm2" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Поиск" + "value": "Открыть текущий каталог в iTerm2" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Pronađi" + "value": "Otvori trenutni direktorij u iTerm2" } }, "ar": { "stringUnit": { "state": "translated", - "value": "بحث" + "value": "فتح الدليل الحالي في iTerm2" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Finn" + "value": "Åpne gjeldende katalog i iTerm2" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Buscar" + "value": "Abrir Diretório Atual no iTerm2" } }, "th": { "stringUnit": { "state": "translated", - "value": "ค้นหา" + "value": "เปิดไดเรกทอรีปัจจุบันใน iTerm2" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Bul" + "value": "Geçerli Dizini iTerm2'de Aç" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Пошук" + "value": "Відкрити поточну теку в iTerm2" } } } }, - "menu.find.useSelectionForFind": { + "menu.openInTerminal": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Use Selection for Find" + "value": "Open Current Directory in Terminal" } }, "ja": { "stringUnit": { "state": "translated", - "value": "選択範囲を検索に使用" + "value": "現在のディレクトリをターミナルで開く" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "使用选中内容查找" + "value": "在终端中打开当前目录" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "使用所選範圍來尋找" + "value": "在「終端機」中開啟目前目錄" } }, "ko": { "stringUnit": { "state": "translated", - "value": "선택 항목을 찾기에 사용" + "value": "현재 디렉토리를 터미널에서 열기" } }, "de": { "stringUnit": { "state": "translated", - "value": "Auswahl für Suche verwenden" + "value": "Aktuelles Verzeichnis in Terminal öffnen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Usar selección para buscar" + "value": "Abrir directorio actual en Terminal" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Utiliser la sélection pour la recherche" + "value": "Ouvrir le répertoire courant dans Terminal" } }, "it": { "stringUnit": { "state": "translated", - "value": "Usa selezione per la ricerca" + "value": "Apri la directory corrente in Terminale" } }, "da": { "stringUnit": { "state": "translated", - "value": "Brug markering til søgning" + "value": "Åbn nuværende mappe i Terminal" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Użyj zaznaczenia do wyszukiwania" + "value": "Otwórz bieżący katalog w Terminalu" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Использовать выделение для поиска" + "value": "Открыть текущий каталог в Терминале" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Koristi odabrano za pretragu" + "value": "Otvori trenutni direktorij u Terminal" } }, "ar": { "stringUnit": { "state": "translated", - "value": "استخدام التحديد للبحث" + "value": "فتح الدليل الحالي في Terminal" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Bruk utvalg for søk" + "value": "Åpne gjeldende katalog i Terminal" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Usar Seleção para Busca" + "value": "Abrir Diretório Atual no Terminal" } }, "th": { "stringUnit": { "state": "translated", - "value": "ใช้ข้อความที่เลือกเพื่อค้นหา" + "value": "เปิดไดเรกทอรีปัจจุบันใน Terminal" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Seçimi Bulmak İçin Kullan" + "value": "Geçerli Dizini Terminal'de Aç" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Використати виділення для пошуку" + "value": "Відкрити поточну теку в Terminal" } } } }, - "menu.notifications.clearAll": { + "menu.openInTower": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Clear All" + "value": "Open Current Directory in Tower" } }, "ja": { "stringUnit": { "state": "translated", - "value": "すべてクリア" + "value": "現在のディレクトリを Tower で開く" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "全部清除" + "value": "在 Tower 中打开当前目录" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "清除全部" + "value": "在 Tower 中開啟目前目錄" } }, "ko": { "stringUnit": { "state": "translated", - "value": "모두 지우기" + "value": "현재 디렉토리를 Tower에서 열기" } }, "de": { "stringUnit": { "state": "translated", - "value": "Alle löschen" + "value": "Aktuelles Verzeichnis in Tower öffnen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Borrar todo" + "value": "Abrir directorio actual en Tower" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Tout effacer" + "value": "Ouvrir le répertoire courant dans Tower" } }, "it": { "stringUnit": { "state": "translated", - "value": "Cancella tutto" + "value": "Apri la directory corrente in Tower" } }, "da": { "stringUnit": { "state": "translated", - "value": "Ryd alle" + "value": "Åbn nuværende mappe i Tower" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Wyczyść wszystko" + "value": "Otwórz bieżący katalog w Tower" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Очистить все" + "value": "Открыть текущий каталог в Tower" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Obriši sve" + "value": "Otvori trenutni direktorij u Tower" } }, "ar": { "stringUnit": { "state": "translated", - "value": "مسح الكل" + "value": "فتح الدليل الحالي في Tower" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Fjern alle" + "value": "Åpne gjeldende katalog i Tower" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Limpar Tudo" + "value": "Abrir Diretório Atual no Tower" } }, "th": { "stringUnit": { "state": "translated", - "value": "ล้างทั้งหมด" + "value": "เปิดไดเรกทอรีปัจจุบันใน Tower" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Tümünü Temizle" + "value": "Geçerli Dizini Tower'da Aç" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Очистити все" + "value": "Відкрити поточну теку в Tower" } } } }, - "menu.notifications.jumpToUnread": { + "menu.openInVSCode": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Jump to Latest Unread" + "value": "Open Current Directory in VS Code (Inline)" } }, "ja": { "stringUnit": { "state": "translated", - "value": "最新の未読にジャンプ" + "value": "現在のディレクトリを VS Code で開く(インライン)" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "跳转到最新未读" + "value": "在 VS Code(内联)中打开当前目录" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "跳至最新未讀" + "value": "在 VS Code(內嵌)中開啟目前目錄" } }, "ko": { "stringUnit": { "state": "translated", - "value": "최신 읽지 않은 항목으로 이동" + "value": "현재 디렉토리를 VS Code (인라인)에서 열기" } }, "de": { "stringUnit": { "state": "translated", - "value": "Zur letzten ungelesenen springen" + "value": "Aktuelles Verzeichnis in VS Code (Inline) öffnen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Ir a la última no leída" + "value": "Abrir directorio actual en VS Code (en línea)" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Aller au dernier message non lu" + "value": "Ouvrir le répertoire courant dans VS Code (intégré)" } }, "it": { "stringUnit": { "state": "translated", - "value": "Vai all'ultimo non letto" + "value": "Apri la directory corrente in VS Code (Inline)" } }, "da": { "stringUnit": { "state": "translated", - "value": "Gå til seneste ulæste" + "value": "Åbn nuværende mappe i VS Code (Inline)" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Przejdź do najnowszego nieprzeczytanego" + "value": "Otwórz bieżący katalog w VS Code (wbudowany)" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Перейти к последнему непрочитанному" + "value": "Открыть текущий каталог в VS Code (встроенный)" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Skoči na najnovije nepročitano" + "value": "Otvori trenutni direktorij u VS Code (Inline)" } }, "ar": { "stringUnit": { "state": "translated", - "value": "الانتقال إلى أحدث غير مقروء" + "value": "فتح الدليل الحالي في VS Code (مضمّن)" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Gå til siste uleste" + "value": "Åpne gjeldende katalog i VS Code (innebygd)" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Ir para Última Não Lida" + "value": "Abrir Diretório Atual no VS Code (Inline)" } }, "th": { "stringUnit": { "state": "translated", - "value": "ข้ามไปยังรายการยังไม่อ่านล่าสุด" + "value": "เปิดไดเรกทอรีปัจจุบันใน VS Code (แบบอินไลน์)" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Son Okunmamışa Atla" + "value": "Geçerli Dizini VS Code'da Aç (Satır İçi)" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Перейти до останнього непрочитаного" + "value": "Відкрити поточну теку в VS Code (вбудований)" } } } }, - "menu.notifications.toggleUnread": { + "menu.openInVSCodeDesktop": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Toggle Unread" + "value": "Open Current Directory in VS Code" } }, "ja": { "stringUnit": { "state": "translated", - "value": "未読を切り替え" + "value": "現在のディレクトリを VS Code で開く" + } + }, + "uk": { + "stringUnit": { + "state": "translated", + "value": "Відкрити поточну теку в VS Code" + } + }, + "ko": { + "stringUnit": { + "state": "translated", + "value": "현재 디렉토리를 VS Code에서 열기" } } } }, - "menu.notifications.markAllRead": { + "menu.openInWarp": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Mark All Read" + "value": "Open Current Directory in Warp" } }, "ja": { "stringUnit": { "state": "translated", - "value": "すべて既読にする" + "value": "現在のディレクトリを Warp で開く" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "全部标记为已读" + "value": "在 Warp 中打开当前目录" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "全部標為已讀" + "value": "在 Warp 中開啟目前目錄" } }, "ko": { "stringUnit": { "state": "translated", - "value": "모두 읽음으로 표시" + "value": "현재 디렉토리를 Warp에서 열기" } }, "de": { "stringUnit": { "state": "translated", - "value": "Alle als gelesen markieren" + "value": "Aktuelles Verzeichnis in Warp öffnen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Marcar todo como leído" + "value": "Abrir directorio actual en Warp" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Tout marquer comme lu" + "value": "Ouvrir le répertoire courant dans Warp" } }, "it": { "stringUnit": { "state": "translated", - "value": "Segna tutto come letto" + "value": "Apri la directory corrente in Warp" } }, "da": { "stringUnit": { "state": "translated", - "value": "Marker alle som læste" + "value": "Åbn nuværende mappe i Warp" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Oznacz wszystko jako przeczytane" + "value": "Otwórz bieżący katalog w Warp" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Отметить все как прочитанные" + "value": "Открыть текущий каталог в Warp" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Označi sve kao pročitano" + "value": "Otvori trenutni direktorij u Warp" } }, "ar": { "stringUnit": { "state": "translated", - "value": "تعليم الكل كمقروء" + "value": "فتح الدليل الحالي في Warp" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Merk alle som lest" + "value": "Åpne gjeldende katalog i Warp" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Marcar Tudo como Lido" + "value": "Abrir Diretório Atual no Warp" } }, "th": { "stringUnit": { "state": "translated", - "value": "ทำเครื่องหมายว่าอ่านทั้งหมดแล้ว" + "value": "เปิดไดเรกทอรีปัจจุบันใน Warp" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Tümünü Okundu İşaretle" + "value": "Geçerli Dizini Warp'ta Aç" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Позначити все як прочитане" + "value": "Відкрити поточну теку в Warp" } } } }, - "menu.notifications.show": { + "menu.openInWindsurf": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Show Notifications" + "value": "Open Current Directory in Windsurf" } }, "ja": { "stringUnit": { "state": "translated", - "value": "通知を表示" + "value": "現在のディレクトリを Windsurf で開く" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "显示通知" + "value": "在 Windsurf 中打开当前目录" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "顯示通知" + "value": "在 Windsurf 中開啟目前目錄" } }, "ko": { "stringUnit": { "state": "translated", - "value": "알림 표시" + "value": "현재 디렉토리를 Windsurf에서 열기" } }, "de": { "stringUnit": { "state": "translated", - "value": "Benachrichtigungen anzeigen" + "value": "Aktuelles Verzeichnis in Windsurf öffnen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Mostrar notificaciones" + "value": "Abrir directorio actual en Windsurf" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Afficher les notifications" + "value": "Ouvrir le répertoire courant dans Windsurf" } }, "it": { "stringUnit": { "state": "translated", - "value": "Mostra notifiche" + "value": "Apri la directory corrente in Windsurf" } }, "da": { "stringUnit": { "state": "translated", - "value": "Vis notifikationer" + "value": "Åbn nuværende mappe i Windsurf" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Pokaż powiadomienia" + "value": "Otwórz bieżący katalog w Windsurf" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Показать уведомления" + "value": "Открыть текущий каталог в Windsurf" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Prikaži obavještenja" + "value": "Otvori trenutni direktorij u Windsurf" } }, "ar": { "stringUnit": { "state": "translated", - "value": "عرض الإشعارات" + "value": "فتح الدليل الحالي في Windsurf" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Vis varsler" + "value": "Åpne gjeldende katalog i Windsurf" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Mostrar Notificações" + "value": "Abrir Diretório Atual no Windsurf" } }, "th": { "stringUnit": { "state": "translated", - "value": "แสดงการแจ้งเตือน" + "value": "เปิดไดเรกทอรีปัจจุบันใน Windsurf" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Bildirimleri Göster" + "value": "Geçerli Dizini Windsurf'te Aç" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Показати сповіщення" + "value": "Відкрити поточну теку в Windsurf" } } } }, - "menu.notifications.title": { + "menu.openInXcode": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Notifications" + "value": "Open Current Directory in Xcode" } }, "ja": { "stringUnit": { "state": "translated", - "value": "通知" + "value": "現在のディレクトリを Xcode で開く" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "通知" + "value": "在 Xcode 中打开当前目录" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "通知" + "value": "在 Xcode 中開啟目前目錄" } }, "ko": { "stringUnit": { "state": "translated", - "value": "알림" + "value": "현재 디렉토리를 Xcode에서 열기" } }, "de": { "stringUnit": { "state": "translated", - "value": "Benachrichtigungen" + "value": "Aktuelles Verzeichnis in Xcode öffnen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Notificaciones" + "value": "Abrir directorio actual en Xcode" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Notifications" + "value": "Ouvrir le répertoire courant dans Xcode" } }, "it": { "stringUnit": { "state": "translated", - "value": "Notifiche" + "value": "Apri la directory corrente in Xcode" } }, "da": { "stringUnit": { "state": "translated", - "value": "Notifikationer" + "value": "Åbn nuværende mappe i Xcode" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Powiadomienia" + "value": "Otwórz bieżący katalog w Xcode" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Уведомления" + "value": "Открыть текущий каталог в Xcode" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Obavještenja" + "value": "Otvori trenutni direktorij u Xcode" } }, "ar": { "stringUnit": { "state": "translated", - "value": "الإشعارات" + "value": "فتح الدليل الحالي في Xcode" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Varsler" + "value": "Åpne gjeldende katalog i Xcode" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Notificações" + "value": "Abrir Diretório Atual no Xcode" } }, "th": { "stringUnit": { "state": "translated", - "value": "การแจ้งเตือน" + "value": "เปิดไดเรกทอรีปัจจุบันใน Xcode" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Bildirimler" + "value": "Geçerli Dizini Xcode'da Aç" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Сповіщення" + "value": "Відкрити поточну теку в Xcode" } } } }, - "menu.openInAndroidStudio": { + "menu.openInZed": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Open Current Directory in Android Studio" + "value": "Open Current Directory in Zed" } }, "ja": { "stringUnit": { "state": "translated", - "value": "現在のディレクトリを Android Studio で開く" + "value": "現在のディレクトリを Zed で開く" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "在 Android Studio 中打开当前目录" + "value": "在 Zed 中打开当前目录" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "在 Android Studio 中開啟目前目錄" + "value": "在 Zed 中開啟目前目錄" } }, "ko": { "stringUnit": { "state": "translated", - "value": "현재 디렉토리를 Android Studio에서 열기" + "value": "현재 디렉토리를 Zed에서 열기" } }, "de": { "stringUnit": { "state": "translated", - "value": "Aktuelles Verzeichnis in Android Studio öffnen" + "value": "Aktuelles Verzeichnis in Zed öffnen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Abrir directorio actual en Android Studio" + "value": "Abrir directorio actual en Zed" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Ouvrir le répertoire courant dans Android Studio" + "value": "Ouvrir le répertoire courant dans Zed" } }, "it": { "stringUnit": { "state": "translated", - "value": "Apri la directory corrente in Android Studio" + "value": "Apri la directory corrente in Zed" } }, "da": { "stringUnit": { "state": "translated", - "value": "Åbn nuværende mappe i Android Studio" + "value": "Åbn nuværende mappe i Zed" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Otwórz bieżący katalog w Android Studio" + "value": "Otwórz bieżący katalog w Zed" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Открыть текущий каталог в Android Studio" + "value": "Открыть текущий каталог в Zed" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Otvori trenutni direktorij u Android Studio" + "value": "Otvori trenutni direktorij u Zed" } }, "ar": { "stringUnit": { "state": "translated", - "value": "فتح الدليل الحالي في Android Studio" + "value": "فتح الدليل الحالي في Zed" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Åpne gjeldende katalog i Android Studio" + "value": "Åpne gjeldende katalog i Zed" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Abrir Diretório Atual no Android Studio" + "value": "Abrir Diretório Atual no Zed" } }, "th": { "stringUnit": { "state": "translated", - "value": "เปิดไดเรกทอรีปัจจุบันใน Android Studio" + "value": "เปิดไดเรกทอรีปัจจุบันใน Zed" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Geçerli Dizini Android Studio'da Aç" + "value": "Geçerli Dizini Zed'de Aç" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Відкрити поточну теку в Android Studio" + "value": "Відкрити поточну теку в Zed" } } } }, - "menu.openInAntigravity": { + "menu.preferences": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Open Current Directory in Antigravity" + "value": "Preferences…" } }, "ja": { "stringUnit": { "state": "translated", - "value": "現在のディレクトリを Antigravity で開く" + "value": "設定…" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "在 Antigravity 中打开当前目录" + "value": "偏好设置..." } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "在 Antigravity 中開啟目前目錄" + "value": "偏好設定..." } }, "ko": { "stringUnit": { "state": "translated", - "value": "현재 디렉토리를 Antigravity에서 열기" + "value": "환경설정…" } }, "de": { "stringUnit": { "state": "translated", - "value": "Aktuelles Verzeichnis in Antigravity öffnen" + "value": "Einstellungen …" } }, "es": { "stringUnit": { "state": "translated", - "value": "Abrir directorio actual en Antigravity" + "value": "Preferencias…" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Ouvrir le répertoire courant dans Antigravity" + "value": "Préférences..." } }, "it": { "stringUnit": { "state": "translated", - "value": "Apri la directory corrente in Antigravity" + "value": "Preferenze…" } }, "da": { "stringUnit": { "state": "translated", - "value": "Åbn nuværende mappe i Antigravity" + "value": "Indstillinger…" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Otwórz bieżący katalog w Antigravity" + "value": "Preferencje…" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Открыть текущий каталог в Antigravity" + "value": "Настройки..." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Otvori trenutni direktorij u Antigravity" + "value": "Postavke…" } }, "ar": { "stringUnit": { "state": "translated", - "value": "فتح الدليل الحالي في Antigravity" + "value": "التفضيلات…" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Åpne gjeldende katalog i Antigravity" + "value": "Innstillinger …" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Abrir Diretório Atual no Antigravity" + "value": "Preferências…" } }, "th": { "stringUnit": { "state": "translated", - "value": "เปิดไดเรกทอรีปัจจุบันใน Antigravity" + "value": "การตั้งค่า..." } }, "tr": { "stringUnit": { "state": "translated", - "value": "Geçerli Dizini Antigravity'de Aç" + "value": "Tercihler…" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Відкрити поточну теку в Antigravity" + "value": "Параметри…" } } } }, - "menu.openInCursor": { + "menu.quitCmux": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Open Current Directory in Cursor" + "value": "Quit cmux" } }, "ja": { "stringUnit": { "state": "translated", - "value": "現在のディレクトリを Cursor で開く" + "value": "cmux を終了" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "在 Cursor 中打开当前目录" + "value": "退出 cmux" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "在 Cursor 中開啟目前目錄" + "value": "結束 cmux" } }, "ko": { "stringUnit": { "state": "translated", - "value": "현재 디렉토리를 Cursor에서 열기" + "value": "cmux 종료" } }, "de": { "stringUnit": { "state": "translated", - "value": "Aktuelles Verzeichnis in Cursor öffnen" + "value": "cmux beenden" } }, "es": { "stringUnit": { "state": "translated", - "value": "Abrir directorio actual en Cursor" + "value": "Salir de cmux" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Ouvrir le répertoire courant dans Cursor" + "value": "Quitter cmux" } }, "it": { "stringUnit": { "state": "translated", - "value": "Apri la directory corrente in Cursor" + "value": "Esci da cmux" } }, "da": { "stringUnit": { "state": "translated", - "value": "Åbn nuværende mappe i Cursor" + "value": "Afslut cmux" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Otwórz bieżący katalog w Cursor" + "value": "Zakończ cmux" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Открыть текущий каталог в Cursor" + "value": "Завершить cmux" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Otvori trenutni direktorij u Cursor" + "value": "Zatvori cmux" } }, "ar": { "stringUnit": { "state": "translated", - "value": "فتح الدليل الحالي في Cursor" + "value": "إنهاء cmux" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Åpne gjeldende katalog i Cursor" + "value": "Avslutt cmux" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Abrir Diretório Atual no Cursor" + "value": "Encerrar o cmux" } }, "th": { "stringUnit": { "state": "translated", - "value": "เปิดไดเรกทอรีปัจจุบันใน Cursor" + "value": "ออกจาก cmux" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Geçerli Dizini Cursor'da Aç" + "value": "cmux'tan Çık" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Відкрити поточну теку в Cursor" + "value": "Завершити cmux" } } } }, - "menu.openInFinder": { + "menu.showNotifications": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Open Current Directory in Finder" + "value": "Show Notifications" } }, "ja": { "stringUnit": { "state": "translated", - "value": "現在のディレクトリを Finder で開く" + "value": "通知を表示" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "在访达中打开当前目录" + "value": "显示通知" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "在 Finder 中開啟目前目錄" + "value": "顯示通知" } }, "ko": { "stringUnit": { "state": "translated", - "value": "현재 디렉토리를 Finder에서 열기" + "value": "알림 표시" } }, "de": { "stringUnit": { "state": "translated", - "value": "Aktuelles Verzeichnis im Finder öffnen" + "value": "Benachrichtigungen anzeigen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Abrir directorio actual en Finder" + "value": "Mostrar notificaciones" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Ouvrir le répertoire courant dans le Finder" + "value": "Afficher les notifications" } }, "it": { "stringUnit": { "state": "translated", - "value": "Apri la directory corrente nel Finder" + "value": "Mostra notifiche" } }, "da": { "stringUnit": { "state": "translated", - "value": "Åbn nuværende mappe i Finder" + "value": "Vis notifikationer" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Otwórz bieżący katalog w Finderze" + "value": "Pokaż powiadomienia" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Открыть текущий каталог в Finder" + "value": "Показать уведомления" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Otvori trenutni direktorij u Finder" + "value": "Prikaži obavještenja" } }, "ar": { "stringUnit": { "state": "translated", - "value": "فتح الدليل الحالي في Finder" + "value": "عرض الإشعارات" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Åpne gjeldende katalog i Finder" + "value": "Vis varsler" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Abrir Diretório Atual no Finder" + "value": "Mostrar Notificações" } }, "th": { "stringUnit": { "state": "translated", - "value": "เปิดไดเรกทอรีปัจจุบันใน Finder" + "value": "แสดงการแจ้งเตือน" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Geçerli Dizini Finder'da Aç" + "value": "Bildirimleri Göster" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Відкрити поточну теку у Finder" + "value": "Показати сповіщення" } } } }, - "menu.openInGhostty": { + "menu.updateLogs.copyFocusLogs": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Open Current Directory in Ghostty" + "value": "Copy Focus Logs" } }, "ja": { "stringUnit": { "state": "translated", - "value": "現在のディレクトリを Ghostty で開く" + "value": "フォーカスログをコピー" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "在 Ghostty 中打开当前目录" + "value": "拷贝焦点日志" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "在 Ghostty 中開啟目前目錄" + "value": "拷貝焦點記錄" } }, "ko": { "stringUnit": { "state": "translated", - "value": "현재 디렉토리를 Ghostty에서 열기" + "value": "포커스 로그 복사" } }, "de": { "stringUnit": { "state": "translated", - "value": "Aktuelles Verzeichnis in Ghostty öffnen" + "value": "Fokus-Protokolle kopieren" } }, "es": { "stringUnit": { "state": "translated", - "value": "Abrir directorio actual en Ghostty" + "value": "Copiar registros de enfoque" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Ouvrir le répertoire courant dans Ghostty" + "value": "Copier les journaux de focus" } }, "it": { "stringUnit": { "state": "translated", - "value": "Apri la directory corrente in Ghostty" + "value": "Copia log di focus" } }, "da": { "stringUnit": { "state": "translated", - "value": "Åbn nuværende mappe i Ghostty" + "value": "Kopier fokuslogfiler" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Otwórz bieżący katalog w Ghostty" + "value": "Kopiuj dzienniki fokusu" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Открыть текущий каталог в Ghostty" + "value": "Скопировать журнал фокуса" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Otvori trenutni direktorij u Ghostty" + "value": "Kopiraj logove fokusa" } }, "ar": { "stringUnit": { "state": "translated", - "value": "فتح الدليل الحالي في Ghostty" + "value": "نسخ سجلات التركيز" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Åpne gjeldende katalog i Ghostty" + "value": "Kopier fokuslogger" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Abrir Diretório Atual no Ghostty" + "value": "Copiar Logs de Foco" } }, "th": { "stringUnit": { "state": "translated", - "value": "เปิดไดเรกทอรีปัจจุบันใน Ghostty" + "value": "คัดลอกบันทึกการโฟกัส" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Geçerli Dizini Ghostty'de Aç" + "value": "Odak Günlüklerini Kopyala" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Відкрити поточну теку в Ghostty" + "value": "Копіювати журнал фокусу" } } } }, - "menu.openInITerm2": { + "menu.updateLogs.copyUpdateLogs": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Open Current Directory in iTerm2" + "value": "Copy Update Logs" } }, "ja": { "stringUnit": { "state": "translated", - "value": "現在のディレクトリを iTerm2 で開く" + "value": "アップデートログをコピー" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "在 iTerm2 中打开当前目录" + "value": "拷贝更新日志" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "在 iTerm2 中開啟目前目錄" + "value": "拷貝更新記錄" } }, "ko": { "stringUnit": { "state": "translated", - "value": "현재 디렉토리를 iTerm2에서 열기" + "value": "업데이트 로그 복사" } }, "de": { "stringUnit": { "state": "translated", - "value": "Aktuelles Verzeichnis in iTerm2 öffnen" + "value": "Update-Protokolle kopieren" } }, "es": { "stringUnit": { "state": "translated", - "value": "Abrir directorio actual en iTerm2" + "value": "Copiar registros de actualización" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Ouvrir le répertoire courant dans iTerm2" + "value": "Copier les journaux de mise à jour" } }, "it": { "stringUnit": { "state": "translated", - "value": "Apri la directory corrente in iTerm2" + "value": "Copia log aggiornamento" } }, "da": { "stringUnit": { "state": "translated", - "value": "Åbn nuværende mappe i iTerm2" + "value": "Kopier opdateringslogfiler" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Otwórz bieżący katalog w iTerm2" + "value": "Kopiuj dzienniki aktualizacji" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Открыть текущий каталог в iTerm2" + "value": "Скопировать журнал обновлений" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Otvori trenutni direktorij u iTerm2" + "value": "Kopiraj logove ažuriranja" } }, "ar": { "stringUnit": { "state": "translated", - "value": "فتح الدليل الحالي في iTerm2" + "value": "نسخ سجلات التحديث" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Åpne gjeldende katalog i iTerm2" + "value": "Kopier oppdateringslogger" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Abrir Diretório Atual no iTerm2" + "value": "Copiar Logs de Atualização" } }, "th": { "stringUnit": { "state": "translated", - "value": "เปิดไดเรกทอรีปัจจุบันใน iTerm2" + "value": "คัดลอกบันทึกการอัปเดต" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Geçerli Dizini iTerm2'de Aç" + "value": "Güncelleme Günlüklerini Kopyala" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Відкрити поточну теку в iTerm2" + "value": "Копіювати журнал оновлень" } } } }, - "menu.openInTerminal": { + "menu.view.actualSize": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Open Current Directory in Terminal" + "value": "Actual Size" } }, "ja": { "stringUnit": { "state": "translated", - "value": "現在のディレクトリをターミナルで開く" + "value": "実際のサイズ" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "在终端中打开当前目录" + "value": "实际大小" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "在「終端機」中開啟目前目錄" + "value": "實際大小" } }, "ko": { "stringUnit": { "state": "translated", - "value": "현재 디렉토리를 터미널에서 열기" + "value": "실제 크기" } }, "de": { "stringUnit": { "state": "translated", - "value": "Aktuelles Verzeichnis in Terminal öffnen" + "value": "Originalgröße" } }, "es": { "stringUnit": { "state": "translated", - "value": "Abrir directorio actual en Terminal" + "value": "Tamaño real" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Ouvrir le répertoire courant dans Terminal" + "value": "Taille réelle" } }, "it": { "stringUnit": { "state": "translated", - "value": "Apri la directory corrente in Terminale" + "value": "Dimensione reale" } }, "da": { "stringUnit": { "state": "translated", - "value": "Åbn nuværende mappe i Terminal" + "value": "Faktisk størrelse" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Otwórz bieżący katalog w Terminalu" + "value": "Rozmiar rzeczywisty" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Открыть текущий каталог в Терминале" + "value": "Фактический размер" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Otvori trenutni direktorij u Terminal" + "value": "Stvarna veličina" } }, "ar": { "stringUnit": { "state": "translated", - "value": "فتح الدليل الحالي في Terminal" + "value": "الحجم الفعلي" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Åpne gjeldende katalog i Terminal" + "value": "Faktisk størrelse" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Abrir Diretório Atual no Terminal" + "value": "Tamanho Real" } }, "th": { "stringUnit": { "state": "translated", - "value": "เปิดไดเรกทอรีปัจจุบันใน Terminal" + "value": "ขนาดจริง" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Geçerli Dizini Terminal'de Aç" + "value": "Gerçek Boyut" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Відкрити поточну теку в Terminal" + "value": "Фактичний розмір" } } } }, - "menu.openInTower": { + "menu.view.back": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Open Current Directory in Tower" + "value": "Back" } }, "ja": { "stringUnit": { "state": "translated", - "value": "現在のディレクトリを Tower で開く" + "value": "戻る" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "在 Tower 中打开当前目录" + "value": "后退" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "在 Tower 中開啟目前目錄" + "value": "上一頁" } }, "ko": { "stringUnit": { "state": "translated", - "value": "현재 디렉토리를 Tower에서 열기" + "value": "뒤로" } }, "de": { "stringUnit": { "state": "translated", - "value": "Aktuelles Verzeichnis in Tower öffnen" + "value": "Zurück" } }, "es": { "stringUnit": { "state": "translated", - "value": "Abrir directorio actual en Tower" + "value": "Atrás" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Ouvrir le répertoire courant dans Tower" + "value": "Précédent" } }, "it": { "stringUnit": { "state": "translated", - "value": "Apri la directory corrente in Tower" + "value": "Indietro" } }, "da": { "stringUnit": { "state": "translated", - "value": "Åbn nuværende mappe i Tower" + "value": "Tilbage" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Otwórz bieżący katalog w Tower" + "value": "Wstecz" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Открыть текущий каталог в Tower" + "value": "Назад" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Otvori trenutni direktorij u Tower" + "value": "Nazad" } }, "ar": { "stringUnit": { "state": "translated", - "value": "فتح الدليل الحالي في Tower" + "value": "رجوع" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Åpne gjeldende katalog i Tower" + "value": "Tilbake" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Abrir Diretório Atual no Tower" + "value": "Voltar" } }, "th": { "stringUnit": { "state": "translated", - "value": "เปิดไดเรกทอรีปัจจุบันใน Tower" + "value": "ย้อนกลับ" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Geçerli Dizini Tower'da Aç" + "value": "Geri" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Відкрити поточну теку в Tower" + "value": "Назад" } } } }, - "menu.openInVSCode": { + "menu.view.clearBrowserHistory": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Open Current Directory in VS Code (Inline)" + "value": "Clear Browser History" } }, "ja": { "stringUnit": { "state": "translated", - "value": "現在のディレクトリを VS Code で開く(インライン)" + "value": "ブラウザ履歴をクリア" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "在 VS Code(内联)中打开当前目录" + "value": "清除浏览器历史记录" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "在 VS Code(內嵌)中開啟目前目錄" + "value": "清除瀏覽記錄" } }, "ko": { "stringUnit": { "state": "translated", - "value": "현재 디렉토리를 VS Code (인라인)에서 열기" + "value": "브라우저 기록 지우기" } }, "de": { "stringUnit": { "state": "translated", - "value": "Aktuelles Verzeichnis in VS Code (Inline) öffnen" + "value": "Browserverlauf löschen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Abrir directorio actual en VS Code (en línea)" + "value": "Borrar historial del navegador" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Ouvrir le répertoire courant dans VS Code (intégré)" + "value": "Effacer l'historique du navigateur" } }, "it": { "stringUnit": { "state": "translated", - "value": "Apri la directory corrente in VS Code (Inline)" + "value": "Cancella cronologia browser" } }, "da": { "stringUnit": { "state": "translated", - "value": "Åbn nuværende mappe i VS Code (Inline)" + "value": "Ryd browserhistorik" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Otwórz bieżący katalog w VS Code (wbudowany)" + "value": "Wyczyść historię przeglądarki" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Открыть текущий каталог в VS Code (встроенный)" + "value": "Очистить историю браузера" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Otvori trenutni direktorij u VS Code (Inline)" + "value": "Obriši historiju preglednika" } }, "ar": { "stringUnit": { "state": "translated", - "value": "فتح الدليل الحالي في VS Code (مضمّن)" + "value": "مسح سجل المتصفح" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Åpne gjeldende katalog i VS Code (innebygd)" + "value": "Tøm nettleserhistorikk" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Abrir Diretório Atual no VS Code (Inline)" + "value": "Limpar Histórico do Navegador" } }, "th": { "stringUnit": { "state": "translated", - "value": "เปิดไดเรกทอรีปัจจุบันใน VS Code (แบบอินไลน์)" + "value": "ล้างประวัติเบราว์เซอร์" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Geçerli Dizini VS Code'da Aç (Satır İçi)" + "value": "Tarayıcı Geçmişini Temizle" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Відкрити поточну теку в VS Code (вбудований)" + "value": "Очистити історію браузера" } } } }, - "menu.openInVSCodeDesktop": { + "menu.view.importFromBrowser": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Open Current Directory in VS Code" + "value": "Import Browser Data…" } }, "ja": { "stringUnit": { "state": "translated", - "value": "現在のディレクトリを VS Code で開く" + "value": "ブラウザーデータを取り込む…" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Відкрити поточну теку в VS Code" + "value": "Імпортувати дані браузера…" } }, "ko": { "stringUnit": { "state": "translated", - "value": "현재 디렉토리를 VS Code에서 열기" + "value": "브라우저 데이터 가져오기…" } } } }, - "menu.openInWarp": { + "menu.view.forward": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Open Current Directory in Warp" + "value": "Forward" } }, "ja": { "stringUnit": { "state": "translated", - "value": "現在のディレクトリを Warp で開く" + "value": "進む" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "在 Warp 中打开当前目录" + "value": "前进" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "在 Warp 中開啟目前目錄" + "value": "下一頁" } }, "ko": { "stringUnit": { "state": "translated", - "value": "현재 디렉토리를 Warp에서 열기" + "value": "앞으로" } }, "de": { "stringUnit": { "state": "translated", - "value": "Aktuelles Verzeichnis in Warp öffnen" + "value": "Vor" } }, "es": { "stringUnit": { "state": "translated", - "value": "Abrir directorio actual en Warp" + "value": "Adelante" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Ouvrir le répertoire courant dans Warp" + "value": "Suivant" } }, "it": { "stringUnit": { "state": "translated", - "value": "Apri la directory corrente in Warp" + "value": "Avanti" } }, "da": { "stringUnit": { "state": "translated", - "value": "Åbn nuværende mappe i Warp" + "value": "Frem" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Otwórz bieżący katalog w Warp" + "value": "Do przodu" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Открыть текущий каталог в Warp" + "value": "Вперед" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Otvori trenutni direktorij u Warp" + "value": "Naprijed" } }, "ar": { "stringUnit": { "state": "translated", - "value": "فتح الدليل الحالي في Warp" + "value": "تقدم" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Åpne gjeldende katalog i Warp" + "value": "Fremover" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Abrir Diretório Atual no Warp" + "value": "Avançar" } }, "th": { "stringUnit": { "state": "translated", - "value": "เปิดไดเรกทอรีปัจจุบันใน Warp" + "value": "ไปข้างหน้า" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Geçerli Dizini Warp'ta Aç" + "value": "İleri" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Відкрити поточну теку в Warp" + "value": "Вперед" } } } }, - "menu.openInWindsurf": { + "menu.view.jumpToUnread": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Open Current Directory in Windsurf" + "value": "Jump to Latest Unread" } }, "ja": { "stringUnit": { "state": "translated", - "value": "現在のディレクトリを Windsurf で開く" + "value": "最新の未読にジャンプ" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "在 Windsurf 中打开当前目录" + "value": "跳转到最新未读" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "在 Windsurf 中開啟目前目錄" + "value": "跳至最新未讀" } }, "ko": { "stringUnit": { "state": "translated", - "value": "현재 디렉토리를 Windsurf에서 열기" + "value": "최신 읽지 않은 항목으로 이동" } }, "de": { "stringUnit": { "state": "translated", - "value": "Aktuelles Verzeichnis in Windsurf öffnen" + "value": "Zur letzten ungelesenen springen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Abrir directorio actual en Windsurf" + "value": "Ir a la última no leída" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Ouvrir le répertoire courant dans Windsurf" + "value": "Aller au dernier message non lu" } }, "it": { "stringUnit": { "state": "translated", - "value": "Apri la directory corrente in Windsurf" + "value": "Vai all'ultimo non letto" } }, "da": { "stringUnit": { "state": "translated", - "value": "Åbn nuværende mappe i Windsurf" + "value": "Gå til seneste ulæste" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Otwórz bieżący katalog w Windsurf" + "value": "Przejdź do najnowszego nieprzeczytanego" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Открыть текущий каталог в Windsurf" + "value": "Перейти к последнему непрочитанному" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Otvori trenutni direktorij u Windsurf" + "value": "Skoči na najnovije nepročitano" } }, "ar": { "stringUnit": { "state": "translated", - "value": "فتح الدليل الحالي في Windsurf" + "value": "الانتقال إلى أحدث غير مقروء" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Åpne gjeldende katalog i Windsurf" + "value": "Gå til siste uleste" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Abrir Diretório Atual no Windsurf" + "value": "Ir para Última Não Lida" } }, "th": { "stringUnit": { "state": "translated", - "value": "เปิดไดเรกทอรีปัจจุบันใน Windsurf" + "value": "ข้ามไปยังรายการยังไม่อ่านล่าสุด" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Geçerli Dizini Windsurf'te Aç" + "value": "Son Okunmamışa Atla" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Відкрити поточну теку в Windsurf" + "value": "Перейти до останнього непрочитаного" } } } }, - "menu.openInXcode": { + "menu.view.nextSurface": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Open Current Directory in Xcode" + "value": "Next Surface" } }, "ja": { "stringUnit": { "state": "translated", - "value": "現在のディレクトリを Xcode で開く" + "value": "次のサーフェス" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "在 Xcode 中打开当前目录" + "value": "下一个 Surface" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "在 Xcode 中開啟目前目錄" + "value": "下一個 Surface" } }, "ko": { "stringUnit": { "state": "translated", - "value": "현재 디렉토리를 Xcode에서 열기" + "value": "다음 화면" } }, "de": { "stringUnit": { "state": "translated", - "value": "Aktuelles Verzeichnis in Xcode öffnen" + "value": "Nächste Oberfläche" } }, "es": { "stringUnit": { "state": "translated", - "value": "Abrir directorio actual en Xcode" + "value": "Siguiente superficie" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Ouvrir le répertoire courant dans Xcode" + "value": "Surface suivante" } }, "it": { "stringUnit": { "state": "translated", - "value": "Apri la directory corrente in Xcode" + "value": "Superficie successiva" } }, "da": { "stringUnit": { "state": "translated", - "value": "Åbn nuværende mappe i Xcode" + "value": "Næste overflade" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Otwórz bieżący katalog w Xcode" + "value": "Następna powierzchnia" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Открыть текущий каталог в Xcode" + "value": "Следующая поверхность" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Otvori trenutni direktorij u Xcode" + "value": "Sljedeća površina" } }, "ar": { "stringUnit": { "state": "translated", - "value": "فتح الدليل الحالي في Xcode" + "value": "السطح التالي" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Åpne gjeldende katalog i Xcode" + "value": "Neste flate" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Abrir Diretório Atual no Xcode" + "value": "Próxima Superfície" } }, "th": { "stringUnit": { "state": "translated", - "value": "เปิดไดเรกทอรีปัจจุบันใน Xcode" + "value": "พื้นผิวถัดไป" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Geçerli Dizini Xcode'da Aç" + "value": "Sonraki Yüzey" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Відкрити поточну теку в Xcode" + "value": "Наступна поверхня" } } } }, - "menu.openInZed": { + "menu.view.nextWorkspace": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Open Current Directory in Zed" + "value": "Next Workspace" } }, "ja": { "stringUnit": { "state": "translated", - "value": "現在のディレクトリを Zed で開く" + "value": "次のワークスペース" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "在 Zed 中打开当前目录" + "value": "下一个工作区" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "在 Zed 中開啟目前目錄" + "value": "下一個工作區" } }, "ko": { "stringUnit": { "state": "translated", - "value": "현재 디렉토리를 Zed에서 열기" + "value": "다음 작업 공간" } }, "de": { "stringUnit": { "state": "translated", - "value": "Aktuelles Verzeichnis in Zed öffnen" + "value": "Nächster Arbeitsbereich" } }, "es": { "stringUnit": { "state": "translated", - "value": "Abrir directorio actual en Zed" + "value": "Siguiente espacio de trabajo" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Ouvrir le répertoire courant dans Zed" + "value": "Espace de travail suivant" } }, "it": { "stringUnit": { "state": "translated", - "value": "Apri la directory corrente in Zed" + "value": "Area di lavoro successiva" } }, "da": { "stringUnit": { "state": "translated", - "value": "Åbn nuværende mappe i Zed" + "value": "Næste arbejdsområde" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Otwórz bieżący katalog w Zed" + "value": "Następna przestrzeń robocza" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Открыть текущий каталог в Zed" + "value": "Следующее рабочее пространство" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Otvori trenutni direktorij u Zed" + "value": "Sljedeći radni prostor" } }, "ar": { "stringUnit": { "state": "translated", - "value": "فتح الدليل الحالي في Zed" + "value": "مساحة العمل التالية" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Åpne gjeldende katalog i Zed" + "value": "Neste arbeidsområde" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Abrir Diretório Atual no Zed" + "value": "Próxima Área de Trabalho" } }, "th": { "stringUnit": { "state": "translated", - "value": "เปิดไดเรกทอรีปัจจุบันใน Zed" + "value": "เวิร์กสเปซถัดไป" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Geçerli Dizini Zed'de Aç" + "value": "Sonraki Çalışma Alanı" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Відкрити поточну теку в Zed" + "value": "Наступна робоча область" } } } }, - "menu.preferences": { + "menu.view.previousSurface": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Preferences…" + "value": "Previous Surface" } }, "ja": { "stringUnit": { "state": "translated", - "value": "設定…" + "value": "前のサーフェス" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "偏好设置..." + "value": "上一个 Surface" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "偏好設定..." + "value": "上一個 Surface" } }, "ko": { "stringUnit": { "state": "translated", - "value": "환경설정…" + "value": "이전 화면" } }, "de": { "stringUnit": { "state": "translated", - "value": "Einstellungen …" + "value": "Vorherige Oberfläche" } }, "es": { "stringUnit": { "state": "translated", - "value": "Preferencias…" + "value": "Superficie anterior" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Préférences..." + "value": "Surface précédente" } }, "it": { "stringUnit": { "state": "translated", - "value": "Preferenze…" + "value": "Superficie precedente" } }, "da": { "stringUnit": { "state": "translated", - "value": "Indstillinger…" + "value": "Forrige overflade" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Preferencje…" + "value": "Poprzednia powierzchnia" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Настройки..." + "value": "Предыдущая поверхность" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Postavke…" + "value": "Prethodna površina" } }, "ar": { "stringUnit": { "state": "translated", - "value": "التفضيلات…" + "value": "السطح السابق" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Innstillinger …" + "value": "Forrige flate" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Preferências…" + "value": "Superfície Anterior" } }, "th": { "stringUnit": { "state": "translated", - "value": "การตั้งค่า..." + "value": "พื้นผิวก่อนหน้า" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Tercihler…" + "value": "Önceki Yüzey" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Параметри…" + "value": "Попередня поверхня" } } } }, - "menu.quitCmux": { + "menu.view.previousWorkspace": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Quit cmux" + "value": "Previous Workspace" } }, "ja": { "stringUnit": { "state": "translated", - "value": "cmux を終了" + "value": "前のワークスペース" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "退出 cmux" + "value": "上一个工作区" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "結束 cmux" + "value": "上一個工作區" } }, "ko": { "stringUnit": { "state": "translated", - "value": "cmux 종료" + "value": "이전 작업 공간" } }, "de": { "stringUnit": { "state": "translated", - "value": "cmux beenden" + "value": "Vorheriger Arbeitsbereich" } }, "es": { "stringUnit": { "state": "translated", - "value": "Salir de cmux" + "value": "Espacio de trabajo anterior" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Quitter cmux" + "value": "Espace de travail précédent" } }, "it": { "stringUnit": { "state": "translated", - "value": "Esci da cmux" + "value": "Area di lavoro precedente" } }, "da": { "stringUnit": { "state": "translated", - "value": "Afslut cmux" + "value": "Forrige arbejdsområde" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Zakończ cmux" + "value": "Poprzednia przestrzeń robocza" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Завершить cmux" + "value": "Предыдущее рабочее пространство" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Zatvori cmux" + "value": "Prethodni radni prostor" } }, "ar": { "stringUnit": { "state": "translated", - "value": "إنهاء cmux" + "value": "مساحة العمل السابقة" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Avslutt cmux" + "value": "Forrige arbeidsområde" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Encerrar o cmux" + "value": "Área de Trabalho Anterior" } }, "th": { "stringUnit": { "state": "translated", - "value": "ออกจาก cmux" + "value": "เวิร์กสเปซก่อนหน้า" } }, "tr": { "stringUnit": { "state": "translated", - "value": "cmux'tan Çık" + "value": "Önceki Çalışma Alanı" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Завершити cmux" + "value": "Попередня робоча область" } } } }, - "menu.showNotifications": { + "menu.view.reloadPage": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Show Notifications" + "value": "Reload Page" } }, "ja": { "stringUnit": { "state": "translated", - "value": "通知を表示" + "value": "ページを再読み込み" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "显示通知" + "value": "重新加载页面" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "顯示通知" + "value": "重新載入頁面" } }, "ko": { "stringUnit": { "state": "translated", - "value": "알림 표시" + "value": "페이지 새로고침" } }, "de": { "stringUnit": { "state": "translated", - "value": "Benachrichtigungen anzeigen" + "value": "Seite neu laden" } }, "es": { "stringUnit": { "state": "translated", - "value": "Mostrar notificaciones" + "value": "Recargar página" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Afficher les notifications" + "value": "Recharger la page" } }, "it": { "stringUnit": { "state": "translated", - "value": "Mostra notifiche" + "value": "Ricarica pagina" } }, "da": { "stringUnit": { "state": "translated", - "value": "Vis notifikationer" + "value": "Genindlæs side" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Pokaż powiadomienia" + "value": "Odśwież stronę" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Показать уведомления" + "value": "Перезагрузить страницу" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Prikaži obavještenja" + "value": "Ponovo učitaj stranicu" } }, "ar": { "stringUnit": { "state": "translated", - "value": "عرض الإشعارات" + "value": "إعادة تحميل الصفحة" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Vis varsler" + "value": "Last inn siden på nytt" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Mostrar Notificações" + "value": "Recarregar Página" } }, "th": { "stringUnit": { "state": "translated", - "value": "แสดงการแจ้งเตือน" + "value": "โหลดหน้าใหม่" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Bildirimleri Göster" + "value": "Sayfayı Yeniden Yükle" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Показати сповіщення" + "value": "Перезавантажити сторінку" } } } }, - "menu.updateLogs.copyFocusLogs": { + "menu.view.renameWorkspace": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Copy Focus Logs" + "value": "Rename Workspace…" } }, "ja": { "stringUnit": { "state": "translated", - "value": "フォーカスログをコピー" + "value": "ワークスペースの名称変更…" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "拷贝焦点日志" + "value": "重命名工作区..." } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "拷貝焦點記錄" + "value": "重新命名工作區..." } }, "ko": { "stringUnit": { "state": "translated", - "value": "포커스 로그 복사" + "value": "작업 공간 이름 변경…" } }, "de": { "stringUnit": { "state": "translated", - "value": "Fokus-Protokolle kopieren" + "value": "Arbeitsbereich umbenennen …" } }, "es": { "stringUnit": { "state": "translated", - "value": "Copiar registros de enfoque" + "value": "Renombrar espacio de trabajo…" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Copier les journaux de focus" + "value": "Renommer l'espace de travail..." } }, "it": { "stringUnit": { "state": "translated", - "value": "Copia log di focus" + "value": "Rinomina area di lavoro…" } }, "da": { "stringUnit": { "state": "translated", - "value": "Kopier fokuslogfiler" + "value": "Omdøb arbejdsområde…" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Kopiuj dzienniki fokusu" + "value": "Zmień nazwę przestrzeni roboczej…" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Скопировать журнал фокуса" + "value": "Переименовать рабочее пространство..." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Kopiraj logove fokusa" + "value": "Preimenuj radni prostor…" } }, "ar": { "stringUnit": { "state": "translated", - "value": "نسخ سجلات التركيز" + "value": "إعادة تسمية مساحة العمل…" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Kopier fokuslogger" + "value": "Gi arbeidsområdet nytt navn …" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Copiar Logs de Foco" + "value": "Renomear Área de Trabalho…" } }, "th": { "stringUnit": { "state": "translated", - "value": "คัดลอกบันทึกการโฟกัส" + "value": "เปลี่ยนชื่อเวิร์กสเปซ..." } }, "tr": { "stringUnit": { "state": "translated", - "value": "Odak Günlüklerini Kopyala" + "value": "Çalışma Alanını Yeniden Adlandır…" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Копіювати журнал фокусу" + "value": "Перейменувати робочу область…" } } } }, - "menu.updateLogs.copyUpdateLogs": { + "menu.view.showJSConsole": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Copy Update Logs" + "value": "Show JavaScript Console" } }, "ja": { "stringUnit": { "state": "translated", - "value": "アップデートログをコピー" + "value": "JavaScriptコンソールを表示" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "拷贝更新日志" + "value": "显示 JavaScript 控制台" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "拷貝更新記錄" + "value": "顯示 JavaScript 主控台" } }, "ko": { "stringUnit": { "state": "translated", - "value": "업데이트 로그 복사" + "value": "JavaScript 콘솔 표시" } }, "de": { "stringUnit": { "state": "translated", - "value": "Update-Protokolle kopieren" + "value": "JavaScript-Konsole anzeigen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Copiar registros de actualización" + "value": "Mostrar consola de JavaScript" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Copier les journaux de mise à jour" + "value": "Afficher la console JavaScript" } }, "it": { "stringUnit": { "state": "translated", - "value": "Copia log aggiornamento" + "value": "Mostra console JavaScript" } }, "da": { "stringUnit": { "state": "translated", - "value": "Kopier opdateringslogfiler" + "value": "Vis JavaScript-konsol" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Kopiuj dzienniki aktualizacji" + "value": "Pokaż konsolę JavaScript" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Скопировать журнал обновлений" + "value": "Показать консоль JavaScript" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Kopiraj logove ažuriranja" + "value": "Prikaži JavaScript konzolu" } }, "ar": { "stringUnit": { "state": "translated", - "value": "نسخ سجلات التحديث" + "value": "عرض وحدة تحكم JavaScript" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Kopier oppdateringslogger" + "value": "Vis JavaScript-konsoll" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Copiar Logs de Atualização" + "value": "Mostrar Console JavaScript" } }, "th": { "stringUnit": { "state": "translated", - "value": "คัดลอกบันทึกการอัปเดต" + "value": "แสดงคอนโซล JavaScript" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Güncelleme Günlüklerini Kopyala" + "value": "JavaScript Konsolunu Göster" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Копіювати журнал оновлень" + "value": "Показати консоль JavaScript" } } } }, - "menu.view.actualSize": { + "menu.view.toggleReactGrab": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Actual Size" + "value": "Toggle React Grab" } }, "ja": { "stringUnit": { "state": "translated", - "value": "実際のサイズ" + "value": "React Grabの切り替え" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "实际大小" + "value": "切换 React Grab" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "實際大小" + "value": "切換 React Grab" } }, "ko": { "stringUnit": { "state": "translated", - "value": "실제 크기" + "value": "React Grab 전환" + } + } + } + }, + "menu.view.showNotifications": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Show Notifications" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "通知を表示" + } + }, + "zh-Hans": { + "stringUnit": { + "state": "translated", + "value": "显示通知" + } + }, + "zh-Hant": { + "stringUnit": { + "state": "translated", + "value": "顯示通知" + } + }, + "ko": { + "stringUnit": { + "state": "translated", + "value": "알림 표시" } }, "de": { "stringUnit": { "state": "translated", - "value": "Originalgröße" + "value": "Benachrichtigungen anzeigen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Tamaño real" + "value": "Mostrar notificaciones" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Taille réelle" + "value": "Afficher les notifications" } }, "it": { "stringUnit": { "state": "translated", - "value": "Dimensione reale" + "value": "Mostra notifiche" } }, "da": { "stringUnit": { "state": "translated", - "value": "Faktisk størrelse" + "value": "Vis notifikationer" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Rozmiar rzeczywisty" + "value": "Pokaż powiadomienia" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Фактический размер" + "value": "Показать уведомления" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Stvarna veličina" + "value": "Prikaži obavještenja" } }, "ar": { "stringUnit": { "state": "translated", - "value": "الحجم الفعلي" + "value": "عرض الإشعارات" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Faktisk størrelse" + "value": "Vis varsler" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Tamanho Real" + "value": "Mostrar Notificações" } }, "th": { "stringUnit": { "state": "translated", - "value": "ขนาดจริง" + "value": "แสดงการแจ้งเตือน" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Gerçek Boyut" + "value": "Bildirimleri Göster" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Фактичний розмір" + "value": "Показати сповіщення" } } } }, - "menu.view.back": { + "menu.view.splitBrowserDown": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Back" + "value": "Split Browser Down" } }, "ja": { "stringUnit": { "state": "translated", - "value": "戻る" + "value": "ブラウザを下に分割" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "后退" + "value": "向下拆分浏览器" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "上一頁" + "value": "向下分割瀏覽器" } }, "ko": { "stringUnit": { "state": "translated", - "value": "뒤로" + "value": "브라우저를 아래로 분할" } }, "de": { "stringUnit": { "state": "translated", - "value": "Zurück" + "value": "Browser nach unten teilen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Atrás" + "value": "Dividir navegador hacia abajo" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Précédent" + "value": "Diviser le navigateur vers le bas" } }, "it": { "stringUnit": { "state": "translated", - "value": "Indietro" + "value": "Dividi browser in basso" } }, "da": { "stringUnit": { "state": "translated", - "value": "Tilbage" + "value": "Opdel browser nedad" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Wstecz" + "value": "Podziel przeglądarkę w dół" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Назад" + "value": "Разделить браузер вниз" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Nazad" + "value": "Podijeli preglednik dolje" } }, "ar": { "stringUnit": { "state": "translated", - "value": "رجوع" + "value": "تقسيم المتصفح للأسفل" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Tilbake" + "value": "Del nettleser ned" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Voltar" + "value": "Dividir Navegador para Baixo" } }, "th": { "stringUnit": { "state": "translated", - "value": "ย้อนกลับ" + "value": "แยกเบราว์เซอร์ลงล่าง" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Geri" + "value": "Tarayıcıyı Aşağı Böl" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Назад" + "value": "Розділити браузер вниз" } } } }, - "menu.view.clearBrowserHistory": { + "menu.view.splitBrowserRight": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Clear Browser History" + "value": "Split Browser Right" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ブラウザ履歴をクリア" + "value": "ブラウザを右に分割" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "清除浏览器历史记录" + "value": "向右拆分浏览器" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "清除瀏覽記錄" + "value": "向右分割瀏覽器" } }, "ko": { "stringUnit": { "state": "translated", - "value": "브라우저 기록 지우기" + "value": "브라우저를 오른쪽으로 분할" } }, "de": { "stringUnit": { "state": "translated", - "value": "Browserverlauf löschen" + "value": "Browser nach rechts teilen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Borrar historial del navegador" + "value": "Dividir navegador a la derecha" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Effacer l'historique du navigateur" + "value": "Diviser le navigateur à droite" } }, "it": { "stringUnit": { "state": "translated", - "value": "Cancella cronologia browser" + "value": "Dividi browser a destra" } }, "da": { "stringUnit": { "state": "translated", - "value": "Ryd browserhistorik" + "value": "Opdel browser til højre" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Wyczyść historię przeglądarki" + "value": "Podziel przeglądarkę w prawo" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Очистить историю браузера" + "value": "Разделить браузер вправо" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Obriši historiju preglednika" + "value": "Podijeli preglednik desno" } }, "ar": { "stringUnit": { "state": "translated", - "value": "مسح سجل المتصفح" + "value": "تقسيم المتصفح لليمين" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Tøm nettleserhistorikk" + "value": "Del nettleser til høyre" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Limpar Histórico do Navegador" + "value": "Dividir Navegador à Direita" } }, "th": { "stringUnit": { "state": "translated", - "value": "ล้างประวัติเบราว์เซอร์" + "value": "แยกเบราว์เซอร์ไปทางขวา" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Tarayıcı Geçmişini Temizle" - } - }, - "uk": { - "stringUnit": { - "state": "translated", - "value": "Очистити історію браузера" - } - } - } - }, - "menu.view.importFromBrowser": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Import Browser Data…" - } - }, - "ja": { - "stringUnit": { - "state": "translated", - "value": "ブラウザーデータを取り込む…" + "value": "Tarayıcıyı Sağa Böl" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Імпортувати дані браузера…" - } - }, - "ko": { - "stringUnit": { - "state": "translated", - "value": "브라우저 데이터 가져오기…" + "value": "Розділити браузер праворуч" } } } }, - "menu.view.forward": { + "menu.view.splitDown": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Forward" + "value": "Split Down" } }, "ja": { "stringUnit": { "state": "translated", - "value": "進む" + "value": "下に分割" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "前进" + "value": "向下拆分" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "下一頁" + "value": "向下分割" } }, "ko": { "stringUnit": { "state": "translated", - "value": "앞으로" + "value": "아래로 분할" } }, "de": { "stringUnit": { "state": "translated", - "value": "Vor" + "value": "Nach unten teilen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Adelante" + "value": "Dividir hacia abajo" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Suivant" + "value": "Diviser vers le bas" } }, "it": { "stringUnit": { "state": "translated", - "value": "Avanti" + "value": "Dividi in basso" } }, "da": { "stringUnit": { "state": "translated", - "value": "Frem" + "value": "Opdel nedad" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Do przodu" + "value": "Podziel w dół" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Вперед" + "value": "Разделить вниз" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Naprijed" + "value": "Podijeli dolje" } }, "ar": { "stringUnit": { "state": "translated", - "value": "تقدم" + "value": "تقسيم للأسفل" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Fremover" + "value": "Del ned" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Avançar" + "value": "Dividir para Baixo" } }, "th": { "stringUnit": { "state": "translated", - "value": "ไปข้างหน้า" + "value": "แยกลงล่าง" } }, "tr": { "stringUnit": { "state": "translated", - "value": "İleri" + "value": "Aşağı Böl" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Вперед" + "value": "Розділити вниз" } } } }, - "menu.view.jumpToUnread": { + "menu.view.splitRight": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Jump to Latest Unread" + "value": "Split Right" } }, "ja": { "stringUnit": { "state": "translated", - "value": "最新の未読にジャンプ" + "value": "右に分割" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "跳转到最新未读" + "value": "向右拆分" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "跳至最新未讀" + "value": "向右分割" } }, "ko": { "stringUnit": { "state": "translated", - "value": "최신 읽지 않은 항목으로 이동" + "value": "오른쪽으로 분할" } }, "de": { "stringUnit": { "state": "translated", - "value": "Zur letzten ungelesenen springen" + "value": "Nach rechts teilen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Ir a la última no leída" + "value": "Dividir a la derecha" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Aller au dernier message non lu" + "value": "Diviser à droite" } }, "it": { "stringUnit": { "state": "translated", - "value": "Vai all'ultimo non letto" + "value": "Dividi a destra" } }, "da": { "stringUnit": { "state": "translated", - "value": "Gå til seneste ulæste" + "value": "Opdel til højre" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Przejdź do najnowszego nieprzeczytanego" + "value": "Podziel w prawo" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Перейти к последнему непрочитанному" + "value": "Разделить вправо" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Skoči na najnovije nepročitano" + "value": "Podijeli desno" } }, "ar": { "stringUnit": { "state": "translated", - "value": "الانتقال إلى أحدث غير مقروء" + "value": "تقسيم لليمين" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Gå til siste uleste" + "value": "Del til høyre" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Ir para Última Não Lida" + "value": "Dividir à Direita" } }, "th": { "stringUnit": { "state": "translated", - "value": "ข้ามไปยังรายการยังไม่อ่านล่าสุด" + "value": "แยกไปทางขวา" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Son Okunmamışa Atla" + "value": "Sağa Böl" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Перейти до останнього непрочитаного" + "value": "Розділити праворуч" } } } }, - "menu.view.nextSurface": { + "menu.view.toggleDevTools": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Next Surface" + "value": "Toggle Developer Tools" } }, "ja": { "stringUnit": { "state": "translated", - "value": "次のサーフェス" + "value": "デベロッパツールの切り替え" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "下一个 Surface" + "value": "切换开发者工具" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "下一個 Surface" + "value": "切換開發者工具" } }, "ko": { "stringUnit": { "state": "translated", - "value": "다음 화면" + "value": "개발자 도구 전환" } }, "de": { "stringUnit": { "state": "translated", - "value": "Nächste Oberfläche" + "value": "Entwicklerwerkzeuge ein-/ausblenden" } }, "es": { "stringUnit": { "state": "translated", - "value": "Siguiente superficie" + "value": "Alternar herramientas de desarrollo" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Surface suivante" + "value": "Afficher/masquer les outils de développement" } }, "it": { "stringUnit": { "state": "translated", - "value": "Superficie successiva" + "value": "Attiva/Disattiva Strumenti sviluppatore" } }, "da": { "stringUnit": { "state": "translated", - "value": "Næste overflade" + "value": "Slå udviklerværktøjer til/fra" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Następna powierzchnia" + "value": "Przełącz narzędzia deweloperskie" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Следующая поверхность" + "value": "Инструменты разработчика" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Sljedeća površina" + "value": "Prebaci razvojne alate" } }, "ar": { "stringUnit": { "state": "translated", - "value": "السطح التالي" + "value": "تبديل أدوات المطور" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Neste flate" + "value": "Slå utviklerverktøy av/på" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Próxima Superfície" + "value": "Alternar Ferramentas do Desenvolvedor" } }, "th": { "stringUnit": { "state": "translated", - "value": "พื้นผิวถัดไป" + "value": "สลับเครื่องมือนักพัฒนา" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Sonraki Yüzey" + "value": "Geliştirici Araçlarını Aç/Kapat" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Наступна поверхня" + "value": "Перемкнути інструменти розробника" } } } }, - "menu.view.nextWorkspace": { + "menu.view.workspace": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Next Workspace" + "value": "Workspace %lld" } }, "ja": { "stringUnit": { "state": "translated", - "value": "次のワークスペース" + "value": "ワークスペース %lld" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "下一个工作区" + "value": "工作区 %lld" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "下一個工作區" + "value": "工作區 %lld" } }, "ko": { "stringUnit": { "state": "translated", - "value": "다음 작업 공간" + "value": "작업 공간 %lld" } }, "de": { "stringUnit": { "state": "translated", - "value": "Nächster Arbeitsbereich" + "value": "Arbeitsbereich %lld" } }, "es": { "stringUnit": { "state": "translated", - "value": "Siguiente espacio de trabajo" + "value": "Espacio de trabajo %lld" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Espace de travail suivant" + "value": "Espace de travail %lld" } }, "it": { "stringUnit": { "state": "translated", - "value": "Area di lavoro successiva" + "value": "Area di lavoro %lld" } }, "da": { "stringUnit": { "state": "translated", - "value": "Næste arbejdsområde" + "value": "Arbejdsområde %lld" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Następna przestrzeń robocza" + "value": "Przestrzeń robocza %lld" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Следующее рабочее пространство" + "value": "Рабочее пространство %lld" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Sljedeći radni prostor" + "value": "Radni prostor %lld" } }, "ar": { "stringUnit": { "state": "translated", - "value": "مساحة العمل التالية" + "value": "مساحة العمل %lld" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Neste arbeidsområde" + "value": "Arbeidsområde %lld" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Próxima Área de Trabalho" + "value": "Área de Trabalho %lld" } }, "th": { "stringUnit": { "state": "translated", - "value": "เวิร์กสเปซถัดไป" + "value": "เวิร์กสเปซ %lld" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Sonraki Çalışma Alanı" + "value": "Çalışma Alanı %lld" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Наступна робоча область" + "value": "Робоча область %lld" } } } }, - "menu.view.previousSurface": { + "menu.view.zoomIn": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Previous Surface" + "value": "Zoom In" } }, "ja": { "stringUnit": { "state": "translated", - "value": "前のサーフェス" + "value": "拡大" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "上一个 Surface" + "value": "放大" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "上一個 Surface" + "value": "放大" } }, "ko": { "stringUnit": { "state": "translated", - "value": "이전 화면" + "value": "확대" } }, "de": { "stringUnit": { "state": "translated", - "value": "Vorherige Oberfläche" + "value": "Einzoomen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Superficie anterior" + "value": "Ampliar" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Surface précédente" + "value": "Zoom avant" } }, "it": { "stringUnit": { "state": "translated", - "value": "Superficie precedente" + "value": "Ingrandisci" } }, "da": { "stringUnit": { "state": "translated", - "value": "Forrige overflade" + "value": "Zoom ind" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Poprzednia powierzchnia" + "value": "Powiększ" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Предыдущая поверхность" + "value": "Увеличить" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Prethodna površina" + "value": "Uvećaj" } }, "ar": { "stringUnit": { "state": "translated", - "value": "السطح السابق" + "value": "تكبير" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Forrige flate" + "value": "Zoom inn" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Superfície Anterior" + "value": "Aumentar Zoom" } }, "th": { "stringUnit": { "state": "translated", - "value": "พื้นผิวก่อนหน้า" + "value": "ซูมเข้า" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Önceki Yüzey" + "value": "Yakınlaştır" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Попередня поверхня" + "value": "Збільшити" } } } }, - "menu.view.previousWorkspace": { + "menu.view.zoomOut": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Previous Workspace" + "value": "Zoom Out" } }, "ja": { "stringUnit": { "state": "translated", - "value": "前のワークスペース" + "value": "縮小" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "上一个工作区" + "value": "缩小" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "上一個工作區" + "value": "縮小" } }, "ko": { "stringUnit": { "state": "translated", - "value": "이전 작업 공간" + "value": "축소" } }, "de": { "stringUnit": { "state": "translated", - "value": "Vorheriger Arbeitsbereich" + "value": "Auszoomen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Espacio de trabajo anterior" + "value": "Reducir" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Espace de travail précédent" + "value": "Zoom arrière" } }, "it": { "stringUnit": { "state": "translated", - "value": "Area di lavoro precedente" + "value": "Riduci" } }, "da": { "stringUnit": { "state": "translated", - "value": "Forrige arbejdsområde" + "value": "Zoom ud" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Poprzednia przestrzeń robocza" + "value": "Pomniejsz" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Предыдущее рабочее пространство" + "value": "Уменьшить" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Prethodni radni prostor" + "value": "Umanji" } }, "ar": { "stringUnit": { "state": "translated", - "value": "مساحة العمل السابقة" + "value": "تصغير" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Forrige arbeidsområde" + "value": "Zoom ut" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Área de Trabalho Anterior" + "value": "Diminuir Zoom" } }, "th": { "stringUnit": { "state": "translated", - "value": "เวิร์กสเปซก่อนหน้า" + "value": "ซูมออก" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Önceki Çalışma Alanı" + "value": "Uzaklaştır" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Попередня робоча область" + "value": "Зменшити" } } } }, - "menu.view.reloadPage": { + "menu.windowNumber": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Reload Page" + "value": "Window %lld" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ページを再読み込み" + "value": "ウインドウ %lld" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "重新加载页面" + "value": "窗口 %lld" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "重新載入頁面" + "value": "視窗 %lld" } }, "ko": { "stringUnit": { "state": "translated", - "value": "페이지 새로고침" + "value": "윈도우 %lld" } }, "de": { "stringUnit": { "state": "translated", - "value": "Seite neu laden" + "value": "Fenster %lld" } }, "es": { "stringUnit": { "state": "translated", - "value": "Recargar página" + "value": "Ventana %lld" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Recharger la page" + "value": "Fenêtre %lld" } }, "it": { "stringUnit": { "state": "translated", - "value": "Ricarica pagina" + "value": "Finestra %lld" } }, "da": { "stringUnit": { "state": "translated", - "value": "Genindlæs side" + "value": "Vindue %lld" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Odśwież stronę" + "value": "Okno %lld" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Перезагрузить страницу" + "value": "Окно %lld" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Ponovo učitaj stranicu" + "value": "Prozor %lld" } }, "ar": { "stringUnit": { "state": "translated", - "value": "إعادة تحميل الصفحة" + "value": "النافذة %lld" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Last inn siden på nytt" + "value": "Vindu %lld" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Recarregar Página" + "value": "Janela %lld" } }, "th": { "stringUnit": { "state": "translated", - "value": "โหลดหน้าใหม่" + "value": "หน้าต่าง %lld" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Sayfayı Yeniden Yükle" + "value": "Pencere %lld" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Перезавантажити сторінку" + "value": "Вікно %lld" } } } }, - "menu.view.renameWorkspace": { + "notifications.clearAll": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Rename Workspace…" + "value": "Clear All" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ワークスペースの名称変更…" + "value": "すべてクリア" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "重命名工作区..." + "value": "全部清除" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "重新命名工作區..." + "value": "清除全部" } }, "ko": { "stringUnit": { "state": "translated", - "value": "작업 공간 이름 변경…" + "value": "모두 지우기" } }, "de": { "stringUnit": { "state": "translated", - "value": "Arbeitsbereich umbenennen …" + "value": "Alle löschen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Renombrar espacio de trabajo…" + "value": "Borrar todo" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Renommer l'espace de travail..." + "value": "Tout effacer" } }, "it": { "stringUnit": { "state": "translated", - "value": "Rinomina area di lavoro…" + "value": "Cancella tutto" } }, "da": { "stringUnit": { "state": "translated", - "value": "Omdøb arbejdsområde…" + "value": "Ryd alle" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Zmień nazwę przestrzeni roboczej…" + "value": "Wyczyść wszystko" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Переименовать рабочее пространство..." + "value": "Очистить все" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Preimenuj radni prostor…" + "value": "Obriši sve" } }, "ar": { "stringUnit": { "state": "translated", - "value": "إعادة تسمية مساحة العمل…" + "value": "مسح الكل" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Gi arbeidsområdet nytt navn …" + "value": "Fjern alle" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Renomear Área de Trabalho…" + "value": "Limpar Tudo" } }, "th": { "stringUnit": { "state": "translated", - "value": "เปลี่ยนชื่อเวิร์กสเปซ..." + "value": "ล้างทั้งหมด" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Çalışma Alanını Yeniden Adlandır…" + "value": "Tümünü Temizle" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Перейменувати робочу область…" + "value": "Очистити все" } } } }, - "menu.view.showJSConsole": { + "notifications.empty.description": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Show JavaScript Console" + "value": "Desktop notifications will appear here for quick review." } }, "ja": { "stringUnit": { "state": "translated", - "value": "JavaScriptコンソールを表示" + "value": "デスクトップ通知がここに表示されます。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "显示 JavaScript 控制台" + "value": "桌面通知将在此处显示,方便快速查看。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "顯示 JavaScript 主控台" + "value": "桌面通知將在這裡顯示,方便您快速查看。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "JavaScript 콘솔 표시" + "value": "데스크톱 알림이 여기에 표시되어 빠르게 확인할 수 있습니다." } }, "de": { "stringUnit": { "state": "translated", - "value": "JavaScript-Konsole anzeigen" + "value": "Desktop-Benachrichtigungen werden hier zur schnellen Überprüfung angezeigt." } }, "es": { "stringUnit": { "state": "translated", - "value": "Mostrar consola de JavaScript" + "value": "Las notificaciones de escritorio aparecerán aquí para su revisión rápida." } }, "fr": { "stringUnit": { "state": "translated", - "value": "Afficher la console JavaScript" + "value": "Les notifications de bureau apparaîtront ici pour une consultation rapide." } }, "it": { "stringUnit": { "state": "translated", - "value": "Mostra console JavaScript" + "value": "Le notifiche desktop appariranno qui per una rapida consultazione." } }, "da": { "stringUnit": { "state": "translated", - "value": "Vis JavaScript-konsol" + "value": "Skrivebordsnotifikationer vises her til hurtig gennemgang." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Pokaż konsolę JavaScript" + "value": "Powiadomienia pulpitu będą się tu pojawiać do szybkiego przeglądu." } }, "ru": { "stringUnit": { "state": "translated", - "value": "Показать консоль JavaScript" + "value": "Уведомления рабочего стола будут отображаться здесь для быстрого просмотра." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Prikaži JavaScript konzolu" + "value": "Obavještenja na radnoj površini će se pojavljivati ovdje radi brzog pregleda." } }, "ar": { "stringUnit": { "state": "translated", - "value": "عرض وحدة تحكم JavaScript" + "value": "ستظهر إشعارات سطح المكتب هنا للمراجعة السريعة." } }, "nb": { "stringUnit": { "state": "translated", - "value": "Vis JavaScript-konsoll" + "value": "Skrivebordsvarsler vises her for rask gjennomgang." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Mostrar Console JavaScript" + "value": "As notificações da área de trabalho aparecerão aqui para revisão rápida." } }, "th": { "stringUnit": { "state": "translated", - "value": "แสดงคอนโซล JavaScript" + "value": "การแจ้งเตือนเดสก์ท็อปจะปรากฏที่นี่เพื่อตรวจสอบอย่างรวดเร็ว" } }, "tr": { "stringUnit": { "state": "translated", - "value": "JavaScript Konsolunu Göster" + "value": "Masaüstü bildirimleri hızlı inceleme için burada görünecek." } }, "uk": { "stringUnit": { "state": "translated", - "value": "Показати консоль JavaScript" - } - } - } - }, - "menu.view.toggleReactGrab": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Toggle React Grab" - } - }, - "ja": { - "stringUnit": { - "state": "translated", - "value": "React Grabの切り替え" - } - }, - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "切换 React Grab" - } - }, - "zh-Hant": { - "stringUnit": { - "state": "translated", - "value": "切換 React Grab" - } - }, - "ko": { - "stringUnit": { - "state": "translated", - "value": "React Grab 전환" + "value": "Сповіщення робочого столу з'являтимуться тут для швидкого перегляду." } } } }, - "menu.view.showNotifications": { + "notifications.empty.subtitle": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Show Notifications" + "value": "Desktop notifications will appear here." } }, "ja": { "stringUnit": { "state": "translated", - "value": "通知を表示" + "value": "デスクトップ通知がここに表示されます。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "显示通知" + "value": "桌面通知将在此处显示。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "顯示通知" + "value": "桌面通知將在這裡顯示。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "알림 표시" + "value": "데스크톱 알림이 여기에 표시됩니다." } }, "de": { "stringUnit": { "state": "translated", - "value": "Benachrichtigungen anzeigen" + "value": "Desktop-Benachrichtigungen werden hier angezeigt." } }, "es": { "stringUnit": { "state": "translated", - "value": "Mostrar notificaciones" + "value": "Las notificaciones de escritorio aparecerán aquí." } }, "fr": { "stringUnit": { "state": "translated", - "value": "Afficher les notifications" + "value": "Les notifications de bureau apparaîtront ici." } }, "it": { "stringUnit": { "state": "translated", - "value": "Mostra notifiche" + "value": "Le notifiche desktop appariranno qui." } }, "da": { "stringUnit": { "state": "translated", - "value": "Vis notifikationer" + "value": "Skrivebordsnotifikationer vises her." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Pokaż powiadomienia" + "value": "Powiadomienia pulpitu będą się tu pojawiać." } }, "ru": { "stringUnit": { "state": "translated", - "value": "Показать уведомления" + "value": "Уведомления рабочего стола будут отображаться здесь." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Prikaži obavještenja" + "value": "Obavještenja na radnoj površini će se pojavljivati ovdje." } }, "ar": { "stringUnit": { "state": "translated", - "value": "عرض الإشعارات" + "value": "ستظهر إشعارات سطح المكتب هنا." } }, "nb": { "stringUnit": { "state": "translated", - "value": "Vis varsler" + "value": "Skrivebordsvarsler vises her." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Mostrar Notificações" + "value": "As notificações da área de trabalho aparecerão aqui." } }, "th": { "stringUnit": { "state": "translated", - "value": "แสดงการแจ้งเตือน" + "value": "การแจ้งเตือนเดสก์ท็อปจะปรากฏที่นี่" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Bildirimleri Göster" + "value": "Masaüstü bildirimleri burada görünecek." } }, "uk": { "stringUnit": { "state": "translated", - "value": "Показати сповіщення" + "value": "Сповіщення робочого столу з'являтимуться тут." } } } }, - "menu.view.splitBrowserDown": { + "notifications.empty.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Split Browser Down" + "value": "No notifications yet" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ブラウザを下に分割" + "value": "まだ通知はありません" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "向下拆分浏览器" + "value": "暂无通知" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "向下分割瀏覽器" + "value": "尚無通知" } }, "ko": { "stringUnit": { "state": "translated", - "value": "브라우저를 아래로 분할" + "value": "아직 알림이 없습니다" } }, "de": { "stringUnit": { "state": "translated", - "value": "Browser nach unten teilen" + "value": "Noch keine Benachrichtigungen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Dividir navegador hacia abajo" + "value": "Aún no hay notificaciones" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Diviser le navigateur vers le bas" + "value": "Aucune notification pour le moment" } }, "it": { "stringUnit": { "state": "translated", - "value": "Dividi browser in basso" + "value": "Nessuna notifica" } }, "da": { "stringUnit": { "state": "translated", - "value": "Opdel browser nedad" + "value": "Ingen notifikationer endnu" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Podziel przeglądarkę w dół" + "value": "Brak powiadomień" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Разделить браузер вниз" + "value": "Уведомлений пока нет" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Podijeli preglednik dolje" + "value": "Još nema obavještenja" } }, "ar": { "stringUnit": { "state": "translated", - "value": "تقسيم المتصفح للأسفل" + "value": "لا توجد إشعارات بعد" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Del nettleser ned" + "value": "Ingen varsler ennå" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Dividir Navegador para Baixo" + "value": "Nenhuma notificação ainda" } }, "th": { "stringUnit": { "state": "translated", - "value": "แยกเบราว์เซอร์ลงล่าง" + "value": "ยังไม่มีการแจ้งเตือน" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Tarayıcıyı Aşağı Böl" + "value": "Henüz bildirim yok" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Розділити браузер вниз" + "value": "Сповіщень ще немає" } } } }, - "menu.view.splitBrowserRight": { + "notifications.jumpToLatest": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Split Browser Right" + "value": "Jump to Latest" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ブラウザを右に分割" + "value": "最新へジャンプ" + } + }, + "uk": { + "stringUnit": { + "state": "translated", + "value": "Перейти до останнього" + } + }, + "ko": { + "stringUnit": { + "state": "translated", + "value": "최신으로 이동" + } + } + } + }, + "notifications.jumpToLatestUnread": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Jump to Latest Unread" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "最新の未読にジャンプ" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "向右拆分浏览器" + "value": "跳转到最新未读" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "向右分割瀏覽器" + "value": "跳至最新未讀" } }, "ko": { "stringUnit": { "state": "translated", - "value": "브라우저를 오른쪽으로 분할" + "value": "최신 읽지 않은 항목으로 이동" } }, "de": { "stringUnit": { "state": "translated", - "value": "Browser nach rechts teilen" + "value": "Zur letzten ungelesenen springen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Dividir navegador a la derecha" + "value": "Ir a la última no leída" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Diviser le navigateur à droite" + "value": "Aller au dernier message non lu" } }, "it": { "stringUnit": { "state": "translated", - "value": "Dividi browser a destra" + "value": "Vai all'ultimo non letto" } }, "da": { "stringUnit": { "state": "translated", - "value": "Opdel browser til højre" + "value": "Gå til seneste ulæste" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Podziel przeglądarkę w prawo" + "value": "Przejdź do najnowszego nieprzeczytanego" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Разделить браузер вправо" + "value": "Перейти к последнему непрочитанному" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Podijeli preglednik desno" + "value": "Skoči na najnovije nepročitano" } }, "ar": { "stringUnit": { "state": "translated", - "value": "تقسيم المتصفح لليمين" + "value": "الانتقال إلى أحدث غير مقروء" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Del nettleser til høyre" + "value": "Gå til siste uleste" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Dividir Navegador à Direita" + "value": "Ir para Última Não Lida" } }, "th": { "stringUnit": { "state": "translated", - "value": "แยกเบราว์เซอร์ไปทางขวา" + "value": "ข้ามไปยังรายการยังไม่อ่านล่าสุด" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Tarayıcıyı Sağa Böl" + "value": "Son Okunmamışa Atla" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Розділити браузер праворуч" + "value": "Перейти до останнього непрочитаного" } } } }, - "menu.view.splitDown": { + "notifications.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Split Down" + "value": "Notifications" } }, "ja": { "stringUnit": { "state": "translated", - "value": "下に分割" + "value": "通知" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "向下拆分" + "value": "通知" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "向下分割" + "value": "通知" } }, "ko": { "stringUnit": { "state": "translated", - "value": "아래로 분할" + "value": "알림" } }, "de": { "stringUnit": { "state": "translated", - "value": "Nach unten teilen" + "value": "Benachrichtigungen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Dividir hacia abajo" + "value": "Notificaciones" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Diviser vers le bas" + "value": "Notifications" } }, "it": { "stringUnit": { "state": "translated", - "value": "Dividi in basso" + "value": "Notifiche" } }, "da": { "stringUnit": { "state": "translated", - "value": "Opdel nedad" + "value": "Notifikationer" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Podziel w dół" + "value": "Powiadomienia" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Разделить вниз" + "value": "Уведомления" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Podijeli dolje" + "value": "Obavještenja" } }, "ar": { "stringUnit": { "state": "translated", - "value": "تقسيم للأسفل" + "value": "الإشعارات" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Del ned" + "value": "Varsler" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Dividir para Baixo" + "value": "Notificações" } }, "th": { "stringUnit": { "state": "translated", - "value": "แยกลงล่าง" + "value": "การแจ้งเตือน" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Aşağı Böl" + "value": "Bildirimler" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Розділити вниз" + "value": "Сповіщення" } } } }, - "menu.view.splitRight": { + "panel.displayName.fallback": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Split Right" + "value": "Tab" } }, "ja": { "stringUnit": { "state": "translated", - "value": "右に分割" + "value": "タブ" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "向右拆分" + "value": "标签页" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "向右分割" + "value": "標籤頁" } }, "ko": { "stringUnit": { "state": "translated", - "value": "오른쪽으로 분할" + "value": "탭" } }, "de": { "stringUnit": { "state": "translated", - "value": "Nach rechts teilen" + "value": "Tab" } }, "es": { "stringUnit": { "state": "translated", - "value": "Dividir a la derecha" + "value": "Pestaña" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Diviser à droite" + "value": "Onglet" } }, "it": { "stringUnit": { "state": "translated", - "value": "Dividi a destra" + "value": "Scheda" } }, "da": { "stringUnit": { "state": "translated", - "value": "Opdel til højre" + "value": "Fane" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Podziel w prawo" + "value": "Karta" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Разделить вправо" + "value": "Вкладка" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Podijeli desno" + "value": "Tab" } }, "ar": { "stringUnit": { "state": "translated", - "value": "تقسيم لليمين" + "value": "لسان" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Del til høyre" + "value": "Fane" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Dividir à Direita" + "value": "Aba" } }, "th": { "stringUnit": { "state": "translated", - "value": "แยกไปทางขวา" + "value": "แท็บ" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Sağa Böl" + "value": "Sekme" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Розділити праворуч" + "value": "Вкладка" } } } }, - "menu.view.toggleDevTools": { + "panel.openFolder.prompt": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Toggle Developer Tools" + "value": "Open" } }, "ja": { "stringUnit": { "state": "translated", - "value": "デベロッパツールの切り替え" + "value": "開く" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "切换开发者工具" + "value": "打开" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "切換開發者工具" + "value": "開啟" } }, "ko": { "stringUnit": { "state": "translated", - "value": "개발자 도구 전환" + "value": "열기" } }, "de": { "stringUnit": { "state": "translated", - "value": "Entwicklerwerkzeuge ein-/ausblenden" + "value": "Öffnen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Alternar herramientas de desarrollo" + "value": "Abrir" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Afficher/masquer les outils de développement" + "value": "Ouvrir" } }, "it": { "stringUnit": { "state": "translated", - "value": "Attiva/Disattiva Strumenti sviluppatore" + "value": "Apri" } }, "da": { "stringUnit": { "state": "translated", - "value": "Slå udviklerværktøjer til/fra" + "value": "Åbn" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Przełącz narzędzia deweloperskie" + "value": "Otwórz" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Инструменты разработчика" + "value": "Открыть" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Prebaci razvojne alate" + "value": "Otvori" } }, "ar": { "stringUnit": { "state": "translated", - "value": "تبديل أدوات المطور" + "value": "فتح" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Slå utviklerverktøy av/på" + "value": "Åpne" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Alternar Ferramentas do Desenvolvedor" + "value": "Abrir" } }, "th": { "stringUnit": { "state": "translated", - "value": "สลับเครื่องมือนักพัฒนา" + "value": "เปิด" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Geliştirici Araçlarını Aç/Kapat" + "value": "Aç" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Перемкнути інструменти розробника" + "value": "Відкрити" } } } }, - "menu.view.workspace": { + "panel.openFolder.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Workspace %lld" + "value": "Open Folder" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ワークスペース %lld" + "value": "フォルダを開く" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "工作区 %lld" + "value": "打开文件夹" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "工作區 %lld" + "value": "開啟資料夾" } }, "ko": { "stringUnit": { "state": "translated", - "value": "작업 공간 %lld" + "value": "폴더 열기" } }, "de": { "stringUnit": { "state": "translated", - "value": "Arbeitsbereich %lld" + "value": "Ordner öffnen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Espacio de trabajo %lld" + "value": "Abrir carpeta" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Espace de travail %lld" + "value": "Ouvrir un dossier" } }, "it": { "stringUnit": { "state": "translated", - "value": "Area di lavoro %lld" + "value": "Apri cartella" } }, "da": { "stringUnit": { "state": "translated", - "value": "Arbejdsområde %lld" + "value": "Åbn mappe" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Przestrzeń robocza %lld" + "value": "Otwórz folder" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Рабочее пространство %lld" + "value": "Открыть папку" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Radni prostor %lld" + "value": "Otvori folder" } }, "ar": { "stringUnit": { "state": "translated", - "value": "مساحة العمل %lld" + "value": "فتح مجلد" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Arbeidsområde %lld" + "value": "Åpne mappe" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Área de Trabalho %lld" + "value": "Abrir Pasta" } }, "th": { "stringUnit": { "state": "translated", - "value": "เวิร์กสเปซ %lld" + "value": "เปิดโฟลเดอร์" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Çalışma Alanı %lld" + "value": "Klasör Aç" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Робоча область %lld" + "value": "Відкрити теку" } } } }, - "menu.view.zoomIn": { + "search.close.help": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Zoom In" + "value": "Close (Esc)" } }, "ja": { "stringUnit": { "state": "translated", - "value": "拡大" + "value": "閉じる (Esc)" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "放大" + "value": "关闭 (Esc)" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "放大" + "value": "關閉 (Esc)" } }, "ko": { "stringUnit": { "state": "translated", - "value": "확대" + "value": "닫기 (Esc)" } }, "de": { "stringUnit": { "state": "translated", - "value": "Einzoomen" + "value": "Schließen (Esc)" } }, "es": { "stringUnit": { "state": "translated", - "value": "Ampliar" + "value": "Cerrar (Esc)" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Zoom avant" + "value": "Fermer (Échap)" } }, "it": { "stringUnit": { "state": "translated", - "value": "Ingrandisci" + "value": "Chiudi (Esc)" } }, "da": { "stringUnit": { "state": "translated", - "value": "Zoom ind" + "value": "Luk (Esc)" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Powiększ" + "value": "Zamknij (Esc)" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Увеличить" + "value": "Закрыть (Esc)" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Uvećaj" + "value": "Zatvori (Esc)" } }, "ar": { "stringUnit": { "state": "translated", - "value": "تكبير" + "value": "إغلاق (Esc)" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Zoom inn" + "value": "Lukk (Esc)" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Aumentar Zoom" + "value": "Fechar (Esc)" } }, "th": { "stringUnit": { "state": "translated", - "value": "ซูมเข้า" + "value": "ปิด (Esc)" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Yakınlaştır" + "value": "Kapat (Esc)" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Збільшити" + "value": "Закрити (Esc)" } } } }, - "menu.view.zoomOut": { + "search.nextMatch.help": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Zoom Out" + "value": "Next match (Return)" } }, "ja": { "stringUnit": { "state": "translated", - "value": "縮小" + "value": "次の一致 (Return)" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "缩小" + "value": "下一个匹配项 (Return)" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "縮小" + "value": "下一個符合項目 (Return)" } }, "ko": { "stringUnit": { "state": "translated", - "value": "축소" + "value": "다음 일치 (Return)" } }, "de": { "stringUnit": { "state": "translated", - "value": "Auszoomen" + "value": "Nächster Treffer (Eingabetaste)" } }, "es": { "stringUnit": { "state": "translated", - "value": "Reducir" + "value": "Siguiente coincidencia (Return)" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Zoom arrière" + "value": "Résultat suivant (Entrée)" } }, "it": { "stringUnit": { "state": "translated", - "value": "Riduci" + "value": "Risultato successivo (Invio)" } }, "da": { "stringUnit": { "state": "translated", - "value": "Zoom ud" + "value": "Næste match (Return)" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Pomniejsz" + "value": "Następne dopasowanie (Return)" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Уменьшить" + "value": "Следующее совпадение (Return)" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Umanji" + "value": "Sljedeći rezultat (Return)" } }, "ar": { "stringUnit": { "state": "translated", - "value": "تصغير" + "value": "التطابق التالي (Return)" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Zoom ut" + "value": "Neste treff (Return)" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Diminuir Zoom" + "value": "Próximo resultado (Return)" } }, "th": { "stringUnit": { "state": "translated", - "value": "ซูมออก" + "value": "ผลลัพธ์ถัดไป (Return)" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Uzaklaştır" + "value": "Sonraki eşleşme (Return)" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Зменшити" + "value": "Наступний збіг (Return)" } } } }, - "menu.windowNumber": { + "search.placeholder": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Window %lld" + "value": "Search" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ウインドウ %lld" + "value": "検索" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "窗口 %lld" + "value": "搜索" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "視窗 %lld" + "value": "搜尋" } }, "ko": { "stringUnit": { "state": "translated", - "value": "윈도우 %lld" + "value": "검색" } }, "de": { "stringUnit": { "state": "translated", - "value": "Fenster %lld" + "value": "Suchen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Ventana %lld" + "value": "Buscar" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Fenêtre %lld" + "value": "Rechercher" } }, "it": { "stringUnit": { "state": "translated", - "value": "Finestra %lld" + "value": "Cerca" } }, "da": { "stringUnit": { "state": "translated", - "value": "Vindue %lld" + "value": "Søg" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Okno %lld" + "value": "Szukaj" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Окно %lld" + "value": "Поиск" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Prozor %lld" + "value": "Pretraži" } }, "ar": { "stringUnit": { "state": "translated", - "value": "النافذة %lld" + "value": "بحث" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Vindu %lld" + "value": "Søk" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Janela %lld" + "value": "Pesquisar" } }, "th": { "stringUnit": { "state": "translated", - "value": "หน้าต่าง %lld" + "value": "ค้นหา" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Pencere %lld" + "value": "Ara" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Вікно %lld" + "value": "Пошук" } } } }, - "notifications.clearAll": { + "search.previousMatch.help": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Clear All" + "value": "Previous match (Shift+Return)" } }, "ja": { "stringUnit": { "state": "translated", - "value": "すべてクリア" + "value": "前の一致 (Shift+Return)" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "全部清除" + "value": "上一个匹配项 (Shift+Return)" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "清除全部" + "value": "上一個符合項目 (Shift+Return)" } }, "ko": { "stringUnit": { "state": "translated", - "value": "모두 지우기" + "value": "이전 일치 (Shift+Return)" } }, "de": { "stringUnit": { "state": "translated", - "value": "Alle löschen" + "value": "Vorheriger Treffer (Umschalt+Eingabetaste)" } }, "es": { "stringUnit": { "state": "translated", - "value": "Borrar todo" + "value": "Coincidencia anterior (Shift+Return)" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Tout effacer" + "value": "Résultat précédent (Maj+Entrée)" } }, "it": { "stringUnit": { "state": "translated", - "value": "Cancella tutto" + "value": "Risultato precedente (Maiusc+Invio)" } }, "da": { "stringUnit": { "state": "translated", - "value": "Ryd alle" + "value": "Forrige match (Shift+Return)" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Wyczyść wszystko" + "value": "Poprzednie dopasowanie (Shift+Return)" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Очистить все" + "value": "Предыдущее совпадение (Shift+Return)" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Obriši sve" + "value": "Prethodni rezultat (Shift+Return)" } }, "ar": { "stringUnit": { "state": "translated", - "value": "مسح الكل" + "value": "التطابق السابق (Shift+Return)" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Fjern alle" + "value": "Forrige treff (Shift+Return)" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Limpar Tudo" + "value": "Resultado anterior (Shift+Return)" } }, "th": { "stringUnit": { "state": "translated", - "value": "ล้างทั้งหมด" + "value": "ผลลัพธ์ก่อนหน้า (Shift+Return)" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Tümünü Temizle" + "value": "Önceki eşleşme (Shift+Return)" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Очистити все" + "value": "Попередній збіг (Shift+Return)" } } } }, - "notifications.empty.description": { + "settings.app.appIcon": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Desktop notifications will appear here for quick review." + "value": "App Icon" } }, "ja": { "stringUnit": { "state": "translated", - "value": "デスクトップ通知がここに表示されます。" + "value": "アプリアイコン" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "桌面通知将在此处显示,方便快速查看。" + "value": "应用图标" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "桌面通知將在這裡顯示,方便您快速查看。" + "value": "App 圖示" } }, "ko": { "stringUnit": { "state": "translated", - "value": "데스크톱 알림이 여기에 표시되어 빠르게 확인할 수 있습니다." + "value": "앱 아이콘" } }, "de": { "stringUnit": { "state": "translated", - "value": "Desktop-Benachrichtigungen werden hier zur schnellen Überprüfung angezeigt." + "value": "App-Symbol" } }, "es": { "stringUnit": { "state": "translated", - "value": "Las notificaciones de escritorio aparecerán aquí para su revisión rápida." + "value": "Ícono de la app" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Les notifications de bureau apparaîtront ici pour une consultation rapide." + "value": "Icône de l'app" } }, "it": { "stringUnit": { "state": "translated", - "value": "Le notifiche desktop appariranno qui per una rapida consultazione." + "value": "Icona app" } }, "da": { "stringUnit": { "state": "translated", - "value": "Skrivebordsnotifikationer vises her til hurtig gennemgang." + "value": "Appikon" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Powiadomienia pulpitu będą się tu pojawiać do szybkiego przeglądu." + "value": "Ikona aplikacji" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Уведомления рабочего стола будут отображаться здесь для быстрого просмотра." + "value": "Значок приложения" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Obavještenja na radnoj površini će se pojavljivati ovdje radi brzog pregleda." + "value": "Ikona aplikacije" } }, "ar": { "stringUnit": { "state": "translated", - "value": "ستظهر إشعارات سطح المكتب هنا للمراجعة السريعة." + "value": "أيقونة التطبيق" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Skrivebordsvarsler vises her for rask gjennomgang." + "value": "Appikon" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "As notificações da área de trabalho aparecerão aqui para revisão rápida." + "value": "Ícone do App" } }, "th": { "stringUnit": { "state": "translated", - "value": "การแจ้งเตือนเดสก์ท็อปจะปรากฏที่นี่เพื่อตรวจสอบอย่างรวดเร็ว" + "value": "ไอคอนแอป" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Masaüstü bildirimleri hızlı inceleme için burada görünecek." + "value": "Uygulama Simgesi" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Сповіщення робочого столу з'являтимуться тут для швидкого перегляду." + "value": "Іконка програми" } } } }, - "notifications.empty.subtitle": { + "settings.app.appearance": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Desktop notifications will appear here." + "value": "Appearance" } }, "ja": { "stringUnit": { "state": "translated", - "value": "デスクトップ通知がここに表示されます。" + "value": "外観" + } + } + } + }, + "settings.app.appIcon.subtitle": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Dock and app switcher" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "Dockとアプリスイッチャー" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "桌面通知将在此处显示。" + "value": "程序坞和应用切换器" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "桌面通知將在這裡顯示。" + "value": "Dock 和 App 切換器" } }, "ko": { "stringUnit": { "state": "translated", - "value": "데스크톱 알림이 여기에 표시됩니다." + "value": "Dock 및 앱 전환기" } }, "de": { "stringUnit": { "state": "translated", - "value": "Desktop-Benachrichtigungen werden hier angezeigt." + "value": "Dock und App-Umschalter" } }, "es": { "stringUnit": { "state": "translated", - "value": "Las notificaciones de escritorio aparecerán aquí." + "value": "Dock y selector de apps" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Les notifications de bureau apparaîtront ici." + "value": "Dock et sélecteur d'apps" } }, "it": { "stringUnit": { "state": "translated", - "value": "Le notifiche desktop appariranno qui." + "value": "Dock e selettore app" } }, "da": { "stringUnit": { "state": "translated", - "value": "Skrivebordsnotifikationer vises her." + "value": "Dock og appskifter" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Powiadomienia pulpitu będą się tu pojawiać." + "value": "Dock i przełącznik aplikacji" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Уведомления рабочего стола будут отображаться здесь." + "value": "Dock и переключатель приложений" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Obavještenja na radnoj površini će se pojavljivati ovdje." + "value": "Dock i prebacivač aplikacija" } }, "ar": { "stringUnit": { "state": "translated", - "value": "ستظهر إشعارات سطح المكتب هنا." + "value": "شريط Dock ومبدّل التطبيقات" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Skrivebordsvarsler vises her." + "value": "Dock og appbytter" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "As notificações da área de trabalho aparecerão aqui." + "value": "Dock e alternador de apps" } }, "th": { "stringUnit": { "state": "translated", - "value": "การแจ้งเตือนเดสก์ท็อปจะปรากฏที่นี่" + "value": "Dock และตัวสลับแอป" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Masaüstü bildirimleri burada görünecek." + "value": "Dock ve uygulama değiştirici" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Сповіщення робочого столу з'являтимуться тут." + "value": "Dock та перемикач програм" } } } }, - "notifications.empty.title": { + "settings.app.dockBadge": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "No notifications yet" + "value": "Dock Badge" } }, "ja": { "stringUnit": { "state": "translated", - "value": "まだ通知はありません" + "value": "Dockバッジ" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "暂无通知" + "value": "程序坞角标" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "尚無通知" + "value": "Dock 標記" } }, "ko": { "stringUnit": { "state": "translated", - "value": "아직 알림이 없습니다" + "value": "Dock 배지" } }, "de": { "stringUnit": { "state": "translated", - "value": "Noch keine Benachrichtigungen" + "value": "Dock-Badge" } }, "es": { "stringUnit": { "state": "translated", - "value": "Aún no hay notificaciones" + "value": "Insignia del Dock" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Aucune notification pour le moment" + "value": "Badge du Dock" } }, "it": { "stringUnit": { "state": "translated", - "value": "Nessuna notifica" + "value": "Badge del Dock" } }, "da": { "stringUnit": { "state": "translated", - "value": "Ingen notifikationer endnu" + "value": "Dock-badge" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Brak powiadomień" + "value": "Plakietka w Docku" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Уведомлений пока нет" + "value": "Значок Dock" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Još nema obavještenja" + "value": "Oznaka na Docku" } }, "ar": { "stringUnit": { "state": "translated", - "value": "لا توجد إشعارات بعد" + "value": "شارة Dock" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Ingen varsler ennå" + "value": "Dock-merke" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Nenhuma notificação ainda" + "value": "Emblema do Dock" } }, "th": { "stringUnit": { "state": "translated", - "value": "ยังไม่มีการแจ้งเตือน" + "value": "ป้าย Dock" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Henüz bildirim yok" - } - }, - "uk": { - "stringUnit": { - "state": "translated", - "value": "Сповіщень ще немає" - } - } - } - }, - "notifications.jumpToLatest": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Jump to Latest" - } - }, - "ja": { - "stringUnit": { - "state": "translated", - "value": "最新へジャンプ" + "value": "Dock Rozeti" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Перейти до останнього" - } - }, - "ko": { - "stringUnit": { - "state": "translated", - "value": "최신으로 이동" + "value": "Значок Dock" } } } }, - "notifications.jumpToLatestUnread": { + "settings.app.dockBadge.subtitle": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Jump to Latest Unread" + "value": "Show unread count on app icon (Dock and Cmd+Tab)." } }, "ja": { "stringUnit": { "state": "translated", - "value": "最新の未読にジャンプ" + "value": "アプリアイコン(DockおよびCmd+Tab)に未読数を表示します。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "跳转到最新未读" + "value": "在应用图标上显示未读计数(程序坞和 Cmd+Tab)。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "跳至最新未讀" + "value": "在 App 圖示上顯示未讀數量(Dock 和 Cmd+Tab)。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "최신 읽지 않은 항목으로 이동" + "value": "앱 아이콘(Dock 및 Cmd+Tab)에 읽지 않은 수를 표시합니다." } }, "de": { "stringUnit": { "state": "translated", - "value": "Zur letzten ungelesenen springen" + "value": "Ungelesene Anzahl auf dem App-Symbol anzeigen (Dock und Cmd+Tab)." } }, "es": { "stringUnit": { "state": "translated", - "value": "Ir a la última no leída" + "value": "Mostrar el recuento de no leídos en el ícono de la app (Dock y Cmd+Tab)." } }, "fr": { "stringUnit": { "state": "translated", - "value": "Aller au dernier message non lu" + "value": "Afficher le nombre de messages non lus sur l'icône de l'app (Dock et Cmd+Tab)." } }, "it": { "stringUnit": { "state": "translated", - "value": "Vai all'ultimo non letto" + "value": "Mostra il conteggio non letti sull'icona dell'app (Dock e Cmd+Tab)." } }, "da": { "stringUnit": { "state": "translated", - "value": "Gå til seneste ulæste" + "value": "Vis antal ulæste på appikonet (Dock og Cmd+Tab)." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Przejdź do najnowszego nieprzeczytanego" + "value": "Pokaż liczbę nieprzeczytanych na ikonie aplikacji (Dock i Cmd+Tab)." } }, "ru": { "stringUnit": { "state": "translated", - "value": "Перейти к последнему непрочитанному" + "value": "Показывать количество непрочитанных на значке приложения (Dock и Cmd+Tab)." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Skoči na najnovije nepročitano" + "value": "Prikaži broj nepročitanih na ikoni aplikacije (Dock i Cmd+Tab)." } }, "ar": { "stringUnit": { "state": "translated", - "value": "الانتقال إلى أحدث غير مقروء" + "value": "عرض عدد غير المقروء على أيقونة التطبيق (Dock و Cmd+Tab)." } }, "nb": { "stringUnit": { "state": "translated", - "value": "Gå til siste uleste" + "value": "Vis antall uleste på appikonet (Dock og Cmd+Tab)." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Ir para Última Não Lida" + "value": "Mostrar contagem de não lidos no ícone do app (Dock e Cmd+Tab)." } }, "th": { "stringUnit": { "state": "translated", - "value": "ข้ามไปยังรายการยังไม่อ่านล่าสุด" + "value": "แสดงจำนวนยังไม่อ่านบนไอคอนแอป (Dock และ Cmd+Tab)" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Son Okunmamışa Atla" + "value": "Uygulama simgesinde (Dock ve Cmd+Tab) okunmamış sayısını göster." } }, "uk": { "stringUnit": { "state": "translated", - "value": "Перейти до останнього непрочитаного" + "value": "Показувати кількість непрочитаних на іконці програми (Dock та Cmd+Tab)." } } } }, - "notifications.title": { + "settings.app.showInMenuBar": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Notifications" + "value": "Show in Menu Bar" } }, "ja": { "stringUnit": { "state": "translated", - "value": "通知" + "value": "メニューバーに表示" } }, - "zh-Hans": { + "uk": { "stringUnit": { "state": "translated", - "value": "通知" + "value": "Показувати в рядку меню" } }, - "zh-Hant": { + "ko": { "stringUnit": { "state": "translated", - "value": "通知" + "value": "메뉴 막대에 표시" } - }, - "ko": { + } + } + }, + "settings.app.menuBarOnly": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "알림" + "value": "Menu Bar Only" } }, - "de": { + "ja": { "stringUnit": { "state": "translated", - "value": "Benachrichtigungen" + "value": "メニューバーのみ" } }, - "es": { + "zh-Hans": { "stringUnit": { "state": "translated", - "value": "Notificaciones" + "value": "仅菜单栏" + } + }, + "zh-Hant": { + "stringUnit": { + "state": "translated", + "value": "僅選單列" + } + }, + "ko": { + "stringUnit": { + "state": "translated", + "value": "메뉴 막대 전용" + } + }, + "de": { + "stringUnit": { + "state": "translated", + "value": "Nur Menüleiste" + } + }, + "es": { + "stringUnit": { + "state": "translated", + "value": "Solo barra de menús" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Notifications" + "value": "Barre des menus uniquement" } }, "it": { "stringUnit": { "state": "translated", - "value": "Notifiche" + "value": "Solo barra dei menu" } }, "da": { "stringUnit": { "state": "translated", - "value": "Notifikationer" + "value": "Kun menulinje" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Powiadomienia" + "value": "Tylko pasek menu" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Уведомления" + "value": "Только строка меню" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Obavještenja" + "value": "Samo traka menija" } }, "ar": { "stringUnit": { "state": "translated", - "value": "الإشعارات" + "value": "شريط القائمة فقط" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Varsler" + "value": "Kun menylinje" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Notificações" + "value": "Apenas barra de menus" } }, "th": { "stringUnit": { "state": "translated", - "value": "การแจ้งเตือน" + "value": "เฉพาะแถบเมนู" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Bildirimler" + "value": "Yalnızca menü çubuğu" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Сповіщення" + "value": "Лише рядок меню" } } } }, - "panel.displayName.fallback": { + "settings.app.menuBarOnly.subtitle": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Tab" + "value": "Hide the Dock icon and Cmd+Tab entry. Use the menu bar item to show cmux." } }, "ja": { "stringUnit": { "state": "translated", - "value": "タブ" + "value": "DockアイコンとCmd+Tabの項目を非表示にします。cmuxを表示するにはメニューバー項目を使います。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "标签页" + "value": "隐藏 Dock 图标和 Cmd+Tab 条目。使用菜单栏项目显示 cmux。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "標籤頁" + "value": "隱藏 Dock 圖示和 Cmd+Tab 項目。使用選單列項目顯示 cmux。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "탭" + "value": "Dock 아이콘과 Cmd+Tab 항목을 숨깁니다. 메뉴 막대 항목으로 cmux를 표시합니다." } }, "de": { "stringUnit": { "state": "translated", - "value": "Tab" + "value": "Blendet das Dock-Symbol und den Cmd+Tab-Eintrag aus. Verwende den Menüleisteneintrag, um cmux anzuzeigen." } }, "es": { "stringUnit": { "state": "translated", - "value": "Pestaña" + "value": "Oculta el ícono del Dock y la entrada de Cmd+Tab. Usa el elemento de la barra de menús para mostrar cmux." } }, "fr": { "stringUnit": { "state": "translated", - "value": "Onglet" + "value": "Masque l’icône du Dock et l’entrée Cmd+Tab. Utilisez l’élément de barre des menus pour afficher cmux." } }, "it": { "stringUnit": { "state": "translated", - "value": "Scheda" + "value": "Nasconde l'icona del Dock e la voce Cmd+Tab. Usa l'elemento nella barra dei menu per mostrare cmux." } }, "da": { "stringUnit": { "state": "translated", - "value": "Fane" + "value": "Skjul Dock-symbolet og Cmd+Tab-posten. Brug menulinjeelementet til at vise cmux." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Karta" + "value": "Ukrywa ikonę Docka i pozycję Cmd+Tab. Użyj elementu na pasku menu, aby pokazać cmux." } }, "ru": { "stringUnit": { "state": "translated", - "value": "Вкладка" + "value": "Скрывает значок Dock и пункт Cmd+Tab. Используйте пункт строки меню, чтобы показать cmux." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Tab" + "value": "Sakriva Dock ikonu i Cmd+Tab stavku. Koristi stavku trake menija za prikaz cmux-a." } }, "ar": { "stringUnit": { "state": "translated", - "value": "لسان" + "value": "يخفي أيقونة Dock وإدخال Cmd+Tab. استخدم عنصر شريط القائمة لإظهار cmux." } }, "nb": { "stringUnit": { "state": "translated", - "value": "Fane" + "value": "Skjuler Dock-symbolet og Cmd+Tab-oppføringen. Bruk menylinjeelementet for å vise cmux." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Aba" + "value": "Oculta o ícone no Dock e a entrada Cmd+Tab. Use o item da barra de menus para mostrar o cmux." } }, "th": { "stringUnit": { "state": "translated", - "value": "แท็บ" + "value": "ซ่อนไอคอน Dock และรายการ Cmd+Tab ใช้รายการในแถบเมนูเพื่อแสดง cmux" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Sekme" + "value": "Dock simgesini ve Cmd+Tab girişini gizler. cmux'u göstermek için menü çubuğu öğesini kullan." } }, "uk": { "stringUnit": { "state": "translated", - "value": "Вкладка" + "value": "Приховує іконку Dock і пункт Cmd+Tab. Використовуйте пункт рядка меню, щоб показати cmux." } } } }, - "panel.openFolder.prompt": { + "settings.app.showInMenuBar.subtitle": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Open" + "value": "Keep cmux in the menu bar for unread notifications and quick actions." } }, "ja": { "stringUnit": { "state": "translated", - "value": "開く" + "value": "未読通知の確認やクイック操作のために、cmuxをメニューバーに表示します。" + } + }, + "uk": { + "stringUnit": { + "state": "translated", + "value": "Залишати cmux у рядку меню для непрочитаних сповіщень та швидких дій." + } + }, + "ko": { + "stringUnit": { + "state": "translated", + "value": "읽지 않은 알림과 빠른 작업을 위해 cmux를 메뉴 막대에 유지합니다." + } + } + } + }, + "settings.app.language": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Language" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "言語" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "打开" + "value": "语言" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "開啟" + "value": "語言" } }, "ko": { "stringUnit": { "state": "translated", - "value": "열기" + "value": "언어" } }, "de": { "stringUnit": { "state": "translated", - "value": "Öffnen" + "value": "Sprache" } }, "es": { "stringUnit": { "state": "translated", - "value": "Abrir" + "value": "Idioma" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Ouvrir" + "value": "Langue" } }, "it": { "stringUnit": { "state": "translated", - "value": "Apri" + "value": "Lingua" } }, "da": { "stringUnit": { "state": "translated", - "value": "Åbn" + "value": "Sprog" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Otwórz" + "value": "Język" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Открыть" + "value": "Язык" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Otvori" + "value": "Jezik" } }, "ar": { "stringUnit": { "state": "translated", - "value": "فتح" + "value": "اللغة" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Åpne" + "value": "Språk" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Abrir" + "value": "Idioma" } }, "th": { "stringUnit": { "state": "translated", - "value": "เปิด" + "value": "ภาษา" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Aç" + "value": "Dil" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Відкрити" + "value": "Мова" } } } }, - "panel.openFolder.title": { + "settings.app.language.restartDialog.confirm": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Open Folder" + "value": "Restart Now" } }, "ja": { "stringUnit": { "state": "translated", - "value": "フォルダを開く" + "value": "今すぐ再起動" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "打开文件夹" + "value": "立即重启" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "開啟資料夾" + "value": "立即重新啟動" } }, "ko": { "stringUnit": { "state": "translated", - "value": "폴더 열기" + "value": "지금 재시작" } }, "de": { "stringUnit": { "state": "translated", - "value": "Ordner öffnen" + "value": "Jetzt neu starten" } }, "es": { "stringUnit": { "state": "translated", - "value": "Abrir carpeta" + "value": "Reiniciar ahora" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Ouvrir un dossier" + "value": "Redémarrer maintenant" } }, "it": { "stringUnit": { "state": "translated", - "value": "Apri cartella" + "value": "Riavvia ora" } }, "da": { "stringUnit": { "state": "translated", - "value": "Åbn mappe" + "value": "Genstart nu" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Otwórz folder" + "value": "Uruchom ponownie teraz" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Открыть папку" + "value": "Перезапустить сейчас" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Otvori folder" + "value": "Ponovo pokreni sada" } }, "ar": { "stringUnit": { "state": "translated", - "value": "فتح مجلد" + "value": "إعادة التشغيل الآن" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Åpne mappe" + "value": "Start på nytt nå" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Abrir Pasta" + "value": "Reiniciar Agora" } }, "th": { "stringUnit": { "state": "translated", - "value": "เปิดโฟลเดอร์" + "value": "รีสตาร์ตเดี๋ยวนี้" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Klasör Aç" + "value": "Şimdi Yeniden Başlat" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Відкрити теку" + "value": "Перезапустити зараз" } } } }, - "search.close.help": { + "settings.app.language.restartDialog.later": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Close (Esc)" + "value": "Later" } }, "ja": { "stringUnit": { "state": "translated", - "value": "閉じる (Esc)" + "value": "後で" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "关闭 (Esc)" + "value": "稍后" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "關閉 (Esc)" + "value": "稍後" } }, "ko": { "stringUnit": { "state": "translated", - "value": "닫기 (Esc)" + "value": "나중에" } }, "de": { "stringUnit": { "state": "translated", - "value": "Schließen (Esc)" + "value": "Später" } }, "es": { "stringUnit": { "state": "translated", - "value": "Cerrar (Esc)" + "value": "Más tarde" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Fermer (Échap)" + "value": "Plus tard" } }, "it": { "stringUnit": { "state": "translated", - "value": "Chiudi (Esc)" + "value": "Più tardi" } }, "da": { "stringUnit": { "state": "translated", - "value": "Luk (Esc)" + "value": "Senere" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Zamknij (Esc)" + "value": "Później" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Закрыть (Esc)" + "value": "Позже" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Zatvori (Esc)" + "value": "Kasnije" } }, "ar": { "stringUnit": { "state": "translated", - "value": "إغلاق (Esc)" + "value": "لاحقًا" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Lukk (Esc)" + "value": "Senere" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Fechar (Esc)" + "value": "Depois" } }, "th": { "stringUnit": { "state": "translated", - "value": "ปิด (Esc)" + "value": "ภายหลัง" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Kapat (Esc)" + "value": "Daha Sonra" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Закрити (Esc)" + "value": "Пізніше" } } } }, - "search.nextMatch.help": { + "settings.app.language.restartDialog.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Next match (Return)" + "value": "Restart to apply language change?" } }, "ja": { "stringUnit": { "state": "translated", - "value": "次の一致 (Return)" + "value": "言語変更を適用するために再起動しますか?" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "下一个匹配项 (Return)" + "value": "重启以应用语言更改?" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "下一個符合項目 (Return)" + "value": "要重新啟動以套用語言變更嗎?" } }, "ko": { "stringUnit": { "state": "translated", - "value": "다음 일치 (Return)" + "value": "언어 변경을 적용하려면 재시작하시겠습니까?" } }, "de": { "stringUnit": { "state": "translated", - "value": "Nächster Treffer (Eingabetaste)" + "value": "Neu starten, um Sprachänderung zu übernehmen?" } }, "es": { "stringUnit": { "state": "translated", - "value": "Siguiente coincidencia (Return)" + "value": "¿Reiniciar para aplicar el cambio de idioma?" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Résultat suivant (Entrée)" + "value": "Redémarrer pour appliquer le changement de langue ?" } }, "it": { "stringUnit": { "state": "translated", - "value": "Risultato successivo (Invio)" + "value": "Riavviare per applicare il cambio di lingua?" } }, "da": { "stringUnit": { "state": "translated", - "value": "Næste match (Return)" + "value": "Genstart for at anvende sprogændring?" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Następne dopasowanie (Return)" + "value": "Uruchomić ponownie, aby zastosować zmianę języka?" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Следующее совпадение (Return)" + "value": "Перезапустить для применения языка?" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Sljedeći rezultat (Return)" + "value": "Ponovo pokrenuti za primjenu promjene jezika?" } }, "ar": { "stringUnit": { "state": "translated", - "value": "التطابق التالي (Return)" + "value": "إعادة التشغيل لتطبيق تغيير اللغة؟" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Neste treff (Return)" + "value": "Starte på nytt for å endre språk?" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Próximo resultado (Return)" + "value": "Reiniciar para aplicar a mudança de idioma?" } }, "th": { "stringUnit": { "state": "translated", - "value": "ผลลัพธ์ถัดไป (Return)" + "value": "รีสตาร์ตเพื่อเปลี่ยนภาษาหรือไม่?" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Sonraki eşleşme (Return)" + "value": "Dil değişikliğini uygulamak için yeniden başlatılsın mı?" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Наступний збіг (Return)" + "value": "Перезапустити для застосування зміни мови?" } } } }, - "search.placeholder": { + "settings.app.language.restartSubtitle": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Search" + "value": "Restart cmux to apply" } }, "ja": { "stringUnit": { "state": "translated", - "value": "検索" + "value": "cmuxを再起動して適用" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "搜索" + "value": "重启 cmux 以应用" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "搜尋" + "value": "重新啟動 cmux 以套用" } }, "ko": { "stringUnit": { "state": "translated", - "value": "검색" + "value": "적용하려면 cmux를 재시작하세요" } }, "de": { "stringUnit": { "state": "translated", - "value": "Suchen" + "value": "cmux neu starten, um Änderung zu übernehmen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Buscar" + "value": "Reinicia cmux para aplicar" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Rechercher" + "value": "Redémarrez cmux pour appliquer" } }, "it": { "stringUnit": { "state": "translated", - "value": "Cerca" + "value": "Riavvia cmux per applicare" } }, "da": { "stringUnit": { "state": "translated", - "value": "Søg" + "value": "Genstart cmux for at anvende" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Szukaj" + "value": "Uruchom ponownie cmux, aby zastosować" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Поиск" + "value": "Перезапустите cmux для применения" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Pretraži" + "value": "Ponovo pokrenite cmux za primjenu" } }, "ar": { "stringUnit": { "state": "translated", - "value": "بحث" + "value": "أعد تشغيل cmux للتطبيق" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Søk" + "value": "Start cmux på nytt for å bruke" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Pesquisar" + "value": "Reinicie o cmux para aplicar" } }, "th": { "stringUnit": { "state": "translated", - "value": "ค้นหา" + "value": "รีสตาร์ต cmux เพื่อนำไปใช้" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Ara" + "value": "Uygulamak için cmux'u yeniden başlatın" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Пошук" + "value": "Перезапустіть cmux для застосування" } } } }, - "search.previousMatch.help": { + "settings.app.newWorkspacePlacement": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Previous match (Shift+Return)" + "value": "New Workspace Placement" } }, "ja": { "stringUnit": { "state": "translated", - "value": "前の一致 (Shift+Return)" + "value": "新規ワークスペースの配置" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "上一个匹配项 (Shift+Return)" + "value": "新工作区位置" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "上一個符合項目 (Shift+Return)" + "value": "新工作區位置" } }, "ko": { "stringUnit": { "state": "translated", - "value": "이전 일치 (Shift+Return)" + "value": "새 작업 공간 위치" } }, "de": { "stringUnit": { "state": "translated", - "value": "Vorheriger Treffer (Umschalt+Eingabetaste)" + "value": "Platzierung neuer Arbeitsbereiche" } }, "es": { "stringUnit": { "state": "translated", - "value": "Coincidencia anterior (Shift+Return)" + "value": "Ubicación de nuevo espacio de trabajo" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Résultat précédent (Maj+Entrée)" + "value": "Emplacement des nouveaux espaces de travail" } }, "it": { "stringUnit": { "state": "translated", - "value": "Risultato precedente (Maiusc+Invio)" + "value": "Posizionamento nuova area di lavoro" } }, "da": { "stringUnit": { "state": "translated", - "value": "Forrige match (Shift+Return)" + "value": "Placering af nyt arbejdsområde" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Poprzednie dopasowanie (Shift+Return)" + "value": "Umieszczenie nowej przestrzeni roboczej" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Предыдущее совпадение (Shift+Return)" + "value": "Расположение нового рабочего пространства" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Prethodni rezultat (Shift+Return)" + "value": "Pozicija novog radnog prostora" } }, "ar": { "stringUnit": { "state": "translated", - "value": "التطابق السابق (Shift+Return)" + "value": "موضع مساحة العمل الجديدة" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Forrige treff (Shift+Return)" + "value": "Plassering av nytt arbeidsområde" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Resultado anterior (Shift+Return)" + "value": "Posição da Nova Área de Trabalho" } }, "th": { "stringUnit": { "state": "translated", - "value": "ผลลัพธ์ก่อนหน้า (Shift+Return)" + "value": "ตำแหน่งเวิร์กสเปซใหม่" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Önceki eşleşme (Shift+Return)" + "value": "Yeni Çalışma Alanı Konumu" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Попередній збіг (Shift+Return)" + "value": "Розташування нової робочої області" } } } }, - "settings.app.appIcon": { + "settings.app.workspaceInheritWorkingDirectory": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "App Icon" + "value": "Inherit Workspace Working Directory" } }, "ja": { "stringUnit": { "state": "translated", - "value": "アプリアイコン" - } - }, - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "应用图标" + "value": "ワークスペースの作業ディレクトリを継承" } - }, - "zh-Hant": { + } + } + }, + "settings.app.workspaceInheritWorkingDirectory.subtitleOff": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "App 圖示" + "value": "New workspaces leave their working directory unset so Ghostty's working-directory setting can apply." } }, - "ko": { + "ja": { "stringUnit": { "state": "translated", - "value": "앱 아이콘" + "value": "新規ワークスペースの作業ディレクトリを未設定にして、Ghostty の working-directory 設定を適用します。" } - }, - "de": { + } + } + }, + "settings.app.workspaceInheritWorkingDirectory.subtitleOn": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "App-Symbol" + "value": "New workspaces start in the focused workspace's working directory." } }, - "es": { + "ja": { "stringUnit": { "state": "translated", - "value": "Ícono de la app" + "value": "新規ワークスペースはフォーカス中のワークスペースの作業ディレクトリで開始します。" } - }, - "fr": { + } + } + }, + "settings.app.settingsFile.openButton": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Icône de l'app" + "value": "Open cmux.json" } }, - "it": { + "ja": { "stringUnit": { "state": "translated", - "value": "Icona app" + "value": "cmux.jsonを開く" } }, - "da": { + "ko": { "stringUnit": { "state": "translated", - "value": "Appikon" + "value": "cmux.json 열기" } - }, - "pl": { + } + } + }, + "settings.settingsJSON.docsButton": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Ikona aplikacji" + "value": "Open Docs" } }, - "ru": { + "ja": { "stringUnit": { "state": "translated", - "value": "Значок приложения" + "value": "ドキュメントを開く" } }, - "bs": { + "ko": { "stringUnit": { "state": "translated", - "value": "Ikona aplikacije" + "value": "문서 열기" } - }, - "ar": { + } + } + }, + "settings.settingsJSON.documentation": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "أيقونة التطبيق" + "value": "Documentation" } }, - "nb": { + "ja": { "stringUnit": { "state": "translated", - "value": "Appikon" + "value": "ドキュメント" } }, - "pt-BR": { + "ko": { "stringUnit": { "state": "translated", - "value": "Ícone do App" + "value": "문서" } - }, - "th": { + } + } + }, + "settings.settingsJSON.documentation.subtitle": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "ไอคอนแอป" + "value": "View supported keys, file locations, schema, and reload behavior." } }, - "tr": { + "ja": { "stringUnit": { "state": "translated", - "value": "Uygulama Simgesi" + "value": "サポートされているキー、ファイルの場所、スキーマ、再読み込み方法を確認します。" } }, - "uk": { + "ko": { "stringUnit": { "state": "translated", - "value": "Іконка програми" + "value": "지원되는 키, 파일 위치, 스키마, 다시 불러오기 동작을 확인합니다." } } } }, - "settings.app.appearance": { + "settings.settingsJSON.file": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Appearance" + "value": "User config file" } }, "ja": { "stringUnit": { "state": "translated", - "value": "外観" + "value": "ユーザー設定ファイル" + } + }, + "ko": { + "stringUnit": { + "state": "translated", + "value": "사용자 설정 파일" } } } }, - "settings.app.appIcon.subtitle": { + "settings.settingsJSON.file.subtitle": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Dock and app switcher" + "value": "Edit cmux-owned app settings, shortcuts, automation, sidebar, notifications, and browser behavior." } }, "ja": { "stringUnit": { "state": "translated", - "value": "Dockとアプリスイッチャー" + "value": "cmux 管理のアプリ設定、ショートカット、オートメーション、サイドバー、通知、ブラウザ動作を編集します。" } }, - "zh-Hans": { + "ko": { "stringUnit": { "state": "translated", - "value": "程序坞和应用切换器" + "value": "cmux가 관리하는 앱 설정, 단축키, 자동화, 사이드바, 알림, 브라우저 동작을 편집합니다." } - }, - "zh-Hant": { + } + } + }, + "settings.settingsJSON.openButton": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Dock 和 App 切換器" + "value": "Open" } }, - "ko": { + "ja": { "stringUnit": { "state": "translated", - "value": "Dock 및 앱 전환기" + "value": "開く" } }, - "de": { + "ko": { "stringUnit": { "state": "translated", - "value": "Dock und App-Umschalter" + "value": "열기" } - }, - "es": { + } + } + }, + "settings.settingsJSON.openFile": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Dock y selector de apps" + "value": "Open cmux.json" } }, - "fr": { + "ja": { "stringUnit": { "state": "translated", - "value": "Dock et sélecteur d'apps" + "value": "cmux.jsonを開く" } }, - "it": { + "ko": { "stringUnit": { "state": "translated", - "value": "Dock e selettore app" + "value": "cmux.json 열기" } - }, - "da": { + } + } + }, + "settings.app.configWindow": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Dock og appskifter" + "value": "Terminal Config" } }, - "pl": { + "ja": { "stringUnit": { "state": "translated", - "value": "Dock i przełącznik aplikacji" + "value": "ターミナル設定" } - }, - "ru": { + } + } + }, + "settings.app.configWindow.openButton": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Dock и переключатель приложений" + "value": "Open Config" } }, - "bs": { + "ja": { "stringUnit": { "state": "translated", - "value": "Dock i prebacivač aplikacija" + "value": "設定を開く" } - }, - "ar": { + } + } + }, + "settings.app.configWindow.subtitle": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "شريط Dock ومبدّل التطبيقات" + "value": "Open the cmux terminal config and generated preview in one utility window." } }, - "nb": { + "ja": { "stringUnit": { "state": "translated", - "value": "Dock og appbytter" + "value": "cmux の端末設定と生成プレビューを 1 つのユーティリティウインドウで開きます。" } - }, - "pt-BR": { + } + } + }, + "settings.config.action.openEditor": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Dock e alternador de apps" + "value": "Open in Editor…" } }, - "th": { + "ja": { "stringUnit": { "state": "translated", - "value": "Dock และตัวสลับแอป" + "value": "エディタで開く…" } - }, - "tr": { + } + } + }, + "settings.config.action.openActiveEditor": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Dock ve uygulama değiştirici" + "value": "Open Active Config…" } }, - "uk": { + "ja": { "stringUnit": { "state": "translated", - "value": "Dock та перемикач програм" + "value": "有効な設定を開く…" } } } }, - "settings.app.dockBadge": { + "settings.config.action.reload": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Dock Badge" + "value": "Reload" } }, "ja": { "stringUnit": { "state": "translated", - "value": "Dockバッジ" + "value": "再読み込み" } - }, - "zh-Hans": { + } + } + }, + "settings.config.action.revealFinder": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "程序坞角标" + "value": "Reveal in Finder" } }, - "zh-Hant": { + "ja": { "stringUnit": { "state": "translated", - "value": "Dock 標記" + "value": "Finderで表示" } - }, - "ko": { + } + } + }, + "settings.config.action.revealActiveFinder": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Dock 배지" + "value": "Reveal Active Config in Finder" } }, - "de": { + "ja": { "stringUnit": { "state": "translated", - "value": "Dock-Badge" + "value": "有効な設定をFinderで表示" } - }, - "es": { + } + } + }, + "settings.config.action.save": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Insignia del Dock" + "value": "Save" } }, - "fr": { + "ja": { "stringUnit": { "state": "translated", - "value": "Badge du Dock" + "value": "保存" } - }, - "it": { + } + } + }, + "settings.config.banner.cmux": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Badge del Dock" + "value": "This is the cmux Ghostty config selected for this build. Edit it here, then Save to reload cmux." } }, - "da": { + "ja": { "stringUnit": { "state": "translated", - "value": "Dock-badge" + "value": "これはこのビルドで選択されている cmux Ghostty 設定です。ここで編集し、保存すると cmux が再読み込みされます。" } - }, - "pl": { + } + } + }, + "settings.config.banner.synced": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Plakietka w Docku" + "value": "This is a generated preview of the effective config. Edit the cmux tab to change what cmux reads." } }, - "ru": { + "ja": { "stringUnit": { "state": "translated", - "value": "Значок Dock" + "value": "これは実効設定の生成プレビューです。cmux が読み込む内容を変更するには cmux タブを編集してください。" } - }, - "bs": { + } + } + }, + "settings.config.banner.syncedNoGhostty": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Oznaka na Docku" + "value": "This is a generated preview of the effective config. No base Ghostty config file was found, so only cmux overrides are shown." } }, - "ar": { + "ja": { "stringUnit": { "state": "translated", - "value": "شارة Dock" + "value": "これは実効設定の生成プレビューです。ベースの Ghostty 設定ファイルが見つからなかったため、cmux の上書き設定のみを表示しています。" } - }, - "nb": { + } + } + }, + "settings.config.source.cmux": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Dock-merke" + "value": "cmux" } }, - "pt-BR": { + "ja": { "stringUnit": { "state": "translated", - "value": "Emblema do Dock" + "value": "cmux" } - }, - "th": { + } + } + }, + "settings.config.source.label": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "ป้าย Dock" + "value": "Config Source" } }, - "tr": { + "ja": { "stringUnit": { "state": "translated", - "value": "Dock Rozeti" + "value": "構成ソース" + } + } + } + }, + "settings.config.source.synced": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "synced" } }, - "uk": { + "ja": { "stringUnit": { "state": "translated", - "value": "Значок Dock" + "value": "同期" } } } }, - "settings.app.dockBadge.subtitle": { + "settings.config.status.reloaded": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Show unread count on app icon (Dock and Cmd+Tab)." + "value": "Reloaded configuration from disk." } }, "ja": { "stringUnit": { "state": "translated", - "value": "アプリアイコン(DockおよびCmd+Tab)に未読数を表示します。" + "value": "ディスクから構成を再読み込みしました。" } - }, - "zh-Hans": { + } + } + }, + "settings.config.status.openFailed": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "在应用图标上显示未读计数(程序坞和 Cmd+Tab)。" + "value": "Couldn't open the cmux config." } }, - "zh-Hant": { + "ja": { "stringUnit": { "state": "translated", - "value": "在 App 圖示上顯示未讀數量(Dock 和 Cmd+Tab)。" + "value": "cmux 設定を開けませんでした。" } - }, - "ko": { + } + } + }, + "settings.config.status.saveFailed": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "앱 아이콘(Dock 및 Cmd+Tab)에 읽지 않은 수를 표시합니다." + "value": "Couldn't save the cmux config." } }, - "de": { + "ja": { "stringUnit": { "state": "translated", - "value": "Ungelesene Anzahl auf dem App-Symbol anzeigen (Dock und Cmd+Tab)." + "value": "cmux 設定を保存できませんでした。" } - }, - "es": { + } + } + }, + "settings.config.status.saved": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Mostrar el recuento de no leídos en el ícono de la app (Dock y Cmd+Tab)." + "value": "Saved to cmux config and reloaded." } }, - "fr": { + "ja": { "stringUnit": { "state": "translated", - "value": "Afficher le nombre de messages non lus sur l'icône de l'app (Dock et Cmd+Tab)." + "value": "cmux 設定に保存し、再読み込みしました。" } - }, - "it": { + } + } + }, + "settings.config.windowTitle": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Mostra il conteggio non letti sull'icona dell'app (Dock e Cmd+Tab)." + "value": "Config" } }, - "da": { + "ja": { "stringUnit": { "state": "translated", - "value": "Vis antal ulæste på appikonet (Dock og Cmd+Tab)." + "value": "構成" } - }, - "pl": { + } + } + }, + "settings.app.commandPaletteSearchAllSurfaces": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Pokaż liczbę nieprzeczytanych na ikonie aplikacji (Dock i Cmd+Tab)." + "value": "Command Palette Searches All Surfaces" } }, - "ru": { + "ja": { "stringUnit": { "state": "translated", - "value": "Показывать количество непрочитанных на значке приложения (Dock и Cmd+Tab)." + "value": "コマンドパレットですべてのサーフェスを検索" } }, - "bs": { + "uk": { "stringUnit": { "state": "translated", - "value": "Prikaži broj nepročitanih na ikoni aplikacije (Dock i Cmd+Tab)." + "value": "Палітра команд шукає всі поверхні" } }, - "ar": { + "ko": { "stringUnit": { "state": "translated", - "value": "عرض عدد غير المقروء على أيقونة التطبيق (Dock و Cmd+Tab)." + "value": "명령어 팔레트에서 모든 서피스 검색" + } + } + } + }, + "settings.app.commandPaletteSearchAllSurfaces.subtitleOff": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Cmd+P matches workspace rows only." } }, - "nb": { + "ja": { "stringUnit": { "state": "translated", - "value": "Vis antall uleste på appikonet (Dock og Cmd+Tab)." + "value": "Cmd+Pはワークスペース行だけを対象にします。" } }, - "pt-BR": { + "uk": { "stringUnit": { "state": "translated", - "value": "Mostrar contagem de não lidos no ícone do app (Dock e Cmd+Tab)." + "value": "Cmd+P шукає лише рядки робочих областей." } }, - "th": { + "ko": { "stringUnit": { "state": "translated", - "value": "แสดงจำนวนยังไม่อ่านบนไอคอนแอป (Dock และ Cmd+Tab)" + "value": "Cmd+P가 워크스페이스 행만 검색합니다." + } + } + } + }, + "settings.app.commandPaletteSearchAllSurfaces.subtitleOn": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Cmd+P also matches terminal, browser, and markdown surfaces across workspaces." } }, - "tr": { + "ja": { "stringUnit": { "state": "translated", - "value": "Uygulama simgesinde (Dock ve Cmd+Tab) okunmamış sayısını göster." + "value": "Cmd+Pでワークスペースをまたいだターミナル、ブラウザ、Markdownのサーフェスも検索できます。" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Показувати кількість непрочитаних на іконці програми (Dock та Cmd+Tab)." + "value": "Cmd+P також шукає термінали, браузери та markdown-поверхні у всіх робочих областях." + } + }, + "ko": { + "stringUnit": { + "state": "translated", + "value": "Cmd+P가 모든 워크스페이스의 터미널, 브라우저, 마크다운 서피스도 검색합니다." } } } }, - "settings.app.showInMenuBar": { + "settings.app.closeWorkspaceOnLastSurfaceShortcut": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Show in Menu Bar" + "value": "Keep Workspace Open When Closing Last Surface" } }, "ja": { "stringUnit": { "state": "translated", - "value": "メニューバーに表示" + "value": "最後のサーフェスを閉じてもワークスペースを残す" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Показувати в рядку меню" + "value": "Залишати робочу область відкритою при закритті останньої поверхні" } }, "ko": { "stringUnit": { "state": "translated", - "value": "메뉴 막대에 표시" + "value": "마지막 서피스를 닫을 때 워크스페이스 유지" } } } }, - "settings.app.menuBarOnly": { + "settings.app.closeWorkspaceOnLastSurfaceShortcut.subtitleOff": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Menu Bar Only" + "value": "When the focused surface is the last one in its workspace, the close-surface shortcut also closes the workspace." } }, "ja": { "stringUnit": { "state": "translated", - "value": "メニューバーのみ" + "value": "フォーカス中のサーフェスがそのワークスペースの最後の1つなら、サーフェスを閉じるショートカットはワークスペースも閉じます。" } }, - "zh-Hans": { + "uk": { "stringUnit": { "state": "translated", - "value": "仅菜单栏" + "value": "Коли активна поверхня є останньою у робочій області, комбінація закриття поверхні також закриває робочу область." } }, - "zh-Hant": { + "ko": { "stringUnit": { "state": "translated", - "value": "僅選單列" + "value": "포커스된 서피스가 워크스페이스의 마지막일 때, 서피스 닫기 단축키로 워크스페이스도 함께 닫힙니다." } - }, - "ko": { + } + } + }, + "settings.app.closeWorkspaceOnLastSurfaceShortcut.subtitleOn": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "메뉴 막대 전용" + "value": "When the focused surface is the last one in its workspace, the close-surface shortcut closes only the surface and keeps the workspace open. Use the close-workspace shortcut to close the workspace explicitly." } }, - "de": { + "ja": { "stringUnit": { "state": "translated", - "value": "Nur Menüleiste" + "value": "フォーカス中のサーフェスがそのワークスペースの最後の1つでも、サーフェスを閉じるショートカットはサーフェスだけを閉じ、ワークスペースは残します。ワークスペースを閉じるショートカットを使うと明示的に閉じられます。" } }, - "es": { + "uk": { "stringUnit": { "state": "translated", - "value": "Solo barra de menús" + "value": "Коли активна поверхня є останньою у робочій області, комбінація закриття поверхні закриває лише поверхню, залишаючи робочу область відкритою. Використовуйте комбінацію закриття робочої області для явного закриття." } }, - "fr": { + "ko": { "stringUnit": { "state": "translated", - "value": "Barre des menus uniquement" + "value": "포커스된 서피스가 워크스페이스의 마지막일 때, 서피스 닫기 단축키로 서피스만 닫고 워크스페이스는 유지됩니다. 워크스페이스를 닫으려면 워크스페이스 닫기 단축키를 사용하세요." } - }, - "it": { + } + } + }, + "settings.app.paneFirstClickFocus": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Solo barra dei menu" + "value": "Focus Pane on First Click" } }, - "da": { + "ja": { "stringUnit": { "state": "translated", - "value": "Kun menulinje" + "value": "最初のクリックでペインにフォーカス" } }, - "pl": { + "uk": { "stringUnit": { "state": "translated", - "value": "Tylko pasek menu" + "value": "Фокус панелі при першому кліку" } }, - "ru": { + "ko": { "stringUnit": { "state": "translated", - "value": "Только строка меню" + "value": "첫 클릭으로 패인 포커스" } - }, - "bs": { + } + } + }, + "settings.app.paneFirstClickFocus.subtitleOff": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Samo traka menija" + "value": "When cmux is inactive, the first click only activates the window. Click again to focus the pane." } }, - "ar": { + "ja": { "stringUnit": { "state": "translated", - "value": "شريط القائمة فقط" + "value": "cmuxが非アクティブのとき、最初のクリックはウインドウをアクティブにするだけです。ペインにフォーカスするにはもう一度クリックします。" } }, - "nb": { + "uk": { "stringUnit": { "state": "translated", - "value": "Kun menylinje" + "value": "Коли cmux неактивний, перший клік лише активує вікно. Клацніть ще раз, щоб сфокусувати панель." } }, - "pt-BR": { + "ko": { "stringUnit": { "state": "translated", - "value": "Apenas barra de menus" + "value": "cmux가 비활성 상태일 때, 첫 번째 클릭은 윈도우만 활성화합니다. 패인을 포커스하려면 다시 클릭하세요." } - }, - "th": { + } + } + }, + "settings.app.paneFirstClickFocus.subtitleOn": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "เฉพาะแถบเมนู" + "value": "When cmux is inactive, clicking a pane activates the window and focuses that pane in one click." } }, - "tr": { + "ja": { "stringUnit": { "state": "translated", - "value": "Yalnızca menü çubuğu" + "value": "cmuxが非アクティブのとき、ペインをクリックすると1回でウインドウをアクティブにしてそのペインへフォーカスします。" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Лише рядок меню" + "value": "Коли cmux неактивний, клік на панель активує вікно та фокусує панель одним кліком." + } + }, + "ko": { + "stringUnit": { + "state": "translated", + "value": "cmux가 비활성 상태일 때, 패인을 클릭하면 윈도우 활성화와 패인 포커스가 한 번에 이루어집니다." } } } }, - "settings.app.menuBarOnly.subtitle": { + "settings.app.openSidebarPRLinks": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Hide the Dock icon and Cmd+Tab entry. Use the menu bar item to show cmux." + "value": "Open Sidebar PR Links in cmux Browser" } }, "ja": { "stringUnit": { "state": "translated", - "value": "DockアイコンとCmd+Tabの項目を非表示にします。cmuxを表示するにはメニューバー項目を使います。" + "value": "サイドバーのPRリンクをcmuxブラウザで開く" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "隐藏 Dock 图标和 Cmd+Tab 条目。使用菜单栏项目显示 cmux。" + "value": "在 cmux 浏览器中打开侧边栏 PR 链接" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "隱藏 Dock 圖示和 Cmd+Tab 項目。使用選單列項目顯示 cmux。" + "value": "在 cmux 瀏覽器中開啟側邊欄 PR 連結" } }, "ko": { "stringUnit": { "state": "translated", - "value": "Dock 아이콘과 Cmd+Tab 항목을 숨깁니다. 메뉴 막대 항목으로 cmux를 표시합니다." + "value": "사이드바 PR 링크를 cmux 브라우저에서 열기" } }, "de": { "stringUnit": { "state": "translated", - "value": "Blendet das Dock-Symbol und den Cmd+Tab-Eintrag aus. Verwende den Menüleisteneintrag, um cmux anzuzeigen." + "value": "Seitenleisten-PR-Links im cmux-Browser öffnen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Oculta el ícono del Dock y la entrada de Cmd+Tab. Usa el elemento de la barra de menús para mostrar cmux." + "value": "Abrir enlaces de PR de la barra lateral en el navegador de cmux" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Masque l’icône du Dock et l’entrée Cmd+Tab. Utilisez l’élément de barre des menus pour afficher cmux." + "value": "Ouvrir les liens PR de la barre latérale dans le navigateur cmux" } }, "it": { "stringUnit": { "state": "translated", - "value": "Nasconde l'icona del Dock e la voce Cmd+Tab. Usa l'elemento nella barra dei menu per mostrare cmux." + "value": "Apri link PR della barra laterale nel browser cmux" } }, "da": { "stringUnit": { "state": "translated", - "value": "Skjul Dock-symbolet og Cmd+Tab-posten. Brug menulinjeelementet til at vise cmux." + "value": "Åbn sidebjælkens PR-links i cmux-browser" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Ukrywa ikonę Docka i pozycję Cmd+Tab. Użyj elementu na pasku menu, aby pokazać cmux." + "value": "Otwieraj linki PR z paska bocznego w przeglądarce cmux" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Скрывает значок Dock и пункт Cmd+Tab. Используйте пункт строки меню, чтобы показать cmux." + "value": "Открывать ссылки PR боковой панели в браузере cmux" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Sakriva Dock ikonu i Cmd+Tab stavku. Koristi stavku trake menija za prikaz cmux-a." + "value": "Otvori PR linkove iz bočne trake u cmux pregledniku" } }, "ar": { "stringUnit": { "state": "translated", - "value": "يخفي أيقونة Dock وإدخال Cmd+Tab. استخدم عنصر شريط القائمة لإظهار cmux." + "value": "فتح روابط طلبات السحب في متصفح cmux" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Skjuler Dock-symbolet og Cmd+Tab-oppføringen. Bruk menylinjeelementet for å vise cmux." + "value": "Åpne sidepanel-PR-lenker i cmux-nettleser" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Oculta o ícone no Dock e a entrada Cmd+Tab. Use o item da barra de menus para mostrar o cmux." + "value": "Abrir Links de PR da Barra Lateral no Navegador do cmux" } }, "th": { "stringUnit": { "state": "translated", - "value": "ซ่อนไอคอน Dock และรายการ Cmd+Tab ใช้รายการในแถบเมนูเพื่อแสดง cmux" + "value": "เปิดลิงก์ PR ในแถบด้านข้างด้วยเบราว์เซอร์ cmux" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Dock simgesini ve Cmd+Tab girişini gizler. cmux'u göstermek için menü çubuğu öğesini kullan." - } - }, - "uk": { - "stringUnit": { - "state": "translated", - "value": "Приховує іконку Dock і пункт Cmd+Tab. Використовуйте пункт рядка меню, щоб показати cmux." - } - } - } - }, - "settings.app.showInMenuBar.subtitle": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Keep cmux in the menu bar for unread notifications and quick actions." - } - }, - "ja": { - "stringUnit": { - "state": "translated", - "value": "未読通知の確認やクイック操作のために、cmuxをメニューバーに表示します。" + "value": "Kenar Çubuğu PR Bağlantılarını cmux Tarayıcısında Aç" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Залишати cmux у рядку меню для непрочитаних сповіщень та швидких дій." - } - }, - "ko": { - "stringUnit": { - "state": "translated", - "value": "읽지 않은 알림과 빠른 작업을 위해 cmux를 메뉴 막대에 유지합니다." + "value": "Відкривати PR-посилання бічної панелі у браузері cmux" } } } }, - "settings.app.language": { + "settings.app.openSidebarPRLinks.subtitleOff": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Language" + "value": "Clicks open in your default browser." } }, "ja": { "stringUnit": { "state": "translated", - "value": "言語" + "value": "クリックするとデフォルトブラウザで開きます。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "语言" + "value": "点击在默认浏览器中打开。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "語言" + "value": "點擊會在您的預設瀏覽器中開啟。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "언어" + "value": "클릭하면 기본 브라우저에서 열립니다." } }, "de": { "stringUnit": { "state": "translated", - "value": "Sprache" + "value": "Klicks öffnen in Ihrem Standardbrowser." } }, "es": { "stringUnit": { "state": "translated", - "value": "Idioma" + "value": "Los clics abren en tu navegador predeterminado." } }, "fr": { "stringUnit": { "state": "translated", - "value": "Langue" + "value": "Les clics ouvrent dans votre navigateur par défaut." } }, "it": { "stringUnit": { "state": "translated", - "value": "Lingua" + "value": "I clic aprono nel browser predefinito." } }, "da": { "stringUnit": { "state": "translated", - "value": "Sprog" + "value": "Klik åbner i din standardbrowser." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Język" + "value": "Kliknięcia otwierają w domyślnej przeglądarce." } }, "ru": { "stringUnit": { "state": "translated", - "value": "Язык" + "value": "Ссылки открываются в браузере по умолчанию." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Jezik" + "value": "Klikovi se otvaraju u podrazumijevanom pregledniku." } }, "ar": { "stringUnit": { "state": "translated", - "value": "اللغة" + "value": "النقرات تفتح في متصفحك الافتراضي." } }, "nb": { "stringUnit": { "state": "translated", - "value": "Språk" + "value": "Klikk åpner i standard nettleser." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Idioma" + "value": "Cliques abrem no seu navegador padrão." } }, "th": { "stringUnit": { "state": "translated", - "value": "ภาษา" + "value": "คลิกจะเปิดในเบราว์เซอร์เริ่มต้นของคุณ" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Dil" + "value": "Tıklamalar varsayılan tarayıcınızda açılır." } }, "uk": { "stringUnit": { "state": "translated", - "value": "Мова" + "value": "Кліки відкриваються у стандартному браузері." } } } }, - "settings.app.language.restartDialog.confirm": { + "settings.app.openSidebarPRLinks.subtitleOn": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Restart Now" + "value": "Clicks open inside cmux browser." } }, "ja": { "stringUnit": { "state": "translated", - "value": "今すぐ再起動" + "value": "クリックするとcmuxブラウザ内で開きます。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "立即重启" + "value": "点击在 cmux 浏览器中打开。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "立即重新啟動" + "value": "點擊會在 cmux 瀏覽器中開啟。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "지금 재시작" + "value": "클릭하면 cmux 브라우저에서 열립니다." } }, "de": { "stringUnit": { "state": "translated", - "value": "Jetzt neu starten" + "value": "Klicks öffnen im cmux-Browser." } }, "es": { "stringUnit": { "state": "translated", - "value": "Reiniciar ahora" + "value": "Los clics abren dentro del navegador de cmux." } }, "fr": { "stringUnit": { "state": "translated", - "value": "Redémarrer maintenant" + "value": "Les clics ouvrent dans le navigateur cmux." } }, "it": { "stringUnit": { "state": "translated", - "value": "Riavvia ora" + "value": "I clic aprono nel browser cmux." } }, "da": { "stringUnit": { "state": "translated", - "value": "Genstart nu" + "value": "Klik åbner i cmux-browseren." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Uruchom ponownie teraz" + "value": "Kliknięcia otwierają w przeglądarce cmux." } }, "ru": { "stringUnit": { "state": "translated", - "value": "Перезапустить сейчас" + "value": "Ссылки открываются во встроенном браузере cmux." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Ponovo pokreni sada" + "value": "Klikovi se otvaraju unutar cmux preglednika." } }, "ar": { "stringUnit": { "state": "translated", - "value": "إعادة التشغيل الآن" + "value": "النقرات تفتح داخل متصفح cmux." } }, "nb": { "stringUnit": { "state": "translated", - "value": "Start på nytt nå" + "value": "Klikk åpner i cmux-nettleseren." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Reiniciar Agora" + "value": "Cliques abrem dentro do navegador do cmux." } }, "th": { "stringUnit": { "state": "translated", - "value": "รีสตาร์ตเดี๋ยวนี้" + "value": "คลิกจะเปิดในเบราว์เซอร์ cmux" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Şimdi Yeniden Başlat" + "value": "Tıklamalar cmux tarayıcısında açılır." } }, "uk": { "stringUnit": { "state": "translated", - "value": "Перезапустити зараз" + "value": "Кліки відкриваються у браузері cmux." } } } }, - "settings.app.language.restartDialog.later": { + "settings.app.openSidebarPRLinks.subtitleDisabled": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Later" + "value": "Enable sidebar PR clickability to choose where PR links open." } }, "ja": { "stringUnit": { "state": "translated", - "value": "後で" + "value": "PRリンクの開き先を選ぶには、サイドバーのPRクリックを有効にしてください。" + } + } + } + }, + "settings.app.openSidebarPRLinks.subtitleHidden": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Enable sidebar PR visibility to choose where PR links open." + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "PRリンクの開き先を選ぶには、サイドバーのPR表示を有効にしてください。" + } + } + } + }, + "settings.app.openSidebarPortLinks": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Open Sidebar Port Links in cmux Browser" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "サイドバーのポートリンクをcmuxブラウザで開く" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "稍后" + "value": "在 cmux 浏览器中打开侧边栏端口链接" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "稍後" + "value": "在 cmux 瀏覽器中開啟側邊欄連接埠連結" } }, "ko": { "stringUnit": { "state": "translated", - "value": "나중에" + "value": "사이드바 포트 링크를 cmux 브라우저에서 열기" } }, "de": { "stringUnit": { "state": "translated", - "value": "Später" + "value": "Seitenleisten-Port-Links im cmux-Browser öffnen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Más tarde" + "value": "Abrir enlaces de puerto de la barra lateral en el navegador de cmux" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Plus tard" + "value": "Ouvrir les liens de port de la barre latérale dans le navigateur cmux" } }, "it": { "stringUnit": { "state": "translated", - "value": "Più tardi" + "value": "Apri link delle porte della barra laterale nel browser cmux" } }, "da": { "stringUnit": { "state": "translated", - "value": "Senere" + "value": "Åbn sidebjælkens portlinks i cmux-browser" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Później" + "value": "Otwieraj linki portów z paska bocznego w przeglądarce cmux" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Позже" + "value": "Открывать ссылки портов боковой панели в браузере cmux" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Kasnije" + "value": "Otvori port linkove iz bočne trake u cmux pregledniku" } }, "ar": { "stringUnit": { "state": "translated", - "value": "لاحقًا" + "value": "فتح روابط المنافذ في متصفح cmux" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Senere" + "value": "Åpne sidepanel-portlenker i cmux-nettleser" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Depois" + "value": "Abrir Links de Porta da Barra Lateral no Navegador do cmux" } }, "th": { "stringUnit": { "state": "translated", - "value": "ภายหลัง" + "value": "เปิดลิงก์พอร์ตในแถบด้านข้างด้วยเบราว์เซอร์ cmux" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Daha Sonra" + "value": "Kenar Çubuğu Port Bağlantılarını cmux Tarayıcısında Aç" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Пізніше" + "value": "Відкривати посилання портів бічної панелі у браузері cmux" } } } }, - "settings.app.language.restartDialog.title": { + "settings.app.openSidebarPortLinks.subtitleOff": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Restart to apply language change?" + "value": "Port clicks open in your default browser." } }, "ja": { "stringUnit": { "state": "translated", - "value": "言語変更を適用するために再起動しますか?" + "value": "ポートをクリックするとデフォルトブラウザで開きます。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "重启以应用语言更改?" + "value": "端口点击在默认浏览器中打开。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "要重新啟動以套用語言變更嗎?" + "value": "連接埠點擊會在您的預設瀏覽器中開啟。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "언어 변경을 적용하려면 재시작하시겠습니까?" + "value": "포트를 클릭하면 기본 브라우저에서 열립니다." } }, "de": { "stringUnit": { "state": "translated", - "value": "Neu starten, um Sprachänderung zu übernehmen?" + "value": "Port-Klicks öffnen in Ihrem Standardbrowser." } }, "es": { "stringUnit": { "state": "translated", - "value": "¿Reiniciar para aplicar el cambio de idioma?" + "value": "Los clics en puertos abren en tu navegador predeterminado." } }, "fr": { "stringUnit": { "state": "translated", - "value": "Redémarrer pour appliquer le changement de langue ?" + "value": "Les clics de port ouvrent dans votre navigateur par défaut." } }, "it": { "stringUnit": { "state": "translated", - "value": "Riavviare per applicare il cambio di lingua?" + "value": "I clic sulle porte aprono nel browser predefinito." } }, "da": { "stringUnit": { "state": "translated", - "value": "Genstart for at anvende sprogændring?" + "value": "Portklik åbner i din standardbrowser." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Uruchomić ponownie, aby zastosować zmianę języka?" + "value": "Kliknięcia portów otwierają w domyślnej przeglądarce." } }, "ru": { "stringUnit": { "state": "translated", - "value": "Перезапустить для применения языка?" + "value": "Ссылки портов открываются в браузере по умолчанию." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Ponovo pokrenuti za primjenu promjene jezika?" + "value": "Klikovi na portove se otvaraju u podrazumijevanom pregledniku." } }, "ar": { "stringUnit": { "state": "translated", - "value": "إعادة التشغيل لتطبيق تغيير اللغة؟" + "value": "نقرات المنافذ تفتح في متصفحك الافتراضي." } }, "nb": { "stringUnit": { "state": "translated", - "value": "Starte på nytt for å endre språk?" + "value": "Portklikk åpner i standard nettleser." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Reiniciar para aplicar a mudança de idioma?" + "value": "Cliques em portas abrem no seu navegador padrão." } }, "th": { "stringUnit": { "state": "translated", - "value": "รีสตาร์ตเพื่อเปลี่ยนภาษาหรือไม่?" + "value": "คลิกพอร์ตจะเปิดในเบราว์เซอร์เริ่มต้นของคุณ" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Dil değişikliğini uygulamak için yeniden başlatılsın mı?" + "value": "Port tıklamaları varsayılan tarayıcınızda açılır." } }, "uk": { "stringUnit": { "state": "translated", - "value": "Перезапустити для застосування зміни мови?" + "value": "Кліки по портах відкриваються у стандартному браузері." } } } }, - "settings.app.language.restartSubtitle": { + "settings.app.openSidebarPortLinks.subtitleOn": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Restart cmux to apply" + "value": "Port clicks open inside cmux browser." } }, "ja": { "stringUnit": { "state": "translated", - "value": "cmuxを再起動して適用" + "value": "ポートをクリックするとcmuxブラウザ内で開きます。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "重启 cmux 以应用" + "value": "端口点击在 cmux 浏览器中打开。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "重新啟動 cmux 以套用" + "value": "連接埠點擊會在 cmux 瀏覽器中開啟。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "적용하려면 cmux를 재시작하세요" + "value": "포트를 클릭하면 cmux 브라우저에서 열립니다." } }, "de": { "stringUnit": { "state": "translated", - "value": "cmux neu starten, um Änderung zu übernehmen" + "value": "Port-Klicks öffnen im cmux-Browser." } }, "es": { "stringUnit": { "state": "translated", - "value": "Reinicia cmux para aplicar" + "value": "Los clics en puertos abren dentro del navegador de cmux." } }, "fr": { "stringUnit": { "state": "translated", - "value": "Redémarrez cmux pour appliquer" + "value": "Les clics de port ouvrent dans le navigateur cmux." } }, "it": { "stringUnit": { "state": "translated", - "value": "Riavvia cmux per applicare" + "value": "I clic sulle porte aprono nel browser cmux." } }, "da": { "stringUnit": { "state": "translated", - "value": "Genstart cmux for at anvende" + "value": "Portklik åbner i cmux-browseren." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Uruchom ponownie cmux, aby zastosować" + "value": "Kliknięcia portów otwierają w przeglądarce cmux." } }, "ru": { "stringUnit": { "state": "translated", - "value": "Перезапустите cmux для применения" + "value": "Ссылки портов открываются во встроенном браузере cmux." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Ponovo pokrenite cmux za primjenu" + "value": "Klikovi na portove se otvaraju unutar cmux preglednika." } }, "ar": { "stringUnit": { "state": "translated", - "value": "أعد تشغيل cmux للتطبيق" + "value": "نقرات المنافذ تفتح داخل متصفح cmux." } }, "nb": { "stringUnit": { "state": "translated", - "value": "Start cmux på nytt for å bruke" + "value": "Portklikk åpner i cmux-nettleseren." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Reinicie o cmux para aplicar" + "value": "Cliques em portas abrem dentro do navegador do cmux." } }, "th": { "stringUnit": { "state": "translated", - "value": "รีสตาร์ต cmux เพื่อนำไปใช้" + "value": "คลิกพอร์ตจะเปิดในเบราว์เซอร์ cmux" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Uygulamak için cmux'u yeniden başlatın" + "value": "Port tıklamaları cmux tarayıcısında açılır." } }, "uk": { "stringUnit": { "state": "translated", - "value": "Перезапустіть cmux для застосування" + "value": "Кліки по портах відкриваються у браузері cmux." } } } }, - "settings.app.newWorkspacePlacement": { + "settings.app.hideAllSidebarDetails": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "New Workspace Placement" + "value": "Hide All Sidebar Details" } }, "ja": { "stringUnit": { "state": "translated", - "value": "新規ワークスペースの配置" - } - }, - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "新工作区位置" + "value": "サイドバーの詳細をすべて隠す" } }, - "zh-Hant": { + "uk": { "stringUnit": { "state": "translated", - "value": "新工作區位置" + "value": "Сховати всі деталі бічної панелі" } }, "ko": { "stringUnit": { "state": "translated", - "value": "새 작업 공간 위치" - } - }, - "de": { - "stringUnit": { - "state": "translated", - "value": "Platzierung neuer Arbeitsbereiche" - } - }, - "es": { - "stringUnit": { - "state": "translated", - "value": "Ubicación de nuevo espacio de trabajo" - } - }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "Emplacement des nouveaux espaces de travail" - } - }, - "it": { - "stringUnit": { - "state": "translated", - "value": "Posizionamento nuova area di lavoro" - } - }, - "da": { - "stringUnit": { - "state": "translated", - "value": "Placering af nyt arbejdsområde" - } - }, - "pl": { - "stringUnit": { - "state": "translated", - "value": "Umieszczenie nowej przestrzeni roboczej" + "value": "사이드바 세부 정보 모두 숨기기" } - }, - "ru": { + } + } + }, + "settings.app.hideAllSidebarDetails.subtitleOff": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Расположение нового рабочего пространства" + "value": "Show secondary workspace details as controlled by the toggles below." } }, - "bs": { + "ja": { "stringUnit": { "state": "translated", - "value": "Pozicija novog radnog prostora" + "value": "下のトグル設定に従って、ワークスペースの補助情報を表示します。" } }, - "ar": { + "uk": { "stringUnit": { "state": "translated", - "value": "موضع مساحة العمل الجديدة" + "value": "Показувати додаткові деталі робочої області відповідно до перемикачів нижче." } }, - "nb": { + "ko": { "stringUnit": { "state": "translated", - "value": "Plassering av nytt arbeidsområde" + "value": "아래 토글에 따라 보조 워크스페이스 세부 정보를 표시합니다." } - }, - "pt-BR": { + } + } + }, + "settings.app.hideAllSidebarDetails.subtitleOn": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Posição da Nova Área de Trabalho" + "value": "Show only the workspace title row. Overrides the detail toggles below." } }, - "th": { + "ja": { "stringUnit": { "state": "translated", - "value": "ตำแหน่งเวิร์กสเปซใหม่" + "value": "ワークスペースのタイトル行だけを表示します。下の詳細トグルより優先されます。" } }, - "tr": { + "uk": { "stringUnit": { "state": "translated", - "value": "Yeni Çalışma Alanı Konumu" + "value": "Показувати лише рядок заголовка робочої області. Замінює перемикачі деталей нижче." } }, - "uk": { + "ko": { "stringUnit": { "state": "translated", - "value": "Розташування нової робочої області" + "value": "워크스페이스 제목 행만 표시합니다. 아래 세부 정보 토글보다 우선합니다." } } } }, - "settings.app.workspaceInheritWorkingDirectory": { + "settings.app.showWorkspaceDescription": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Inherit Workspace Working Directory" + "value": "Show Workspace Description in Sidebar" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ワークスペースの作業ディレクトリを継承" + "value": "サイドバーにワークスペースの説明を表示" } } } }, - "settings.app.workspaceInheritWorkingDirectory.subtitleOff": { + "settings.app.showWorkspaceDescription.subtitle": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "New workspaces leave their working directory unset so Ghostty's working-directory setting can apply." + "value": "Display custom workspace descriptions below the workspace title." } }, "ja": { "stringUnit": { "state": "translated", - "value": "新規ワークスペースの作業ディレクトリを未設定にして、Ghostty の working-directory 設定を適用します。" + "value": "ワークスペース名の下にカスタム説明を表示します。" } } } }, - "settings.app.workspaceInheritWorkingDirectory.subtitleOn": { + "settings.app.renameSelectsName": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "New workspaces start in the focused workspace's working directory." + "value": "Rename Selects Existing Name" } }, "ja": { "stringUnit": { "state": "translated", - "value": "新規ワークスペースはフォーカス中のワークスペースの作業ディレクトリで開始します。" + "value": "名称変更時に既存の名前を選択" } - } - } - }, - "settings.app.settingsFile.openButton": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "zh-Hans": { "stringUnit": { "state": "translated", - "value": "Open cmux.json" + "value": "重命名时选中现有名称" } }, - "ja": { + "zh-Hant": { "stringUnit": { "state": "translated", - "value": "cmux.jsonを開く" + "value": "重新命名時選取現有名稱" } }, "ko": { "stringUnit": { "state": "translated", - "value": "cmux.json 열기" + "value": "이름 변경 시 기존 이름 선택" } - } - } - }, - "settings.settingsJSON.docsButton": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "de": { "stringUnit": { "state": "translated", - "value": "Open Docs" + "value": "Umbenennen wählt vorhandenen Namen aus" } }, - "ja": { + "es": { "stringUnit": { "state": "translated", - "value": "ドキュメントを開く" + "value": "Renombrar selecciona el nombre existente" } }, - "ko": { + "fr": { "stringUnit": { "state": "translated", - "value": "문서 열기" + "value": "Le renommage sélectionne le nom existant" } - } - } - }, - "settings.settingsJSON.documentation": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "it": { "stringUnit": { "state": "translated", - "value": "Documentation" + "value": "Rinomina seleziona il nome esistente" } }, - "ja": { + "da": { "stringUnit": { "state": "translated", - "value": "ドキュメント" + "value": "Omdøbning markerer eksisterende navn" } }, - "ko": { + "pl": { "stringUnit": { "state": "translated", - "value": "문서" + "value": "Zmiana nazwy zaznacza istniejącą nazwę" } - } - } - }, - "settings.settingsJSON.documentation.subtitle": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "ru": { "stringUnit": { "state": "translated", - "value": "View supported keys, file locations, schema, and reload behavior." + "value": "Переименование выделяет имя" } }, - "ja": { + "bs": { "stringUnit": { "state": "translated", - "value": "サポートされているキー、ファイルの場所、スキーマ、再読み込み方法を確認します。" + "value": "Preimenovanje odabere postojeći naziv" } }, - "ko": { + "ar": { "stringUnit": { "state": "translated", - "value": "지원되는 키, 파일 위치, 스키마, 다시 불러오기 동작을 확인합니다." + "value": "إعادة التسمية تحدد الاسم الحالي" } - } - } - }, - "settings.settingsJSON.file": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "nb": { "stringUnit": { "state": "translated", - "value": "User config file" + "value": "Omdøping velger eksisterende navn" } }, - "ja": { + "pt-BR": { "stringUnit": { "state": "translated", - "value": "ユーザー設定ファイル" + "value": "Renomear Seleciona o Nome Existente" } }, - "ko": { + "th": { "stringUnit": { "state": "translated", - "value": "사용자 설정 파일" + "value": "เลือกชื่อเมื่อเปลี่ยนชื่อ" + } + }, + "tr": { + "stringUnit": { + "state": "translated", + "value": "Yeniden Adlandırma Mevcut Adı Seçer" + } + }, + "uk": { + "stringUnit": { + "state": "translated", + "value": "Виділяти назву при перейменуванні" } } } }, - "settings.settingsJSON.file.subtitle": { + "settings.app.renameSelectsName.subtitleOff": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Edit cmux-owned app settings, shortcuts, automation, sidebar, notifications, and browser behavior." + "value": "Command Palette rename keeps the caret at the end." } }, "ja": { "stringUnit": { "state": "translated", - "value": "cmux 管理のアプリ設定、ショートカット、オートメーション、サイドバー、通知、ブラウザ動作を編集します。" + "value": "コマンドパレットの名称変更ではキャレットが末尾に置かれます。" } }, - "ko": { - "stringUnit": { - "state": "translated", - "value": "cmux가 관리하는 앱 설정, 단축키, 자동화, 사이드바, 알림, 브라우저 동작을 편집합니다." - } - } - } - }, - "settings.settingsJSON.openButton": { - "extractionState": "manual", - "localizations": { - "en": { + "zh-Hans": { "stringUnit": { "state": "translated", - "value": "Open" + "value": "命令面板重命名时光标保持在末尾。" } }, - "ja": { + "zh-Hant": { "stringUnit": { "state": "translated", - "value": "開く" + "value": "指令面板重新命名時,游標保持在結尾。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "열기" - } - } - } - }, - "settings.settingsJSON.openFile": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Open cmux.json" + "value": "명령어 팔레트의 이름 변경 시 커서가 끝에 위치합니다." } }, - "ja": { + "de": { "stringUnit": { "state": "translated", - "value": "cmux.jsonを開く" + "value": "Beim Umbenennen in der Befehlspalette bleibt der Cursor am Ende." } }, - "ko": { + "es": { "stringUnit": { "state": "translated", - "value": "cmux.json 열기" + "value": "Renombrar en la paleta de comandos mantiene el cursor al final." } - } - } - }, - "settings.app.configWindow": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "fr": { "stringUnit": { "state": "translated", - "value": "Terminal Config" + "value": "Le renommage via la palette de commandes maintient le curseur à la fin." } }, - "ja": { + "it": { "stringUnit": { "state": "translated", - "value": "ターミナル設定" + "value": "La rinomina nella Tavolozza comandi mantiene il cursore alla fine." } - } - } - }, - "settings.app.configWindow.openButton": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "da": { "stringUnit": { "state": "translated", - "value": "Open Config" + "value": "Omdøbning i kommandopaletten beholder markøren til sidst." } }, - "ja": { + "pl": { "stringUnit": { "state": "translated", - "value": "設定を開く" + "value": "Zmiana nazwy w palecie poleceń pozostawia kursor na końcu." } - } - } - }, - "settings.app.configWindow.subtitle": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "ru": { "stringUnit": { "state": "translated", - "value": "Open the cmux terminal config and generated preview in one utility window." + "value": "Переименование в палитре команд оставляет курсор в конце." } }, - "ja": { + "bs": { "stringUnit": { "state": "translated", - "value": "cmux の端末設定と生成プレビューを 1 つのユーティリティウインドウで開きます。" + "value": "Preimenovanje u paleti naredbi zadržava kursor na kraju." } - } - } - }, - "settings.config.action.openEditor": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "ar": { "stringUnit": { "state": "translated", - "value": "Open in Editor…" + "value": "إعادة التسمية في لوحة الأوامر تبقي المؤشر في النهاية." } }, - "ja": { + "nb": { "stringUnit": { "state": "translated", - "value": "エディタで開く…" + "value": "Omdøping i kommandopaletten beholder markøren på slutten." } - } - } - }, - "settings.config.action.openActiveEditor": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "pt-BR": { "stringUnit": { "state": "translated", - "value": "Open Active Config…" + "value": "A renomeação na Paleta de Comandos mantém o cursor no final." } }, - "ja": { + "th": { "stringUnit": { "state": "translated", - "value": "有効な設定を開く…" + "value": "การเปลี่ยนชื่อในแถบคำสั่งจะเก็บเคอร์เซอร์ไว้ที่ท้าย" } - } - } - }, - "settings.config.action.reload": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "tr": { "stringUnit": { "state": "translated", - "value": "Reload" + "value": "Komut Paleti yeniden adlandırması imleci sonda tutar." } }, - "ja": { + "uk": { "stringUnit": { "state": "translated", - "value": "再読み込み" + "value": "Перейменування в палітрі команд залишає курсор в кінці." } } } }, - "settings.config.action.revealFinder": { + "settings.app.renameSelectsName.subtitleOn": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Reveal in Finder" + "value": "Command Palette rename starts with all text selected." } }, "ja": { "stringUnit": { "state": "translated", - "value": "Finderで表示" - } - } - } - }, - "settings.config.action.revealActiveFinder": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Reveal Active Config in Finder" + "value": "コマンドパレットの名称変更ではテキスト全体が選択された状態で始まります。" } }, - "ja": { + "zh-Hans": { "stringUnit": { "state": "translated", - "value": "有効な設定をFinderで表示" + "value": "命令面板重命名时全选文本。" } - } - } - }, - "settings.config.action.save": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "zh-Hant": { "stringUnit": { "state": "translated", - "value": "Save" + "value": "指令面板重新命名時,會先選取所有文字。" } }, - "ja": { + "ko": { "stringUnit": { "state": "translated", - "value": "保存" + "value": "명령어 팔레트의 이름 변경 시 전체 텍스트가 선택됩니다." } - } - } - }, - "settings.config.banner.cmux": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "de": { "stringUnit": { "state": "translated", - "value": "This is the cmux Ghostty config selected for this build. Edit it here, then Save to reload cmux." + "value": "Beim Umbenennen in der Befehlspalette wird der gesamte Text ausgewählt." } }, - "ja": { + "es": { "stringUnit": { "state": "translated", - "value": "これはこのビルドで選択されている cmux Ghostty 設定です。ここで編集し、保存すると cmux が再読み込みされます。" + "value": "Renombrar en la paleta de comandos inicia con todo el texto seleccionado." } - } - } - }, - "settings.config.banner.synced": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "fr": { "stringUnit": { "state": "translated", - "value": "This is a generated preview of the effective config. Edit the cmux tab to change what cmux reads." + "value": "Le renommage via la palette de commandes commence avec tout le texte sélectionné." } }, - "ja": { + "it": { "stringUnit": { "state": "translated", - "value": "これは実効設定の生成プレビューです。cmux が読み込む内容を変更するには cmux タブを編集してください。" + "value": "La rinomina nella Tavolozza comandi inizia con tutto il testo selezionato." } - } - } - }, - "settings.config.banner.syncedNoGhostty": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "da": { "stringUnit": { "state": "translated", - "value": "This is a generated preview of the effective config. No base Ghostty config file was found, so only cmux overrides are shown." + "value": "Omdøbning i kommandopaletten starter med al tekst markeret." } }, - "ja": { + "pl": { "stringUnit": { "state": "translated", - "value": "これは実効設定の生成プレビューです。ベースの Ghostty 設定ファイルが見つからなかったため、cmux の上書き設定のみを表示しています。" + "value": "Zmiana nazwy w palecie poleceń rozpoczyna z zaznaczonym całym tekstem." } - } - } - }, - "settings.config.source.cmux": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "ru": { "stringUnit": { "state": "translated", - "value": "cmux" + "value": "Переименование в палитре команд начинается с выделения всего текста." } }, - "ja": { + "bs": { "stringUnit": { "state": "translated", - "value": "cmux" + "value": "Preimenovanje u paleti naredbi počinje sa svim odabranim tekstom." } - } - } - }, - "settings.config.source.label": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "ar": { "stringUnit": { "state": "translated", - "value": "Config Source" + "value": "إعادة التسمية في لوحة الأوامر تبدأ بتحديد كل النص." } }, - "ja": { + "nb": { "stringUnit": { "state": "translated", - "value": "構成ソース" + "value": "Omdøping i kommandopaletten starter med all tekst valgt." } - } - } - }, - "settings.config.source.synced": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "pt-BR": { "stringUnit": { "state": "translated", - "value": "synced" + "value": "A renomeação na Paleta de Comandos começa com todo o texto selecionado." } }, - "ja": { + "th": { "stringUnit": { "state": "translated", - "value": "同期" + "value": "การเปลี่ยนชื่อในแถบคำสั่งจะเลือกข้อความทั้งหมด" } - } - } - }, - "settings.config.status.reloaded": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "tr": { "stringUnit": { "state": "translated", - "value": "Reloaded configuration from disk." + "value": "Komut Paleti yeniden adlandırması tüm metin seçili olarak başlar." } }, - "ja": { + "uk": { "stringUnit": { "state": "translated", - "value": "ディスクから構成を再読み込みしました。" + "value": "Перейменування в палітрі команд починає з виділення всього тексту." } } } }, - "settings.config.status.openFailed": { + "settings.app.iMessageMode": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Couldn't open the cmux config." + "value": "iMessage Mode" } }, "ja": { "stringUnit": { "state": "translated", - "value": "cmux 設定を開けませんでした。" + "value": "iMessageモード" } } } }, - "settings.config.status.saveFailed": { + "settings.app.iMessageMode.subtitle": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Couldn't save the cmux config." + "value": "Move a workspace to the top and show the submitted message when you send an agent prompt." } }, "ja": { "stringUnit": { "state": "translated", - "value": "cmux 設定を保存できませんでした。" + "value": "エージェントのプロンプトを送信したときにワークスペースを一番上へ移動し、送信したメッセージを表示します。" } } } }, - "settings.config.status.saved": { + "settings.app.reorderOnNotification": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Saved to cmux config and reloaded." + "value": "Reorder on Notification" } }, "ja": { "stringUnit": { "state": "translated", - "value": "cmux 設定に保存し、再読み込みしました。" - } - } - } - }, - "settings.config.windowTitle": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Config" + "value": "通知時に並べ替え" } }, - "ja": { + "zh-Hans": { "stringUnit": { "state": "translated", - "value": "構成" + "value": "收到通知时重新排序" } - } - } - }, - "settings.app.commandPaletteSearchAllSurfaces": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "zh-Hant": { "stringUnit": { "state": "translated", - "value": "Command Palette Searches All Surfaces" + "value": "收到通知時重新排序" } }, - "ja": { + "ko": { "stringUnit": { "state": "translated", - "value": "コマンドパレットですべてのサーフェスを検索" + "value": "알림 시 순서 변경" } }, - "uk": { + "de": { "stringUnit": { "state": "translated", - "value": "Палітра команд шукає всі поверхні" + "value": "Bei Benachrichtigung neu sortieren" } }, - "ko": { + "es": { "stringUnit": { "state": "translated", - "value": "명령어 팔레트에서 모든 서피스 검색" + "value": "Reordenar al recibir notificación" } - } - } - }, - "settings.app.commandPaletteSearchAllSurfaces.subtitleOff": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "fr": { "stringUnit": { "state": "translated", - "value": "Cmd+P matches workspace rows only." + "value": "Réordonner à la notification" } }, - "ja": { + "it": { "stringUnit": { "state": "translated", - "value": "Cmd+Pはワークスペース行だけを対象にします。" + "value": "Riordina alla notifica" } }, - "uk": { + "da": { "stringUnit": { "state": "translated", - "value": "Cmd+P шукає лише рядки робочих областей." + "value": "Omarranger ved notifikation" } }, - "ko": { + "pl": { "stringUnit": { "state": "translated", - "value": "Cmd+P가 워크스페이스 행만 검색합니다." + "value": "Zmiana kolejności przy powiadomieniu" } - } - } - }, - "settings.app.commandPaletteSearchAllSurfaces.subtitleOn": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "ru": { "stringUnit": { "state": "translated", - "value": "Cmd+P also matches terminal, browser, and markdown surfaces across workspaces." + "value": "Перемещение при уведомлении" } }, - "ja": { + "bs": { "stringUnit": { "state": "translated", - "value": "Cmd+Pでワークスペースをまたいだターミナル、ブラウザ、Markdownのサーフェスも検索できます。" + "value": "Prerasporedi pri obavještenju" } }, - "uk": { + "ar": { "stringUnit": { "state": "translated", - "value": "Cmd+P також шукає термінали, браузери та markdown-поверхні у всіх робочих областях." + "value": "إعادة الترتيب عند الإشعار" } }, - "ko": { + "nb": { "stringUnit": { "state": "translated", - "value": "Cmd+P가 모든 워크스페이스의 터미널, 브라우저, 마크다운 서피스도 검색합니다." + "value": "Omorganiser ved varsel" } - } - } - }, - "settings.app.closeWorkspaceOnLastSurfaceShortcut": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "pt-BR": { "stringUnit": { "state": "translated", - "value": "Keep Workspace Open When Closing Last Surface" + "value": "Reordenar ao Receber Notificação" } }, - "ja": { + "th": { "stringUnit": { "state": "translated", - "value": "最後のサーフェスを閉じてもワークスペースを残す" + "value": "จัดเรียงใหม่เมื่อมีการแจ้งเตือน" } }, - "uk": { + "tr": { "stringUnit": { "state": "translated", - "value": "Залишати робочу область відкритою при закритті останньої поверхні" + "value": "Bildirimde Yeniden Sırala" } }, - "ko": { + "uk": { "stringUnit": { "state": "translated", - "value": "마지막 서피스를 닫을 때 워크스페이스 유지" + "value": "Переміщення при сповіщенні" } } } }, - "settings.app.closeWorkspaceOnLastSurfaceShortcut.subtitleOff": { + "settings.app.reorderOnNotification.subtitle": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "When the focused surface is the last one in its workspace, the close-surface shortcut also closes the workspace." + "value": "Move workspaces to the top when they receive a notification. Disable for stable shortcut positions." } }, "ja": { "stringUnit": { "state": "translated", - "value": "フォーカス中のサーフェスがそのワークスペースの最後の1つなら、サーフェスを閉じるショートカットはワークスペースも閉じます。" + "value": "通知を受け取ったワークスペースを一番上に移動します。ショートカット位置を固定するには無効にしてください。" } }, - "uk": { + "zh-Hans": { "stringUnit": { "state": "translated", - "value": "Коли активна поверхня є останньою у робочій області, комбінація закриття поверхні також закриває робочу область." + "value": "收到通知时将工作区移至顶部。禁用以保持快捷键位置稳定。" } }, - "ko": { - "stringUnit": { - "state": "translated", - "value": "포커스된 서피스가 워크스페이스의 마지막일 때, 서피스 닫기 단축키로 워크스페이스도 함께 닫힙니다." - } - } - } - }, - "settings.app.closeWorkspaceOnLastSurfaceShortcut.subtitleOn": { - "extractionState": "manual", - "localizations": { - "en": { + "zh-Hant": { "stringUnit": { "state": "translated", - "value": "When the focused surface is the last one in its workspace, the close-surface shortcut closes only the surface and keeps the workspace open. Use the close-workspace shortcut to close the workspace explicitly." + "value": "收到通知時將工作區移至最上方。停用此選項可維持穩定的快捷鍵位置。" } }, - "ja": { + "ko": { "stringUnit": { "state": "translated", - "value": "フォーカス中のサーフェスがそのワークスペースの最後の1つでも、サーフェスを閉じるショートカットはサーフェスだけを閉じ、ワークスペースは残します。ワークスペースを閉じるショートカットを使うと明示的に閉じられます。" + "value": "알림을 받은 작업 공간을 맨 위로 이동합니다. 단축키 위치를 고정하려면 비활성화하세요." } }, - "uk": { + "de": { "stringUnit": { "state": "translated", - "value": "Коли активна поверхня є останньою у робочій області, комбінація закриття поверхні закриває лише поверхню, залишаючи робочу область відкритою. Використовуйте комбінацію закриття робочої області для явного закриття." + "value": "Arbeitsbereiche nach oben verschieben, wenn sie eine Benachrichtigung erhalten. Deaktivieren Sie dies für stabile Tastenkürzel-Positionen." } }, - "ko": { + "es": { "stringUnit": { "state": "translated", - "value": "포커스된 서피스가 워크스페이스의 마지막일 때, 서피스 닫기 단축키로 서피스만 닫고 워크스페이스는 유지됩니다. 워크스페이스를 닫으려면 워크스페이스 닫기 단축키를 사용하세요." + "value": "Mover espacios de trabajo al inicio cuando reciben una notificación. Desactiva para posiciones de atajo estables." } - } - } - }, - "settings.app.paneFirstClickFocus": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "fr": { "stringUnit": { "state": "translated", - "value": "Focus Pane on First Click" + "value": "Déplacer les espaces de travail en haut lorsqu'ils reçoivent une notification. Désactivez pour des positions de raccourcis stables." } }, - "ja": { + "it": { "stringUnit": { "state": "translated", - "value": "最初のクリックでペインにフォーカス" + "value": "Sposta le aree di lavoro in cima quando ricevono una notifica. Disabilita per posizioni di scorciatoia stabili." } }, - "uk": { + "da": { "stringUnit": { "state": "translated", - "value": "Фокус панелі при першому кліку" + "value": "Flyt arbejdsområder til toppen, når de modtager en notifikation. Deaktiver for stabile genvejspositioner." } }, - "ko": { + "pl": { "stringUnit": { "state": "translated", - "value": "첫 클릭으로 패인 포커스" + "value": "Przenoś przestrzenie robocze na górę, gdy otrzymają powiadomienie. Wyłącz, aby zachować stałe pozycje skrótów." } - } - } - }, - "settings.app.paneFirstClickFocus.subtitleOff": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "ru": { "stringUnit": { "state": "translated", - "value": "When cmux is inactive, the first click only activates the window. Click again to focus the pane." + "value": "Перемещать рабочие пространства наверх при получении уведомления. Отключите для стабильных позиций сочетаний клавиш." } }, - "ja": { + "bs": { "stringUnit": { "state": "translated", - "value": "cmuxが非アクティブのとき、最初のクリックはウインドウをアクティブにするだけです。ペインにフォーカスするにはもう一度クリックします。" + "value": "Pomjeri radne prostore na vrh kada prime obavještenje. Onemogućite za stabilne pozicije prečica." } }, - "uk": { + "ar": { "stringUnit": { "state": "translated", - "value": "Коли cmux неактивний, перший клік лише активує вікно. Клацніть ще раз, щоб сфокусувати панель." + "value": "نقل مساحات العمل إلى الأعلى عند تلقي إشعار. قم بالتعطيل للحفاظ على مواضع الاختصارات الثابتة." } }, - "ko": { + "nb": { "stringUnit": { "state": "translated", - "value": "cmux가 비활성 상태일 때, 첫 번째 클릭은 윈도우만 활성화합니다. 패인을 포커스하려면 다시 클릭하세요." + "value": "Flytt arbeidsområder til toppen når de mottar et varsel. Deaktiver for stabile snarveiposisjoner." } - } - } - }, - "settings.app.paneFirstClickFocus.subtitleOn": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "pt-BR": { "stringUnit": { "state": "translated", - "value": "When cmux is inactive, clicking a pane activates the window and focuses that pane in one click." + "value": "Move áreas de trabalho para o topo ao receber uma notificação. Desative para posições de atalho estáveis." } }, - "ja": { + "th": { "stringUnit": { "state": "translated", - "value": "cmuxが非アクティブのとき、ペインをクリックすると1回でウインドウをアクティブにしてそのペインへフォーカスします。" + "value": "ย้ายเวิร์กสเปซไปด้านบนเมื่อได้รับการแจ้งเตือน ปิดใช้งานเพื่อให้ตำแหน่งทางลัดคงที่" } }, - "uk": { + "tr": { "stringUnit": { "state": "translated", - "value": "Коли cmux неактивний, клік на панель активує вікно та фокусує панель одним кліком." + "value": "Bildirim aldıklarında çalışma alanlarını en üste taşı. Sabit kısayol konumları için devre dışı bırakın." } }, - "ko": { + "uk": { "stringUnit": { "state": "translated", - "value": "cmux가 비활성 상태일 때, 패인을 클릭하면 윈도우 활성화와 패인 포커스가 한 번에 이루어집니다." + "value": "Переміщувати робочі області нагору при отриманні сповіщення. Вимкніть для стабільних позицій комбінацій клавіш." } } } }, - "settings.app.openSidebarPRLinks": { + "settings.app.showBranchDirectory": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Open Sidebar PR Links in cmux Browser" + "value": "Show Branch + Directory in Sidebar" } }, "ja": { "stringUnit": { "state": "translated", - "value": "サイドバーのPRリンクをcmuxブラウザで開く" + "value": "サイドバーにブランチ+ディレクトリを表示" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "在 cmux 浏览器中打开侧边栏 PR 链接" + "value": "在侧边栏显示分支和目录" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "在 cmux 瀏覽器中開啟側邊欄 PR 連結" + "value": "在側邊欄顯示分支與目錄" } }, "ko": { "stringUnit": { "state": "translated", - "value": "사이드바 PR 링크를 cmux 브라우저에서 열기" + "value": "사이드바에 브랜치 + 디렉토리 표시" } }, "de": { "stringUnit": { "state": "translated", - "value": "Seitenleisten-PR-Links im cmux-Browser öffnen" + "value": "Branch + Verzeichnis in Seitenleiste anzeigen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Abrir enlaces de PR de la barra lateral en el navegador de cmux" + "value": "Mostrar rama + directorio en la barra lateral" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Ouvrir les liens PR de la barre latérale dans le navigateur cmux" + "value": "Afficher la branche et le répertoire dans la barre latérale" } }, "it": { "stringUnit": { "state": "translated", - "value": "Apri link PR della barra laterale nel browser cmux" + "value": "Mostra branch e directory nella barra laterale" } }, "da": { "stringUnit": { "state": "translated", - "value": "Åbn sidebjælkens PR-links i cmux-browser" + "value": "Vis gren + mappe i sidebjælke" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Otwieraj linki PR z paska bocznego w przeglądarce cmux" + "value": "Pokaż gałąź + katalog na pasku bocznym" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Открывать ссылки PR боковой панели в браузере cmux" + "value": "Показывать ветку и каталог в боковой панели" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Otvori PR linkove iz bočne trake u cmux pregledniku" + "value": "Prikaži granu i direktorij u bočnoj traci" } }, "ar": { "stringUnit": { "state": "translated", - "value": "فتح روابط طلبات السحب في متصفح cmux" + "value": "عرض الفرع والدليل في الشريط الجانبي" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Åpne sidepanel-PR-lenker i cmux-nettleser" + "value": "Vis gren + katalog i sidepanelet" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Abrir Links de PR da Barra Lateral no Navegador do cmux" + "value": "Mostrar Branch + Diretório na Barra Lateral" } }, "th": { "stringUnit": { "state": "translated", - "value": "เปิดลิงก์ PR ในแถบด้านข้างด้วยเบราว์เซอร์ cmux" + "value": "แสดงสาขา + ไดเรกทอรีในแถบด้านข้าง" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Kenar Çubuğu PR Bağlantılarını cmux Tarayıcısında Aç" + "value": "Kenar Çubuğunda Dal + Dizin Göster" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Відкривати PR-посилання бічної панелі у браузері cmux" + "value": "Показувати гілку + теку в бічній панелі" } } } }, - "settings.app.openSidebarPRLinks.subtitleOff": { + "settings.app.showBranchDirectory.subtitle": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Clicks open in your default browser." + "value": "Display the built-in git branch and working-directory row." } }, "ja": { "stringUnit": { "state": "translated", - "value": "クリックするとデフォルトブラウザで開きます。" + "value": "組み込みのgitブランチと作業ディレクトリの行を表示します。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "点击在默认浏览器中打开。" + "value": "显示内置的 Git 分支和工作目录行。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "點擊會在您的預設瀏覽器中開啟。" + "value": "顯示內建的 git 分支及工作目錄列。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "클릭하면 기본 브라우저에서 열립니다." + "value": "기본 제공 git 브랜치 및 작업 디렉토리 행을 표시합니다." } }, "de": { "stringUnit": { "state": "translated", - "value": "Klicks öffnen in Ihrem Standardbrowser." + "value": "Die integrierte Git-Branch- und Arbeitsverzeichniszeile anzeigen." } }, "es": { "stringUnit": { "state": "translated", - "value": "Los clics abren en tu navegador predeterminado." + "value": "Mostrar la fila integrada de rama git y directorio de trabajo." } }, "fr": { "stringUnit": { "state": "translated", - "value": "Les clics ouvrent dans votre navigateur par défaut." + "value": "Afficher la ligne de branche git et de répertoire de travail intégrée." } }, "it": { "stringUnit": { "state": "translated", - "value": "I clic aprono nel browser predefinito." + "value": "Visualizza la riga integrata con il branch git e la directory di lavoro." } }, "da": { "stringUnit": { "state": "translated", - "value": "Klik åbner i din standardbrowser." + "value": "Vis den indbyggede git-gren og arbejdsmapperækken." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Kliknięcia otwierają w domyślnej przeglądarce." + "value": "Wyświetlaj wbudowany wiersz gałęzi git i katalogu roboczego." } }, "ru": { "stringUnit": { "state": "translated", - "value": "Ссылки открываются в браузере по умолчанию." + "value": "Отображать встроенную строку ветки git и рабочего каталога." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Klikovi se otvaraju u podrazumijevanom pregledniku." + "value": "Prikaži ugrađeni red za git granu i radni direktorij." } }, "ar": { "stringUnit": { "state": "translated", - "value": "النقرات تفتح في متصفحك الافتراضي." + "value": "عرض صف فرع git المدمج ودليل العمل." } }, "nb": { "stringUnit": { "state": "translated", - "value": "Klikk åpner i standard nettleser." + "value": "Vis den innebygde git-grenen og arbeidskatalograden." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Cliques abrem no seu navegador padrão." + "value": "Exibir a linha integrada de branch git e diretório de trabalho." } }, "th": { "stringUnit": { "state": "translated", - "value": "คลิกจะเปิดในเบราว์เซอร์เริ่มต้นของคุณ" + "value": "แสดงแถวสาขา git และไดเรกทอรีทำงานในตัว" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Tıklamalar varsayılan tarayıcınızda açılır." + "value": "Yerleşik git dalı ve çalışma dizini satırını göster." } }, "uk": { "stringUnit": { "state": "translated", - "value": "Кліки відкриваються у стандартному браузері." + "value": "Відображати вбудований рядок з гілкою git та робочою текою." } } } }, - "settings.app.openSidebarPRLinks.subtitleOn": { + "settings.app.showLog": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Clicks open inside cmux browser." + "value": "Show Latest Log in Sidebar" } }, "ja": { "stringUnit": { "state": "translated", - "value": "クリックするとcmuxブラウザ内で開きます。" + "value": "サイドバーに最新ログを表示" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "点击在 cmux 浏览器中打开。" + "value": "在侧边栏显示最新日志" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "點擊會在 cmux 瀏覽器中開啟。" + "value": "在側邊欄顯示最新記錄" } }, "ko": { "stringUnit": { "state": "translated", - "value": "클릭하면 cmux 브라우저에서 열립니다." + "value": "사이드바에 최신 로그 표시" } }, "de": { "stringUnit": { "state": "translated", - "value": "Klicks öffnen im cmux-Browser." + "value": "Letztes Protokoll in Seitenleiste anzeigen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Los clics abren dentro del navegador de cmux." + "value": "Mostrar último registro en la barra lateral" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Les clics ouvrent dans le navigateur cmux." + "value": "Afficher le dernier journal dans la barre latérale" } }, "it": { "stringUnit": { "state": "translated", - "value": "I clic aprono nel browser cmux." + "value": "Mostra ultimo log nella barra laterale" } }, "da": { "stringUnit": { "state": "translated", - "value": "Klik åbner i cmux-browseren." + "value": "Vis seneste log i sidebjælke" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Kliknięcia otwierają w przeglądarce cmux." + "value": "Pokaż najnowszy dziennik na pasku bocznym" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Ссылки открываются во встроенном браузере cmux." + "value": "Показывать последний журнал в боковой панели" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Klikovi se otvaraju unutar cmux preglednika." + "value": "Prikaži najnoviji log u bočnoj traci" } }, "ar": { "stringUnit": { "state": "translated", - "value": "النقرات تفتح داخل متصفح cmux." + "value": "عرض أحدث سجل في الشريط الجانبي" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Klikk åpner i cmux-nettleseren." + "value": "Vis siste logg i sidepanelet" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Cliques abrem dentro do navegador do cmux." + "value": "Mostrar Último Log na Barra Lateral" } }, "th": { "stringUnit": { "state": "translated", - "value": "คลิกจะเปิดในเบราว์เซอร์ cmux" + "value": "แสดงบันทึกล่าสุดในแถบด้านข้าง" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Tıklamalar cmux tarayıcısında açılır." + "value": "Kenar Çubuğunda Son Günlüğü Göster" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Кліки відкриваються у браузері cmux." - } - } - } - }, - "settings.app.openSidebarPRLinks.subtitleDisabled": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Enable sidebar PR clickability to choose where PR links open." - } - }, - "ja": { - "stringUnit": { - "state": "translated", - "value": "PRリンクの開き先を選ぶには、サイドバーのPRクリックを有効にしてください。" - } - } - } - }, - "settings.app.openSidebarPRLinks.subtitleHidden": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Enable sidebar PR visibility to choose where PR links open." - } - }, - "ja": { - "stringUnit": { - "state": "translated", - "value": "PRリンクの開き先を選ぶには、サイドバーのPR表示を有効にしてください。" + "value": "Показувати останній журнал у бічній панелі" } } } }, - "settings.app.openSidebarPortLinks": { + "settings.app.showLog.subtitle": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Open Sidebar Port Links in cmux Browser" + "value": "Display the latest imperative log/status message." } }, "ja": { "stringUnit": { "state": "translated", - "value": "サイドバーのポートリンクをcmuxブラウザで開く" + "value": "最新の命令型ログ/ステータスメッセージを表示します。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "在 cmux 浏览器中打开侧边栏端口链接" + "value": "显示最新的命令式日志/状态消息。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "在 cmux 瀏覽器中開啟側邊欄連接埠連結" + "value": "顯示最新的命令式記錄或狀態訊息。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "사이드바 포트 링크를 cmux 브라우저에서 열기" + "value": "최신 명령형 로그/상태 메시지를 표시합니다." } }, "de": { "stringUnit": { "state": "translated", - "value": "Seitenleisten-Port-Links im cmux-Browser öffnen" + "value": "Die letzte imperative Protokoll-/Statusmeldung anzeigen." } }, "es": { "stringUnit": { "state": "translated", - "value": "Abrir enlaces de puerto de la barra lateral en el navegador de cmux" + "value": "Mostrar el último mensaje imperativo de registro/estado." } }, "fr": { "stringUnit": { "state": "translated", - "value": "Ouvrir les liens de port de la barre latérale dans le navigateur cmux" + "value": "Afficher le dernier message de journal/statut impératif." } }, "it": { "stringUnit": { "state": "translated", - "value": "Apri link delle porte della barra laterale nel browser cmux" + "value": "Visualizza l'ultimo messaggio di log/stato imperativo." } }, "da": { "stringUnit": { "state": "translated", - "value": "Åbn sidebjælkens portlinks i cmux-browser" + "value": "Vis den seneste imperative log/statusmeddelelse." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Otwieraj linki portów z paska bocznego w przeglądarce cmux" + "value": "Wyświetlaj najnowszy komunikat dziennika/statusu." } }, "ru": { "stringUnit": { "state": "translated", - "value": "Открывать ссылки портов боковой панели в браузере cmux" + "value": "Отображать последнее служебное сообщение журнала/статуса." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Otvori port linkove iz bočne trake u cmux pregledniku" + "value": "Prikaži najnoviju imperativnu log/statusnu poruku." } }, "ar": { "stringUnit": { "state": "translated", - "value": "فتح روابط المنافذ في متصفح cmux" + "value": "عرض أحدث رسالة سجل/حالة." } }, "nb": { "stringUnit": { "state": "translated", - "value": "Åpne sidepanel-portlenker i cmux-nettleser" + "value": "Vis den siste imperative logg-/statusmeldingen." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Abrir Links de Porta da Barra Lateral no Navegador do cmux" + "value": "Exibir a última mensagem imperativa de log/status." } }, "th": { "stringUnit": { "state": "translated", - "value": "เปิดลิงก์พอร์ตในแถบด้านข้างด้วยเบราว์เซอร์ cmux" + "value": "แสดงข้อความบันทึก/สถานะล่าสุด" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Kenar Çubuğu Port Bağlantılarını cmux Tarayıcısında Aç" + "value": "Son zorunlu günlük/durum mesajını göster." } }, "uk": { "stringUnit": { "state": "translated", - "value": "Відкривати посилання портів бічної панелі у браузері cmux" + "value": "Відображати останнє імперативне повідомлення журналу/статусу." } } } }, - "settings.app.openSidebarPortLinks.subtitleOff": { + "settings.app.showMetadata": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Port clicks open in your default browser." + "value": "Show Custom Metadata in Sidebar" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ポートをクリックするとデフォルトブラウザで開きます。" + "value": "サイドバーにカスタムメタデータを表示" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "端口点击在默认浏览器中打开。" + "value": "在侧边栏显示自定义元数据" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "連接埠點擊會在您的預設瀏覽器中開啟。" + "value": "在側邊欄顯示自訂中繼資料" } }, "ko": { "stringUnit": { "state": "translated", - "value": "포트를 클릭하면 기본 브라우저에서 열립니다." + "value": "사이드바에 사용자 지정 메타데이터 표시" } }, "de": { "stringUnit": { "state": "translated", - "value": "Port-Klicks öffnen in Ihrem Standardbrowser." + "value": "Benutzerdefinierte Metadaten in Seitenleiste anzeigen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Los clics en puertos abren en tu navegador predeterminado." + "value": "Mostrar metadatos personalizados en la barra lateral" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Les clics de port ouvrent dans votre navigateur par défaut." + "value": "Afficher les métadonnées personnalisées dans la barre latérale" } }, "it": { "stringUnit": { "state": "translated", - "value": "I clic sulle porte aprono nel browser predefinito." + "value": "Mostra metadati personalizzati nella barra laterale" } }, "da": { "stringUnit": { "state": "translated", - "value": "Portklik åbner i din standardbrowser." + "value": "Vis brugerdefinerede metadata i sidebjælke" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Kliknięcia portów otwierają w domyślnej przeglądarce." + "value": "Pokaż własne metadane na pasku bocznym" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Ссылки портов открываются в браузере по умолчанию." + "value": "Показывать метаданные в боковой панели" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Klikovi na portove se otvaraju u podrazumijevanom pregledniku." + "value": "Prikaži prilagođene metapodatke u bočnoj traci" } }, "ar": { "stringUnit": { "state": "translated", - "value": "نقرات المنافذ تفتح في متصفحك الافتراضي." + "value": "عرض البيانات الوصفية المخصصة في الشريط الجانبي" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Portklikk åpner i standard nettleser." + "value": "Vis egendefinerte metadata i sidepanelet" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Cliques em portas abrem no seu navegador padrão." + "value": "Mostrar Metadados Personalizados na Barra Lateral" } }, "th": { "stringUnit": { "state": "translated", - "value": "คลิกพอร์ตจะเปิดในเบราว์เซอร์เริ่มต้นของคุณ" + "value": "แสดงข้อมูลเมตาที่กำหนดเองในแถบด้านข้าง" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Port tıklamaları varsayılan tarayıcınızda açılır." + "value": "Kenar Çubuğunda Özel Üst Veriyi Göster" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Кліки по портах відкриваються у стандартному браузері." + "value": "Показувати власні метадані в бічній панелі" } } } }, - "settings.app.openSidebarPortLinks.subtitleOn": { + "settings.app.showMetadata.subtitle": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Port clicks open inside cmux browser." + "value": "Display custom metadata from report_meta/set_status and report_meta_block." } }, "ja": { "stringUnit": { "state": "translated", - "value": "ポートをクリックするとcmuxブラウザ内で開きます。" + "value": "report_meta/set_statusおよびreport_meta_blockからのカスタムメタデータを表示します。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "端口点击在 cmux 浏览器中打开。" + "value": "显示来自 report_meta/set_status 和 report_meta_block 的自定义元数据。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "連接埠點擊會在 cmux 瀏覽器中開啟。" + "value": "顯示來自 report_meta/set_status 和 report_meta_block 的自訂中繼資料。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "포트를 클릭하면 cmux 브라우저에서 열립니다." + "value": "report_meta/set_status 및 report_meta_block의 사용자 지정 메타데이터를 표시합니다." } }, "de": { "stringUnit": { "state": "translated", - "value": "Port-Klicks öffnen im cmux-Browser." + "value": "Benutzerdefinierte Metadaten von report_meta/set_status und report_meta_block anzeigen." } }, "es": { "stringUnit": { "state": "translated", - "value": "Los clics en puertos abren dentro del navegador de cmux." + "value": "Mostrar metadatos personalizados de report_meta/set_status y report_meta_block." } }, "fr": { "stringUnit": { "state": "translated", - "value": "Les clics de port ouvrent dans le navigateur cmux." + "value": "Afficher les métadonnées personnalisées de report_meta/set_status et report_meta_block." } }, "it": { "stringUnit": { "state": "translated", - "value": "I clic sulle porte aprono nel browser cmux." + "value": "Visualizza metadati personalizzati da report_meta/set_status e report_meta_block." } }, "da": { "stringUnit": { "state": "translated", - "value": "Portklik åbner i cmux-browseren." + "value": "Vis brugerdefinerede metadata fra report_meta/set_status og report_meta_block." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Kliknięcia portów otwierają w przeglądarce cmux." + "value": "Wyświetlaj własne metadane z report_meta/set_status i report_meta_block." } }, "ru": { "stringUnit": { "state": "translated", - "value": "Ссылки портов открываются во встроенном браузере cmux." + "value": "Отображать пользовательские метаданные из report_meta/set_status и report_meta_block." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Klikovi na portove se otvaraju unutar cmux preglednika." + "value": "Prikaži prilagođene metapodatke iz report_meta/set_status i report_meta_block." } }, "ar": { "stringUnit": { "state": "translated", - "value": "نقرات المنافذ تفتح داخل متصفح cmux." + "value": "عرض البيانات الوصفية المخصصة من report_meta/set_status و report_meta_block." } }, "nb": { "stringUnit": { "state": "translated", - "value": "Portklikk åpner i cmux-nettleseren." + "value": "Vis egendefinerte metadata fra report_meta/set_status og report_meta_block." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Cliques em portas abrem dentro do navegador do cmux." + "value": "Exibir metadados personalizados de report_meta/set_status e report_meta_block." } }, "th": { "stringUnit": { "state": "translated", - "value": "คลิกพอร์ตจะเปิดในเบราว์เซอร์ cmux" + "value": "แสดงข้อมูลเมตาที่กำหนดเองจาก report_meta/set_status และ report_meta_block" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Port tıklamaları cmux tarayıcısında açılır." + "value": "report_meta/set_status ve report_meta_block'tan özel üst veriyi göster." } }, "uk": { "stringUnit": { "state": "translated", - "value": "Кліки по портах відкриваються у браузері cmux." + "value": "Відображати власні метадані з report_meta/set_status та report_meta_block." } } } }, - "settings.app.hideAllSidebarDetails": { + "settings.app.showNotificationMessage": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Hide All Sidebar Details" + "value": "Show Notification Message in Sidebar" } }, "ja": { "stringUnit": { "state": "translated", - "value": "サイドバーの詳細をすべて隠す" + "value": "サイドバーに通知メッセージを表示" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Сховати всі деталі бічної панелі" + "value": "Показувати повідомлення сповіщення в бічній панелі" } }, "ko": { "stringUnit": { "state": "translated", - "value": "사이드바 세부 정보 모두 숨기기" + "value": "사이드바에 알림 메시지 표시" } } } }, - "settings.app.hideAllSidebarDetails.subtitleOff": { + "settings.app.showNotificationMessage.subtitle": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Show secondary workspace details as controlled by the toggles below." + "value": "Display the latest notification message below the workspace title." } }, "ja": { "stringUnit": { "state": "translated", - "value": "下のトグル設定に従って、ワークスペースの補助情報を表示します。" + "value": "ワークスペース名の下に最新の通知メッセージを表示します。" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Показувати додаткові деталі робочої області відповідно до перемикачів нижче." + "value": "Відображати останнє повідомлення сповіщення під заголовком робочої області." } }, "ko": { "stringUnit": { "state": "translated", - "value": "아래 토글에 따라 보조 워크스페이스 세부 정보를 표시합니다." + "value": "워크스페이스 제목 아래에 최신 알림 메시지를 표시합니다." } } } }, - "settings.app.hideAllSidebarDetails.subtitleOn": { + "settings.app.showPorts": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Show only the workspace title row. Overrides the detail toggles below." + "value": "Show Listening Ports in Sidebar" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ワークスペースのタイトル行だけを表示します。下の詳細トグルより優先されます。" + "value": "サイドバーにリスニングポートを表示" } }, - "uk": { + "zh-Hans": { "stringUnit": { "state": "translated", - "value": "Показувати лише рядок заголовка робочої області. Замінює перемикачі деталей нижче." + "value": "在侧边栏显示监听端口" } }, - "ko": { + "zh-Hant": { "stringUnit": { "state": "translated", - "value": "워크스페이스 제목 행만 표시합니다. 아래 세부 정보 토글보다 우선합니다." + "value": "在側邊欄顯示監聽連接埠" } - } - } - }, - "settings.app.showWorkspaceDescription": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "ko": { "stringUnit": { "state": "translated", - "value": "Show Workspace Description in Sidebar" + "value": "사이드바에 수신 대기 포트 표시" } }, - "ja": { + "de": { "stringUnit": { "state": "translated", - "value": "サイドバーにワークスペースの説明を表示" + "value": "Lauschende Ports in Seitenleiste anzeigen" } - } - } - }, - "settings.app.showWorkspaceDescription.subtitle": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "es": { "stringUnit": { "state": "translated", - "value": "Display custom workspace descriptions below the workspace title." + "value": "Mostrar puertos en escucha en la barra lateral" } }, - "ja": { + "fr": { "stringUnit": { "state": "translated", - "value": "ワークスペース名の下にカスタム説明を表示します。" + "value": "Afficher les ports en écoute dans la barre latérale" } - } - } - }, - "settings.app.renameSelectsName": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "it": { "stringUnit": { "state": "translated", - "value": "Rename Selects Existing Name" + "value": "Mostra porte in ascolto nella barra laterale" } }, - "ja": { + "da": { "stringUnit": { "state": "translated", - "value": "名称変更時に既存の名前を選択" + "value": "Vis lyttende porte i sidebjælke" } }, - "zh-Hans": { + "pl": { "stringUnit": { "state": "translated", - "value": "重命名时选中现有名称" + "value": "Pokaż nasłuchujące porty na pasku bocznym" } }, - "zh-Hant": { + "ru": { "stringUnit": { "state": "translated", - "value": "重新命名時選取現有名稱" + "value": "Показывать прослушиваемые порты в боковой панели" } }, - "ko": { + "bs": { "stringUnit": { "state": "translated", - "value": "이름 변경 시 기존 이름 선택" + "value": "Prikaži osluškivane portove u bočnoj traci" } }, - "de": { + "ar": { "stringUnit": { "state": "translated", - "value": "Umbenennen wählt vorhandenen Namen aus" + "value": "عرض المنافذ النشطة في الشريط الجانبي" } }, - "es": { + "nb": { "stringUnit": { "state": "translated", - "value": "Renombrar selecciona el nombre existente" + "value": "Vis lyttende porter i sidepanelet" } }, - "fr": { + "pt-BR": { "stringUnit": { "state": "translated", - "value": "Le renommage sélectionne le nom existant" + "value": "Mostrar Portas em Escuta na Barra Lateral" } }, - "it": { + "th": { "stringUnit": { "state": "translated", - "value": "Rinomina seleziona il nome esistente" + "value": "แสดงพอร์ตที่กำลังรับฟังในแถบด้านข้าง" } }, - "da": { + "tr": { "stringUnit": { "state": "translated", - "value": "Omdøbning markerer eksisterende navn" + "value": "Kenar Çubuğunda Dinlenen Portları Göster" } }, - "pl": { + "uk": { "stringUnit": { "state": "translated", - "value": "Zmiana nazwy zaznacza istniejącą nazwę" + "value": "Показувати порти в бічній панелі" } - }, - "ru": { + } + } + }, + "settings.app.showSSH": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Переименование выделяет имя" + "value": "Show SSH in Sidebar" } }, - "bs": { + "ja": { "stringUnit": { "state": "translated", - "value": "Preimenovanje odabere postojeći naziv" + "value": "サイドバーにSSHを表示" } }, - "ar": { + "uk": { "stringUnit": { "state": "translated", - "value": "إعادة التسمية تحدد الاسم الحالي" + "value": "Показувати SSH у бічній панелі" } }, - "nb": { + "ko": { "stringUnit": { "state": "translated", - "value": "Omdøping velger eksisterende navn" + "value": "사이드바에 SSH 표시" } - }, - "pt-BR": { + } + } + }, + "settings.app.showSSH.subtitle": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Renomear Seleciona o Nome Existente" + "value": "Display the SSH target for remote workspaces in its own row." } }, - "th": { + "ja": { "stringUnit": { "state": "translated", - "value": "เลือกชื่อเมื่อเปลี่ยนชื่อ" + "value": "リモートワークスペースのSSHターゲットを専用の行に表示します。" } }, - "tr": { + "uk": { "stringUnit": { "state": "translated", - "value": "Yeniden Adlandırma Mevcut Adı Seçer" + "value": "Відображати ціль SSH для віддалених робочих областей у окремому рядку." } }, - "uk": { + "ko": { "stringUnit": { "state": "translated", - "value": "Виділяти назву при перейменуванні" + "value": "원격 워크스페이스의 SSH 대상을 별도 행으로 표시합니다." } } } }, - "settings.app.renameSelectsName.subtitleOff": { + "settings.app.showPorts.subtitle": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Command Palette rename keeps the caret at the end." + "value": "Display detected listening ports for the active workspace." } }, "ja": { "stringUnit": { "state": "translated", - "value": "コマンドパレットの名称変更ではキャレットが末尾に置かれます。" + "value": "アクティブなワークスペースで検出されたリスニングポートを表示します。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "命令面板重命名时光标保持在末尾。" + "value": "显示活动工作区检测到的监听端口。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "指令面板重新命名時,游標保持在結尾。" + "value": "顯示使用中工作區偵測到的監聽連接埠。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "명령어 팔레트의 이름 변경 시 커서가 끝에 위치합니다." + "value": "활성 작업 공간에서 감지된 수신 대기 포트를 표시합니다." } }, "de": { "stringUnit": { "state": "translated", - "value": "Beim Umbenennen in der Befehlspalette bleibt der Cursor am Ende." + "value": "Erkannte lauschende Ports für den aktiven Arbeitsbereich anzeigen." } }, "es": { "stringUnit": { "state": "translated", - "value": "Renombrar en la paleta de comandos mantiene el cursor al final." + "value": "Mostrar los puertos en escucha detectados para el espacio de trabajo activo." } }, "fr": { "stringUnit": { "state": "translated", - "value": "Le renommage via la palette de commandes maintient le curseur à la fin." + "value": "Afficher les ports en écoute détectés pour l'espace de travail actif." } }, "it": { "stringUnit": { "state": "translated", - "value": "La rinomina nella Tavolozza comandi mantiene il cursore alla fine." + "value": "Visualizza le porte in ascolto rilevate per l'area di lavoro attiva." } }, "da": { "stringUnit": { "state": "translated", - "value": "Omdøbning i kommandopaletten beholder markøren til sidst." + "value": "Vis registrerede lyttende porte for det aktive arbejdsområde." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Zmiana nazwy w palecie poleceń pozostawia kursor na końcu." + "value": "Wyświetlaj wykryte nasłuchujące porty dla aktywnej przestrzeni roboczej." } }, "ru": { "stringUnit": { "state": "translated", - "value": "Переименование в палитре команд оставляет курсор в конце." + "value": "Отображать обнаруженные прослушиваемые порты для активного рабочего пространства." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Preimenovanje u paleti naredbi zadržava kursor na kraju." + "value": "Prikaži otkrivene osluškivane portove za aktivni radni prostor." } }, "ar": { "stringUnit": { "state": "translated", - "value": "إعادة التسمية في لوحة الأوامر تبقي المؤشر في النهاية." + "value": "عرض المنافذ المكتشفة لمساحة العمل النشطة." } }, "nb": { "stringUnit": { "state": "translated", - "value": "Omdøping i kommandopaletten beholder markøren på slutten." + "value": "Vis oppdagede lyttende porter for det aktive arbeidsområdet." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "A renomeação na Paleta de Comandos mantém o cursor no final." + "value": "Exibir portas em escuta detectadas para a área de trabalho ativa." } }, "th": { "stringUnit": { "state": "translated", - "value": "การเปลี่ยนชื่อในแถบคำสั่งจะเก็บเคอร์เซอร์ไว้ที่ท้าย" + "value": "แสดงพอร์ตที่ตรวจพบสำหรับเวิร์กสเปซที่ใช้งานอยู่" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Komut Paleti yeniden adlandırması imleci sonda tutar." + "value": "Etkin çalışma alanı için algılanan dinlenen portları göster." } }, "uk": { "stringUnit": { "state": "translated", - "value": "Перейменування в палітрі команд залишає курсор в кінці." + "value": "Відображати виявлені порти для активної робочої області." } } } }, - "settings.app.renameSelectsName.subtitleOn": { + "settings.app.showProgress": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Command Palette rename starts with all text selected." + "value": "Show Progress in Sidebar" } }, "ja": { "stringUnit": { "state": "translated", - "value": "コマンドパレットの名称変更ではテキスト全体が選択された状態で始まります。" + "value": "サイドバーに進捗を表示" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "命令面板重命名时全选文本。" + "value": "在侧边栏显示进度" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "指令面板重新命名時,會先選取所有文字。" + "value": "在側邊欄顯示進度" } }, "ko": { "stringUnit": { "state": "translated", - "value": "명령어 팔레트의 이름 변경 시 전체 텍스트가 선택됩니다." + "value": "사이드바에 진행 상황 표시" } }, "de": { "stringUnit": { "state": "translated", - "value": "Beim Umbenennen in der Befehlspalette wird der gesamte Text ausgewählt." + "value": "Fortschritt in Seitenleiste anzeigen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Renombrar en la paleta de comandos inicia con todo el texto seleccionado." + "value": "Mostrar progreso en la barra lateral" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Le renommage via la palette de commandes commence avec tout le texte sélectionné." + "value": "Afficher la progression dans la barre latérale" } }, "it": { "stringUnit": { "state": "translated", - "value": "La rinomina nella Tavolozza comandi inizia con tutto il testo selezionato." + "value": "Mostra progresso nella barra laterale" } }, "da": { "stringUnit": { "state": "translated", - "value": "Omdøbning i kommandopaletten starter med al tekst markeret." + "value": "Vis fremskridt i sidebjælke" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Zmiana nazwy w palecie poleceń rozpoczyna z zaznaczonym całym tekstem." + "value": "Pokaż postęp na pasku bocznym" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Переименование в палитре команд начинается с выделения всего текста." + "value": "Показывать прогресс в боковой панели" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Preimenovanje u paleti naredbi počinje sa svim odabranim tekstom." + "value": "Prikaži napredak u bočnoj traci" } }, "ar": { "stringUnit": { "state": "translated", - "value": "إعادة التسمية في لوحة الأوامر تبدأ بتحديد كل النص." + "value": "عرض التقدم في الشريط الجانبي" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Omdøping i kommandopaletten starter med all tekst valgt." + "value": "Vis fremdrift i sidepanelet" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "A renomeação na Paleta de Comandos começa com todo o texto selecionado." + "value": "Mostrar Progresso na Barra Lateral" } }, "th": { "stringUnit": { "state": "translated", - "value": "การเปลี่ยนชื่อในแถบคำสั่งจะเลือกข้อความทั้งหมด" + "value": "แสดงความคืบหน้าในแถบด้านข้าง" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Komut Paleti yeniden adlandırması tüm metin seçili olarak başlar." + "value": "Kenar Çubuğunda İlerlemeyi Göster" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Перейменування в палітрі команд починає з виділення всього тексту." + "value": "Показувати прогрес у бічній панелі" } } } }, - "settings.app.iMessageMode": { + "settings.app.showProgress.subtitle": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "iMessage Mode" + "value": "Display the built-in progress bar from set_progress." } }, "ja": { "stringUnit": { "state": "translated", - "value": "iMessageモード" - } - } - } - }, - "settings.app.iMessageMode.subtitle": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Move a workspace to the top and show the submitted message when you send an agent prompt." - } - }, - "ja": { - "stringUnit": { - "state": "translated", - "value": "エージェントのプロンプトを送信したときにワークスペースを一番上へ移動し、送信したメッセージを表示します。" - } - } - } - }, - "settings.app.reorderOnNotification": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Reorder on Notification" - } - }, - "ja": { - "stringUnit": { - "state": "translated", - "value": "通知時に並べ替え" + "value": "set_progressによる組み込みプログレスバーを表示します。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "收到通知时重新排序" + "value": "显示来自 set_progress 的内置进度条。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "收到通知時重新排序" + "value": "顯示來自 set_progress 的內建進度列。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "알림 시 순서 변경" + "value": "set_progress의 기본 제공 진행 표시줄을 표시합니다." } }, "de": { "stringUnit": { "state": "translated", - "value": "Bei Benachrichtigung neu sortieren" + "value": "Den integrierten Fortschrittsbalken von set_progress anzeigen." } }, "es": { "stringUnit": { "state": "translated", - "value": "Reordenar al recibir notificación" + "value": "Mostrar la barra de progreso integrada de set_progress." } }, "fr": { "stringUnit": { "state": "translated", - "value": "Réordonner à la notification" + "value": "Afficher la barre de progression intégrée de set_progress." } }, "it": { "stringUnit": { "state": "translated", - "value": "Riordina alla notifica" + "value": "Visualizza la barra di progresso integrata da set_progress." } }, "da": { "stringUnit": { "state": "translated", - "value": "Omarranger ved notifikation" + "value": "Vis den indbyggede fremskridtslinje fra set_progress." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Zmiana kolejności przy powiadomieniu" + "value": "Wyświetlaj wbudowany pasek postępu z set_progress." } }, "ru": { "stringUnit": { "state": "translated", - "value": "Перемещение при уведомлении" + "value": "Отображать встроенный индикатор прогресса из set_progress." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Prerasporedi pri obavještenju" + "value": "Prikaži ugrađenu traku napretka iz set_progress." } }, "ar": { "stringUnit": { "state": "translated", - "value": "إعادة الترتيب عند الإشعار" + "value": "عرض شريط التقدم المدمج من set_progress." } }, "nb": { "stringUnit": { "state": "translated", - "value": "Omorganiser ved varsel" + "value": "Vis den innebygde fremdriftsindikatoren fra set_progress." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Reordenar ao Receber Notificação" + "value": "Exibir a barra de progresso integrada de set_progress." } }, "th": { "stringUnit": { "state": "translated", - "value": "จัดเรียงใหม่เมื่อมีการแจ้งเตือน" + "value": "แสดงแถบความคืบหน้าในตัวจาก set_progress" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Bildirimde Yeniden Sırala" + "value": "set_progress'ten yerleşik ilerleme çubuğunu göster." } }, "uk": { "stringUnit": { "state": "translated", - "value": "Переміщення при сповіщенні" + "value": "Відображати вбудований індикатор прогресу з set_progress." } } } }, - "settings.app.reorderOnNotification.subtitle": { + "settings.app.showWorkspaceTitlebar": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Move workspaces to the top when they receive a notification. Disable for stable shortcut positions." + "value": "Show Workspace Title Bar" } }, "ja": { "stringUnit": { "state": "translated", - "value": "通知を受け取ったワークスペースを一番上に移動します。ショートカット位置を固定するには無効にしてください。" - } - }, - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "收到通知时将工作区移至顶部。禁用以保持快捷键位置稳定。" + "value": "ワークスペースのタイトルバーを表示" } }, - "zh-Hant": { + "uk": { "stringUnit": { "state": "translated", - "value": "收到通知時將工作區移至最上方。停用此選項可維持穩定的快捷鍵位置。" + "value": "Показувати заголовок робочої області" } }, "ko": { "stringUnit": { "state": "translated", - "value": "알림을 받은 작업 공간을 맨 위로 이동합니다. 단축키 위치를 고정하려면 비활성화하세요." - } - }, - "de": { - "stringUnit": { - "state": "translated", - "value": "Arbeitsbereiche nach oben verschieben, wenn sie eine Benachrichtigung erhalten. Deaktivieren Sie dies für stabile Tastenkürzel-Positionen." - } - }, - "es": { - "stringUnit": { - "state": "translated", - "value": "Mover espacios de trabajo al inicio cuando reciben una notificación. Desactiva para posiciones de atajo estables." + "value": "워크스페이스 제목 표시줄 표시" } - }, - "fr": { + } + } + }, + "settings.app.showWorkspaceTitlebar.subtitleOff": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Déplacer les espaces de travail en haut lorsqu'ils reçoivent une notification. Désactivez pour des positions de raccourcis stables." + "value": "Hide the folder and active title above pane tabs." } }, - "it": { + "ja": { "stringUnit": { "state": "translated", - "value": "Sposta le aree di lavoro in cima quando ricevono una notifica. Disabilita per posizioni di scorciatoia stabili." + "value": "ペインタブの上にあるフォルダ名と現在のタイトルを隠します。" } }, - "da": { + "uk": { "stringUnit": { "state": "translated", - "value": "Flyt arbejdsområder til toppen, når de modtager en notifikation. Deaktiver for stabile genvejspositioner." + "value": "Сховати теку та активний заголовок над вкладками панелей." } }, - "pl": { + "ko": { "stringUnit": { "state": "translated", - "value": "Przenoś przestrzenie robocze na górę, gdy otrzymają powiadomienie. Wyłącz, aby zachować stałe pozycje skrótów." + "value": "패인 탭 위의 폴더 및 활성 제목을 숨깁니다." } - }, - "ru": { + } + } + }, + "settings.app.showWorkspaceTitlebar.subtitleOn": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Перемещать рабочие пространства наверх при получении уведомления. Отключите для стабильных позиций сочетаний клавиш." + "value": "Show the folder and active title above pane tabs." } }, - "bs": { + "ja": { "stringUnit": { "state": "translated", - "value": "Pomjeri radne prostore na vrh kada prime obavještenje. Onemogućite za stabilne pozicije prečica." + "value": "ペインタブの上にフォルダ名と現在のタイトルを表示します。" } }, - "ar": { + "uk": { "stringUnit": { "state": "translated", - "value": "نقل مساحات العمل إلى الأعلى عند تلقي إشعار. قم بالتعطيل للحفاظ على مواضع الاختصارات الثابتة." + "value": "Показувати теку та активний заголовок над вкладками панелей." } }, - "nb": { + "ko": { "stringUnit": { "state": "translated", - "value": "Flytt arbeidsområder til toppen når de mottar et varsel. Deaktiver for stabile snarveiposisjoner." + "value": "패인 탭 위에 폴더 및 활성 제목을 표시합니다." } - }, - "pt-BR": { + } + } + }, + "settings.app.fadeButtons": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Move áreas de trabalho para o topo ao receber uma notificação. Desative para posições de atalho estáveis." + "value": "Fade Buttons" } }, - "th": { + "ja": { "stringUnit": { "state": "translated", - "value": "ย้ายเวิร์กสเปซไปด้านบนเมื่อได้รับการแจ้งเตือน ปิดใช้งานเพื่อให้ตำแหน่งทางลัดคงที่" + "value": "ボタンをフェード表示" } }, - "tr": { + "uk": { "stringUnit": { "state": "translated", - "value": "Bildirim aldıklarında çalışma alanlarını en üste taşı. Sabit kısayol konumları için devre dışı bırakın." + "value": "Приховування кнопок" } }, - "uk": { + "ko": { "stringUnit": { "state": "translated", - "value": "Переміщувати робочі області нагору при отриманні сповіщення. Вимкніть для стабільних позицій комбінацій клавіш." + "value": "버튼 페이드" } } } }, - "settings.app.showBranchDirectory": { + "settings.app.fadeButtons.subtitleOff": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Show Branch + Directory in Sidebar" + "value": "Keep action buttons always visible." } }, "ja": { "stringUnit": { "state": "translated", - "value": "サイドバーにブランチ+ディレクトリを表示" + "value": "操作ボタンを常に表示します。" } }, - "zh-Hans": { + "uk": { "stringUnit": { "state": "translated", - "value": "在侧边栏显示分支和目录" + "value": "Кнопки дій завжди видимі." } }, - "zh-Hant": { + "ko": { "stringUnit": { "state": "translated", - "value": "在側邊欄顯示分支與目錄" + "value": "액션 버튼을 항상 표시합니다." } - }, - "ko": { + } + } + }, + "settings.app.fadeButtons.subtitleOn": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "사이드바에 브랜치 + 디렉토리 표시" + "value": "Show action buttons only on hover." } }, - "de": { + "ja": { "stringUnit": { "state": "translated", - "value": "Branch + Verzeichnis in Seitenleiste anzeigen" + "value": "操作ボタンはホバー時のみ表示します。" } }, - "es": { + "uk": { "stringUnit": { "state": "translated", - "value": "Mostrar rama + directorio en la barra lateral" + "value": "Кнопки дій з'являються лише при наведенні." } }, - "fr": { + "ko": { "stringUnit": { "state": "translated", - "value": "Afficher la branche et le répertoire dans la barre latérale" + "value": "마우스를 올렸을 때만 액션 버튼을 표시합니다." } - }, - "it": { + } + } + }, + "settings.app.minimalMode": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Mostra branch e directory nella barra laterale" + "value": "Minimal Mode" } }, - "da": { + "ja": { "stringUnit": { "state": "translated", - "value": "Vis gren + mappe i sidebjælke" + "value": "ミニマルモード" } }, - "pl": { + "uk": { "stringUnit": { "state": "translated", - "value": "Pokaż gałąź + katalog na pasku bocznym" + "value": "Мінімальний режим" } }, - "ru": { + "ko": { "stringUnit": { "state": "translated", - "value": "Показывать ветку и каталог в боковой панели" + "value": "미니멀 모드" } - }, - "bs": { + } + } + }, + "settings.app.minimalMode.subtitleOff": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Prikaži granu i direktorij u bočnoj traci" + "value": "Use the standard workspace title bar and controls." } }, - "ar": { + "ja": { "stringUnit": { "state": "translated", - "value": "عرض الفرع والدليل في الشريط الجانبي" + "value": "標準のワークスペースタイトルバーと操作を使います。" } }, - "nb": { + "uk": { "stringUnit": { "state": "translated", - "value": "Vis gren + katalog i sidepanelet" + "value": "Використовувати стандартний заголовок робочої області та елементи керування." } }, - "pt-BR": { + "ko": { "stringUnit": { "state": "translated", - "value": "Mostrar Branch + Diretório na Barra Lateral" + "value": "기본 워크스페이스 제목 표시줄과 컨트롤을 사용합니다." } - }, - "th": { + } + } + }, + "settings.app.minimalMode.subtitleOn": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "แสดงสาขา + ไดเรกทอรีในแถบด้านข้าง" + "value": "Hide the workspace title bar and move workspace controls into the sidebar." } }, - "tr": { + "ja": { "stringUnit": { "state": "translated", - "value": "Kenar Çubuğunda Dal + Dizin Göster" + "value": "ワークスペースのタイトルバーを隠し、ワークスペース操作をサイドバーに移動します。" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Показувати гілку + теку в бічній панелі" + "value": "Сховати заголовок робочої області та перемістити елементи керування в бічну панель." + } + }, + "ko": { + "stringUnit": { + "state": "translated", + "value": "워크스페이스 제목 표시줄을 숨기고 워크스페이스 컨트롤을 사이드바로 이동합니다." } } } }, - "settings.app.showBranchDirectory.subtitle": { + "settings.app.showPullRequests": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Display the built-in git branch and working-directory row." + "value": "Show Pull Requests in Sidebar" } }, "ja": { "stringUnit": { "state": "translated", - "value": "組み込みのgitブランチと作業ディレクトリの行を表示します。" + "value": "サイドバーにプルリクエストを表示" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "显示内置的 Git 分支和工作目录行。" + "value": "在侧边栏显示拉取请求" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "顯示內建的 git 分支及工作目錄列。" + "value": "在側邊欄顯示 Pull Request" } }, "ko": { "stringUnit": { "state": "translated", - "value": "기본 제공 git 브랜치 및 작업 디렉토리 행을 표시합니다." + "value": "사이드바에 Pull Request 표시" } }, "de": { "stringUnit": { "state": "translated", - "value": "Die integrierte Git-Branch- und Arbeitsverzeichniszeile anzeigen." + "value": "Pull Requests in Seitenleiste anzeigen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Mostrar la fila integrada de rama git y directorio de trabajo." + "value": "Mostrar pull requests en la barra lateral" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Afficher la ligne de branche git et de répertoire de travail intégrée." + "value": "Afficher les Pull Requests dans la barre latérale" } }, "it": { "stringUnit": { "state": "translated", - "value": "Visualizza la riga integrata con il branch git e la directory di lavoro." + "value": "Mostra Pull Request nella barra laterale" } }, "da": { "stringUnit": { "state": "translated", - "value": "Vis den indbyggede git-gren og arbejdsmapperækken." + "value": "Vis pull requests i sidebjælke" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Wyświetlaj wbudowany wiersz gałęzi git i katalogu roboczego." + "value": "Pokaż pull requesty na pasku bocznym" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Отображать встроенную строку ветки git и рабочего каталога." + "value": "Показывать запросы на слияние в боковой панели" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Prikaži ugrađeni red za git granu i radni direktorij." + "value": "Prikaži pull zahtjeve u bočnoj traci" } }, "ar": { "stringUnit": { "state": "translated", - "value": "عرض صف فرع git المدمج ودليل العمل." + "value": "عرض طلبات السحب في الشريط الجانبي" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Vis den innebygde git-grenen og arbeidskatalograden." + "value": "Vis pull-forespørsler i sidepanelet" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Exibir a linha integrada de branch git e diretório de trabalho." + "value": "Mostrar Pull Requests na Barra Lateral" } }, "th": { "stringUnit": { "state": "translated", - "value": "แสดงแถวสาขา git และไดเรกทอรีทำงานในตัว" + "value": "แสดง Pull Request ในแถบด้านข้าง" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Yerleşik git dalı ve çalışma dizini satırını göster." + "value": "Kenar Çubuğunda Çekme İsteklerini Göster" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Відображати вбудований рядок з гілкою git та робочою текою." + "value": "Показувати запити на злиття в бічній панелі" } } } }, - "settings.app.showLog": { + "settings.app.showPullRequests.subtitle": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Show Latest Log in Sidebar" + "value": "Display review items (PR/MR/etc.) with status and number." } }, "ja": { "stringUnit": { "state": "translated", - "value": "サイドバーに最新ログを表示" + "value": "ステータスと番号付きのレビュー項目(PR/MRなど)を表示します。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "在侧边栏显示最新日志" + "value": "显示包含状态和编号的审查项(PR/MR 等)。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "在側邊欄顯示最新記錄" + "value": "顯示審查項目(PR/MR 等),包含狀態和編號。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "사이드바에 최신 로그 표시" + "value": "상태와 번호가 있는 리뷰 항목(PR/MR 등)을 표시합니다." } }, "de": { "stringUnit": { "state": "translated", - "value": "Letztes Protokoll in Seitenleiste anzeigen" + "value": "Review-Elemente (PR/MR/etc.) mit Status und Nummer anzeigen." } }, "es": { "stringUnit": { "state": "translated", - "value": "Mostrar último registro en la barra lateral" + "value": "Mostrar elementos de revisión (PR/MR/etc.) con estado y número." } }, "fr": { "stringUnit": { "state": "translated", - "value": "Afficher le dernier journal dans la barre latérale" + "value": "Afficher les éléments de revue (PR/MR/etc.) avec le statut et le numéro." } }, "it": { "stringUnit": { "state": "translated", - "value": "Mostra ultimo log nella barra laterale" + "value": "Visualizza elementi di revisione (PR/MR/ecc.) con stato e numero." } }, "da": { "stringUnit": { "state": "translated", - "value": "Vis seneste log i sidebjælke" + "value": "Vis gennemgangselementer (PR/MR osv.) med status og nummer." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Pokaż najnowszy dziennik na pasku bocznym" + "value": "Wyświetlaj elementy przeglądu (PR/MR/itp.) ze statusem i numerem." } }, "ru": { "stringUnit": { "state": "translated", - "value": "Показывать последний журнал в боковой панели" + "value": "Отображать элементы проверки (PR/MR и т.д.) со статусом и номером." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Prikaži najnoviji log u bočnoj traci" + "value": "Prikaži stavke za pregled (PR/MR/itd.) sa statusom i brojem." } }, "ar": { "stringUnit": { "state": "translated", - "value": "عرض أحدث سجل في الشريط الجانبي" + "value": "عرض عناصر المراجعة (طلبات السحب/الدمج/إلخ.) مع الحالة والرقم." } }, "nb": { "stringUnit": { "state": "translated", - "value": "Vis siste logg i sidepanelet" + "value": "Vis gjennomgangselementer (PR/MR/osv.) med status og nummer." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Mostrar Último Log na Barra Lateral" + "value": "Exibir itens de revisão (PR/MR/etc.) com status e número." } }, "th": { "stringUnit": { "state": "translated", - "value": "แสดงบันทึกล่าสุดในแถบด้านข้าง" + "value": "แสดงรายการตรวจสอบ (PR/MR/อื่นๆ) พร้อมสถานะและหมายเลข" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Kenar Çubuğunda Son Günlüğü Göster" + "value": "Durum ve numarayla inceleme öğelerini (PR/MR/vb.) göster." } }, "uk": { "stringUnit": { "state": "translated", - "value": "Показувати останній журнал у бічній панелі" + "value": "Відображати елементи перегляду (PR/MR тощо) зі статусом і номером." } } } }, - "settings.app.showLog.subtitle": { + "settings.app.showPullRequests.subtitle.basic": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Display the latest imperative log/status message." + "value": "Display review items (PR/MR/etc.) with status and number." } }, "ja": { "stringUnit": { "state": "translated", - "value": "最新の命令型ログ/ステータスメッセージを表示します。" + "value": "ステータスと番号付きのレビュー項目(PR/MRなど)を表示します。" + } + } + } + }, + "settings.app.makeSidebarPullRequestClickable": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Make Sidebar PR Clickable" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "サイドバーのPRをクリック可能にする" + } + } + } + }, + "settings.app.makeSidebarPullRequestClickable.subtitle": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Review items stay visible as plain text, and clicks in that area select the workspace row." + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "レビュー項目は通常のテキストとして表示され、その領域をクリックするとワークスペース行が選択されます。" + } + } + } + }, + "settings.app.sidebarBranchLayout": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Sidebar Branch Layout" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "サイドバーのブランチレイアウト" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "显示最新的命令式日志/状态消息。" + "value": "侧边栏分支布局" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "顯示最新的命令式記錄或狀態訊息。" + "value": "側邊欄分支版面" } }, "ko": { "stringUnit": { "state": "translated", - "value": "최신 명령형 로그/상태 메시지를 표시합니다." + "value": "사이드바 브랜치 레이아웃" } }, "de": { "stringUnit": { "state": "translated", - "value": "Die letzte imperative Protokoll-/Statusmeldung anzeigen." + "value": "Seitenleisten-Branch-Layout" } }, "es": { "stringUnit": { "state": "translated", - "value": "Mostrar el último mensaje imperativo de registro/estado." + "value": "Disposición de ramas en la barra lateral" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Afficher le dernier message de journal/statut impératif." + "value": "Disposition des branches dans la barre latérale" } }, "it": { "stringUnit": { "state": "translated", - "value": "Visualizza l'ultimo messaggio di log/stato imperativo." + "value": "Layout branch nella barra laterale" } }, "da": { "stringUnit": { "state": "translated", - "value": "Vis den seneste imperative log/statusmeddelelse." + "value": "Sidebjælkens grenlayout" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Wyświetlaj najnowszy komunikat dziennika/statusu." + "value": "Układ gałęzi na pasku bocznym" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Отображать последнее служебное сообщение журнала/статуса." + "value": "Макет веток в боковой панели" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Prikaži najnoviju imperativnu log/statusnu poruku." + "value": "Raspored grana u bočnoj traci" } }, "ar": { "stringUnit": { "state": "translated", - "value": "عرض أحدث رسالة سجل/حالة." + "value": "تخطيط الفروع في الشريط الجانبي" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Vis den siste imperative logg-/statusmeldingen." + "value": "Grenoppsett i sidepanelet" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Exibir a última mensagem imperativa de log/status." + "value": "Layout de Branch na Barra Lateral" } }, "th": { "stringUnit": { "state": "translated", - "value": "แสดงข้อความบันทึก/สถานะล่าสุด" + "value": "เค้าโครงสาขาในแถบด้านข้าง" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Son zorunlu günlük/durum mesajını göster." + "value": "Kenar Çubuğu Dal Düzeni" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Відображати останнє імперативне повідомлення журналу/статусу." + "value": "Макет гілок у бічній панелі" } } } }, - "settings.app.showMetadata": { + "settings.app.sidebarBranchLayout.inline": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Show Custom Metadata in Sidebar" + "value": "Inline" } }, "ja": { "stringUnit": { "state": "translated", - "value": "サイドバーにカスタムメタデータを表示" + "value": "インライン" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "在侧边栏显示自定义元数据" + "value": "单行" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "在側邊欄顯示自訂中繼資料" + "value": "行內" } }, "ko": { "stringUnit": { "state": "translated", - "value": "사이드바에 사용자 지정 메타데이터 표시" + "value": "인라인" } }, "de": { "stringUnit": { "state": "translated", - "value": "Benutzerdefinierte Metadaten in Seitenleiste anzeigen" + "value": "Einzeilig" } }, "es": { "stringUnit": { "state": "translated", - "value": "Mostrar metadatos personalizados en la barra lateral" + "value": "En línea" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Afficher les métadonnées personnalisées dans la barre latérale" + "value": "En ligne" } }, "it": { "stringUnit": { "state": "translated", - "value": "Mostra metadati personalizzati nella barra laterale" + "value": "In linea" } }, "da": { "stringUnit": { "state": "translated", - "value": "Vis brugerdefinerede metadata i sidebjælke" + "value": "Inline" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Pokaż własne metadane na pasku bocznym" + "value": "W linii" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Показывать метаданные в боковой панели" + "value": "В строку" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Prikaži prilagođene metapodatke u bočnoj traci" + "value": "U redu" } }, "ar": { "stringUnit": { "state": "translated", - "value": "عرض البيانات الوصفية المخصصة في الشريط الجانبي" + "value": "سطري" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Vis egendefinerte metadata i sidepanelet" + "value": "Innebygd" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Mostrar Metadados Personalizados na Barra Lateral" + "value": "Em Linha" } }, "th": { "stringUnit": { "state": "translated", - "value": "แสดงข้อมูลเมตาที่กำหนดเองในแถบด้านข้าง" + "value": "แบบอินไลน์" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Kenar Çubuğunda Özel Üst Veriyi Göster" + "value": "Satır İçi" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Показувати власні метадані в бічній панелі" + "value": "В рядок" } } } }, - "settings.app.showMetadata.subtitle": { + "settings.app.sidebarBranchLayout.subtitleInline": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Display custom metadata from report_meta/set_status and report_meta_block." + "value": "Inline: all branches share one line." } }, "ja": { "stringUnit": { "state": "translated", - "value": "report_meta/set_statusおよびreport_meta_blockからのカスタムメタデータを表示します。" + "value": "インライン: すべてのブランチが1行に表示されます。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "显示来自 report_meta/set_status 和 report_meta_block 的自定义元数据。" + "value": "单行:所有分支共享一行。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "顯示來自 report_meta/set_status 和 report_meta_block 的自訂中繼資料。" + "value": "行內:所有分支共用一行。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "report_meta/set_status 및 report_meta_block의 사용자 지정 메타데이터를 표시합니다." + "value": "인라인: 모든 브랜치가 한 줄에 표시됩니다." } }, "de": { "stringUnit": { "state": "translated", - "value": "Benutzerdefinierte Metadaten von report_meta/set_status und report_meta_block anzeigen." + "value": "Einzeilig: Alle Branches teilen sich eine Zeile." } }, "es": { "stringUnit": { "state": "translated", - "value": "Mostrar metadatos personalizados de report_meta/set_status y report_meta_block." + "value": "En línea: todas las ramas comparten una sola línea." } }, "fr": { "stringUnit": { "state": "translated", - "value": "Afficher les métadonnées personnalisées de report_meta/set_status et report_meta_block." + "value": "En ligne : toutes les branches partagent une seule ligne." } }, "it": { "stringUnit": { "state": "translated", - "value": "Visualizza metadati personalizzati da report_meta/set_status e report_meta_block." + "value": "In linea: tutti i branch condividono una riga." } }, "da": { "stringUnit": { "state": "translated", - "value": "Vis brugerdefinerede metadata fra report_meta/set_status og report_meta_block." + "value": "Inline: alle grene deler én linje." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Wyświetlaj własne metadane z report_meta/set_status i report_meta_block." + "value": "W linii: wszystkie gałęzie w jednym wierszu." } }, "ru": { "stringUnit": { "state": "translated", - "value": "Отображать пользовательские метаданные из report_meta/set_status и report_meta_block." + "value": "В строку: все ветки в одной строке." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Prikaži prilagođene metapodatke iz report_meta/set_status i report_meta_block." + "value": "U redu: sve grane dijele jednu liniju." } }, "ar": { "stringUnit": { "state": "translated", - "value": "عرض البيانات الوصفية المخصصة من report_meta/set_status و report_meta_block." + "value": "سطري: جميع الفروع تشترك في سطر واحد." } }, "nb": { "stringUnit": { "state": "translated", - "value": "Vis egendefinerte metadata fra report_meta/set_status og report_meta_block." + "value": "Innebygd: alle grener deler én linje." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Exibir metadados personalizados de report_meta/set_status e report_meta_block." + "value": "Em Linha: todas as branches compartilham uma linha." } }, "th": { "stringUnit": { "state": "translated", - "value": "แสดงข้อมูลเมตาที่กำหนดเองจาก report_meta/set_status และ report_meta_block" + "value": "แบบอินไลน์: สาขาทั้งหมดแสดงในบรรทัดเดียว" } }, "tr": { "stringUnit": { "state": "translated", - "value": "report_meta/set_status ve report_meta_block'tan özel üst veriyi göster." - } - }, - "uk": { - "stringUnit": { - "state": "translated", - "value": "Відображати власні метадані з report_meta/set_status та report_meta_block." - } - } - } - }, - "settings.app.showNotificationMessage": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Show Notification Message in Sidebar" - } - }, - "ja": { - "stringUnit": { - "state": "translated", - "value": "サイドバーに通知メッセージを表示" - } - }, - "uk": { - "stringUnit": { - "state": "translated", - "value": "Показувати повідомлення сповіщення в бічній панелі" - } - }, - "ko": { - "stringUnit": { - "state": "translated", - "value": "사이드바에 알림 메시지 표시" - } - } - } - }, - "settings.app.showNotificationMessage.subtitle": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Display the latest notification message below the workspace title." - } - }, - "ja": { - "stringUnit": { - "state": "translated", - "value": "ワークスペース名の下に最新の通知メッセージを表示します。" + "value": "Satır İçi: tüm dallar tek satırı paylaşır." } }, "uk": { "stringUnit": { "state": "translated", - "value": "Відображати останнє повідомлення сповіщення під заголовком робочої області." - } - }, - "ko": { - "stringUnit": { - "state": "translated", - "value": "워크스페이스 제목 아래에 최신 알림 메시지를 표시합니다." + "value": "В рядок: усі гілки в одному рядку." } } } }, - "settings.app.showPorts": { + "settings.app.sidebarBranchLayout.subtitleVertical": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Show Listening Ports in Sidebar" + "value": "Vertical: each branch appears on its own line." } }, "ja": { "stringUnit": { "state": "translated", - "value": "サイドバーにリスニングポートを表示" + "value": "縦: 各ブランチがそれぞれの行に表示されます。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "在侧边栏显示监听端口" + "value": "垂直:每个分支独占一行。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "在側邊欄顯示監聽連接埠" + "value": "垂直:每個分支獨立一行。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "사이드바에 수신 대기 포트 표시" + "value": "세로: 각 브랜치가 별도의 줄에 표시됩니다." } }, "de": { "stringUnit": { "state": "translated", - "value": "Lauschende Ports in Seitenleiste anzeigen" + "value": "Vertikal: Jeder Branch erscheint in einer eigenen Zeile." } }, "es": { "stringUnit": { "state": "translated", - "value": "Mostrar puertos en escucha en la barra lateral" + "value": "Vertical: cada rama aparece en su propia línea." } }, "fr": { "stringUnit": { "state": "translated", - "value": "Afficher les ports en écoute dans la barre latérale" + "value": "Vertical : chaque branche apparaît sur sa propre ligne." } }, "it": { "stringUnit": { "state": "translated", - "value": "Mostra porte in ascolto nella barra laterale" + "value": "Verticale: ogni branch appare sulla propria riga." } }, "da": { "stringUnit": { "state": "translated", - "value": "Vis lyttende porte i sidebjælke" + "value": "Lodret: hver gren vises på sin egen linje." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Pokaż nasłuchujące porty na pasku bocznym" + "value": "Pionowo: każda gałąź w osobnym wierszu." } }, "ru": { "stringUnit": { "state": "translated", - "value": "Показывать прослушиваемые порты в боковой панели" + "value": "Вертикально: каждая ветка на отдельной строке." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Prikaži osluškivane portove u bočnoj traci" + "value": "Vertikalno: svaka grana se pojavljuje u svom redu." } }, "ar": { "stringUnit": { "state": "translated", - "value": "عرض المنافذ النشطة في الشريط الجانبي" + "value": "عمودي: كل فرع يظهر في سطر خاص به." } }, "nb": { "stringUnit": { "state": "translated", - "value": "Vis lyttende porter i sidepanelet" + "value": "Vertikal: hver gren vises på sin egen linje." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Mostrar Portas em Escuta na Barra Lateral" + "value": "Vertical: cada branch aparece em sua própria linha." } }, "th": { "stringUnit": { "state": "translated", - "value": "แสดงพอร์ตที่กำลังรับฟังในแถบด้านข้าง" + "value": "แบบแนวตั้ง: แต่ละสาขาแสดงในบรรทัดของตัวเอง" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Kenar Çubuğunda Dinlenen Portları Göster" - } - }, - "uk": { - "stringUnit": { - "state": "translated", - "value": "Показувати порти в бічній панелі" - } - } - } - }, - "settings.app.showSSH": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Show SSH in Sidebar" - } - }, - "ja": { - "stringUnit": { - "state": "translated", - "value": "サイドバーにSSHを表示" - } - }, - "uk": { - "stringUnit": { - "state": "translated", - "value": "Показувати SSH у бічній панелі" - } - }, - "ko": { - "stringUnit": { - "state": "translated", - "value": "사이드바에 SSH 표시" - } - } - } - }, - "settings.app.showSSH.subtitle": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Display the SSH target for remote workspaces in its own row." - } - }, - "ja": { - "stringUnit": { - "state": "translated", - "value": "リモートワークスペースのSSHターゲットを専用の行に表示します。" + "value": "Dikey: her dal kendi satırında görünür." } }, "uk": { "stringUnit": { "state": "translated", - "value": "Відображати ціль SSH для віддалених робочих областей у окремому рядку." - } - }, - "ko": { - "stringUnit": { - "state": "translated", - "value": "원격 워크스페이스의 SSH 대상을 별도 행으로 표시합니다." + "value": "Вертикально: кожна гілка на окремому рядку." } } } }, - "settings.app.showPorts.subtitle": { + "settings.app.sidebarBranchLayout.vertical": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Display detected listening ports for the active workspace." + "value": "Vertical" } }, "ja": { "stringUnit": { "state": "translated", - "value": "アクティブなワークスペースで検出されたリスニングポートを表示します。" + "value": "縦" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "显示活动工作区检测到的监听端口。" + "value": "垂直" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "顯示使用中工作區偵測到的監聽連接埠。" + "value": "垂直" } }, "ko": { "stringUnit": { "state": "translated", - "value": "활성 작업 공간에서 감지된 수신 대기 포트를 표시합니다." + "value": "세로" } }, "de": { "stringUnit": { "state": "translated", - "value": "Erkannte lauschende Ports für den aktiven Arbeitsbereich anzeigen." + "value": "Vertikal" } }, "es": { "stringUnit": { "state": "translated", - "value": "Mostrar los puertos en escucha detectados para el espacio de trabajo activo." + "value": "Vertical" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Afficher les ports en écoute détectés pour l'espace de travail actif." + "value": "Vertical" } }, "it": { "stringUnit": { "state": "translated", - "value": "Visualizza le porte in ascolto rilevate per l'area di lavoro attiva." + "value": "Verticale" } }, "da": { "stringUnit": { "state": "translated", - "value": "Vis registrerede lyttende porte for det aktive arbejdsområde." + "value": "Lodret" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Wyświetlaj wykryte nasłuchujące porty dla aktywnej przestrzeni roboczej." + "value": "Pionowo" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Отображать обнаруженные прослушиваемые порты для активного рабочего пространства." + "value": "Вертикально" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Prikaži otkrivene osluškivane portove za aktivni radni prostor." + "value": "Vertikalno" } }, "ar": { "stringUnit": { "state": "translated", - "value": "عرض المنافذ المكتشفة لمساحة العمل النشطة." + "value": "عمودي" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Vis oppdagede lyttende porter for det aktive arbeidsområdet." + "value": "Vertikal" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Exibir portas em escuta detectadas para a área de trabalho ativa." + "value": "Vertical" } }, "th": { "stringUnit": { "state": "translated", - "value": "แสดงพอร์ตที่ตรวจพบสำหรับเวิร์กสเปซที่ใช้งานอยู่" + "value": "แนวตั้ง" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Etkin çalışma alanı için algılanan dinlenen portları göster." + "value": "Dikey" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Відображати виявлені порти для активної робочої області." + "value": "Вертикально" } } } }, - "settings.app.showProgress": { + "settings.app.telemetry": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Show Progress in Sidebar" + "value": "Send anonymous telemetry" } }, "ja": { "stringUnit": { "state": "translated", - "value": "サイドバーに進捗を表示" + "value": "匿名のテレメトリを送信" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "在侧边栏显示进度" + "value": "发送匿名遥测数据" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "在側邊欄顯示進度" + "value": "傳送匿名遙測資料" } }, "ko": { "stringUnit": { "state": "translated", - "value": "사이드바에 진행 상황 표시" + "value": "익명 원격 측정 전송" } }, "de": { "stringUnit": { "state": "translated", - "value": "Fortschritt in Seitenleiste anzeigen" + "value": "Anonyme Telemetriedaten senden" } }, "es": { "stringUnit": { "state": "translated", - "value": "Mostrar progreso en la barra lateral" + "value": "Enviar telemetría anónima" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Afficher la progression dans la barre latérale" + "value": "Envoyer des données de télémétrie anonymes" } }, "it": { "stringUnit": { "state": "translated", - "value": "Mostra progresso nella barra laterale" + "value": "Invia telemetria anonima" } }, "da": { "stringUnit": { "state": "translated", - "value": "Vis fremskridt i sidebjælke" + "value": "Send anonym telemetri" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Pokaż postęp na pasku bocznym" + "value": "Wysyłaj anonimową telemetrię" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Показывать прогресс в боковой панели" + "value": "Отправлять анонимную телеметрию" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Prikaži napredak u bočnoj traci" + "value": "Šalji anonimnu telemetriju" } }, "ar": { "stringUnit": { "state": "translated", - "value": "عرض التقدم في الشريط الجانبي" + "value": "إرسال بيانات تحليلية مجهولة" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Vis fremdrift i sidepanelet" + "value": "Send anonym telemetri" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Mostrar Progresso na Barra Lateral" + "value": "Enviar telemetria anônima" } }, "th": { "stringUnit": { "state": "translated", - "value": "แสดงความคืบหน้าในแถบด้านข้าง" + "value": "ส่งข้อมูลการวิเคราะห์แบบไม่ระบุตัวตน" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Kenar Çubuğunda İlerlemeyi Göster" + "value": "Anonim telemetri gönder" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Показувати прогрес у бічній панелі" + "value": "Надсилати анонімну телеметрію" } } } }, - "settings.app.showProgress.subtitle": { + "settings.app.telemetry.subtitle": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Display the built-in progress bar from set_progress." + "value": "Share anonymized crash and usage data to help improve cmux." } }, "ja": { "stringUnit": { "state": "translated", - "value": "set_progressによる組み込みプログレスバーを表示します。" + "value": "cmuxの改善に役立てるため、匿名化されたクラッシュおよび使用状況データを共有します。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "显示来自 set_progress 的内置进度条。" + "value": "分享匿名的崩溃和使用数据,帮助改进 cmux。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "顯示來自 set_progress 的內建進度列。" + "value": "分享匿名的當機與使用資料,以協助改善 cmux。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "set_progress의 기본 제공 진행 표시줄을 표시합니다." + "value": "cmux 개선을 위해 익명화된 충돌 및 사용 데이터를 공유합니다." } }, "de": { "stringUnit": { "state": "translated", - "value": "Den integrierten Fortschrittsbalken von set_progress anzeigen." + "value": "Anonymisierte Absturz- und Nutzungsdaten teilen, um cmux zu verbessern." } }, "es": { "stringUnit": { "state": "translated", - "value": "Mostrar la barra de progreso integrada de set_progress." + "value": "Compartir datos anónimos de fallos y uso para ayudar a mejorar cmux." } }, "fr": { "stringUnit": { "state": "translated", - "value": "Afficher la barre de progression intégrée de set_progress." + "value": "Partager des données anonymisées de plantage et d'utilisation pour aider à améliorer cmux." } }, "it": { "stringUnit": { "state": "translated", - "value": "Visualizza la barra di progresso integrata da set_progress." + "value": "Condividi dati anonimi su arresti anomali e utilizzo per migliorare cmux." } }, "da": { "stringUnit": { "state": "translated", - "value": "Vis den indbyggede fremskridtslinje fra set_progress." + "value": "Del anonymiserede nedbrud- og brugsdata for at hjælpe med at forbedre cmux." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Wyświetlaj wbudowany pasek postępu z set_progress." + "value": "Udostępniaj zanonimizowane dane o awariach i użyciu, aby pomóc ulepszyć cmux." } }, "ru": { "stringUnit": { "state": "translated", - "value": "Отображать встроенный индикатор прогресса из set_progress." + "value": "Делиться анонимными данными о сбоях и использовании для улучшения cmux." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Prikaži ugrađenu traku napretka iz set_progress." + "value": "Dijelite anonimizirane podatke o padovima i korištenju kako biste pomogli u poboljšanju cmux." } }, "ar": { "stringUnit": { "state": "translated", - "value": "عرض شريط التقدم المدمج من set_progress." + "value": "مشاركة بيانات الأعطال والاستخدام المجهولة للمساعدة في تحسين cmux." } }, "nb": { "stringUnit": { "state": "translated", - "value": "Vis den innebygde fremdriftsindikatoren fra set_progress." + "value": "Del anonymiserte krasj- og bruksdata for å bidra til å forbedre cmux." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Exibir a barra de progresso integrada de set_progress." + "value": "Compartilhar dados anonimizados de falhas e uso para ajudar a melhorar o cmux." } }, "th": { "stringUnit": { "state": "translated", - "value": "แสดงแถบความคืบหน้าในตัวจาก set_progress" + "value": "แชร์ข้อมูลการขัดข้องและการใช้งานแบบไม่ระบุตัวตนเพื่อช่วยปรับปรุง cmux" } }, "tr": { "stringUnit": { "state": "translated", - "value": "set_progress'ten yerleşik ilerleme çubuğunu göster." + "value": "cmux'u iyileştirmek için anonimleştirilmiş çökme ve kullanım verilerini paylaş." } }, "uk": { "stringUnit": { "state": "translated", - "value": "Відображати вбудований індикатор прогресу з set_progress." + "value": "Надсилати анонімні дані про збої та використання для покращення cmux." } } } }, - "settings.app.showWorkspaceTitlebar": { + "settings.app.telemetry.subtitleChanged": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Show Workspace Title Bar" + "value": "Change takes effect on next launch." } }, "ja": { "stringUnit": { "state": "translated", - "value": "ワークスペースのタイトルバーを表示" + "value": "変更は次回起動時に反映されます。" } }, - "uk": { + "zh-Hans": { "stringUnit": { "state": "translated", - "value": "Показувати заголовок робочої області" + "value": "更改将在下次启动时生效。" } }, - "ko": { - "stringUnit": { - "state": "translated", - "value": "워크스페이스 제목 표시줄 표시" - } - } - } - }, - "settings.app.showWorkspaceTitlebar.subtitleOff": { - "extractionState": "manual", - "localizations": { - "en": { + "zh-Hant": { "stringUnit": { "state": "translated", - "value": "Hide the folder and active title above pane tabs." + "value": "變更將在下次啟動時生效。" } }, - "ja": { + "ko": { "stringUnit": { "state": "translated", - "value": "ペインタブの上にあるフォルダ名と現在のタイトルを隠します。" + "value": "변경 사항은 다음 실행 시 적용됩니다." } }, - "uk": { + "de": { "stringUnit": { "state": "translated", - "value": "Сховати теку та активний заголовок над вкладками панелей." + "value": "Änderung wird beim nächsten Start wirksam." } }, - "ko": { + "es": { "stringUnit": { "state": "translated", - "value": "패인 탭 위의 폴더 및 활성 제목을 숨깁니다." + "value": "El cambio se aplicará en el próximo inicio." } - } - } - }, - "settings.app.showWorkspaceTitlebar.subtitleOn": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "fr": { "stringUnit": { "state": "translated", - "value": "Show the folder and active title above pane tabs." + "value": "La modification prendra effet au prochain lancement." } }, - "ja": { + "it": { "stringUnit": { "state": "translated", - "value": "ペインタブの上にフォルダ名と現在のタイトルを表示します。" + "value": "La modifica avrà effetto al prossimo avvio." } }, - "uk": { + "da": { "stringUnit": { "state": "translated", - "value": "Показувати теку та активний заголовок над вкладками панелей." + "value": "Ændringen træder i kraft ved næste start." } }, - "ko": { + "pl": { "stringUnit": { "state": "translated", - "value": "패인 탭 위에 폴더 및 활성 제목을 표시합니다." + "value": "Zmiana zacznie obowiązywać po ponownym uruchomieniu." } - } - } - }, - "settings.app.fadeButtons": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "ru": { "stringUnit": { "state": "translated", - "value": "Fade Buttons" + "value": "Изменение вступит в силу при следующем запуске." } }, - "ja": { + "bs": { "stringUnit": { "state": "translated", - "value": "ボタンをフェード表示" + "value": "Promjena stupa na snagu pri sljedećem pokretanju." } }, - "uk": { + "ar": { "stringUnit": { "state": "translated", - "value": "Приховування кнопок" + "value": "يسري التغيير عند التشغيل التالي." } }, - "ko": { + "nb": { "stringUnit": { "state": "translated", - "value": "버튼 페이드" + "value": "Endringen trer i kraft ved neste oppstart." } - } - } - }, - "settings.app.fadeButtons.subtitleOff": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "pt-BR": { "stringUnit": { "state": "translated", - "value": "Keep action buttons always visible." + "value": "A alteração terá efeito na próxima inicialização." } }, - "ja": { + "th": { "stringUnit": { "state": "translated", - "value": "操作ボタンを常に表示します。" + "value": "การเปลี่ยนแปลงจะมีผลเมื่อเปิดใหม่ครั้งถัดไป" } }, - "uk": { + "tr": { "stringUnit": { "state": "translated", - "value": "Кнопки дій завжди видимі." + "value": "Değişiklik bir sonraki başlatmada geçerli olur." } }, - "ko": { + "uk": { "stringUnit": { "state": "translated", - "value": "액션 버튼을 항상 표시합니다." + "value": "Зміна набуде чинності при наступному запуску." } } } }, - "settings.app.fadeButtons.subtitleOn": { + "settings.app.theme": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Show action buttons only on hover." + "value": "Theme" } }, "ja": { "stringUnit": { "state": "translated", - "value": "操作ボタンはホバー時のみ表示します。" + "value": "テーマ" } }, - "uk": { + "zh-Hans": { "stringUnit": { "state": "translated", - "value": "Кнопки дій з'являються лише при наведенні." + "value": "主题" + } + }, + "zh-Hant": { + "stringUnit": { + "state": "translated", + "value": "主題" } }, "ko": { "stringUnit": { "state": "translated", - "value": "마우스를 올렸을 때만 액션 버튼을 표시합니다." + "value": "테마" } - } - } - }, - "settings.app.minimalMode": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "de": { "stringUnit": { "state": "translated", - "value": "Minimal Mode" + "value": "Design" } }, - "ja": { + "es": { "stringUnit": { "state": "translated", - "value": "ミニマルモード" + "value": "Tema" } }, - "uk": { + "fr": { "stringUnit": { "state": "translated", - "value": "Мінімальний режим" + "value": "Thème" } }, - "ko": { + "it": { "stringUnit": { "state": "translated", - "value": "미니멀 모드" + "value": "Tema" } - } - } - }, - "settings.app.minimalMode.subtitleOff": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "da": { "stringUnit": { "state": "translated", - "value": "Use the standard workspace title bar and controls." + "value": "Tema" } }, - "ja": { + "pl": { "stringUnit": { "state": "translated", - "value": "標準のワークスペースタイトルバーと操作を使います。" + "value": "Motyw" } }, - "uk": { + "ru": { "stringUnit": { "state": "translated", - "value": "Використовувати стандартний заголовок робочої області та елементи керування." + "value": "Тема" } }, - "ko": { + "bs": { "stringUnit": { "state": "translated", - "value": "기본 워크스페이스 제목 표시줄과 컨트롤을 사용합니다." + "value": "Tema" } - } - } - }, - "settings.app.minimalMode.subtitleOn": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "ar": { "stringUnit": { "state": "translated", - "value": "Hide the workspace title bar and move workspace controls into the sidebar." + "value": "المظهر" } }, - "ja": { + "nb": { "stringUnit": { "state": "translated", - "value": "ワークスペースのタイトルバーを隠し、ワークスペース操作をサイドバーに移動します。" + "value": "Tema" } }, - "uk": { + "pt-BR": { "stringUnit": { "state": "translated", - "value": "Сховати заголовок робочої області та перемістити елементи керування в бічну панель." + "value": "Tema" } }, - "ko": { + "th": { "stringUnit": { "state": "translated", - "value": "워크스페이스 제목 표시줄을 숨기고 워크스페이스 컨트롤을 사이드바로 이동합니다." + "value": "ธีม" + } + }, + "tr": { + "stringUnit": { + "state": "translated", + "value": "Tema" + } + }, + "uk": { + "stringUnit": { + "state": "translated", + "value": "Тема" } } } }, - "settings.app.showPullRequests": { + "settings.app.warnBeforeQuit": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Show Pull Requests in Sidebar" + "value": "Warn Before Quit" } }, "ja": { "stringUnit": { "state": "translated", - "value": "サイドバーにプルリクエストを表示" + "value": "終了前に警告" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "在侧边栏显示拉取请求" + "value": "退出前警告" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "在側邊欄顯示 Pull Request" + "value": "結束前警告" } }, "ko": { "stringUnit": { "state": "translated", - "value": "사이드바에 Pull Request 표시" + "value": "종료 전 경고" } }, "de": { "stringUnit": { "state": "translated", - "value": "Pull Requests in Seitenleiste anzeigen" + "value": "Vor dem Beenden warnen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Mostrar pull requests en la barra lateral" + "value": "Advertir antes de salir" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Afficher les Pull Requests dans la barre latérale" + "value": "Avertir avant de quitter" } }, "it": { "stringUnit": { "state": "translated", - "value": "Mostra Pull Request nella barra laterale" + "value": "Avvisa prima di uscire" } }, "da": { "stringUnit": { "state": "translated", - "value": "Vis pull requests i sidebjælke" + "value": "Advar før afslutning" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Pokaż pull requesty na pasku bocznym" + "value": "Ostrzegaj przed zamknięciem" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Показывать запросы на слияние в боковой панели" + "value": "Предупреждать перед выходом" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Prikaži pull zahtjeve u bočnoj traci" + "value": "Upozori prije zatvaranja" } }, "ar": { "stringUnit": { "state": "translated", - "value": "عرض طلبات السحب في الشريط الجانبي" + "value": "التحذير قبل الإنهاء" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Vis pull-forespørsler i sidepanelet" + "value": "Advar før avslutning" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Mostrar Pull Requests na Barra Lateral" + "value": "Avisar Antes de Encerrar" } }, "th": { "stringUnit": { "state": "translated", - "value": "แสดง Pull Request ในแถบด้านข้าง" + "value": "เตือนก่อนออก" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Kenar Çubuğunda Çekme İsteklerini Göster" + "value": "Çıkmadan Önce Uyar" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Показувати запити на злиття в бічній панелі" + "value": "Попереджувати перед виходом" } } } }, - "settings.app.showPullRequests.subtitle": { + "settings.app.warnBeforeQuit.subtitleOff": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Display review items (PR/MR/etc.) with status and number." + "value": "Cmd+Q quits immediately without confirmation." } }, "ja": { "stringUnit": { "state": "translated", - "value": "ステータスと番号付きのレビュー項目(PR/MRなど)を表示します。" + "value": "Cmd+Qで確認なしにすぐ終了します。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "显示包含状态和编号的审查项(PR/MR 等)。" + "value": "Cmd+Q 直接退出,无需确认。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "顯示審查項目(PR/MR 等),包含狀態和編號。" + "value": "Cmd+Q 會立即結束,不顯示確認提示。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "상태와 번호가 있는 리뷰 항목(PR/MR 등)을 표시합니다." + "value": "Cmd+Q를 누르면 확인 없이 즉시 종료됩니다." } }, "de": { "stringUnit": { "state": "translated", - "value": "Review-Elemente (PR/MR/etc.) mit Status und Nummer anzeigen." + "value": "Cmd+Q beendet sofort ohne Bestätigung." } }, "es": { "stringUnit": { "state": "translated", - "value": "Mostrar elementos de revisión (PR/MR/etc.) con estado y número." + "value": "Cmd+Q sale inmediatamente sin confirmación." } }, "fr": { "stringUnit": { "state": "translated", - "value": "Afficher les éléments de revue (PR/MR/etc.) avec le statut et le numéro." + "value": "Cmd+Q quitte immédiatement sans confirmation." } }, "it": { "stringUnit": { "state": "translated", - "value": "Visualizza elementi di revisione (PR/MR/ecc.) con stato e numero." + "value": "Cmd+Q esce immediatamente senza conferma." } }, "da": { "stringUnit": { "state": "translated", - "value": "Vis gennemgangselementer (PR/MR osv.) med status og nummer." + "value": "Cmd+Q afslutter øjeblikkeligt uden bekræftelse." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Wyświetlaj elementy przeglądu (PR/MR/itp.) ze statusem i numerem." + "value": "Cmd+Q zamyka natychmiast bez potwierdzenia." } }, "ru": { "stringUnit": { "state": "translated", - "value": "Отображать элементы проверки (PR/MR и т.д.) со статусом и номером." + "value": "Cmd+Q завершает приложение немедленно без подтверждения." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Prikaži stavke za pregled (PR/MR/itd.) sa statusom i brojem." + "value": "Cmd+Q odmah zatvara bez potvrde." } }, "ar": { "stringUnit": { "state": "translated", - "value": "عرض عناصر المراجعة (طلبات السحب/الدمج/إلخ.) مع الحالة والرقم." + "value": "Cmd+Q ينهي فورًا بدون تأكيد." } }, "nb": { "stringUnit": { "state": "translated", - "value": "Vis gjennomgangselementer (PR/MR/osv.) med status og nummer." + "value": "Cmd+Q avslutter umiddelbart uten bekreftelse." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Exibir itens de revisão (PR/MR/etc.) com status e número." + "value": "Cmd+Q encerra imediatamente sem confirmação." } }, "th": { "stringUnit": { "state": "translated", - "value": "แสดงรายการตรวจสอบ (PR/MR/อื่นๆ) พร้อมสถานะและหมายเลข" + "value": "Cmd+Q ออกทันทีโดยไม่มีการยืนยัน" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Durum ve numarayla inceleme öğelerini (PR/MR/vb.) göster." + "value": "Cmd+Q onay olmadan hemen çıkar." } }, "uk": { "stringUnit": { "state": "translated", - "value": "Відображати елементи перегляду (PR/MR тощо) зі статусом і номером." + "value": "Cmd+Q закриває програму негайно без підтвердження." } } } }, - "settings.app.watchGitStatus": { + "settings.app.warnBeforeQuit.subtitleOn": { "extractionState": "manual", "localizations": { - "ar": { + "en": { "stringUnit": { "state": "translated", - "value": "مراقبة حالة Git في الشريط الجانبي" + "value": "Show a confirmation before quitting with Cmd+Q." } }, - "bs": { + "ja": { "stringUnit": { "state": "translated", - "value": "Prati Git status u bočnoj traci" + "value": "Cmd+Qで終了する前に確認を表示します。" } }, - "da": { + "zh-Hans": { "stringUnit": { "state": "translated", - "value": "Overvåg Git-status i sidepanelet" + "value": "使用 Cmd+Q 退出前显示确认对话框。" } }, - "de": { + "zh-Hant": { "stringUnit": { "state": "translated", - "value": "Git-Status in der Seitenleiste überwachen" + "value": "使用 Cmd+Q 結束前顯示確認提示。" } }, - "en": { + "ko": { + "stringUnit": { + "state": "translated", + "value": "Cmd+Q로 종료하기 전에 확인 대화상자를 표시합니다." + } + }, + "de": { "stringUnit": { "state": "translated", - "value": "Watch Git Status in Sidebar" + "value": "Vor dem Beenden mit Cmd+Q eine Bestätigung anzeigen." } }, "es": { "stringUnit": { "state": "translated", - "value": "Vigilar el estado de Git en la barra lateral" + "value": "Mostrar una confirmación antes de salir con Cmd+Q." } }, "fr": { "stringUnit": { "state": "translated", - "value": "Surveiller l’état Git dans la barre latérale" + "value": "Afficher une confirmation avant de quitter avec Cmd+Q." } }, "it": { "stringUnit": { "state": "translated", - "value": "Monitora lo stato Git nella barra laterale" + "value": "Mostra una conferma prima di uscire con Cmd+Q." } }, - "ja": { + "da": { "stringUnit": { "state": "translated", - "value": "サイドバーで Git 状態を監視" + "value": "Vis en bekræftelse, før du afslutter med Cmd+Q." } }, - "ko": { + "pl": { "stringUnit": { "state": "translated", - "value": "사이드바에서 Git 상태 감시" + "value": "Pokaż potwierdzenie przed zamknięciem za pomocą Cmd+Q." } }, - "nb": { + "ru": { "stringUnit": { "state": "translated", - "value": "Overvåk Git-status i sidepanelet" + "value": "Показывать подтверждение перед выходом по Cmd+Q." } }, - "pl": { + "bs": { "stringUnit": { "state": "translated", - "value": "Monitoruj status Git na pasku bocznym" + "value": "Prikaži potvrdu prije zatvaranja sa Cmd+Q." } }, - "pt-BR": { + "ar": { "stringUnit": { "state": "translated", - "value": "Monitorar status do Git na barra lateral" + "value": "عرض تأكيد قبل الإنهاء بـ Cmd+Q." } }, - "ru": { + "nb": { + "stringUnit": { + "state": "translated", + "value": "Vis en bekreftelse før avslutning med Cmd+Q." + } + }, + "pt-BR": { "stringUnit": { "state": "translated", - "value": "Отслеживать состояние Git на боковой панели" + "value": "Mostrar uma confirmação antes de encerrar com Cmd+Q." } }, "th": { "stringUnit": { "state": "translated", - "value": "ติดตามสถานะ Git ในแถบด้านข้าง" + "value": "แสดงการยืนยันก่อนออกด้วย Cmd+Q" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Kenar çubuğunda Git durumunu izle" + "value": "Cmd+Q ile çıkmadan önce onay göster." } }, "uk": { "stringUnit": { "state": "translated", - "value": "Відстежувати стан Git на бічній панелі" + "value": "Показувати підтвердження перед виходом через Cmd+Q." } - }, - "zh-Hans": { + } + } + }, + "settings.app.warnBeforeClosingTab": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "在侧边栏监视 Git 状态" + "value": "Warn Before Closing Tab" } }, - "zh-Hant": { + "ja": { "stringUnit": { "state": "translated", - "value": "在側邊欄監視 Git 狀態" + "value": "タブを閉じる前に警告" } } } }, - "settings.app.watchGitStatus.subtitle": { + "settings.app.warnBeforeClosingTab.subtitleOff": { "extractionState": "manual", "localizations": { - "ar": { + "en": { "stringUnit": { "state": "translated", - "value": "حدّث بيانات الفرع وطلبات السحب في الشريط الجانبي من تغييرات ملفات المستودع دون استطلاع git." + "value": "Tabs close immediately without confirmation." } }, - "bs": { + "ja": { "stringUnit": { "state": "translated", - "value": "Ažuriraj granu i PR metapodatke u bočnoj traci iz promjena datoteka repozitorija bez anketiranja git-a." + "value": "確認なしにすぐタブを閉じます。" } - }, - "da": { + } + } + }, + "settings.app.warnBeforeClosingTab.subtitleOn": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Opdater sidepanelets gren- og PR-metadata fra ændringer i repositoryfiler uden at polle git." + "value": "Show a confirmation before closing a tab." } }, - "de": { + "ja": { "stringUnit": { "state": "translated", - "value": "Aktualisiert Branch- und PR-Metadaten in der Seitenleiste aus Repository-Dateiänderungen, ohne git abzufragen." + "value": "タブを閉じる前に確認を表示します。" } - }, + } + } + }, + "settings.notifications.sound.custom.choose.button": { + "extractionState": "manual", + "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Update sidebar branch and PR metadata from repository file changes without polling git." + "value": "Choose..." } }, - "es": { + "ja": { "stringUnit": { "state": "translated", - "value": "Actualiza la rama y los metadatos de PR de la barra lateral desde cambios de archivos del repositorio sin consultar git periódicamente." + "value": "選択..." } }, - "fr": { + "uk": { "stringUnit": { "state": "translated", - "value": "Met à jour la branche et les métadonnées de PR de la barre latérale depuis les changements de fichiers du dépôt, sans interroger git." + "value": "Вибрати..." } }, - "it": { + "ko": { + "stringUnit": { + "state": "translated", + "value": "선택..." + } + } + } + }, + "settings.notifications.sound.custom.choose.prompt": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Aggiorna ramo e metadati PR nella barra laterale dalle modifiche ai file del repository senza interrogare git." + "value": "Choose" } }, "ja": { "stringUnit": { "state": "translated", - "value": "git をポーリングせず、リポジトリのファイル変更からサイドバーのブランチと PR メタデータを更新します。" + "value": "選択" } }, - "ko": { + "uk": { "stringUnit": { "state": "translated", - "value": "git을 폴링하지 않고 저장소 파일 변경으로 사이드바 브랜치와 PR 메타데이터를 업데이트합니다." + "value": "Вибрати" } }, - "nb": { + "ko": { "stringUnit": { "state": "translated", - "value": "Oppdater sidepanelets gren- og PR-metadata fra endringer i repositoryfiler uten å spørre git." + "value": "선택" } - }, - "pl": { + } + } + }, + "settings.notifications.sound.custom.choose.title": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Aktualizuj gałąź i metadane PR na pasku bocznym na podstawie zmian plików repozytorium bez odpytywania git." + "value": "Choose Notification Sound" } }, - "pt-BR": { + "ja": { "stringUnit": { "state": "translated", - "value": "Atualize a branch e os metadados de PR da barra lateral a partir de mudanças nos arquivos do repositório sem consultar o git periodicamente." + "value": "通知サウンドを選択" } }, - "ru": { + "uk": { "stringUnit": { "state": "translated", - "value": "Обновлять ветку и метаданные PR на боковой панели по изменениям файлов репозитория без опроса git." + "value": "Вибрати звук сповіщення" } }, - "th": { + "ko": { "stringUnit": { "state": "translated", - "value": "อัปเดตสาขาและข้อมูลเมตา PR ในแถบด้านข้างจากการเปลี่ยนแปลงไฟล์ของที่เก็บโดยไม่ต้อง polling git" + "value": "알림 소리 선택" } - }, - "tr": { + } + } + }, + "settings.notifications.sound.custom.clear.button": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Kenar çubuğu dal ve PR meta verilerini git’i yoklamadan depo dosyası değişikliklerinden güncelle." + "value": "Clear" } }, - "uk": { + "ja": { "stringUnit": { "state": "translated", - "value": "Оновлювати гілку та метадані PR на бічній панелі за змінами файлів репозиторію без опитування git." + "value": "クリア" } }, - "zh-Hans": { + "uk": { "stringUnit": { "state": "translated", - "value": "根据仓库文件变化更新侧边栏分支和 PR 元数据,而不轮询 git。" + "value": "Очистити" } }, - "zh-Hant": { + "ko": { "stringUnit": { "state": "translated", - "value": "根據儲存庫檔案變更更新側邊欄分支與 PR 中繼資料,而不輪詢 git。" + "value": "지우기" } } } }, - "settings.app.showPullRequests.subtitle.basic": { + "settings.notifications.sound.custom.error.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Display review items (PR/MR/etc.) with status and number." + "value": "Custom Notification Sound Error" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ステータスと番号付きのレビュー項目(PR/MRなど)を表示します。" + "value": "カスタム通知サウンドのエラー" } - } - } - }, - "settings.app.makeSidebarPullRequestClickable": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "uk": { "stringUnit": { "state": "translated", - "value": "Make Sidebar PR Clickable" + "value": "Помилка власного звуку сповіщення" } }, - "ja": { + "ko": { "stringUnit": { "state": "translated", - "value": "サイドバーのPRをクリック可能にする" + "value": "사용자 지정 알림 소리 오류" } } } }, - "settings.app.makeSidebarPullRequestClickable.subtitle": { + "settings.notifications.sound.custom.file.none": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Review items stay visible as plain text, and clicks in that area select the workspace row." + "value": "No file selected" } }, "ja": { "stringUnit": { "state": "translated", - "value": "レビュー項目は通常のテキストとして表示され、その領域をクリックするとワークスペース行が選択されます。" + "value": "ファイル未選択" + } + }, + "uk": { + "stringUnit": { + "state": "translated", + "value": "Файл не вибрано" + } + }, + "ko": { + "stringUnit": { + "state": "translated", + "value": "선택된 파일 없음" } } } }, - "settings.app.sidebarBranchLayout": { + "settings.notifications.sound.custom.status.empty": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Sidebar Branch Layout" + "value": "Choose a custom audio file first." } }, "ja": { "stringUnit": { "state": "translated", - "value": "サイドバーのブランチレイアウト" + "value": "先にカスタム音声ファイルを選択してください。" } }, - "zh-Hans": { + "uk": { "stringUnit": { "state": "translated", - "value": "侧边栏分支布局" + "value": "Спочатку виберіть файл аудіо." } }, - "zh-Hant": { + "ko": { "stringUnit": { "state": "translated", - "value": "側邊欄分支版面" + "value": "먼저 사용자 지정 오디오 파일을 선택하세요." } - }, - "ko": { + } + } + }, + "settings.notifications.sound.custom.status.missingExtensionPrefix": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "사이드바 브랜치 레이아웃" + "value": "File needs an extension: " } }, - "de": { + "ja": { "stringUnit": { "state": "translated", - "value": "Seitenleisten-Branch-Layout" + "value": "拡張子が必要です: " } }, - "es": { + "uk": { "stringUnit": { "state": "translated", - "value": "Disposición de ramas en la barra lateral" + "value": "Файлу потрібне розширення: " } }, - "fr": { + "ko": { "stringUnit": { "state": "translated", - "value": "Disposition des branches dans la barre latérale" + "value": "파일에 확장자가 필요합니다: " } - }, - "it": { + } + } + }, + "settings.notifications.sound.custom.status.missingFilePrefix": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Layout branch nella barra laterale" + "value": "File not found: " } }, - "da": { + "ja": { "stringUnit": { "state": "translated", - "value": "Sidebjælkens grenlayout" + "value": "ファイルが見つかりません: " } }, - "pl": { + "uk": { "stringUnit": { "state": "translated", - "value": "Układ gałęzi na pasku bocznym" + "value": "Файл не знайдено: " } }, - "ru": { + "ko": { "stringUnit": { "state": "translated", - "value": "Макет веток в боковой панели" + "value": "파일을 찾을 수 없습니다: " } - }, - "bs": { + } + } + }, + "settings.notifications.sound.custom.status.prepareFailed": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Raspored grana u bočnoj traci" + "value": "Could not prepare this file for notifications. Try WAV, AIFF, or CAF." } }, - "ar": { + "ja": { "stringUnit": { "state": "translated", - "value": "تخطيط الفروع في الشريط الجانبي" + "value": "通知用にこのファイルを準備できませんでした。WAV、AIFF、またはCAFを試してください。" } }, - "nb": { + "uk": { "stringUnit": { "state": "translated", - "value": "Grenoppsett i sidepanelet" + "value": "Не вдалося підготувати цей файл для сповіщень. Спробуйте WAV, AIFF або CAF." } }, - "pt-BR": { + "ko": { "stringUnit": { "state": "translated", - "value": "Layout de Branch na Barra Lateral" + "value": "이 파일을 알림용으로 준비할 수 없습니다. WAV, AIFF 또는 CAF를 사용해 보세요." } - }, - "th": { + } + } + }, + "settings.notifications.sound.custom.status.ready": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "เค้าโครงสาขาในแถบด้านข้าง" + "value": "Ready for notifications." } }, - "tr": { + "ja": { "stringUnit": { "state": "translated", - "value": "Kenar Çubuğu Dal Düzeni" + "value": "通知用の準備ができました。" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Макет гілок у бічній панелі" + "value": "Готовий для сповіщень." + } + }, + "ko": { + "stringUnit": { + "state": "translated", + "value": "알림 준비 완료." } } } }, - "settings.app.sidebarBranchLayout.inline": { + "settings.notifications.sound.custom.status.readyConverted": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Inline" + "value": "Prepared for notifications (converted to CAF)." } }, "ja": { "stringUnit": { "state": "translated", - "value": "インライン" + "value": "通知用に準備しました(CAFに変換)。" } }, - "zh-Hans": { + "uk": { "stringUnit": { "state": "translated", - "value": "单行" + "value": "Підготовлений для сповіщень (конвертовано в CAF)." } }, - "zh-Hant": { + "ko": { "stringUnit": { "state": "translated", - "value": "行內" + "value": "알림 준비 완료 (CAF로 변환됨)." } - }, - "ko": { + } + } + }, + "settings.notifications.sound.subtitle": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "인라인" + "value": "Sound played when a notification arrives." } }, - "de": { + "ja": { "stringUnit": { "state": "translated", - "value": "Einzeilig" + "value": "通知を受信したときに再生するサウンドです。" } }, - "es": { + "uk": { "stringUnit": { "state": "translated", - "value": "En línea" + "value": "Звук, який відтворюється при надходженні сповіщення." } }, - "fr": { + "ko": { "stringUnit": { "state": "translated", - "value": "En ligne" + "value": "알림이 도착했을 때 재생되는 소리입니다." } - }, - "it": { + } + } + }, + "settings.notifications.paneRing.subtitle": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "In linea" + "value": "Show a blue ring around panes with unread notifications." } }, - "da": { + "ja": { "stringUnit": { "state": "translated", - "value": "Inline" + "value": "未読の通知があるペインの周囲に青いリングを表示します。" } }, - "pl": { + "uk": { "stringUnit": { "state": "translated", - "value": "W linii" + "value": "Показувати синє кільце навколо панелей з непрочитаними сповіщеннями." } }, - "ru": { + "ko": { "stringUnit": { "state": "translated", - "value": "В строку" + "value": "읽지 않은 알림이 있는 패인 주위에 파란색 링을 표시합니다." } - }, - "bs": { + } + } + }, + "settings.notifications.paneFlash.subtitle": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "U redu" + "value": "Briefly flash a blue outline when cmux highlights a pane." } }, - "ar": { + "ja": { "stringUnit": { "state": "translated", - "value": "سطري" + "value": "cmux がペインを強調表示するときに短い青いアウトラインを表示します。" } }, - "nb": { + "uk": { "stringUnit": { "state": "translated", - "value": "Innebygd" + "value": "Короткочасно підсвічувати синьою рамкою панель, на яку cmux звертає увагу." } }, - "pt-BR": { + "ko": { "stringUnit": { "state": "translated", - "value": "Em Linha" + "value": "cmux가 패인을 강조할 때 파란색 테두리를 잠시 깜빡입니다." } - }, - "th": { + } + } + }, + "settings.notifications.paneFlash.title": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "แบบอินไลน์" + "value": "Pane Flash" } }, - "tr": { + "ja": { "stringUnit": { "state": "translated", - "value": "Satır İçi" + "value": "ペインフラッシュ" } }, "uk": { "stringUnit": { "state": "translated", - "value": "В рядок" + "value": "Підсвічування панелі" + } + }, + "ko": { + "stringUnit": { + "state": "translated", + "value": "패인 플래시" } } } }, - "settings.app.sidebarBranchLayout.subtitleInline": { + "settings.notifications.paneRing.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Inline: all branches share one line." + "value": "Unread Pane Ring" } }, "ja": { "stringUnit": { "state": "translated", - "value": "インライン: すべてのブランチが1行に表示されます。" - } - }, - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "单行:所有分支共享一行。" + "value": "未読ペインリング" } }, - "zh-Hant": { + "uk": { "stringUnit": { "state": "translated", - "value": "行內:所有分支共用一行。" + "value": "Кільце непрочитаних панелей" } }, "ko": { "stringUnit": { "state": "translated", - "value": "인라인: 모든 브랜치가 한 줄에 표시됩니다." + "value": "읽지 않은 패인 링" } - }, - "de": { + } + } + }, + "settings.notifications.sound.title": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Einzeilig: Alle Branches teilen sich eine Zeile." + "value": "Notification Sound" } }, - "es": { + "ja": { "stringUnit": { "state": "translated", - "value": "En línea: todas las ramas comparten una sola línea." + "value": "通知サウンド" } }, - "fr": { + "uk": { "stringUnit": { "state": "translated", - "value": "En ligne : toutes les branches partagent une seule ligne." + "value": "Звук сповіщення" } }, - "it": { + "ko": { "stringUnit": { "state": "translated", - "value": "In linea: tutti i branch condividono una riga." + "value": "알림 소리" } - }, - "da": { - "stringUnit": { - "state": "translated", - "value": "Inline: alle grene deler én linje." - } - }, - "pl": { - "stringUnit": { - "state": "translated", - "value": "W linii: wszystkie gałęzie w jednym wierszu." - } - }, - "ru": { + } + } + }, + "settings.notifications.desktop": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "В строку: все ветки в одной строке." + "value": "Desktop Notifications" } }, - "bs": { + "ja": { "stringUnit": { "state": "translated", - "value": "U redu: sve grane dijele jednu liniju." + "value": "デスクトップ通知" } - }, - "ar": { + } + } + }, + "settings.notifications.command": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "سطري: جميع الفروع تشترك في سطر واحد." + "value": "Notification Command" } }, - "nb": { + "ja": { "stringUnit": { "state": "translated", - "value": "Innebygd: alle grener deler én linje." + "value": "通知コマンド" } - }, - "pt-BR": { + } + } + }, + "settings.notifications.command.subtitle": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Em Linha: todas as branches compartilham uma linha." + "value": "Run a shell command when a notification arrives. $CMUX_NOTIFICATION_TITLE, $CMUX_NOTIFICATION_SUBTITLE, $CMUX_NOTIFICATION_BODY are set." } }, - "th": { + "ja": { "stringUnit": { "state": "translated", - "value": "แบบอินไลน์: สาขาทั้งหมดแสดงในบรรทัดเดียว" + "value": "通知が届いたときにシェルコマンドを実行します。$CMUX_NOTIFICATION_TITLE、$CMUX_NOTIFICATION_SUBTITLE、$CMUX_NOTIFICATION_BODY が設定されます。" } - }, - "tr": { + } + } + }, + "settings.notifications.command.placeholder": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Satır İçi: tüm dallar tek satırı paylaşır." + "value": "say \"done\"" } }, - "uk": { + "ja": { "stringUnit": { "state": "translated", - "value": "В рядок: усі гілки в одному рядку." + "value": "say \"done\"" } } } }, - "settings.app.sidebarBranchLayout.subtitleVertical": { + "settings.automation.claudeCode": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Vertical: each branch appears on its own line." + "value": "Claude Code Integration" } }, "ja": { "stringUnit": { "state": "translated", - "value": "縦: 各ブランチがそれぞれの行に表示されます。" + "value": "Claude Code連携" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "垂直:每个分支独占一行。" + "value": "Claude Code 集成" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "垂直:每個分支獨立一行。" + "value": "Claude Code 整合" } }, "ko": { "stringUnit": { "state": "translated", - "value": "세로: 각 브랜치가 별도의 줄에 표시됩니다." + "value": "Claude Code 연동" } }, "de": { "stringUnit": { "state": "translated", - "value": "Vertikal: Jeder Branch erscheint in einer eigenen Zeile." + "value": "Claude Code-Integration" } }, "es": { "stringUnit": { "state": "translated", - "value": "Vertical: cada rama aparece en su propia línea." + "value": "Integración con Claude Code" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Vertical : chaque branche apparaît sur sa propre ligne." + "value": "Intégration Claude Code" } }, "it": { "stringUnit": { "state": "translated", - "value": "Verticale: ogni branch appare sulla propria riga." + "value": "Integrazione Claude Code" } }, "da": { "stringUnit": { "state": "translated", - "value": "Lodret: hver gren vises på sin egen linje." + "value": "Claude Code-integration" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Pionowo: każda gałąź w osobnym wierszu." + "value": "Integracja z Claude Code" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Вертикально: каждая ветка на отдельной строке." + "value": "Интеграция с Claude Code" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Vertikalno: svaka grana se pojavljuje u svom redu." + "value": "Claude Code integracija" } }, "ar": { "stringUnit": { "state": "translated", - "value": "عمودي: كل فرع يظهر في سطر خاص به." + "value": "تكامل Claude Code" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Vertikal: hver gren vises på sin egen linje." + "value": "Claude Code-integrering" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Vertical: cada branch aparece em sua própria linha." + "value": "Integração com Claude Code" } }, "th": { "stringUnit": { "state": "translated", - "value": "แบบแนวตั้ง: แต่ละสาขาแสดงในบรรทัดของตัวเอง" + "value": "การผสานรวม Claude Code" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Dikey: her dal kendi satırında görünür." + "value": "Claude Code Entegrasyonu" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Вертикально: кожна гілка на окремому рядку." + "value": "Інтеграція з Claude Code" } } } }, - "settings.app.sidebarBranchLayout.vertical": { + "settings.automation.claudeCode.customPath": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Vertical" + "value": "Claude Binary Path" } }, "ja": { "stringUnit": { "state": "translated", - "value": "縦" - } - }, - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "垂直" + "value": "Claudeバイナリパス" } }, - "zh-Hant": { + "ko": { "stringUnit": { "state": "translated", - "value": "垂直" + "value": "Claude 바이너리 경로" } - }, - "ko": { + } + } + }, + "settings.automation.claudeCode.customPath.placeholder": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "세로" + "value": "e.g. /usr/local/bin/claude" } }, - "de": { + "ja": { "stringUnit": { "state": "translated", - "value": "Vertikal" + "value": "例: /usr/local/bin/claude" } }, - "es": { + "ko": { "stringUnit": { "state": "translated", - "value": "Vertical" + "value": "예: /usr/local/bin/claude" } - }, - "fr": { + } + } + }, + "settings.automation.claudeCode.customPath.subtitle": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Vertical" + "value": "Custom path to the claude binary. Leave empty to use PATH." } }, - "it": { + "ja": { "stringUnit": { "state": "translated", - "value": "Verticale" + "value": "claudeバイナリのカスタムパス。空欄の場合はPATHを使用します。" } }, - "da": { + "ko": { "stringUnit": { "state": "translated", - "value": "Lodret" + "value": "claude 바이너리의 사용자 지정 경로입니다. PATH를 사용하려면 비워두세요." } - }, - "pl": { + } + } + }, + "settings.automation.ripgrep.customPath": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Pionowo" + "value": "Ripgrep Binary Path" } }, - "ru": { + "ja": { "stringUnit": { "state": "translated", - "value": "Вертикально" + "value": "Ripgrepバイナリパス" } }, - "bs": { + "ko": { "stringUnit": { "state": "translated", - "value": "Vertikalno" + "value": "Ripgrep 바이너리 경로" } - }, - "ar": { + } + } + }, + "settings.automation.ripgrep.customPath.placeholder": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "عمودي" + "value": "e.g. /etc/profiles/per-user/you/bin/rg" } }, - "nb": { + "ja": { "stringUnit": { "state": "translated", - "value": "Vertikal" + "value": "例: /etc/profiles/per-user/you/bin/rg" } }, - "pt-BR": { + "ko": { "stringUnit": { "state": "translated", - "value": "Vertical" + "value": "예: /etc/profiles/per-user/you/bin/rg" } - }, - "th": { + } + } + }, + "settings.automation.ripgrep.customPath.subtitle": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "แนวตั้ง" + "value": "Custom path to the rg binary used by Find. Leave empty to use common install locations and PATH." } }, - "tr": { + "ja": { "stringUnit": { "state": "translated", - "value": "Dikey" + "value": "Findで使用するrgバイナリのカスタムパス。空欄の場合は一般的なインストール先とPATHを使用します。" } }, - "uk": { + "ko": { "stringUnit": { "state": "translated", - "value": "Вертикально" + "value": "Find에서 사용하는 rg 바이너리의 사용자 지정 경로입니다. 일반 설치 위치와 PATH를 사용하려면 비워두세요." } } } }, - "settings.app.telemetry": { + "settings.automation.claudeCode.note": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Send anonymous telemetry" + "value": "When enabled, cmux wraps the claude command to inject session tracking and notification hooks. Disable if you prefer to manage Claude Code hooks yourself." } }, "ja": { "stringUnit": { "state": "translated", - "value": "匿名のテレメトリを送信" + "value": "有効にすると、cmuxはclaudeコマンドをラップしてセッション追跡と通知フックを挿入します。Claude Codeのフックを自分で管理する場合は無効にしてください。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "发送匿名遥测数据" + "value": "启用后,cmux 会包装 claude 命令以注入会话跟踪和通知钩子。如果您希望自行管理 Claude Code 钩子,请禁用此选项。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "傳送匿名遙測資料" + "value": "啟用後,cmux 會包裝 claude 指令以注入工作階段追蹤和通知掛鉤。如果您偏好自行管理 Claude Code 掛鉤,請停用此選項。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "익명 원격 측정 전송" + "value": "활성화하면 cmux가 claude 명령을 래핑하여 세션 추적 및 알림 훅을 삽입합니다. Claude Code 훅을 직접 관리하려면 비활성화하세요." } }, "de": { "stringUnit": { "state": "translated", - "value": "Anonyme Telemetriedaten senden" + "value": "Wenn aktiviert, umhüllt cmux den claude-Befehl, um Sitzungsverfolgung und Benachrichtigungs-Hooks einzufügen. Deaktivieren Sie dies, wenn Sie Claude Code-Hooks selbst verwalten möchten." } }, "es": { "stringUnit": { "state": "translated", - "value": "Enviar telemetría anónima" + "value": "Cuando está activado, cmux envuelve el comando claude para inyectar seguimiento de sesión y hooks de notificación. Desactiva si prefieres gestionar los hooks de Claude Code tú mismo." } }, "fr": { "stringUnit": { "state": "translated", - "value": "Envoyer des données de télémétrie anonymes" + "value": "Lorsque cette option est activée, cmux encapsule la commande claude pour injecter le suivi de session et les hooks de notification. Désactivez si vous préférez gérer les hooks Claude Code vous-même." } }, "it": { "stringUnit": { "state": "translated", - "value": "Invia telemetria anonima" + "value": "Quando abilitato, cmux avvolge il comando claude per iniettare il tracciamento della sessione e gli hook di notifica. Disabilita se preferisci gestire gli hook di Claude Code manualmente." } }, "da": { "stringUnit": { "state": "translated", - "value": "Send anonym telemetri" + "value": "Når aktiveret, wrapper cmux claude-kommandoen for at injicere sessionssporing og notifikationshooks. Deaktiver, hvis du foretrækker at administrere Claude Code-hooks selv." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Wysyłaj anonimową telemetrię" + "value": "Po włączeniu cmux opakowuje polecenie claude, aby wstrzyknąć śledzenie sesji i hooki powiadomień. Wyłącz, jeśli wolisz samodzielnie zarządzać hookami Claude Code." } }, "ru": { "stringUnit": { "state": "translated", - "value": "Отправлять анонимную телеметрию" + "value": "При включении cmux оборачивает команду claude для отслеживания сеансов и уведомлений. Отключите, если предпочитаете управлять хуками Claude Code самостоятельно." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Šalji anonimnu telemetriju" + "value": "Kada je omogućeno, cmux omotava naredbu claude kako bi ubacio praćenje sesije i zakačke za obavještenja. Onemogućite ako preferirate sami upravljati Claude Code zakačkama." } }, "ar": { "stringUnit": { "state": "translated", - "value": "إرسال بيانات تحليلية مجهولة" + "value": "عند التفعيل، يغلّف cmux أمر claude لحقن تتبع الجلسة وخطافات الإشعارات. قم بالتعطيل إذا كنت تفضل إدارة خطافات Claude Code بنفسك." } }, "nb": { "stringUnit": { "state": "translated", - "value": "Send anonym telemetri" + "value": "Når aktivert, pakker cmux inn claude-kommandoen for å injisere sesjonssporing og varslingsmekanismer. Deaktiver hvis du foretrekker å håndtere Claude Code-mekanismer selv." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Enviar telemetria anônima" + "value": "Quando ativado, o cmux encapsula o comando claude para injetar rastreamento de sessão e hooks de notificação. Desative se preferir gerenciar os hooks do Claude Code você mesmo." } }, "th": { "stringUnit": { "state": "translated", - "value": "ส่งข้อมูลการวิเคราะห์แบบไม่ระบุตัวตน" + "value": "เมื่อเปิดใช้งาน cmux จะห่อคำสั่ง claude เพื่อเพิ่มการติดตามเซสชันและตะขอการแจ้งเตือน ปิดใช้งานหากคุณต้องการจัดการตะขอ Claude Code ด้วยตัวเอง" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Anonim telemetri gönder" + "value": "Etkinleştirildiğinde, cmux oturum izleme ve bildirim kancaları eklemek için claude komutunu sarar. Claude Code kancalarını kendiniz yönetmeyi tercih ediyorsanız devre dışı bırakın." } }, "uk": { "stringUnit": { "state": "translated", - "value": "Надсилати анонімну телеметрію" + "value": "Якщо увімкнено, cmux обгортає команду claude для інʼєкції відстеження сеансів та хуків сповіщень. Вимкніть, якщо бажаєте самостійно керувати хуками Claude Code." } } } }, - "settings.app.telemetry.subtitle": { + "settings.automation.claudeCode.subtitleOff": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Share anonymized crash and usage data to help improve cmux." + "value": "Claude Code runs without cmux integration." } }, "ja": { "stringUnit": { "state": "translated", - "value": "cmuxの改善に役立てるため、匿名化されたクラッシュおよび使用状況データを共有します。" + "value": "Claude Codeはcmux連携なしで実行されます。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "分享匿名的崩溃和使用数据,帮助改进 cmux。" + "value": "Claude Code 在没有 cmux 集成的情况下运行。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "分享匿名的當機與使用資料,以協助改善 cmux。" + "value": "Claude Code 在不使用 cmux 整合的情況下運行。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "cmux 개선을 위해 익명화된 충돌 및 사용 데이터를 공유합니다." + "value": "Claude Code가 cmux 연동 없이 실행됩니다." } }, "de": { "stringUnit": { "state": "translated", - "value": "Anonymisierte Absturz- und Nutzungsdaten teilen, um cmux zu verbessern." + "value": "Claude Code wird ohne cmux-Integration ausgeführt." } }, "es": { "stringUnit": { "state": "translated", - "value": "Compartir datos anónimos de fallos y uso para ayudar a mejorar cmux." + "value": "Claude Code se ejecuta sin integración con cmux." } }, "fr": { "stringUnit": { "state": "translated", - "value": "Partager des données anonymisées de plantage et d'utilisation pour aider à améliorer cmux." + "value": "Claude Code s'exécute sans intégration cmux." } }, "it": { "stringUnit": { "state": "translated", - "value": "Condividi dati anonimi su arresti anomali e utilizzo per migliorare cmux." + "value": "Claude Code viene eseguito senza integrazione cmux." } }, "da": { "stringUnit": { "state": "translated", - "value": "Del anonymiserede nedbrud- og brugsdata for at hjælpe med at forbedre cmux." + "value": "Claude Code kører uden cmux-integration." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Udostępniaj zanonimizowane dane o awariach i użyciu, aby pomóc ulepszyć cmux." + "value": "Claude Code działa bez integracji z cmux." } }, "ru": { "stringUnit": { "state": "translated", - "value": "Делиться анонимными данными о сбоях и использовании для улучшения cmux." + "value": "Claude Code работает без интеграции с cmux." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Dijelite anonimizirane podatke o padovima i korištenju kako biste pomogli u poboljšanju cmux." + "value": "Claude Code radi bez cmux integracije." } }, "ar": { "stringUnit": { "state": "translated", - "value": "مشاركة بيانات الأعطال والاستخدام المجهولة للمساعدة في تحسين cmux." + "value": "يعمل Claude Code بدون تكامل cmux." } }, "nb": { "stringUnit": { "state": "translated", - "value": "Del anonymiserte krasj- og bruksdata for å bidra til å forbedre cmux." + "value": "Claude Code kjører uten cmux-integrering." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Compartilhar dados anonimizados de falhas e uso para ajudar a melhorar o cmux." + "value": "O Claude Code é executado sem integração com o cmux." } }, "th": { "stringUnit": { "state": "translated", - "value": "แชร์ข้อมูลการขัดข้องและการใช้งานแบบไม่ระบุตัวตนเพื่อช่วยปรับปรุง cmux" + "value": "Claude Code ทำงานโดยไม่มีการผสานรวม cmux" } }, "tr": { "stringUnit": { "state": "translated", - "value": "cmux'u iyileştirmek için anonimleştirilmiş çökme ve kullanım verilerini paylaş." + "value": "Claude Code cmux entegrasyonu olmadan çalışır." } }, "uk": { "stringUnit": { "state": "translated", - "value": "Надсилати анонімні дані про збої та використання для покращення cmux." + "value": "Claude Code працює без інтеграції з cmux." } } } }, - "settings.app.telemetry.subtitleChanged": { + "settings.automation.claudeCode.subtitleOn": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Change takes effect on next launch." + "value": "Sidebar shows Claude session status and notifications." } }, "ja": { "stringUnit": { "state": "translated", - "value": "変更は次回起動時に反映されます。" + "value": "サイドバーにClaudeセッションのステータスと通知が表示されます。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "更改将在下次启动时生效。" + "value": "侧边栏显示 Claude 会话状态和通知。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "變更將在下次啟動時生效。" + "value": "側邊欄顯示 Claude 工作階段狀態和通知。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "변경 사항은 다음 실행 시 적용됩니다." + "value": "사이드바에 Claude 세션 상태와 알림이 표시됩니다." } }, "de": { "stringUnit": { "state": "translated", - "value": "Änderung wird beim nächsten Start wirksam." + "value": "Die Seitenleiste zeigt den Claude-Sitzungsstatus und Benachrichtigungen an." } }, "es": { "stringUnit": { "state": "translated", - "value": "El cambio se aplicará en el próximo inicio." + "value": "La barra lateral muestra el estado de la sesión de Claude y las notificaciones." } }, "fr": { "stringUnit": { "state": "translated", - "value": "La modification prendra effet au prochain lancement." + "value": "La barre latérale affiche le statut de la session Claude et les notifications." } }, "it": { "stringUnit": { "state": "translated", - "value": "La modifica avrà effetto al prossimo avvio." + "value": "La barra laterale mostra lo stato della sessione Claude e le notifiche." } }, "da": { "stringUnit": { "state": "translated", - "value": "Ændringen træder i kraft ved næste start." + "value": "Sidebjælken viser Claude-sessionsstatus og notifikationer." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Zmiana zacznie obowiązywać po ponownym uruchomieniu." + "value": "Pasek boczny pokazuje status sesji Claude i powiadomienia." } }, "ru": { "stringUnit": { "state": "translated", - "value": "Изменение вступит в силу при следующем запуске." + "value": "Боковая панель показывает статус сеанса Claude и уведомления." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Promjena stupa na snagu pri sljedećem pokretanju." + "value": "Bočna traka prikazuje status Claude sesije i obavještenja." } }, "ar": { "stringUnit": { "state": "translated", - "value": "يسري التغيير عند التشغيل التالي." + "value": "يعرض الشريط الجانبي حالة جلسة Claude والإشعارات." } }, "nb": { "stringUnit": { "state": "translated", - "value": "Endringen trer i kraft ved neste oppstart." + "value": "Sidepanelet viser Claude-sesjonsstatus og varsler." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "A alteração terá efeito na próxima inicialização." + "value": "A barra lateral mostra o status da sessão do Claude e notificações." } }, "th": { "stringUnit": { "state": "translated", - "value": "การเปลี่ยนแปลงจะมีผลเมื่อเปิดใหม่ครั้งถัดไป" + "value": "แถบด้านข้างแสดงสถานะเซสชัน Claude และการแจ้งเตือน" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Değişiklik bir sonraki başlatmada geçerli olur." + "value": "Kenar çubuğu Claude oturum durumunu ve bildirimlerini gösterir." } }, "uk": { "stringUnit": { "state": "translated", - "value": "Зміна набуде чинності при наступному запуску." + "value": "Бічна панель показує статус сеансу Claude та сповіщення." } } } }, - "settings.app.theme": { + "settings.automation.cursor": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Theme" + "value": "Cursor Integration" } }, "ja": { "stringUnit": { "state": "translated", - "value": "テーマ" + "value": "Cursor連携" } }, - "zh-Hans": { + "ko": { "stringUnit": { "state": "translated", - "value": "主题" + "value": "Cursor 연동" + } + } + } + }, + "settings.automation.cursor.note": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Hooks must be installed with `cmux hooks cursor install`. They no-op outside cmux terminals." } }, - "zh-Hant": { + "ja": { "stringUnit": { "state": "translated", - "value": "主題" + "value": "フックは`cmux hooks cursor install`でインストールする必要があります。cmuxターミナル外では動作しません。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "테마" + "value": "`cmux hooks cursor install`로 훅을 설치해야 합니다. cmux 터미널 외부에서는 작동하지 않습니다." } - }, - "de": { + } + } + }, + "settings.automation.cursor.subtitleOff": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Design" + "value": "Cursor runs without cmux integration." } }, - "es": { + "ja": { "stringUnit": { "state": "translated", - "value": "Tema" + "value": "Cursorはcmux連携なしで動作します。" } }, - "fr": { + "ko": { "stringUnit": { "state": "translated", - "value": "Thème" + "value": "Cursor가 cmux 연동 없이 실행됩니다." } - }, - "it": { + } + } + }, + "settings.automation.cursor.subtitleOn": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Tema" + "value": "Sidebar shows Cursor agent status and notifications." } }, - "da": { + "ja": { "stringUnit": { "state": "translated", - "value": "Tema" + "value": "サイドバーにCursorエージェントのステータスと通知が表示されます。" } }, - "pl": { + "ko": { "stringUnit": { "state": "translated", - "value": "Motyw" + "value": "사이드바에 Cursor 에이전트 상태와 알림이 표시됩니다." + } + } + } + }, + "settings.automation.gemini": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Gemini CLI Integration" } }, - "ru": { + "ja": { "stringUnit": { "state": "translated", - "value": "Тема" + "value": "Gemini CLI連携" } }, - "bs": { + "ko": { "stringUnit": { "state": "translated", - "value": "Tema" + "value": "Gemini CLI 연동" + } + } + } + }, + "settings.automation.gemini.note": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Hooks must be installed with `cmux hooks gemini install`. They no-op outside cmux terminals." } }, - "ar": { + "ja": { "stringUnit": { "state": "translated", - "value": "المظهر" + "value": "フックは`cmux hooks gemini install`でインストールする必要があります。cmuxターミナル外では動作しません。" } }, - "nb": { + "ko": { "stringUnit": { "state": "translated", - "value": "Tema" + "value": "`cmux hooks gemini install`로 훅을 설치해야 합니다. cmux 터미널 외부에서는 작동하지 않습니다." + } + } + } + }, + "settings.automation.gemini.subtitleOff": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Gemini runs without cmux integration." } }, - "pt-BR": { + "ja": { "stringUnit": { "state": "translated", - "value": "Tema" + "value": "GeminiはCmux連携なしで動作します。" } }, - "th": { + "ko": { "stringUnit": { "state": "translated", - "value": "ธีม" + "value": "Gemini가 cmux 연동 없이 실행됩니다." + } + } + } + }, + "settings.automation.gemini.subtitleOn": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Sidebar shows Gemini session status and notifications." } }, - "tr": { + "ja": { "stringUnit": { "state": "translated", - "value": "Tema" + "value": "サイドバーにGeminiセッションのステータスと通知が表示されます。" } }, - "uk": { + "ko": { "stringUnit": { "state": "translated", - "value": "Тема" + "value": "사이드바에 Gemini 세션 상태와 알림이 표시됩니다." } } } }, - "settings.app.warnBeforeQuit": { + "settings.automation.openAccess.dialog.cancel": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Warn Before Quit" + "value": "Cancel" } }, "ja": { "stringUnit": { "state": "translated", - "value": "終了前に警告" + "value": "キャンセル" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "退出前警告" + "value": "取消" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "結束前警告" + "value": "取消" } }, "ko": { "stringUnit": { "state": "translated", - "value": "종료 전 경고" + "value": "취소" } }, "de": { "stringUnit": { "state": "translated", - "value": "Vor dem Beenden warnen" + "value": "Abbrechen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Advertir antes de salir" + "value": "Cancelar" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Avertir avant de quitter" + "value": "Annuler" } }, "it": { "stringUnit": { "state": "translated", - "value": "Avvisa prima di uscire" + "value": "Annulla" } }, "da": { "stringUnit": { "state": "translated", - "value": "Advar før afslutning" + "value": "Annuller" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Ostrzegaj przed zamknięciem" + "value": "Anuluj" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Предупреждать перед выходом" + "value": "Отменить" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Upozori prije zatvaranja" + "value": "Otkaži" } }, "ar": { "stringUnit": { "state": "translated", - "value": "التحذير قبل الإنهاء" + "value": "إلغاء" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Advar før avslutning" + "value": "Avbryt" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Avisar Antes de Encerrar" + "value": "Cancelar" } }, "th": { "stringUnit": { "state": "translated", - "value": "เตือนก่อนออก" + "value": "ยกเลิก" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Çıkmadan Önce Uyar" + "value": "Vazgeç" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Попереджувати перед виходом" + "value": "Скасувати" } } } }, - "settings.app.warnBeforeQuit.subtitleOff": { + "settings.automation.openAccess.dialog.confirm": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Cmd+Q quits immediately without confirmation." + "value": "Enable Full Open Access" } }, "ja": { "stringUnit": { "state": "translated", - "value": "Cmd+Qで確認なしにすぐ終了します。" + "value": "フルオープンアクセスを有効にする" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "Cmd+Q 直接退出,无需确认。" + "value": "启用完全开放访问" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "Cmd+Q 會立即結束,不顯示確認提示。" + "value": "啟用完全開放存取" } }, "ko": { "stringUnit": { "state": "translated", - "value": "Cmd+Q를 누르면 확인 없이 즉시 종료됩니다." + "value": "전체 개방 접근 활성화" } }, "de": { "stringUnit": { "state": "translated", - "value": "Cmd+Q beendet sofort ohne Bestätigung." + "value": "Vollständigen offenen Zugriff aktivieren" } }, "es": { "stringUnit": { "state": "translated", - "value": "Cmd+Q sale inmediatamente sin confirmación." + "value": "Activar acceso abierto completo" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Cmd+Q quitte immédiatement sans confirmation." + "value": "Activer l'accès ouvert complet" } }, "it": { "stringUnit": { "state": "translated", - "value": "Cmd+Q esce immediatamente senza conferma." + "value": "Abilita accesso aperto completo" } }, "da": { "stringUnit": { "state": "translated", - "value": "Cmd+Q afslutter øjeblikkeligt uden bekræftelse." + "value": "Aktiver fuld åben adgang" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Cmd+Q zamyka natychmiast bez potwierdzenia." + "value": "Włącz pełny otwarty dostęp" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Cmd+Q завершает приложение немедленно без подтверждения." + "value": "Включить полный открытый доступ" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Cmd+Q odmah zatvara bez potvrde." + "value": "Omogući potpuni otvoreni pristup" } }, "ar": { "stringUnit": { "state": "translated", - "value": "Cmd+Q ينهي فورًا بدون تأكيد." + "value": "تفعيل الوصول المفتوح الكامل" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Cmd+Q avslutter umiddelbart uten bekreftelse." + "value": "Aktiver full åpen tilgang" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Cmd+Q encerra imediatamente sem confirmação." + "value": "Ativar Acesso Aberto Total" } }, "th": { "stringUnit": { "state": "translated", - "value": "Cmd+Q ออกทันทีโดยไม่มีการยืนยัน" + "value": "เปิดใช้งานการเข้าถึงเปิดแบบเต็ม" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Cmd+Q onay olmadan hemen çıkar." + "value": "Tam Açık Erişimi Etkinleştir" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Cmd+Q закриває програму негайно без підтвердження." + "value": "Увімкнути повний відкритий доступ" } } } }, - "settings.app.warnBeforeQuit.subtitleOn": { + "settings.automation.openAccess.dialog.message": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Show a confirmation before quitting with Cmd+Q." + "value": "This disables ancestry and password checks and opens the socket to all local users. Only enable when you understand the risk." } }, "ja": { "stringUnit": { "state": "translated", - "value": "Cmd+Qで終了する前に確認を表示します。" + "value": "これにより、祖先プロセスチェックとパスワードチェックが無効になり、すべてのローカルユーザーにソケットが公開されます。リスクを理解した上で有効にしてください。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "使用 Cmd+Q 退出前显示确认对话框。" + "value": "这将禁用祖先和密码检查,并向所有本地用户开放套接字。请确保您了解其中的风险后再启用。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "使用 Cmd+Q 結束前顯示確認提示。" + "value": "這將停用來源驗證和密碼檢查,並將 Socket 開放給所有本機使用者。請確認您了解風險後再啟用。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "Cmd+Q로 종료하기 전에 확인 대화상자를 표시합니다." + "value": "이 설정은 출처 확인 및 비밀번호 검사를 비활성화하고 모든 로컬 사용자에게 소켓을 개방합니다. 위험을 이해한 경우에만 활성화하세요." } }, "de": { "stringUnit": { "state": "translated", - "value": "Vor dem Beenden mit Cmd+Q eine Bestätigung anzeigen." + "value": "Dies deaktiviert Abstammungs- und Passwortprüfungen und öffnet den Socket für alle lokalen Benutzer. Aktivieren Sie dies nur, wenn Sie das Risiko verstehen." } }, "es": { "stringUnit": { "state": "translated", - "value": "Mostrar una confirmación antes de salir con Cmd+Q." + "value": "Esto desactiva las verificaciones de ascendencia y contraseña, y abre el socket a todos los usuarios locales. Activa solo si comprendes el riesgo." } }, "fr": { "stringUnit": { "state": "translated", - "value": "Afficher une confirmation avant de quitter avec Cmd+Q." + "value": "Cela désactive les vérifications de parenté et de mot de passe et ouvre le socket à tous les utilisateurs locaux. N'activez que si vous comprenez les risques." } }, "it": { "stringUnit": { "state": "translated", - "value": "Mostra una conferma prima di uscire con Cmd+Q." + "value": "Questa operazione disabilita i controlli di discendenza e password e apre il socket a tutti gli utenti locali. Abilita solo se comprendi il rischio." } }, "da": { "stringUnit": { "state": "translated", - "value": "Vis en bekræftelse, før du afslutter med Cmd+Q." + "value": "Dette deaktiverer herkomst- og adgangskodekontrol og åbner socketen for alle lokale brugere. Aktiver kun, når du forstår risikoen." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Pokaż potwierdzenie przed zamknięciem za pomocą Cmd+Q." + "value": "To wyłącza sprawdzanie pochodzenia i hasła oraz otwiera gniazdo dla wszystkich lokalnych użytkowników. Włączaj tylko wtedy, gdy rozumiesz ryzyko." } }, "ru": { "stringUnit": { "state": "translated", - "value": "Показывать подтверждение перед выходом по Cmd+Q." + "value": "Это отключает проверку происхождения и пароля и открывает сокет для всех локальных пользователей. Включайте только если понимаете риски." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Prikaži potvrdu prije zatvaranja sa Cmd+Q." + "value": "Ovo onemogućava provjere porijekla i lozinke i otvara utičnicu svim lokalnim korisnicima. Omogućite samo kada razumijete rizik." } }, "ar": { "stringUnit": { "state": "translated", - "value": "عرض تأكيد قبل الإنهاء بـ Cmd+Q." + "value": "يؤدي هذا إلى تعطيل فحوصات النسب وكلمة المرور ويفتح المقبس لجميع المستخدمين المحليين. قم بالتفعيل فقط عندما تفهم المخاطر." } }, "nb": { "stringUnit": { "state": "translated", - "value": "Vis en bekreftelse før avslutning med Cmd+Q." + "value": "Dette deaktiverer opphavs- og passordkontroller og åpner socketen for alle lokale brukere. Aktiver bare når du forstår risikoen." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Mostrar uma confirmação antes de encerrar com Cmd+Q." + "value": "Isto desativa verificações de ancestralidade e senha e abre o socket para todos os usuários locais. Ative somente quando entender os riscos." } }, "th": { "stringUnit": { "state": "translated", - "value": "แสดงการยืนยันก่อนออกด้วย Cmd+Q" + "value": "การดำเนินการนี้จะปิดใช้งานการตรวจสอบสายสืบทอดและรหัสผ่าน และเปิดซ็อกเก็ตให้ผู้ใช้ในเครื่องทุกคน เปิดใช้งานเฉพาะเมื่อคุณเข้าใจความเสี่ยง" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Cmd+Q ile çıkmadan önce onay göster." + "value": "Bu, soy ve parola denetimlerini devre dışı bırakır ve soketi tüm yerel kullanıcılara açar. Yalnızca riski anladığınızda etkinleştirin." } }, "uk": { "stringUnit": { "state": "translated", - "value": "Показувати підтвердження перед виходом через Cmd+Q." + "value": "Це вимикає перевірку походження та пароля і відкриває сокет для всіх локальних користувачів. Вмикайте лише якщо розумієте ризики." } } } }, - "settings.app.warnBeforeClosingTab": { + "settings.automation.openAccess.dialog.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Warn Before Closing Tab" + "value": "Enable full open access?" } }, "ja": { "stringUnit": { "state": "translated", - "value": "タブを閉じる前に警告" + "value": "フルオープンアクセスを有効にしますか?" } - } - } - }, - "settings.app.warnBeforeClosingTab.subtitleOff": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "zh-Hans": { "stringUnit": { "state": "translated", - "value": "Tabs close immediately without confirmation." + "value": "启用完全开放访问?" } }, - "ja": { + "zh-Hant": { "stringUnit": { "state": "translated", - "value": "確認なしにすぐタブを閉じます。" + "value": "要啟用完全開放存取嗎?" } - } - } - }, - "settings.app.warnBeforeClosingTab.subtitleOn": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "ko": { "stringUnit": { "state": "translated", - "value": "Show a confirmation before closing a tab." + "value": "전체 개방 접근을 활성화하시겠습니까?" } }, - "ja": { + "de": { "stringUnit": { "state": "translated", - "value": "タブを閉じる前に確認を表示します。" + "value": "Vollständigen offenen Zugriff aktivieren?" } - } - } - }, - "settings.notifications.sound.custom.choose.button": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "es": { "stringUnit": { "state": "translated", - "value": "Choose..." + "value": "¿Activar acceso abierto completo?" } }, - "ja": { + "fr": { "stringUnit": { "state": "translated", - "value": "選択..." + "value": "Activer l'accès ouvert complet ?" } }, - "uk": { + "it": { "stringUnit": { "state": "translated", - "value": "Вибрати..." + "value": "Abilitare l'accesso aperto completo?" } }, - "ko": { + "da": { "stringUnit": { "state": "translated", - "value": "선택..." + "value": "Aktiver fuld åben adgang?" } - } - } - }, - "settings.notifications.sound.custom.choose.prompt": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "pl": { "stringUnit": { "state": "translated", - "value": "Choose" + "value": "Włączyć pełny otwarty dostęp?" } }, - "ja": { + "ru": { "stringUnit": { "state": "translated", - "value": "選択" + "value": "Включить полный открытый доступ?" } }, - "uk": { + "bs": { "stringUnit": { "state": "translated", - "value": "Вибрати" + "value": "Omogućiti potpuni otvoreni pristup?" } }, - "ko": { + "ar": { "stringUnit": { "state": "translated", - "value": "선택" + "value": "تفعيل الوصول المفتوح الكامل؟" } - } - } - }, - "settings.notifications.sound.custom.choose.title": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "nb": { "stringUnit": { "state": "translated", - "value": "Choose Notification Sound" + "value": "Aktivere full åpen tilgang?" } }, - "ja": { + "pt-BR": { "stringUnit": { "state": "translated", - "value": "通知サウンドを選択" + "value": "Ativar acesso aberto total?" } }, - "uk": { + "th": { "stringUnit": { "state": "translated", - "value": "Вибрати звук сповіщення" + "value": "เปิดใช้งานการเข้าถึงเปิดแบบเต็มหรือไม่?" } }, - "ko": { + "tr": { "stringUnit": { "state": "translated", - "value": "알림 소리 선택" + "value": "Tam açık erişim etkinleştirilsin mi?" + } + }, + "uk": { + "stringUnit": { + "state": "translated", + "value": "Увімкнути повний відкритий доступ?" } } } }, - "settings.notifications.sound.custom.clear.button": { + "settings.automation.openAccessWarning": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Clear" + "value": "Warning: Full open access makes the control socket world-readable/writable on this Mac and disables auth checks. Use only for local debugging." } }, "ja": { "stringUnit": { "state": "translated", - "value": "クリア" + "value": "警告: フルオープンアクセスにすると、このMac上の制御ソケットが誰でも読み書き可能になり、認証チェックが無効になります。ローカルデバッグ用途にのみ使用してください。" } }, - "uk": { + "zh-Hans": { "stringUnit": { "state": "translated", - "value": "Очистити" + "value": "警告:完全开放访问将使控制套接字在此 Mac 上对所有用户可读/可写,并禁用身份验证检查。仅用于本地调试。" } }, - "ko": { - "stringUnit": { - "state": "translated", - "value": "지우기" - } - } - } - }, - "settings.notifications.sound.custom.error.title": { - "extractionState": "manual", - "localizations": { - "en": { + "zh-Hant": { "stringUnit": { "state": "translated", - "value": "Custom Notification Sound Error" + "value": "警告:完全開放存取會讓控制 Socket 在此 Mac 上可被所有人讀寫,並停用驗證檢查。僅供本機除錯使用。" } }, - "ja": { + "ko": { "stringUnit": { "state": "translated", - "value": "カスタム通知サウンドのエラー" + "value": "경고: 전체 개방 접근은 이 Mac에서 제어 소켓을 누구나 읽고 쓸 수 있게 하며 인증 검사를 비활성화합니다. 로컬 디버깅 전용으로만 사용하세요." } }, - "uk": { + "de": { "stringUnit": { "state": "translated", - "value": "Помилка власного звуку сповіщення" + "value": "Warnung: Vollständiger offener Zugriff macht den Steuerungs-Socket auf diesem Mac für alle les- und schreibbar und deaktiviert Authentifizierungsprüfungen. Nur für lokales Debugging verwenden." } }, - "ko": { + "es": { "stringUnit": { "state": "translated", - "value": "사용자 지정 알림 소리 오류" + "value": "Advertencia: El acceso abierto completo hace que el socket de control sea legible/escribible para todos en este Mac y desactiva las verificaciones de autenticación. Usa solo para depuración local." } - } - } - }, - "settings.notifications.sound.custom.file.none": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "fr": { "stringUnit": { "state": "translated", - "value": "No file selected" + "value": "Attention : l'accès ouvert complet rend le socket de contrôle lisible/inscriptible par tous sur ce Mac et désactive les vérifications d'authentification. À utiliser uniquement pour le débogage local." } }, - "ja": { + "it": { "stringUnit": { "state": "translated", - "value": "ファイル未選択" + "value": "Attenzione: l'accesso aperto completo rende il socket di controllo leggibile/scrivibile da tutti su questo Mac e disabilita i controlli di autenticazione. Usa solo per il debug locale." } }, - "uk": { + "da": { "stringUnit": { "state": "translated", - "value": "Файл не вибрано" + "value": "Advarsel: Fuld åben adgang gør kontrolsocketen læsbar/skrivbar for alle på denne Mac og deaktiverer autentifikationskontrol. Brug kun til lokal fejlsøgning." } }, - "ko": { + "pl": { "stringUnit": { "state": "translated", - "value": "선택된 파일 없음" + "value": "Ostrzeżenie: Pełny otwarty dostęp czyni gniazdo sterujące odczytywalnym/zapisywalnym dla wszystkich na tym Macu i wyłącza sprawdzanie uwierzytelniania. Używaj tylko do lokalnego debugowania." } - } - } - }, - "settings.notifications.sound.custom.status.empty": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "ru": { "stringUnit": { "state": "translated", - "value": "Choose a custom audio file first." + "value": "Внимание: полный открытый доступ делает управляющий сокет доступным для чтения и записи всем пользователям на этом Mac и отключает проверку авторизации. Используйте только для локальной отладки." } }, - "ja": { + "bs": { "stringUnit": { "state": "translated", - "value": "先にカスタム音声ファイルを選択してください。" + "value": "Upozorenje: Potpuni otvoreni pristup čini kontrolnu utičnicu čitljivom/zapisivom za sve na ovom Macu i onemogućava provjere autentikacije. Koristite samo za lokalno debugiranje." } }, - "uk": { + "ar": { "stringUnit": { "state": "translated", - "value": "Спочатку виберіть файл аудіо." + "value": "تحذير: الوصول المفتوح الكامل يجعل مقبس التحكم قابلاً للقراءة والكتابة من الجميع على هذا الـ Mac ويعطل فحوصات المصادقة. استخدم فقط لأغراض التصحيح المحلي." } }, - "ko": { + "nb": { "stringUnit": { "state": "translated", - "value": "먼저 사용자 지정 오디오 파일을 선택하세요." + "value": "Advarsel: Full åpen tilgang gjør kontrollsocketen lese-/skrivbar for alle på denne Mac-en og deaktiverer autentiseringskontroller. Bruk kun for lokal feilsøking." } - } - } - }, - "settings.notifications.sound.custom.status.missingExtensionPrefix": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "pt-BR": { "stringUnit": { "state": "translated", - "value": "File needs an extension: " + "value": "Aviso: O acesso aberto total torna o socket de controle legível/gravável por todos neste Mac e desativa verificações de autenticação. Use apenas para depuração local." } }, - "ja": { + "th": { "stringUnit": { "state": "translated", - "value": "拡張子が必要です: " + "value": "คำเตือน: การเข้าถึงเปิดแบบเต็มทำให้ซ็อกเก็ตควบคุมอ่าน/เขียนได้จากทุกผู้ใช้บน Mac นี้และปิดใช้งานการตรวจสอบสิทธิ์ ใช้สำหรับการดีบักในเครื่องเท่านั้น" } }, - "uk": { + "tr": { "stringUnit": { "state": "translated", - "value": "Файлу потрібне розширення: " + "value": "Uyarı: Tam açık erişim, kontrol soketini bu Mac'te herkes tarafından okunabilir/yazılabilir yapar ve kimlik doğrulama denetimlerini devre dışı bırakır. Yalnızca yerel hata ayıklama için kullanın." } }, - "ko": { + "uk": { "stringUnit": { "state": "translated", - "value": "파일에 확장자가 필요합니다: " + "value": "Увага: повний відкритий доступ робить керуючий сокет доступним для читання/запису всім на цьому Mac та вимикає перевірки автентифікації. Використовуйте лише для локального налагодження." } } } }, - "settings.notifications.sound.custom.status.missingFilePrefix": { + "settings.automation.port.note": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "File not found: " + "value": "Each workspace gets CMUX_PORT and CMUX_PORT_END env vars with a dedicated port range. New terminals inherit these values." } }, "ja": { "stringUnit": { "state": "translated", - "value": "ファイルが見つかりません: " + "value": "各ワークスペースにはCMUX_PORTとCMUX_PORT_END環境変数で専用のポート範囲が割り当てられます。新しいターミナルはこれらの値を継承します。" } }, - "uk": { + "zh-Hans": { "stringUnit": { "state": "translated", - "value": "Файл не знайдено: " + "value": "每个工作区会获得 CMUX_PORT 和 CMUX_PORT_END 环境变量,包含专用的端口范围。新终端会继承这些值。" } }, - "ko": { - "stringUnit": { - "state": "translated", - "value": "파일을 찾을 수 없습니다: " - } - } - } - }, - "settings.notifications.sound.custom.status.prepareFailed": { - "extractionState": "manual", - "localizations": { - "en": { + "zh-Hant": { "stringUnit": { "state": "translated", - "value": "Could not prepare this file for notifications. Try WAV, AIFF, or CAF." + "value": "每個工作區都會取得包含專用連接埠範圍的 CMUX_PORT 和 CMUX_PORT_END 環境變數。新終端機會繼承這些值。" } }, - "ja": { + "ko": { "stringUnit": { "state": "translated", - "value": "通知用にこのファイルを準備できませんでした。WAV、AIFF、またはCAFを試してください。" + "value": "각 작업 공간에 전용 포트 범위가 있는 CMUX_PORT 및 CMUX_PORT_END 환경 변수가 할당됩니다. 새 터미널은 이 값을 상속합니다." } }, - "uk": { + "de": { "stringUnit": { "state": "translated", - "value": "Не вдалося підготувати цей файл для сповіщень. Спробуйте WAV, AIFF або CAF." + "value": "Jeder Arbeitsbereich erhält CMUX_PORT- und CMUX_PORT_END-Umgebungsvariablen mit einem dedizierten Portbereich. Neue Terminals erben diese Werte." } }, - "ko": { + "es": { "stringUnit": { "state": "translated", - "value": "이 파일을 알림용으로 준비할 수 없습니다. WAV, AIFF 또는 CAF를 사용해 보세요." + "value": "Cada espacio de trabajo recibe las variables de entorno CMUX_PORT y CMUX_PORT_END con un rango de puertos dedicado. Los nuevos terminales heredan estos valores." } - } - } - }, - "settings.notifications.sound.custom.status.ready": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "fr": { "stringUnit": { "state": "translated", - "value": "Ready for notifications." + "value": "Chaque espace de travail reçoit les variables d'environnement CMUX_PORT et CMUX_PORT_END avec une plage de ports dédiée. Les nouveaux terminaux héritent de ces valeurs." } }, - "ja": { + "it": { "stringUnit": { "state": "translated", - "value": "通知用の準備ができました。" + "value": "Ogni area di lavoro riceve le variabili d'ambiente CMUX_PORT e CMUX_PORT_END con un intervallo di porte dedicato. I nuovi terminali ereditano questi valori." } }, - "uk": { + "da": { "stringUnit": { "state": "translated", - "value": "Готовий для сповіщень." + "value": "Hvert arbejdsområde får CMUX_PORT og CMUX_PORT_END miljøvariabler med et dedikeret portområde. Nye terminaler arver disse værdier." } }, - "ko": { + "pl": { "stringUnit": { "state": "translated", - "value": "알림 준비 완료." + "value": "Każda przestrzeń robocza otrzymuje zmienne środowiskowe CMUX_PORT i CMUX_PORT_END z dedykowanym zakresem portów. Nowe terminale dziedziczą te wartości." } - } - } - }, - "settings.notifications.sound.custom.status.readyConverted": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "ru": { "stringUnit": { "state": "translated", - "value": "Prepared for notifications (converted to CAF)." + "value": "Каждое рабочее пространство получает переменные окружения CMUX_PORT и CMUX_PORT_END с выделенным диапазоном портов. Новые терминалы наследуют эти значения." } }, - "ja": { + "bs": { "stringUnit": { "state": "translated", - "value": "通知用に準備しました(CAFに変換)。" + "value": "Svaki radni prostor dobija CMUX_PORT i CMUX_PORT_END varijable okruženja sa dodijeljenim rasponom portova. Novi terminali nasljeđuju ove vrijednosti." } }, - "uk": { + "ar": { "stringUnit": { "state": "translated", - "value": "Підготовлений для сповіщень (конвертовано в CAF)." + "value": "تحصل كل مساحة عمل على متغيرات البيئة CMUX_PORT و CMUX_PORT_END مع نطاق منافذ مخصص. ترث الطرفيات الجديدة هذه القيم." } }, - "ko": { + "nb": { "stringUnit": { "state": "translated", - "value": "알림 준비 완료 (CAF로 변환됨)." + "value": "Hvert arbeidsområde får CMUX_PORT- og CMUX_PORT_END-miljøvariabler med et dedikert portområde. Nye terminaler arver disse verdiene." } - } - } - }, - "settings.notifications.sound.subtitle": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "pt-BR": { "stringUnit": { "state": "translated", - "value": "Sound played when a notification arrives." + "value": "Cada área de trabalho recebe as variáveis de ambiente CMUX_PORT e CMUX_PORT_END com uma faixa de portas dedicada. Novos terminais herdam esses valores." } }, - "ja": { + "th": { "stringUnit": { "state": "translated", - "value": "通知を受信したときに再生するサウンドです。" + "value": "แต่ละเวิร์กสเปซจะได้รับตัวแปรสภาพแวดล้อม CMUX_PORT และ CMUX_PORT_END พร้อมช่วงพอร์ตเฉพาะ เทอร์มินัลใหม่จะสืบทอดค่าเหล่านี้" } }, - "uk": { + "tr": { "stringUnit": { "state": "translated", - "value": "Звук, який відтворюється при надходженні сповіщення." + "value": "Her çalışma alanı ayrılmış bir port aralığıyla CMUX_PORT ve CMUX_PORT_END ortam değişkenlerini alır. Yeni terminaller bu değerleri devralır." } }, - "ko": { + "uk": { "stringUnit": { "state": "translated", - "value": "알림이 도착했을 때 재생되는 소리입니다." + "value": "Кожна робоча область отримує змінні середовища CMUX_PORT та CMUX_PORT_END з виділеним діапазоном портів. Нові термінали успадковують ці значення." } } } }, - "settings.notifications.paneRing.subtitle": { + "settings.automation.portBase": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Show a blue ring around panes with unread notifications." + "value": "Port Base" } }, "ja": { "stringUnit": { "state": "translated", - "value": "未読の通知があるペインの周囲に青いリングを表示します。" + "value": "ポートベース" } }, - "uk": { + "zh-Hans": { "stringUnit": { "state": "translated", - "value": "Показувати синє кільце навколо панелей з непрочитаними сповіщеннями." + "value": "起始端口" } }, - "ko": { + "zh-Hant": { "stringUnit": { "state": "translated", - "value": "읽지 않은 알림이 있는 패인 주위에 파란색 링을 표시합니다." + "value": "連接埠起始值" } - } - } - }, - "settings.notifications.paneFlash.subtitle": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "ko": { "stringUnit": { "state": "translated", - "value": "Briefly flash a blue outline when cmux highlights a pane." + "value": "포트 기준값" } }, - "ja": { + "de": { "stringUnit": { "state": "translated", - "value": "cmux がペインを強調表示するときに短い青いアウトラインを表示します。" + "value": "Port-Basis" } }, - "uk": { + "es": { "stringUnit": { "state": "translated", - "value": "Короткочасно підсвічувати синьою рамкою панель, на яку cmux звертає увагу." + "value": "Puerto base" } }, - "ko": { + "fr": { "stringUnit": { "state": "translated", - "value": "cmux가 패인을 강조할 때 파란색 테두리를 잠시 깜빡입니다." + "value": "Port de base" } - } - } - }, - "settings.notifications.paneFlash.title": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "it": { "stringUnit": { "state": "translated", - "value": "Pane Flash" + "value": "Porta base" } }, - "ja": { + "da": { "stringUnit": { "state": "translated", - "value": "ペインフラッシュ" + "value": "Portbase" } }, - "uk": { + "pl": { "stringUnit": { "state": "translated", - "value": "Підсвічування панелі" + "value": "Port bazowy" } }, - "ko": { + "ru": { "stringUnit": { "state": "translated", - "value": "패인 플래시" + "value": "Базовый порт" } - } - } - }, - "settings.notifications.paneRing.title": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "bs": { "stringUnit": { "state": "translated", - "value": "Unread Pane Ring" + "value": "Početni port" } }, - "ja": { + "ar": { "stringUnit": { "state": "translated", - "value": "未読ペインリング" + "value": "المنفذ الأساسي" } }, - "uk": { + "nb": { "stringUnit": { "state": "translated", - "value": "Кільце непрочитаних панелей" + "value": "Portbase" } }, - "ko": { + "pt-BR": { "stringUnit": { "state": "translated", - "value": "읽지 않은 패인 링" + "value": "Porta Base" } - } - } - }, - "settings.notifications.sound.title": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "th": { "stringUnit": { "state": "translated", - "value": "Notification Sound" + "value": "พอร์ตเริ่มต้น" } }, - "ja": { + "tr": { "stringUnit": { "state": "translated", - "value": "通知サウンド" + "value": "Port Tabanı" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Звук сповіщення" - } - }, - "ko": { - "stringUnit": { - "state": "translated", - "value": "알림 소리" - } - } - } - }, - "settings.notifications.desktop": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Desktop Notifications" - } - }, - "ja": { - "stringUnit": { - "state": "translated", - "value": "デスクトップ通知" - } - } - } - }, - "settings.notifications.command": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Notification Command" - } - }, - "ja": { - "stringUnit": { - "state": "translated", - "value": "通知コマンド" - } - } - } - }, - "settings.notifications.command.subtitle": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Run a shell command when a notification arrives. $CMUX_NOTIFICATION_TITLE, $CMUX_NOTIFICATION_SUBTITLE, $CMUX_NOTIFICATION_BODY are set." - } - }, - "ja": { - "stringUnit": { - "state": "translated", - "value": "通知が届いたときにシェルコマンドを実行します。$CMUX_NOTIFICATION_TITLE、$CMUX_NOTIFICATION_SUBTITLE、$CMUX_NOTIFICATION_BODY が設定されます。" - } - } - } - }, - "settings.notifications.command.placeholder": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "say \"done\"" - } - }, - "ja": { - "stringUnit": { - "state": "translated", - "value": "say \"done\"" + "value": "Базовий порт" } } } }, - "settings.automation.claudeCode": { + "settings.automation.portBase.subtitle": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Claude Code Integration" + "value": "Starting port for CMUX_PORT env var." } }, "ja": { "stringUnit": { "state": "translated", - "value": "Claude Code連携" + "value": "CMUX_PORT環境変数の開始ポート。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "Claude Code 集成" + "value": "CMUX_PORT 环境变量的起始端口。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "Claude Code 整合" + "value": "CMUX_PORT 環境變數的起始連接埠。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "Claude Code 연동" + "value": "CMUX_PORT 환경 변수의 시작 포트." } }, "de": { "stringUnit": { "state": "translated", - "value": "Claude Code-Integration" + "value": "Startport für die CMUX_PORT-Umgebungsvariable." } }, "es": { "stringUnit": { "state": "translated", - "value": "Integración con Claude Code" + "value": "Puerto inicial para la variable de entorno CMUX_PORT." } }, "fr": { "stringUnit": { "state": "translated", - "value": "Intégration Claude Code" + "value": "Port de départ pour la variable d'environnement CMUX_PORT." } }, "it": { "stringUnit": { "state": "translated", - "value": "Integrazione Claude Code" + "value": "Porta iniziale per la variabile d'ambiente CMUX_PORT." } }, "da": { "stringUnit": { "state": "translated", - "value": "Claude Code-integration" + "value": "Startport for CMUX_PORT-miljøvariabel." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Integracja z Claude Code" + "value": "Port początkowy dla zmiennej środowiskowej CMUX_PORT." } }, "ru": { "stringUnit": { "state": "translated", - "value": "Интеграция с Claude Code" + "value": "Начальный порт для переменной окружения CMUX_PORT." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Claude Code integracija" + "value": "Početni port za CMUX_PORT varijablu okruženja." } }, "ar": { "stringUnit": { "state": "translated", - "value": "تكامل Claude Code" + "value": "المنفذ الابتدائي لمتغير البيئة CMUX_PORT." } }, "nb": { "stringUnit": { "state": "translated", - "value": "Claude Code-integrering" + "value": "Startport for CMUX_PORT-miljøvariabelen." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Integração com Claude Code" + "value": "Porta inicial para a variável de ambiente CMUX_PORT." } }, "th": { "stringUnit": { "state": "translated", - "value": "การผสานรวม Claude Code" + "value": "พอร์ตเริ่มต้นสำหรับตัวแปรสภาพแวดล้อม CMUX_PORT" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Claude Code Entegrasyonu" + "value": "CMUX_PORT ortam değişkeni için başlangıç portu." } }, "uk": { "stringUnit": { "state": "translated", - "value": "Інтеграція з Claude Code" + "value": "Початковий порт для змінної середовища CMUX_PORT." } } } }, - "settings.automation.claudeCode.customPath": { + "settings.automation.portRange": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Claude Binary Path" + "value": "Port Range Size" } }, "ja": { "stringUnit": { "state": "translated", - "value": "Claudeバイナリパス" + "value": "ポート範囲サイズ" } }, - "ko": { + "zh-Hans": { "stringUnit": { "state": "translated", - "value": "Claude 바이너리 경로" + "value": "端口范围大小" } - } - } - }, - "settings.automation.claudeCode.customPath.placeholder": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "zh-Hant": { "stringUnit": { "state": "translated", - "value": "e.g. /usr/local/bin/claude" + "value": "連接埠範圍大小" } }, - "ja": { + "ko": { "stringUnit": { "state": "translated", - "value": "例: /usr/local/bin/claude" + "value": "포트 범위 크기" } }, - "ko": { + "de": { "stringUnit": { "state": "translated", - "value": "예: /usr/local/bin/claude" + "value": "Portbereichsgröße" } - } - } - }, - "settings.automation.claudeCode.customPath.subtitle": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "es": { "stringUnit": { "state": "translated", - "value": "Custom path to the claude binary. Leave empty to use PATH." + "value": "Tamaño del rango de puertos" } }, - "ja": { + "fr": { "stringUnit": { "state": "translated", - "value": "claudeバイナリのカスタムパス。空欄の場合はPATHを使用します。" + "value": "Taille de la plage de ports" } }, - "ko": { + "it": { "stringUnit": { "state": "translated", - "value": "claude 바이너리의 사용자 지정 경로입니다. PATH를 사용하려면 비워두세요." + "value": "Dimensione intervallo porte" } - } - } - }, - "settings.automation.ripgrep.customPath": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "da": { "stringUnit": { "state": "translated", - "value": "Ripgrep Binary Path" + "value": "Portområdestørrelse" } }, - "ja": { + "pl": { "stringUnit": { "state": "translated", - "value": "Ripgrepバイナリパス" + "value": "Rozmiar zakresu portów" } }, - "ko": { + "ru": { "stringUnit": { "state": "translated", - "value": "Ripgrep 바이너리 경로" + "value": "Размер диапазона портов" } - } - } - }, - "settings.automation.ripgrep.customPath.placeholder": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "bs": { "stringUnit": { "state": "translated", - "value": "e.g. /etc/profiles/per-user/you/bin/rg" + "value": "Veličina raspona portova" } }, - "ja": { + "ar": { "stringUnit": { "state": "translated", - "value": "例: /etc/profiles/per-user/you/bin/rg" + "value": "حجم نطاق المنافذ" } }, - "ko": { + "nb": { "stringUnit": { "state": "translated", - "value": "예: /etc/profiles/per-user/you/bin/rg" + "value": "Portområdestørrelse" } - } - } - }, - "settings.automation.ripgrep.customPath.subtitle": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "pt-BR": { "stringUnit": { "state": "translated", - "value": "Custom path to the rg binary used by Find. Leave empty to use common install locations and PATH." + "value": "Tamanho da Faixa de Portas" } }, - "ja": { + "th": { "stringUnit": { "state": "translated", - "value": "Findで使用するrgバイナリのカスタムパス。空欄の場合は一般的なインストール先とPATHを使用します。" + "value": "ขนาดช่วงพอร์ต" } }, - "ko": { + "tr": { "stringUnit": { "state": "translated", - "value": "Find에서 사용하는 rg 바이너리의 사용자 지정 경로입니다. 일반 설치 위치와 PATH를 사용하려면 비워두세요." + "value": "Port Aralığı Boyutu" + } + }, + "uk": { + "stringUnit": { + "state": "translated", + "value": "Розмір діапазону портів" } } } }, - "settings.automation.claudeCode.note": { + "settings.automation.portRange.subtitle": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "When enabled, cmux wraps the claude command to inject session tracking and notification hooks. Disable if you prefer to manage Claude Code hooks yourself." + "value": "Number of ports per workspace." } }, "ja": { "stringUnit": { "state": "translated", - "value": "有効にすると、cmuxはclaudeコマンドをラップしてセッション追跡と通知フックを挿入します。Claude Codeのフックを自分で管理する場合は無効にしてください。" + "value": "ワークスペースあたりのポート数。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "启用后,cmux 会包装 claude 命令以注入会话跟踪和通知钩子。如果您希望自行管理 Claude Code 钩子,请禁用此选项。" + "value": "每个工作区的端口数量。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "啟用後,cmux 會包裝 claude 指令以注入工作階段追蹤和通知掛鉤。如果您偏好自行管理 Claude Code 掛鉤,請停用此選項。" + "value": "每個工作區的連接埠數量。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "활성화하면 cmux가 claude 명령을 래핑하여 세션 추적 및 알림 훅을 삽입합니다. Claude Code 훅을 직접 관리하려면 비활성화하세요." + "value": "작업 공간당 포트 수." } }, "de": { "stringUnit": { "state": "translated", - "value": "Wenn aktiviert, umhüllt cmux den claude-Befehl, um Sitzungsverfolgung und Benachrichtigungs-Hooks einzufügen. Deaktivieren Sie dies, wenn Sie Claude Code-Hooks selbst verwalten möchten." + "value": "Anzahl der Ports pro Arbeitsbereich." } }, "es": { "stringUnit": { "state": "translated", - "value": "Cuando está activado, cmux envuelve el comando claude para inyectar seguimiento de sesión y hooks de notificación. Desactiva si prefieres gestionar los hooks de Claude Code tú mismo." + "value": "Número de puertos por espacio de trabajo." } }, "fr": { "stringUnit": { "state": "translated", - "value": "Lorsque cette option est activée, cmux encapsule la commande claude pour injecter le suivi de session et les hooks de notification. Désactivez si vous préférez gérer les hooks Claude Code vous-même." + "value": "Nombre de ports par espace de travail." } }, "it": { "stringUnit": { "state": "translated", - "value": "Quando abilitato, cmux avvolge il comando claude per iniettare il tracciamento della sessione e gli hook di notifica. Disabilita se preferisci gestire gli hook di Claude Code manualmente." + "value": "Numero di porte per area di lavoro." } }, "da": { "stringUnit": { "state": "translated", - "value": "Når aktiveret, wrapper cmux claude-kommandoen for at injicere sessionssporing og notifikationshooks. Deaktiver, hvis du foretrækker at administrere Claude Code-hooks selv." + "value": "Antal porte pr. arbejdsområde." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Po włączeniu cmux opakowuje polecenie claude, aby wstrzyknąć śledzenie sesji i hooki powiadomień. Wyłącz, jeśli wolisz samodzielnie zarządzać hookami Claude Code." + "value": "Liczba portów na przestrzeń roboczą." } }, "ru": { "stringUnit": { "state": "translated", - "value": "При включении cmux оборачивает команду claude для отслеживания сеансов и уведомлений. Отключите, если предпочитаете управлять хуками Claude Code самостоятельно." + "value": "Количество портов на рабочее пространство." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Kada je omogućeno, cmux omotava naredbu claude kako bi ubacio praćenje sesije i zakačke za obavještenja. Onemogućite ako preferirate sami upravljati Claude Code zakačkama." + "value": "Broj portova po radnom prostoru." } }, "ar": { "stringUnit": { "state": "translated", - "value": "عند التفعيل، يغلّف cmux أمر claude لحقن تتبع الجلسة وخطافات الإشعارات. قم بالتعطيل إذا كنت تفضل إدارة خطافات Claude Code بنفسك." + "value": "عدد المنافذ لكل مساحة عمل." } }, "nb": { "stringUnit": { "state": "translated", - "value": "Når aktivert, pakker cmux inn claude-kommandoen for å injisere sesjonssporing og varslingsmekanismer. Deaktiver hvis du foretrekker å håndtere Claude Code-mekanismer selv." + "value": "Antall porter per arbeidsområde." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Quando ativado, o cmux encapsula o comando claude para injetar rastreamento de sessão e hooks de notificação. Desative se preferir gerenciar os hooks do Claude Code você mesmo." + "value": "Número de portas por área de trabalho." } }, "th": { "stringUnit": { "state": "translated", - "value": "เมื่อเปิดใช้งาน cmux จะห่อคำสั่ง claude เพื่อเพิ่มการติดตามเซสชันและตะขอการแจ้งเตือน ปิดใช้งานหากคุณต้องการจัดการตะขอ Claude Code ด้วยตัวเอง" + "value": "จำนวนพอร์ตต่อเวิร์กสเปซ" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Etkinleştirildiğinde, cmux oturum izleme ve bildirim kancaları eklemek için claude komutunu sarar. Claude Code kancalarını kendiniz yönetmeyi tercih ediyorsanız devre dışı bırakın." + "value": "Çalışma alanı başına port sayısı." } }, "uk": { "stringUnit": { "state": "translated", - "value": "Якщо увімкнено, cmux обгортає команду claude для інʼєкції відстеження сеансів та хуків сповіщень. Вимкніть, якщо бажаєте самостійно керувати хуками Claude Code." + "value": "Кількість портів на робочу область." } } } }, - "settings.automation.claudeCode.subtitleOff": { + "settings.automation.socketMode": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Claude Code runs without cmux integration." + "value": "Socket Control Mode" } }, "ja": { "stringUnit": { "state": "translated", - "value": "Claude Codeはcmux連携なしで実行されます。" + "value": "ソケット制御モード" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "Claude Code 在没有 cmux 集成的情况下运行。" + "value": "套接字控制模式" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "Claude Code 在不使用 cmux 整合的情況下運行。" + "value": "Socket 控制模式" } }, "ko": { "stringUnit": { "state": "translated", - "value": "Claude Code가 cmux 연동 없이 실행됩니다." + "value": "소켓 제어 모드" } }, "de": { "stringUnit": { "state": "translated", - "value": "Claude Code wird ohne cmux-Integration ausgeführt." + "value": "Socket-Steuerungsmodus" } }, "es": { "stringUnit": { "state": "translated", - "value": "Claude Code se ejecuta sin integración con cmux." + "value": "Modo de control del socket" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Claude Code s'exécute sans intégration cmux." + "value": "Mode de contrôle du socket" } }, "it": { "stringUnit": { "state": "translated", - "value": "Claude Code viene eseguito senza integrazione cmux." + "value": "Modalità controllo socket" } }, "da": { "stringUnit": { "state": "translated", - "value": "Claude Code kører uden cmux-integration." + "value": "Socket-kontroltilstand" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Claude Code działa bez integracji z cmux." + "value": "Tryb sterowania gniazdem" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Claude Code работает без интеграции с cmux." + "value": "Режим управления сокетом" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Claude Code radi bez cmux integracije." + "value": "Režim kontrolne utičnice" } }, "ar": { "stringUnit": { "state": "translated", - "value": "يعمل Claude Code بدون تكامل cmux." + "value": "وضع التحكم بالمقبس" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Claude Code kjører uten cmux-integrering." + "value": "Socket-kontrollmodus" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "O Claude Code é executado sem integração com o cmux." + "value": "Modo de Controle do Socket" } }, "th": { "stringUnit": { "state": "translated", - "value": "Claude Code ทำงานโดยไม่มีการผสานรวม cmux" + "value": "โหมดควบคุมซ็อกเก็ต" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Claude Code cmux entegrasyonu olmadan çalışır." + "value": "Soket Kontrol Modu" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Claude Code працює без інтеграції з cmux." + "value": "Режим керуючого сокета" } } } }, - "settings.automation.claudeCode.subtitleOn": { + "settings.automation.socketMode.note": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Sidebar shows Claude session status and notifications." + "value": "Controls access to the local Unix socket for programmatic control. Choose a mode that matches your threat model." } }, "ja": { "stringUnit": { "state": "translated", - "value": "サイドバーにClaudeセッションのステータスと通知が表示されます。" + "value": "プログラムによる制御のためのローカルUnix socketへのアクセスを制御します。脅威モデルに合ったモードを選択してください。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "侧边栏显示 Claude 会话状态和通知。" + "value": "控制本地 Unix 套接字的访问权限,用于程序化控制。请选择与您的安全需求匹配的模式。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "側邊欄顯示 Claude 工作階段狀態和通知。" + "value": "控制本機 Unix Socket 的程式化控制存取。選擇符合您安全需求的模式。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "사이드바에 Claude 세션 상태와 알림이 표시됩니다." + "value": "프로그래밍 방식 제어를 위한 로컬 Unix 소켓 접근을 제어합니다. 보안 모델에 맞는 모드를 선택하세요." } }, "de": { "stringUnit": { "state": "translated", - "value": "Die Seitenleiste zeigt den Claude-Sitzungsstatus und Benachrichtigungen an." + "value": "Steuert den Zugriff auf den lokalen Unix-Socket für programmatische Steuerung. Wählen Sie einen Modus, der Ihrem Bedrohungsmodell entspricht." } }, "es": { "stringUnit": { "state": "translated", - "value": "La barra lateral muestra el estado de la sesión de Claude y las notificaciones." + "value": "Controla el acceso al socket Unix local para control programático. Elige un modo que coincida con tu modelo de amenazas." } }, "fr": { "stringUnit": { "state": "translated", - "value": "La barre latérale affiche le statut de la session Claude et les notifications." + "value": "Contrôle l'accès au socket Unix local pour le contrôle programmatique. Choisissez un mode adapté à votre modèle de menace." } }, "it": { "stringUnit": { "state": "translated", - "value": "La barra laterale mostra lo stato della sessione Claude e le notifiche." + "value": "Controlla l'accesso al socket Unix locale per il controllo programmatico. Scegli una modalità adeguata al tuo modello di rischio." } }, "da": { "stringUnit": { "state": "translated", - "value": "Sidebjælken viser Claude-sessionsstatus og notifikationer." + "value": "Styrer adgangen til den lokale Unix-socket til programmatisk kontrol. Vælg en tilstand, der passer til din trusselsmodel." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Pasek boczny pokazuje status sesji Claude i powiadomienia." + "value": "Kontroluje dostęp do lokalnego gniazda Unix do programowego sterowania. Wybierz tryb odpowiadający Twojemu modelowi zagrożeń." } }, "ru": { "stringUnit": { "state": "translated", - "value": "Боковая панель показывает статус сеанса Claude и уведомления." + "value": "Управляет доступом к локальному Unix-сокету для программного управления. Выберите режим, соответствующий вашей модели угроз." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Bočna traka prikazuje status Claude sesije i obavještenja." + "value": "Kontroliše pristup lokalnoj Unix utičnici za programsku kontrolu. Odaberite režim koji odgovara vašem modelu prijetnji." } }, "ar": { "stringUnit": { "state": "translated", - "value": "يعرض الشريط الجانبي حالة جلسة Claude والإشعارات." + "value": "يتحكم بالوصول إلى مقبس Unix المحلي للتحكم البرمجي. اختر الوضع الذي يتناسب مع نموذج التهديد الخاص بك." } }, "nb": { "stringUnit": { "state": "translated", - "value": "Sidepanelet viser Claude-sesjonsstatus og varsler." + "value": "Styrer tilgang til den lokale Unix-socketen for programmatisk kontroll. Velg en modus som passer til din trusselmodell." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "A barra lateral mostra o status da sessão do Claude e notificações." + "value": "Controla o acesso ao socket Unix local para controle programático. Escolha um modo que corresponda ao seu modelo de ameaça." } }, "th": { "stringUnit": { "state": "translated", - "value": "แถบด้านข้างแสดงสถานะเซสชัน Claude และการแจ้งเตือน" + "value": "ควบคุมการเข้าถึงซ็อกเก็ต Unix ในเครื่องสำหรับการควบคุมแบบโปรแกรม เลือกโหมดที่ตรงกับรูปแบบภัยคุกคามของคุณ" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Kenar çubuğu Claude oturum durumunu ve bildirimlerini gösterir." + "value": "Programatik kontrol için yerel Unix soketine erişimi kontrol eder. Tehdit modelinize uyan bir mod seçin." } }, "uk": { "stringUnit": { "state": "translated", - "value": "Бічна панель показує статус сеансу Claude та сповіщення." + "value": "Керує доступом до локального Unix-сокета для програмного контролю. Виберіть режим відповідно до вашої моделі загроз." } } } }, - "settings.automation.suppressSubagentNotifications": { - "extractionState": "manual", - "localizations": {"ar":{"stringUnit":{"state":"translated","value":"إخفاء إشعارات الوكلاء الفرعيين"}},"bs":{"stringUnit":{"state":"translated","value":"Sakrij obavještenja podagenata"}},"da":{"stringUnit":{"state":"translated","value":"Skjul underagent-notifikationer"}},"de":{"stringUnit":{"state":"translated","value":"Unteragent-Benachrichtigungen unterdrücken"}},"en":{"stringUnit":{"state":"translated","value":"Suppress Subagent Notifications"}},"es":{"stringUnit":{"state":"translated","value":"Suprimir notificaciones de subagentes"}},"fr":{"stringUnit":{"state":"translated","value":"Masquer les notifications des sous-agents"}},"it":{"stringUnit":{"state":"translated","value":"Nascondi notifiche dei sottoagenti"}},"ja":{"stringUnit":{"state":"translated","value":"サブエージェント通知を抑制"}},"ko":{"stringUnit":{"state":"translated","value":"하위 에이전트 알림 억제"}},"nb":{"stringUnit":{"state":"translated","value":"Undertrykk underagentvarsler"}},"pl":{"stringUnit":{"state":"translated","value":"Ukryj powiadomienia podagentów"}},"pt-BR":{"stringUnit":{"state":"translated","value":"Suprimir notificações de subagentes"}},"ru":{"stringUnit":{"state":"translated","value":"Подавлять уведомления подагентов"}},"th":{"stringUnit":{"state":"translated","value":"ซ่อนการแจ้งเตือนของเอเจนต์ย่อย"}},"tr":{"stringUnit":{"state":"translated","value":"Alt ajan bildirimlerini gizle"}},"uk":{"stringUnit":{"state":"translated","value":"Приховати сповіщення підлеглих агентів"}},"zh-Hans":{"stringUnit":{"state":"translated","value":"隐藏子代理通知"}},"zh-Hant":{"stringUnit":{"state":"translated","value":"隱藏子代理通知"}}} - }, - "settings.automation.suppressSubagentNotifications.note": { - "extractionState": "manual", - "localizations": {"ar":{"stringUnit":{"state":"translated","value":"يستخدم تسلسل العمليات الأبوي من عمليات الخطافات. عطّله إذا كان يجب أن تطلق جلسات Codex أو Claude المتداخلة إشعارات الإكمال."}},"bs":{"stringUnit":{"state":"translated","value":"Koristi hijerarhiju procesa iz hook procesa. Isključite ako ugniježđene Codex ili Claude sesije trebaju slati obavještenja o završetku."}},"da":{"stringUnit":{"state":"translated","value":"Bruger proceshierarki fra hook-processer. Slå fra, hvis indlejrede Codex- eller Claude-sessioner skal udløse fuldførelsesnotifikationer."}},"de":{"stringUnit":{"state":"translated","value":"Verwendet die Prozessabstammung der Hook-Prozesse. Deaktivieren, wenn verschachtelte Codex- oder Claude-Sitzungen Abschlussbenachrichtigungen auslösen sollen."}},"en":{"stringUnit":{"state":"translated","value":"Uses process ancestry from hook processes. Disable if nested Codex or Claude sessions should trigger completion notifications."}},"es":{"stringUnit":{"state":"translated","value":"Usa la ascendencia de procesos de los hooks. Desactívalo si las sesiones anidadas de Codex o Claude deben generar notificaciones de finalización."}},"fr":{"stringUnit":{"state":"translated","value":"Utilise l’ascendance des processus de hooks. Désactivez cette option si les sessions Codex ou Claude imbriquées doivent déclencher des notifications de fin."}},"it":{"stringUnit":{"state":"translated","value":"Usa la gerarchia dei processi dei hook. Disattiva se le sessioni Codex o Claude annidate devono inviare notifiche di completamento."}},"ja":{"stringUnit":{"state":"translated","value":"フックプロセスの親子関係を使用します。ネストされた Codex または Claude セッションでも完了通知を出したい場合は無効にしてください。"}},"ko":{"stringUnit":{"state":"translated","value":"훅 프로세스의 상위 프로세스 관계를 사용합니다. 중첩된 Codex 또는 Claude 세션도 완료 알림을 보내야 한다면 비활성화하세요."}},"nb":{"stringUnit":{"state":"translated","value":"Bruker prosesshierarki fra hook-prosesser. Slå av hvis innebygde Codex- eller Claude-økter skal utløse fullføringsvarsler."}},"pl":{"stringUnit":{"state":"translated","value":"Używa hierarchii procesów hooków. Wyłącz, jeśli zagnieżdżone sesje Codex lub Claude mają wywoływać powiadomienia o zakończeniu."}},"pt-BR":{"stringUnit":{"state":"translated","value":"Usa a hierarquia de processos dos hooks. Desative se sessões aninhadas do Codex ou Claude devem disparar notificações de conclusão."}},"ru":{"stringUnit":{"state":"translated","value":"Использует иерархию процессов из hook-процессов. Отключите, если вложенные сеансы Codex или Claude должны отправлять уведомления о завершении."}},"th":{"stringUnit":{"state":"translated","value":"ใช้ลำดับชั้นของโปรเซสจากโปรเซส hook ปิดตัวเลือกนี้หากเซสชัน Codex หรือ Claude แบบซ้อนควรส่งการแจ้งเตือนเมื่อเสร็จ"}},"tr":{"stringUnit":{"state":"translated","value":"Hook süreçlerinin üst işlem zincirini kullanır. İç içe Codex veya Claude oturumları tamamlanma bildirimi göndermeliyse kapatın."}},"uk":{"stringUnit":{"state":"translated","value":"Використовує ієрархію процесів із hook-процесів. Вимкніть, якщо вкладені сеанси Codex або Claude мають надсилати сповіщення про завершення."}},"zh-Hans":{"stringUnit":{"state":"translated","value":"使用 hook 进程的进程层级。若嵌套的 Codex 或 Claude 会话应触发完成通知,请将其关闭。"}},"zh-Hant":{"stringUnit":{"state":"translated","value":"使用 hook 程序的程序層級。若巢狀 Codex 或 Claude 工作階段應觸發完成通知,請將其關閉。"}}} - }, - "settings.automation.suppressSubagentNotifications.subtitleOff": { - "extractionState": "manual", - "localizations": {"ar":{"stringUnit":{"state":"translated","value":"تُرسل إكمالات الوكلاء الفرعيين إشعارات مثل الوكلاء الأعلى مستوى."}},"bs":{"stringUnit":{"state":"translated","value":"Završeci dječijih agenata šalju obavještenja kao agenti najvišeg nivoa."}},"da":{"stringUnit":{"state":"translated","value":"Underagenters fuldførelser giver besked som topniveau-agenter."}},"de":{"stringUnit":{"state":"translated","value":"Abschlüsse von Unteragenten benachrichtigen wie Top-Level-Agenten."}},"en":{"stringUnit":{"state":"translated","value":"Child agent completions notify like top-level agents."}},"es":{"stringUnit":{"state":"translated","value":"Las finalizaciones de agentes secundarios notifican como agentes de nivel superior."}},"fr":{"stringUnit":{"state":"translated","value":"Les fins d’agents enfants notifient comme les agents de premier niveau."}},"it":{"stringUnit":{"state":"translated","value":"I completamenti degli agenti figli inviano notifiche come gli agenti di primo livello."}},"ja":{"stringUnit":{"state":"translated","value":"子エージェントの完了もトップレベルのエージェントと同様に通知します。"}},"ko":{"stringUnit":{"state":"translated","value":"하위 에이전트 완료도 최상위 에이전트처럼 알립니다."}},"nb":{"stringUnit":{"state":"translated","value":"Fullføringer fra underagenter varsler som toppnivåagenter."}},"pl":{"stringUnit":{"state":"translated","value":"Ukończenia agentów podrzędnych powiadamiają jak agenci najwyższego poziomu."}},"pt-BR":{"stringUnit":{"state":"translated","value":"Conclusões de agentes filhos notificam como agentes de nível superior."}},"ru":{"stringUnit":{"state":"translated","value":"Завершения дочерних агентов уведомляют как агенты верхнего уровня."}},"th":{"stringUnit":{"state":"translated","value":"การทำงานเสร็จของเอเจนต์ลูกจะแจ้งเตือนเหมือนเอเจนต์ระดับบนสุด"}},"tr":{"stringUnit":{"state":"translated","value":"Alt ajan tamamlanmaları üst düzey ajanlar gibi bildirim gönderir."}},"uk":{"stringUnit":{"state":"translated","value":"Завершення дочірніх агентів сповіщають як агенти верхнього рівня."}},"zh-Hans":{"stringUnit":{"state":"translated","value":"子代理完成时会像顶层代理一样通知。"}},"zh-Hant":{"stringUnit":{"state":"translated","value":"子代理完成時會像頂層代理一樣通知。"}}} - }, - "settings.automation.suppressSubagentNotifications.subtitleOn": { - "extractionState": "manual", - "localizations": {"ar":{"stringUnit":{"state":"translated","value":"تبقى إكمالات الوكلاء الفرعيين في Feed بدون إشعارات."}},"bs":{"stringUnit":{"state":"translated","value":"Završeci dječijih agenata ostaju u Feed-u bez obavještenja."}},"da":{"stringUnit":{"state":"translated","value":"Underagenters fuldførelser bliver i Feed uden notifikationer."}},"de":{"stringUnit":{"state":"translated","value":"Abschlüsse von Unteragenten bleiben ohne Benachrichtigungen im Feed."}},"en":{"stringUnit":{"state":"translated","value":"Child agent completions stay in Feed without notifications."}},"es":{"stringUnit":{"state":"translated","value":"Las finalizaciones de agentes secundarios permanecen en Feed sin notificaciones."}},"fr":{"stringUnit":{"state":"translated","value":"Les fins d’agents enfants restent dans Feed sans notifications."}},"it":{"stringUnit":{"state":"translated","value":"I completamenti degli agenti figli restano in Feed senza notifiche."}},"ja":{"stringUnit":{"state":"translated","value":"子エージェントの完了は通知せずFeedにのみ残ります。"}},"ko":{"stringUnit":{"state":"translated","value":"하위 에이전트 완료는 알림 없이 Feed에만 남습니다."}},"nb":{"stringUnit":{"state":"translated","value":"Fullføringer fra underagenter blir i Feed uten varsler."}},"pl":{"stringUnit":{"state":"translated","value":"Ukończenia agentów podrzędnych pozostają w Feed bez powiadomień."}},"pt-BR":{"stringUnit":{"state":"translated","value":"Conclusões de agentes filhos ficam no Feed sem notificações."}},"ru":{"stringUnit":{"state":"translated","value":"Завершения дочерних агентов остаются в Feed без уведомлений."}},"th":{"stringUnit":{"state":"translated","value":"การทำงานเสร็จของเอเจนต์ลูกจะอยู่ใน Feed โดยไม่มีการแจ้งเตือน"}},"tr":{"stringUnit":{"state":"translated","value":"Alt ajan tamamlanmaları bildirim olmadan Feed’de kalır."}},"uk":{"stringUnit":{"state":"translated","value":"Завершення дочірніх агентів залишаються у Feed без сповіщень."}},"zh-Hans":{"stringUnit":{"state":"translated","value":"子代理完成事件会留在 Feed 中且不通知。"}},"zh-Hant":{"stringUnit":{"state":"translated","value":"子代理完成事件會留在 Feed 中且不通知。"}}} - }, - "settings.automation.cursor": { + "settings.automation.socketOverrides.note": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Cursor Integration" + "value": "Overrides: CMUX_SOCKET_ENABLE, CMUX_SOCKET_MODE, and CMUX_SOCKET_PATH (set CMUX_ALLOW_SOCKET_OVERRIDE=1 for stable/nightly builds)." } }, "ja": { "stringUnit": { "state": "translated", - "value": "Cursor連携" + "value": "オーバーライド: CMUX_SOCKET_ENABLE、CMUX_SOCKET_MODE、CMUX_SOCKET_PATH(stable/nightlyビルドではCMUX_ALLOW_SOCKET_OVERRIDE=1を設定)。" } }, - "ko": { - "stringUnit": { - "state": "translated", - "value": "Cursor 연동" - } - } - } - }, - "settings.automation.cursor.note": { - "extractionState": "manual", - "localizations": { - "en": { + "zh-Hans": { "stringUnit": { "state": "translated", - "value": "Hooks must be installed with `cmux hooks cursor install`. They no-op outside cmux terminals." + "value": "覆盖项:CMUX_SOCKET_ENABLE、CMUX_SOCKET_MODE 和 CMUX_SOCKET_PATH(对稳定版/每日构建版需设置 CMUX_ALLOW_SOCKET_OVERRIDE=1)。" } }, - "ja": { + "zh-Hant": { "stringUnit": { "state": "translated", - "value": "フックは`cmux hooks cursor install`でインストールする必要があります。cmuxターミナル外では動作しません。" + "value": "覆寫設定:CMUX_SOCKET_ENABLE、CMUX_SOCKET_MODE 和 CMUX_SOCKET_PATH(穩定版/每夜版需設定 CMUX_ALLOW_SOCKET_OVERRIDE=1)。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "`cmux hooks cursor install`로 훅을 설치해야 합니다. cmux 터미널 외부에서는 작동하지 않습니다." - } - } - } - }, - "settings.automation.cursor.subtitleOff": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Cursor runs without cmux integration." + "value": "재정의: CMUX_SOCKET_ENABLE, CMUX_SOCKET_MODE, CMUX_SOCKET_PATH (안정/나이틀리 빌드의 경우 CMUX_ALLOW_SOCKET_OVERRIDE=1 설정)." } }, - "ja": { + "de": { "stringUnit": { "state": "translated", - "value": "Cursorはcmux連携なしで動作します。" + "value": "Überschreibungen: CMUX_SOCKET_ENABLE, CMUX_SOCKET_MODE und CMUX_SOCKET_PATH (setzen Sie CMUX_ALLOW_SOCKET_OVERRIDE=1 für Stable-/Nightly-Builds)." } }, - "ko": { - "stringUnit": { - "state": "translated", - "value": "Cursor가 cmux 연동 없이 실행됩니다." - } - } - } - }, - "settings.automation.cursor.subtitleOn": { - "extractionState": "manual", - "localizations": { - "en": { + "es": { "stringUnit": { "state": "translated", - "value": "Sidebar shows Cursor agent status and notifications." + "value": "Sobreescrituras: CMUX_SOCKET_ENABLE, CMUX_SOCKET_MODE y CMUX_SOCKET_PATH (establece CMUX_ALLOW_SOCKET_OVERRIDE=1 para compilaciones estables/nightly)." } }, - "ja": { + "fr": { "stringUnit": { "state": "translated", - "value": "サイドバーにCursorエージェントのステータスと通知が表示されます。" + "value": "Remplacements : CMUX_SOCKET_ENABLE, CMUX_SOCKET_MODE et CMUX_SOCKET_PATH (définissez CMUX_ALLOW_SOCKET_OVERRIDE=1 pour les builds stable/nightly)." } }, - "ko": { - "stringUnit": { - "state": "translated", - "value": "사이드바에 Cursor 에이전트 상태와 알림이 표시됩니다." - } - } - } - }, - "settings.automation.gemini": { - "extractionState": "manual", - "localizations": { - "en": { + "it": { "stringUnit": { "state": "translated", - "value": "Gemini CLI Integration" + "value": "Override: CMUX_SOCKET_ENABLE, CMUX_SOCKET_MODE e CMUX_SOCKET_PATH (imposta CMUX_ALLOW_SOCKET_OVERRIDE=1 per le build stable/nightly)." } }, - "ja": { + "da": { "stringUnit": { "state": "translated", - "value": "Gemini CLI連携" + "value": "Tilsidesættelser: CMUX_SOCKET_ENABLE, CMUX_SOCKET_MODE og CMUX_SOCKET_PATH (sæt CMUX_ALLOW_SOCKET_OVERRIDE=1 for stabile/nightly builds)." } }, - "ko": { - "stringUnit": { - "state": "translated", - "value": "Gemini CLI 연동" - } - } - } - }, - "settings.automation.gemini.note": { - "extractionState": "manual", - "localizations": { - "en": { + "pl": { "stringUnit": { "state": "translated", - "value": "Hooks must be installed with `cmux hooks gemini install`. They no-op outside cmux terminals." + "value": "Nadpisania: CMUX_SOCKET_ENABLE, CMUX_SOCKET_MODE i CMUX_SOCKET_PATH (ustaw CMUX_ALLOW_SOCKET_OVERRIDE=1 dla wersji stabilnych/nightly)." } }, - "ja": { + "ru": { "stringUnit": { "state": "translated", - "value": "フックは`cmux hooks gemini install`でインストールする必要があります。cmuxターミナル外では動作しません。" + "value": "Переопределения: CMUX_SOCKET_ENABLE, CMUX_SOCKET_MODE и CMUX_SOCKET_PATH (установите CMUX_ALLOW_SOCKET_OVERRIDE=1 для стабильных/ночных сборок)." } }, - "ko": { + "bs": { "stringUnit": { "state": "translated", - "value": "`cmux hooks gemini install`로 훅을 설치해야 합니다. cmux 터미널 외부에서는 작동하지 않습니다." + "value": "Premošćenja: CMUX_SOCKET_ENABLE, CMUX_SOCKET_MODE i CMUX_SOCKET_PATH (postavite CMUX_ALLOW_SOCKET_OVERRIDE=1 za stabilne/nightly verzije)." } - } - } - }, - "settings.automation.gemini.subtitleOff": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "ar": { "stringUnit": { "state": "translated", - "value": "Gemini runs without cmux integration." + "value": "التجاوزات: CMUX_SOCKET_ENABLE و CMUX_SOCKET_MODE و CMUX_SOCKET_PATH (اضبط CMUX_ALLOW_SOCKET_OVERRIDE=1 لبناءات stable/nightly)." } }, - "ja": { + "nb": { "stringUnit": { "state": "translated", - "value": "GeminiはCmux連携なしで動作します。" + "value": "Overstyringer: CMUX_SOCKET_ENABLE, CMUX_SOCKET_MODE og CMUX_SOCKET_PATH (sett CMUX_ALLOW_SOCKET_OVERRIDE=1 for stabile/nattlige bygg)." } }, - "ko": { + "pt-BR": { "stringUnit": { "state": "translated", - "value": "Gemini가 cmux 연동 없이 실행됩니다." + "value": "Substituições: CMUX_SOCKET_ENABLE, CMUX_SOCKET_MODE e CMUX_SOCKET_PATH (defina CMUX_ALLOW_SOCKET_OVERRIDE=1 para builds stable/nightly)." } - } - } - }, - "settings.automation.gemini.subtitleOn": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "th": { "stringUnit": { "state": "translated", - "value": "Sidebar shows Gemini session status and notifications." + "value": "การแทนที่: CMUX_SOCKET_ENABLE, CMUX_SOCKET_MODE และ CMUX_SOCKET_PATH (ตั้ง CMUX_ALLOW_SOCKET_OVERRIDE=1 สำหรับบิลด์ stable/nightly)" } }, - "ja": { + "tr": { "stringUnit": { "state": "translated", - "value": "サイドバーにGeminiセッションのステータスと通知が表示されます。" + "value": "Geçersiz kılmalar: CMUX_SOCKET_ENABLE, CMUX_SOCKET_MODE ve CMUX_SOCKET_PATH (kararlı/gece derlemeleri için CMUX_ALLOW_SOCKET_OVERRIDE=1 ayarlayın)." } }, - "ko": { + "uk": { "stringUnit": { "state": "translated", - "value": "사이드바에 Gemini 세션 상태와 알림이 표시됩니다." + "value": "Перевизначення: CMUX_SOCKET_ENABLE, CMUX_SOCKET_MODE та CMUX_SOCKET_PATH (встановіть CMUX_ALLOW_SOCKET_OVERRIDE=1 для стабільних/нічних збірок)." } } } }, - "settings.automation.openAccess.dialog.cancel": { + "settings.automation.socketPassword": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Cancel" + "value": "Socket Password" } }, "ja": { "stringUnit": { "state": "translated", - "value": "キャンセル" + "value": "ソケットパスワード" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "取消" + "value": "套接字密码" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "取消" + "value": "Socket 密碼" } }, "ko": { "stringUnit": { "state": "translated", - "value": "취소" + "value": "소켓 비밀번호" } }, "de": { "stringUnit": { "state": "translated", - "value": "Abbrechen" + "value": "Socket-Passwort" } }, "es": { "stringUnit": { "state": "translated", - "value": "Cancelar" + "value": "Contraseña del socket" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Annuler" + "value": "Mot de passe du socket" } }, "it": { "stringUnit": { "state": "translated", - "value": "Annulla" + "value": "Password socket" } }, "da": { "stringUnit": { "state": "translated", - "value": "Annuller" + "value": "Socket-adgangskode" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Anuluj" + "value": "Hasło gniazda" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Отменить" + "value": "Пароль сокета" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Otkaži" + "value": "Lozinka utičnice" } }, "ar": { "stringUnit": { "state": "translated", - "value": "إلغاء" + "value": "كلمة مرور المقبس" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Avbryt" + "value": "Socket-passord" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Cancelar" + "value": "Senha do Socket" } }, "th": { "stringUnit": { "state": "translated", - "value": "ยกเลิก" + "value": "รหัสผ่านซ็อกเก็ต" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Vazgeç" + "value": "Soket Parolası" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Скасувати" + "value": "Пароль сокета" } } } }, - "settings.automation.openAccess.dialog.confirm": { + "settings.automation.socketPassword.change": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Enable Full Open Access" + "value": "Change" } }, "ja": { "stringUnit": { "state": "translated", - "value": "フルオープンアクセスを有効にする" + "value": "変更" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "启用完全开放访问" + "value": "更改" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "啟用完全開放存取" + "value": "變更" } }, "ko": { "stringUnit": { "state": "translated", - "value": "전체 개방 접근 활성화" + "value": "변경" } }, "de": { "stringUnit": { "state": "translated", - "value": "Vollständigen offenen Zugriff aktivieren" + "value": "Ändern" } }, "es": { "stringUnit": { "state": "translated", - "value": "Activar acceso abierto completo" + "value": "Cambiar" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Activer l'accès ouvert complet" + "value": "Modifier" } }, "it": { "stringUnit": { "state": "translated", - "value": "Abilita accesso aperto completo" + "value": "Modifica" } }, "da": { "stringUnit": { "state": "translated", - "value": "Aktiver fuld åben adgang" + "value": "Skift" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Włącz pełny otwarty dostęp" + "value": "Zmień" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Включить полный открытый доступ" + "value": "Изменить" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Omogući potpuni otvoreni pristup" + "value": "Promijeni" } }, "ar": { "stringUnit": { "state": "translated", - "value": "تفعيل الوصول المفتوح الكامل" + "value": "تغيير" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Aktiver full åpen tilgang" + "value": "Endre" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Ativar Acesso Aberto Total" + "value": "Alterar" } }, "th": { "stringUnit": { "state": "translated", - "value": "เปิดใช้งานการเข้าถึงเปิดแบบเต็ม" + "value": "เปลี่ยน" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Tam Açık Erişimi Etkinleştir" + "value": "Değiştir" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Увімкнути повний відкритий доступ" + "value": "Змінити" } } } }, - "settings.automation.openAccess.dialog.message": { + "settings.automation.socketPassword.clear": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "This disables ancestry and password checks and opens the socket to all local users. Only enable when you understand the risk." + "value": "Clear" } }, "ja": { "stringUnit": { "state": "translated", - "value": "これにより、祖先プロセスチェックとパスワードチェックが無効になり、すべてのローカルユーザーにソケットが公開されます。リスクを理解した上で有効にしてください。" + "value": "クリア" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "这将禁用祖先和密码检查,并向所有本地用户开放套接字。请确保您了解其中的风险后再启用。" + "value": "清除" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "這將停用來源驗證和密碼檢查,並將 Socket 開放給所有本機使用者。請確認您了解風險後再啟用。" + "value": "清除" } }, "ko": { "stringUnit": { "state": "translated", - "value": "이 설정은 출처 확인 및 비밀번호 검사를 비활성화하고 모든 로컬 사용자에게 소켓을 개방합니다. 위험을 이해한 경우에만 활성화하세요." + "value": "지우기" } }, "de": { "stringUnit": { "state": "translated", - "value": "Dies deaktiviert Abstammungs- und Passwortprüfungen und öffnet den Socket für alle lokalen Benutzer. Aktivieren Sie dies nur, wenn Sie das Risiko verstehen." + "value": "Löschen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Esto desactiva las verificaciones de ascendencia y contraseña, y abre el socket a todos los usuarios locales. Activa solo si comprendes el riesgo." + "value": "Borrar" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Cela désactive les vérifications de parenté et de mot de passe et ouvre le socket à tous les utilisateurs locaux. N'activez que si vous comprenez les risques." + "value": "Effacer" } }, "it": { "stringUnit": { "state": "translated", - "value": "Questa operazione disabilita i controlli di discendenza e password e apre il socket a tutti gli utenti locali. Abilita solo se comprendi il rischio." + "value": "Cancella" } }, "da": { "stringUnit": { "state": "translated", - "value": "Dette deaktiverer herkomst- og adgangskodekontrol og åbner socketen for alle lokale brugere. Aktiver kun, når du forstår risikoen." + "value": "Ryd" } }, "pl": { "stringUnit": { "state": "translated", - "value": "To wyłącza sprawdzanie pochodzenia i hasła oraz otwiera gniazdo dla wszystkich lokalnych użytkowników. Włączaj tylko wtedy, gdy rozumiesz ryzyko." + "value": "Wyczyść" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Это отключает проверку происхождения и пароля и открывает сокет для всех локальных пользователей. Включайте только если понимаете риски." + "value": "Очистить" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Ovo onemogućava provjere porijekla i lozinke i otvara utičnicu svim lokalnim korisnicima. Omogućite samo kada razumijete rizik." + "value": "Obriši" } }, "ar": { "stringUnit": { "state": "translated", - "value": "يؤدي هذا إلى تعطيل فحوصات النسب وكلمة المرور ويفتح المقبس لجميع المستخدمين المحليين. قم بالتفعيل فقط عندما تفهم المخاطر." + "value": "مسح" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Dette deaktiverer opphavs- og passordkontroller og åpner socketen for alle lokale brukere. Aktiver bare når du forstår risikoen." + "value": "Fjern" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Isto desativa verificações de ancestralidade e senha e abre o socket para todos os usuários locais. Ative somente quando entender os riscos." + "value": "Limpar" } }, "th": { "stringUnit": { "state": "translated", - "value": "การดำเนินการนี้จะปิดใช้งานการตรวจสอบสายสืบทอดและรหัสผ่าน และเปิดซ็อกเก็ตให้ผู้ใช้ในเครื่องทุกคน เปิดใช้งานเฉพาะเมื่อคุณเข้าใจความเสี่ยง" + "value": "ล้าง" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Bu, soy ve parola denetimlerini devre dışı bırakır ve soketi tüm yerel kullanıcılara açar. Yalnızca riski anladığınızda etkinleştirin." + "value": "Temizle" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Це вимикає перевірку походження та пароля і відкриває сокет для всіх локальних користувачів. Вмикайте лише якщо розумієте ризики." + "value": "Очистити" } } } }, - "settings.automation.openAccess.dialog.title": { + "settings.automation.socketPassword.clearFailed": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Enable full open access?" + "value": "Failed to clear password (%@)." } }, "ja": { "stringUnit": { "state": "translated", - "value": "フルオープンアクセスを有効にしますか?" + "value": "パスワードのクリアに失敗しました(%@)。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "启用完全开放访问?" + "value": "清除密码失败 (%@)。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "要啟用完全開放存取嗎?" + "value": "清除密碼失敗(%@)。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "전체 개방 접근을 활성화하시겠습니까?" + "value": "비밀번호 지우기 실패 (%@)." } }, "de": { "stringUnit": { "state": "translated", - "value": "Vollständigen offenen Zugriff aktivieren?" + "value": "Passwort konnte nicht gelöscht werden (%@)." } }, "es": { "stringUnit": { "state": "translated", - "value": "¿Activar acceso abierto completo?" + "value": "No se pudo borrar la contraseña (%@)." } }, "fr": { "stringUnit": { "state": "translated", - "value": "Activer l'accès ouvert complet ?" + "value": "Impossible d'effacer le mot de passe (%@)." } }, "it": { "stringUnit": { "state": "translated", - "value": "Abilitare l'accesso aperto completo?" + "value": "Impossibile cancellare la password (%@)." } }, "da": { "stringUnit": { "state": "translated", - "value": "Aktiver fuld åben adgang?" + "value": "Kunne ikke rydde adgangskode (%@)." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Włączyć pełny otwarty dostęp?" + "value": "Nie udało się wyczyścić hasła (%@)." } }, "ru": { "stringUnit": { "state": "translated", - "value": "Включить полный открытый доступ?" + "value": "Не удалось очистить пароль (%@)." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Omogućiti potpuni otvoreni pristup?" + "value": "Nije uspjelo brisanje lozinke (%@)." } }, "ar": { "stringUnit": { "state": "translated", - "value": "تفعيل الوصول المفتوح الكامل؟" + "value": "فشل مسح كلمة المرور (%@)." } }, "nb": { "stringUnit": { "state": "translated", - "value": "Aktivere full åpen tilgang?" + "value": "Kunne ikke fjerne passord (%@)." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Ativar acesso aberto total?" + "value": "Falha ao limpar a senha (%@)." } }, "th": { "stringUnit": { "state": "translated", - "value": "เปิดใช้งานการเข้าถึงเปิดแบบเต็มหรือไม่?" + "value": "ไม่สามารถล้างรหัสผ่านได้ (%@)" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Tam açık erişim etkinleştirilsin mi?" + "value": "Parola temizlenemedi (%@)." } }, "uk": { "stringUnit": { "state": "translated", - "value": "Увімкнути повний відкритий доступ?" + "value": "Не вдалося очистити пароль (%@)." } } } }, - "settings.automation.openAccessWarning": { + "settings.automation.socketPassword.cleared": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Warning: Full open access makes the control socket world-readable/writable on this Mac and disables auth checks. Use only for local debugging." + "value": "Password cleared." } }, "ja": { "stringUnit": { "state": "translated", - "value": "警告: フルオープンアクセスにすると、このMac上の制御ソケットが誰でも読み書き可能になり、認証チェックが無効になります。ローカルデバッグ用途にのみ使用してください。" + "value": "パスワードをクリアしました。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "警告:完全开放访问将使控制套接字在此 Mac 上对所有用户可读/可写,并禁用身份验证检查。仅用于本地调试。" + "value": "密码已清除。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "警告:完全開放存取會讓控制 Socket 在此 Mac 上可被所有人讀寫,並停用驗證檢查。僅供本機除錯使用。" + "value": "密碼已清除。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "경고: 전체 개방 접근은 이 Mac에서 제어 소켓을 누구나 읽고 쓸 수 있게 하며 인증 검사를 비활성화합니다. 로컬 디버깅 전용으로만 사용하세요." + "value": "비밀번호가 지워졌습니다." } }, "de": { "stringUnit": { "state": "translated", - "value": "Warnung: Vollständiger offener Zugriff macht den Steuerungs-Socket auf diesem Mac für alle les- und schreibbar und deaktiviert Authentifizierungsprüfungen. Nur für lokales Debugging verwenden." + "value": "Passwort gelöscht." } }, "es": { "stringUnit": { "state": "translated", - "value": "Advertencia: El acceso abierto completo hace que el socket de control sea legible/escribible para todos en este Mac y desactiva las verificaciones de autenticación. Usa solo para depuración local." + "value": "Contraseña borrada." } }, "fr": { "stringUnit": { "state": "translated", - "value": "Attention : l'accès ouvert complet rend le socket de contrôle lisible/inscriptible par tous sur ce Mac et désactive les vérifications d'authentification. À utiliser uniquement pour le débogage local." + "value": "Mot de passe effacé." } }, "it": { "stringUnit": { "state": "translated", - "value": "Attenzione: l'accesso aperto completo rende il socket di controllo leggibile/scrivibile da tutti su questo Mac e disabilita i controlli di autenticazione. Usa solo per il debug locale." + "value": "Password cancellata." } }, "da": { "stringUnit": { "state": "translated", - "value": "Advarsel: Fuld åben adgang gør kontrolsocketen læsbar/skrivbar for alle på denne Mac og deaktiverer autentifikationskontrol. Brug kun til lokal fejlsøgning." + "value": "Adgangskode ryddet." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Ostrzeżenie: Pełny otwarty dostęp czyni gniazdo sterujące odczytywalnym/zapisywalnym dla wszystkich na tym Macu i wyłącza sprawdzanie uwierzytelniania. Używaj tylko do lokalnego debugowania." + "value": "Hasło wyczyszczone." } }, "ru": { "stringUnit": { "state": "translated", - "value": "Внимание: полный открытый доступ делает управляющий сокет доступным для чтения и записи всем пользователям на этом Mac и отключает проверку авторизации. Используйте только для локальной отладки." + "value": "Пароль очищен." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Upozorenje: Potpuni otvoreni pristup čini kontrolnu utičnicu čitljivom/zapisivom za sve na ovom Macu i onemogućava provjere autentikacije. Koristite samo za lokalno debugiranje." + "value": "Lozinka obrisana." } }, "ar": { "stringUnit": { "state": "translated", - "value": "تحذير: الوصول المفتوح الكامل يجعل مقبس التحكم قابلاً للقراءة والكتابة من الجميع على هذا الـ Mac ويعطل فحوصات المصادقة. استخدم فقط لأغراض التصحيح المحلي." + "value": "تم مسح كلمة المرور." } }, "nb": { "stringUnit": { "state": "translated", - "value": "Advarsel: Full åpen tilgang gjør kontrollsocketen lese-/skrivbar for alle på denne Mac-en og deaktiverer autentiseringskontroller. Bruk kun for lokal feilsøking." + "value": "Passord fjernet." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Aviso: O acesso aberto total torna o socket de controle legível/gravável por todos neste Mac e desativa verificações de autenticação. Use apenas para depuração local." + "value": "Senha removida." } }, "th": { "stringUnit": { "state": "translated", - "value": "คำเตือน: การเข้าถึงเปิดแบบเต็มทำให้ซ็อกเก็ตควบคุมอ่าน/เขียนได้จากทุกผู้ใช้บน Mac นี้และปิดใช้งานการตรวจสอบสิทธิ์ ใช้สำหรับการดีบักในเครื่องเท่านั้น" + "value": "ล้างรหัสผ่านแล้ว" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Uyarı: Tam açık erişim, kontrol soketini bu Mac'te herkes tarafından okunabilir/yazılabilir yapar ve kimlik doğrulama denetimlerini devre dışı bırakır. Yalnızca yerel hata ayıklama için kullanın." + "value": "Parola temizlendi." } }, "uk": { "stringUnit": { "state": "translated", - "value": "Увага: повний відкритий доступ робить керуючий сокет доступним для читання/запису всім на цьому Mac та вимикає перевірки автентифікації. Використовуйте лише для локального налагодження." + "value": "Пароль очищено." } } } }, - "settings.automation.port.note": { + "settings.automation.socketPassword.enterFirst": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Each workspace gets CMUX_PORT and CMUX_PORT_END env vars with a dedicated port range. New terminals inherit these values." + "value": "Enter a password first." } }, "ja": { "stringUnit": { "state": "translated", - "value": "各ワークスペースにはCMUX_PORTとCMUX_PORT_END環境変数で専用のポート範囲が割り当てられます。新しいターミナルはこれらの値を継承します。" + "value": "まずパスワードを入力してください。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "每个工作区会获得 CMUX_PORT 和 CMUX_PORT_END 环境变量,包含专用的端口范围。新终端会继承这些值。" + "value": "请先输入密码。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "每個工作區都會取得包含專用連接埠範圍的 CMUX_PORT 和 CMUX_PORT_END 環境變數。新終端機會繼承這些值。" + "value": "請先輸入密碼。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "각 작업 공간에 전용 포트 범위가 있는 CMUX_PORT 및 CMUX_PORT_END 환경 변수가 할당됩니다. 새 터미널은 이 값을 상속합니다." + "value": "먼저 비밀번호를 입력하세요." } }, "de": { "stringUnit": { "state": "translated", - "value": "Jeder Arbeitsbereich erhält CMUX_PORT- und CMUX_PORT_END-Umgebungsvariablen mit einem dedizierten Portbereich. Neue Terminals erben diese Werte." + "value": "Geben Sie zuerst ein Passwort ein." } }, "es": { "stringUnit": { "state": "translated", - "value": "Cada espacio de trabajo recibe las variables de entorno CMUX_PORT y CMUX_PORT_END con un rango de puertos dedicado. Los nuevos terminales heredan estos valores." + "value": "Introduce una contraseña primero." } }, "fr": { "stringUnit": { "state": "translated", - "value": "Chaque espace de travail reçoit les variables d'environnement CMUX_PORT et CMUX_PORT_END avec une plage de ports dédiée. Les nouveaux terminaux héritent de ces valeurs." + "value": "Saisissez d'abord un mot de passe." } }, "it": { "stringUnit": { "state": "translated", - "value": "Ogni area di lavoro riceve le variabili d'ambiente CMUX_PORT e CMUX_PORT_END con un intervallo di porte dedicato. I nuovi terminali ereditano questi valori." + "value": "Inserisci prima una password." } }, "da": { "stringUnit": { "state": "translated", - "value": "Hvert arbejdsområde får CMUX_PORT og CMUX_PORT_END miljøvariabler med et dedikeret portområde. Nye terminaler arver disse værdier." + "value": "Indtast en adgangskode først." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Każda przestrzeń robocza otrzymuje zmienne środowiskowe CMUX_PORT i CMUX_PORT_END z dedykowanym zakresem portów. Nowe terminale dziedziczą te wartości." + "value": "Najpierw wprowadź hasło." } }, "ru": { "stringUnit": { "state": "translated", - "value": "Каждое рабочее пространство получает переменные окружения CMUX_PORT и CMUX_PORT_END с выделенным диапазоном портов. Новые терминалы наследуют эти значения." + "value": "Сначала введите пароль." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Svaki radni prostor dobija CMUX_PORT i CMUX_PORT_END varijable okruženja sa dodijeljenim rasponom portova. Novi terminali nasljeđuju ove vrijednosti." + "value": "Prvo unesite lozinku." } }, "ar": { "stringUnit": { "state": "translated", - "value": "تحصل كل مساحة عمل على متغيرات البيئة CMUX_PORT و CMUX_PORT_END مع نطاق منافذ مخصص. ترث الطرفيات الجديدة هذه القيم." + "value": "أدخل كلمة مرور أولاً." } }, "nb": { "stringUnit": { "state": "translated", - "value": "Hvert arbeidsområde får CMUX_PORT- og CMUX_PORT_END-miljøvariabler med et dedikert portområde. Nye terminaler arver disse verdiene." + "value": "Skriv inn et passord først." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Cada área de trabalho recebe as variáveis de ambiente CMUX_PORT e CMUX_PORT_END com uma faixa de portas dedicada. Novos terminais herdam esses valores." + "value": "Insira uma senha primeiro." } }, "th": { "stringUnit": { "state": "translated", - "value": "แต่ละเวิร์กสเปซจะได้รับตัวแปรสภาพแวดล้อม CMUX_PORT และ CMUX_PORT_END พร้อมช่วงพอร์ตเฉพาะ เทอร์มินัลใหม่จะสืบทอดค่าเหล่านี้" + "value": "ป้อนรหัสผ่านก่อน" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Her çalışma alanı ayrılmış bir port aralığıyla CMUX_PORT ve CMUX_PORT_END ortam değişkenlerini alır. Yeni terminaller bu değerleri devralır." + "value": "Önce bir parola girin." } }, "uk": { "stringUnit": { "state": "translated", - "value": "Кожна робоча область отримує змінні середовища CMUX_PORT та CMUX_PORT_END з виділеним діапазоном портів. Нові термінали успадковують ці значення." + "value": "Спочатку введіть пароль." } } } }, - "settings.automation.portBase": { + "settings.automation.socketPassword.placeholder": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Port Base" + "value": "Password" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ポートベース" + "value": "パスワード" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "起始端口" + "value": "密码" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "連接埠起始值" + "value": "密碼" } }, "ko": { "stringUnit": { "state": "translated", - "value": "포트 기준값" + "value": "비밀번호" } }, "de": { "stringUnit": { "state": "translated", - "value": "Port-Basis" + "value": "Passwort" } }, "es": { "stringUnit": { "state": "translated", - "value": "Puerto base" + "value": "Contraseña" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Port de base" + "value": "Mot de passe" } }, "it": { "stringUnit": { "state": "translated", - "value": "Porta base" + "value": "Password" } }, "da": { "stringUnit": { "state": "translated", - "value": "Portbase" + "value": "Adgangskode" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Port bazowy" + "value": "Hasło" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Базовый порт" + "value": "Пароль" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Početni port" + "value": "Lozinka" } }, "ar": { "stringUnit": { "state": "translated", - "value": "المنفذ الأساسي" + "value": "كلمة المرور" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Portbase" + "value": "Passord" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Porta Base" + "value": "Senha" } }, "th": { "stringUnit": { "state": "translated", - "value": "พอร์ตเริ่มต้น" + "value": "รหัสผ่าน" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Port Tabanı" + "value": "Parola" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Базовий порт" + "value": "Пароль" } } } }, - "settings.automation.portBase.subtitle": { + "settings.automation.socketPassword.saveFailed": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Starting port for CMUX_PORT env var." + "value": "Failed to save password (%@)." } }, "ja": { "stringUnit": { "state": "translated", - "value": "CMUX_PORT環境変数の開始ポート。" + "value": "パスワードの保存に失敗しました(%@)。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "CMUX_PORT 环境变量的起始端口。" + "value": "保存密码失败 (%@)。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "CMUX_PORT 環境變數的起始連接埠。" + "value": "儲存密碼失敗(%@)。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "CMUX_PORT 환경 변수의 시작 포트." + "value": "비밀번호 저장 실패 (%@)." } }, "de": { "stringUnit": { "state": "translated", - "value": "Startport für die CMUX_PORT-Umgebungsvariable." + "value": "Passwort konnte nicht gespeichert werden (%@)." } }, "es": { "stringUnit": { "state": "translated", - "value": "Puerto inicial para la variable de entorno CMUX_PORT." + "value": "No se pudo guardar la contraseña (%@)." } }, "fr": { "stringUnit": { "state": "translated", - "value": "Port de départ pour la variable d'environnement CMUX_PORT." + "value": "Impossible d'enregistrer le mot de passe (%@)." } }, "it": { "stringUnit": { "state": "translated", - "value": "Porta iniziale per la variabile d'ambiente CMUX_PORT." + "value": "Impossibile salvare la password (%@)." } }, "da": { "stringUnit": { "state": "translated", - "value": "Startport for CMUX_PORT-miljøvariabel." + "value": "Kunne ikke gemme adgangskode (%@)." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Port początkowy dla zmiennej środowiskowej CMUX_PORT." + "value": "Nie udało się zapisać hasła (%@)." } }, "ru": { "stringUnit": { "state": "translated", - "value": "Начальный порт для переменной окружения CMUX_PORT." + "value": "Не удалось сохранить пароль (%@)." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Početni port za CMUX_PORT varijablu okruženja." + "value": "Nije uspjelo spremanje lozinke (%@)." } }, "ar": { "stringUnit": { "state": "translated", - "value": "المنفذ الابتدائي لمتغير البيئة CMUX_PORT." + "value": "فشل حفظ كلمة المرور (%@)." } }, "nb": { "stringUnit": { "state": "translated", - "value": "Startport for CMUX_PORT-miljøvariabelen." + "value": "Kunne ikke lagre passord (%@)." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Porta inicial para a variável de ambiente CMUX_PORT." + "value": "Falha ao salvar a senha (%@)." } }, "th": { "stringUnit": { "state": "translated", - "value": "พอร์ตเริ่มต้นสำหรับตัวแปรสภาพแวดล้อม CMUX_PORT" + "value": "ไม่สามารถบันทึกรหัสผ่านได้ (%@)" } }, "tr": { "stringUnit": { "state": "translated", - "value": "CMUX_PORT ortam değişkeni için başlangıç portu." + "value": "Parola kaydedilemedi (%@)." } }, "uk": { "stringUnit": { "state": "translated", - "value": "Початковий порт для змінної середовища CMUX_PORT." + "value": "Не вдалося зберегти пароль (%@)." } } } }, - "settings.automation.portRange": { + "settings.automation.socketPassword.saved": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Port Range Size" + "value": "Password saved." } }, "ja": { "stringUnit": { "state": "translated", - "value": "ポート範囲サイズ" + "value": "パスワードを保存しました。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "端口范围大小" + "value": "密码已保存。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "連接埠範圍大小" + "value": "密碼已儲存。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "포트 범위 크기" + "value": "비밀번호가 저장되었습니다." } }, "de": { "stringUnit": { "state": "translated", - "value": "Portbereichsgröße" + "value": "Passwort gespeichert." } }, "es": { "stringUnit": { "state": "translated", - "value": "Tamaño del rango de puertos" + "value": "Contraseña guardada." } }, "fr": { "stringUnit": { "state": "translated", - "value": "Taille de la plage de ports" + "value": "Mot de passe enregistré." } }, "it": { "stringUnit": { "state": "translated", - "value": "Dimensione intervallo porte" + "value": "Password salvata." } }, "da": { "stringUnit": { "state": "translated", - "value": "Portområdestørrelse" + "value": "Adgangskode gemt." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Rozmiar zakresu portów" + "value": "Hasło zapisane." } }, "ru": { "stringUnit": { "state": "translated", - "value": "Размер диапазона портов" + "value": "Пароль сохранен." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Veličina raspona portova" + "value": "Lozinka spremljena." } }, "ar": { "stringUnit": { "state": "translated", - "value": "حجم نطاق المنافذ" + "value": "تم حفظ كلمة المرور." } }, "nb": { "stringUnit": { "state": "translated", - "value": "Portområdestørrelse" + "value": "Passord lagret." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Tamanho da Faixa de Portas" + "value": "Senha salva." } }, "th": { "stringUnit": { "state": "translated", - "value": "ขนาดช่วงพอร์ต" + "value": "บันทึกรหัสผ่านแล้ว" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Port Aralığı Boyutu" + "value": "Parola kaydedildi." } }, "uk": { "stringUnit": { "state": "translated", - "value": "Розмір діапазону портів" + "value": "Пароль збережено." } } } }, - "settings.automation.portRange.subtitle": { + "settings.automation.socketPassword.set": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Number of ports per workspace." + "value": "Set" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ワークスペースあたりのポート数。" + "value": "設定" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "每个工作区的端口数量。" + "value": "设置" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "每個工作區的連接埠數量。" + "value": "設定" } }, "ko": { "stringUnit": { "state": "translated", - "value": "작업 공간당 포트 수." + "value": "설정" } }, "de": { "stringUnit": { "state": "translated", - "value": "Anzahl der Ports pro Arbeitsbereich." + "value": "Festlegen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Número de puertos por espacio de trabajo." + "value": "Establecer" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Nombre de ports par espace de travail." + "value": "Définir" } }, "it": { "stringUnit": { "state": "translated", - "value": "Numero di porte per area di lavoro." + "value": "Imposta" } }, "da": { "stringUnit": { "state": "translated", - "value": "Antal porte pr. arbejdsområde." + "value": "Angiv" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Liczba portów na przestrzeń roboczą." + "value": "Ustaw" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Количество портов на рабочее пространство." + "value": "Установить" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Broj portova po radnom prostoru." + "value": "Postavi" } }, "ar": { "stringUnit": { "state": "translated", - "value": "عدد المنافذ لكل مساحة عمل." + "value": "تعيين" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Antall porter per arbeidsområde." + "value": "Angi" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Número de portas por área de trabalho." + "value": "Definir" } }, "th": { "stringUnit": { "state": "translated", - "value": "จำนวนพอร์ตต่อเวิร์กสเปซ" + "value": "ตั้งค่า" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Çalışma alanı başına port sayısı." + "value": "Ayarla" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Кількість портів на робочу область." + "value": "Встановити" } } } }, - "settings.automation.socketMode": { + "settings.automation.socketPassword.subtitleSet": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Socket Control Mode" + "value": "Stored in Application Support." } }, "ja": { "stringUnit": { "state": "translated", - "value": "ソケット制御モード" + "value": "Application Supportに保存済み。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "套接字控制模式" + "value": "存储在应用程序支持目录中。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "Socket 控制模式" + "value": "儲存於 Application Support。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "소켓 제어 모드" + "value": "Application Support에 저장됨." } }, "de": { "stringUnit": { "state": "translated", - "value": "Socket-Steuerungsmodus" + "value": "Gespeichert in Application Support." } }, "es": { "stringUnit": { "state": "translated", - "value": "Modo de control del socket" + "value": "Almacenada en Application Support." } }, "fr": { "stringUnit": { "state": "translated", - "value": "Mode de contrôle du socket" + "value": "Stocké dans Application Support." } }, "it": { "stringUnit": { "state": "translated", - "value": "Modalità controllo socket" + "value": "Memorizzata nel Supporto Applicazioni." } }, "da": { "stringUnit": { "state": "translated", - "value": "Socket-kontroltilstand" + "value": "Gemt i Application Support." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Tryb sterowania gniazdem" + "value": "Przechowywane w Application Support." } }, "ru": { "stringUnit": { "state": "translated", - "value": "Режим управления сокетом" + "value": "Хранится в Application Support." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Režim kontrolne utičnice" + "value": "Pohranjena u Application Support." } }, "ar": { "stringUnit": { "state": "translated", - "value": "وضع التحكم بالمقبس" + "value": "مخزنة في Application Support." } }, "nb": { "stringUnit": { "state": "translated", - "value": "Socket-kontrollmodus" + "value": "Lagret i Application Support." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Modo de Controle do Socket" + "value": "Armazenada em Application Support." } }, "th": { "stringUnit": { "state": "translated", - "value": "โหมดควบคุมซ็อกเก็ต" + "value": "จัดเก็บใน Application Support" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Soket Kontrol Modu" + "value": "Uygulama Desteği klasöründe saklanır." } }, "uk": { "stringUnit": { "state": "translated", - "value": "Режим керуючого сокета" + "value": "Збережено в Application Support." } } } }, - "settings.automation.socketMode.note": { + "settings.automation.socketPassword.subtitleUnset": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Controls access to the local Unix socket for programmatic control. Choose a mode that matches your threat model." + "value": "No password set. External clients will be blocked until one is configured." } }, "ja": { "stringUnit": { "state": "translated", - "value": "プログラムによる制御のためのローカルUnix socketへのアクセスを制御します。脅威モデルに合ったモードを選択してください。" + "value": "パスワードが設定されていません。設定するまで外部クライアントはブロックされます。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "控制本地 Unix 套接字的访问权限,用于程序化控制。请选择与您的安全需求匹配的模式。" + "value": "未设置密码。外部客户端将被阻止,直到配置密码为止。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "控制本機 Unix Socket 的程式化控制存取。選擇符合您安全需求的模式。" + "value": "尚未設定密碼。外部用戶端將被封鎖,直到設定密碼為止。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "프로그래밍 방식 제어를 위한 로컬 Unix 소켓 접근을 제어합니다. 보안 모델에 맞는 모드를 선택하세요." + "value": "비밀번호가 설정되지 않았습니다. 비밀번호를 구성하기 전까지 외부 클라이언트가 차단됩니다." } }, "de": { "stringUnit": { "state": "translated", - "value": "Steuert den Zugriff auf den lokalen Unix-Socket für programmatische Steuerung. Wählen Sie einen Modus, der Ihrem Bedrohungsmodell entspricht." + "value": "Kein Passwort festgelegt. Externe Clients werden blockiert, bis eines konfiguriert ist." } }, "es": { "stringUnit": { "state": "translated", - "value": "Controla el acceso al socket Unix local para control programático. Elige un modo que coincida con tu modelo de amenazas." + "value": "No se ha establecido contraseña. Los clientes externos serán bloqueados hasta que se configure una." } }, "fr": { "stringUnit": { "state": "translated", - "value": "Contrôle l'accès au socket Unix local pour le contrôle programmatique. Choisissez un mode adapté à votre modèle de menace." + "value": "Aucun mot de passe défini. Les clients externes seront bloqués tant qu'un mot de passe n'aura pas été configuré." } }, "it": { "stringUnit": { "state": "translated", - "value": "Controlla l'accesso al socket Unix locale per il controllo programmatico. Scegli una modalità adeguata al tuo modello di rischio." + "value": "Nessuna password impostata. I client esterni verranno bloccati finché non ne viene configurata una." } }, "da": { "stringUnit": { "state": "translated", - "value": "Styrer adgangen til den lokale Unix-socket til programmatisk kontrol. Vælg en tilstand, der passer til din trusselsmodel." + "value": "Ingen adgangskode angivet. Eksterne klienter blokeres, indtil en er konfigureret." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Kontroluje dostęp do lokalnego gniazda Unix do programowego sterowania. Wybierz tryb odpowiadający Twojemu modelowi zagrożeń." + "value": "Hasło nie jest ustawione. Klienty zewnętrzne będą blokowane, dopóki nie zostanie skonfigurowane." } }, "ru": { "stringUnit": { "state": "translated", - "value": "Управляет доступом к локальному Unix-сокету для программного управления. Выберите режим, соответствующий вашей модели угроз." + "value": "Пароль не установлен. Внешние клиенты будут заблокированы, пока он не будет настроен." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Kontroliše pristup lokalnoj Unix utičnici za programsku kontrolu. Odaberite režim koji odgovara vašem modelu prijetnji." + "value": "Lozinka nije postavljena. Vanjski klijenti će biti blokirani dok se ne konfiguriše." } }, "ar": { "stringUnit": { "state": "translated", - "value": "يتحكم بالوصول إلى مقبس Unix المحلي للتحكم البرمجي. اختر الوضع الذي يتناسب مع نموذج التهديد الخاص بك." + "value": "لم يتم تعيين كلمة مرور. سيتم حظر العملاء الخارجيين حتى يتم تكوين واحدة." } }, "nb": { "stringUnit": { "state": "translated", - "value": "Styrer tilgang til den lokale Unix-socketen for programmatisk kontroll. Velg en modus som passer til din trusselmodell." + "value": "Ingen passord angitt. Eksterne klienter vil bli blokkert inntil et passord er konfigurert." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Controla o acesso ao socket Unix local para controle programático. Escolha um modo que corresponda ao seu modelo de ameaça." + "value": "Nenhuma senha definida. Clientes externos serão bloqueados até que uma seja configurada." } }, "th": { "stringUnit": { "state": "translated", - "value": "ควบคุมการเข้าถึงซ็อกเก็ต Unix ในเครื่องสำหรับการควบคุมแบบโปรแกรม เลือกโหมดที่ตรงกับรูปแบบภัยคุกคามของคุณ" + "value": "ยังไม่ได้ตั้งรหัสผ่าน ไคลเอ็นต์ภายนอกจะถูกบล็อกจนกว่าจะกำหนดค่า" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Programatik kontrol için yerel Unix soketine erişimi kontrol eder. Tehdit modelinize uyan bir mod seçin." + "value": "Parola ayarlanmadı. Bir parola yapılandırılana kadar harici istemciler engellenecek." } }, "uk": { "stringUnit": { "state": "translated", - "value": "Керує доступом до локального Unix-сокета для програмного контролю. Виберіть режим відповідно до вашої моделі загроз." + "value": "Пароль не встановлено. Зовнішні клієнти будуть заблоковані, поки його не налаштувати." } } } }, - "settings.automation.socketOverrides.note": { + "settings.blendMode.behindWindow": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Overrides: CMUX_SOCKET_ENABLE, CMUX_SOCKET_MODE, and CMUX_SOCKET_PATH (set CMUX_ALLOW_SOCKET_OVERRIDE=1 for stable/nightly builds)." + "value": "Behind Window" } }, "ja": { "stringUnit": { "state": "translated", - "value": "オーバーライド: CMUX_SOCKET_ENABLE、CMUX_SOCKET_MODE、CMUX_SOCKET_PATH(stable/nightlyビルドではCMUX_ALLOW_SOCKET_OVERRIDE=1を設定)。" + "value": "ウインドウの背面" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "覆盖项:CMUX_SOCKET_ENABLE、CMUX_SOCKET_MODE 和 CMUX_SOCKET_PATH(对稳定版/每日构建版需设置 CMUX_ALLOW_SOCKET_OVERRIDE=1)。" + "value": "窗口后方" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "覆寫設定:CMUX_SOCKET_ENABLE、CMUX_SOCKET_MODE 和 CMUX_SOCKET_PATH(穩定版/每夜版需設定 CMUX_ALLOW_SOCKET_OVERRIDE=1)。" + "value": "視窗後方" } }, "ko": { "stringUnit": { "state": "translated", - "value": "재정의: CMUX_SOCKET_ENABLE, CMUX_SOCKET_MODE, CMUX_SOCKET_PATH (안정/나이틀리 빌드의 경우 CMUX_ALLOW_SOCKET_OVERRIDE=1 설정)." + "value": "윈도우 뒤" } }, "de": { "stringUnit": { "state": "translated", - "value": "Überschreibungen: CMUX_SOCKET_ENABLE, CMUX_SOCKET_MODE und CMUX_SOCKET_PATH (setzen Sie CMUX_ALLOW_SOCKET_OVERRIDE=1 für Stable-/Nightly-Builds)." + "value": "Hinter dem Fenster" } }, "es": { "stringUnit": { "state": "translated", - "value": "Sobreescrituras: CMUX_SOCKET_ENABLE, CMUX_SOCKET_MODE y CMUX_SOCKET_PATH (establece CMUX_ALLOW_SOCKET_OVERRIDE=1 para compilaciones estables/nightly)." + "value": "Detrás de la ventana" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Remplacements : CMUX_SOCKET_ENABLE, CMUX_SOCKET_MODE et CMUX_SOCKET_PATH (définissez CMUX_ALLOW_SOCKET_OVERRIDE=1 pour les builds stable/nightly)." + "value": "Derrière la fenêtre" } }, "it": { "stringUnit": { "state": "translated", - "value": "Override: CMUX_SOCKET_ENABLE, CMUX_SOCKET_MODE e CMUX_SOCKET_PATH (imposta CMUX_ALLOW_SOCKET_OVERRIDE=1 per le build stable/nightly)." + "value": "Dietro la finestra" } }, "da": { "stringUnit": { "state": "translated", - "value": "Tilsidesættelser: CMUX_SOCKET_ENABLE, CMUX_SOCKET_MODE og CMUX_SOCKET_PATH (sæt CMUX_ALLOW_SOCKET_OVERRIDE=1 for stabile/nightly builds)." + "value": "Bag vindue" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Nadpisania: CMUX_SOCKET_ENABLE, CMUX_SOCKET_MODE i CMUX_SOCKET_PATH (ustaw CMUX_ALLOW_SOCKET_OVERRIDE=1 dla wersji stabilnych/nightly)." + "value": "Za oknem" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Переопределения: CMUX_SOCKET_ENABLE, CMUX_SOCKET_MODE и CMUX_SOCKET_PATH (установите CMUX_ALLOW_SOCKET_OVERRIDE=1 для стабильных/ночных сборок)." + "value": "За окном" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Premošćenja: CMUX_SOCKET_ENABLE, CMUX_SOCKET_MODE i CMUX_SOCKET_PATH (postavite CMUX_ALLOW_SOCKET_OVERRIDE=1 za stabilne/nightly verzije)." + "value": "Iza prozora" } }, "ar": { "stringUnit": { "state": "translated", - "value": "التجاوزات: CMUX_SOCKET_ENABLE و CMUX_SOCKET_MODE و CMUX_SOCKET_PATH (اضبط CMUX_ALLOW_SOCKET_OVERRIDE=1 لبناءات stable/nightly)." + "value": "خلف النافذة" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Overstyringer: CMUX_SOCKET_ENABLE, CMUX_SOCKET_MODE og CMUX_SOCKET_PATH (sett CMUX_ALLOW_SOCKET_OVERRIDE=1 for stabile/nattlige bygg)." + "value": "Bak vinduet" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Substituições: CMUX_SOCKET_ENABLE, CMUX_SOCKET_MODE e CMUX_SOCKET_PATH (defina CMUX_ALLOW_SOCKET_OVERRIDE=1 para builds stable/nightly)." + "value": "Atrás da Janela" } }, "th": { "stringUnit": { "state": "translated", - "value": "การแทนที่: CMUX_SOCKET_ENABLE, CMUX_SOCKET_MODE และ CMUX_SOCKET_PATH (ตั้ง CMUX_ALLOW_SOCKET_OVERRIDE=1 สำหรับบิลด์ stable/nightly)" + "value": "ด้านหลังหน้าต่าง" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Geçersiz kılmalar: CMUX_SOCKET_ENABLE, CMUX_SOCKET_MODE ve CMUX_SOCKET_PATH (kararlı/gece derlemeleri için CMUX_ALLOW_SOCKET_OVERRIDE=1 ayarlayın)." + "value": "Pencerenin Arkası" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Перевизначення: CMUX_SOCKET_ENABLE, CMUX_SOCKET_MODE та CMUX_SOCKET_PATH (встановіть CMUX_ALLOW_SOCKET_OVERRIDE=1 для стабільних/нічних збірок)." + "value": "За вікном" } } } }, - "settings.automation.socketPassword": { + "settings.blendMode.withinWindow": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Socket Password" + "value": "Within Window" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ソケットパスワード" + "value": "ウインドウ内" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "套接字密码" + "value": "窗口内部" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "Socket 密碼" + "value": "視窗內" } }, "ko": { "stringUnit": { "state": "translated", - "value": "소켓 비밀번호" + "value": "윈도우 내" } }, "de": { "stringUnit": { "state": "translated", - "value": "Socket-Passwort" + "value": "Innerhalb des Fensters" } }, "es": { "stringUnit": { "state": "translated", - "value": "Contraseña del socket" + "value": "Dentro de la ventana" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Mot de passe du socket" + "value": "Dans la fenêtre" } }, "it": { "stringUnit": { "state": "translated", - "value": "Password socket" + "value": "All'interno della finestra" } }, "da": { "stringUnit": { "state": "translated", - "value": "Socket-adgangskode" + "value": "Inden i vindue" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Hasło gniazda" + "value": "W oknie" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Пароль сокета" + "value": "Внутри окна" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Lozinka utičnice" + "value": "Unutar prozora" } }, "ar": { "stringUnit": { "state": "translated", - "value": "كلمة مرور المقبس" + "value": "داخل النافذة" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Socket-passord" + "value": "Inni vinduet" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Senha do Socket" + "value": "Dentro da Janela" } }, "th": { "stringUnit": { "state": "translated", - "value": "รหัสผ่านซ็อกเก็ต" + "value": "ภายในหน้าต่าง" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Soket Parolası" + "value": "Pencere İçinde" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Пароль сокета" + "value": "Усередині вікна" } } } }, - "settings.automation.socketPassword.change": { + "settings.browser.externalPatterns": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Change" + "value": "URLs to Always Open Externally" } }, "ja": { "stringUnit": { "state": "translated", - "value": "変更" + "value": "常に外部で開くURL" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "更改" + "value": "始终在外部打开的 URL" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "變更" + "value": "一律在外部開啟的 URL" } }, "ko": { "stringUnit": { "state": "translated", - "value": "변경" + "value": "항상 외부에서 열 URL" } }, "de": { "stringUnit": { "state": "translated", - "value": "Ändern" + "value": "URLs, die immer extern geöffnet werden" } }, "es": { "stringUnit": { "state": "translated", - "value": "Cambiar" + "value": "URLs para abrir siempre externamente" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Modifier" + "value": "URL à toujours ouvrir dans un navigateur externe" } }, "it": { "stringUnit": { "state": "translated", - "value": "Modifica" + "value": "URL da aprire sempre esternamente" } }, "da": { "stringUnit": { "state": "translated", - "value": "Skift" + "value": "URL'er der altid åbnes eksternt" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Zmień" + "value": "Adresy URL otwierane zawsze zewnętrznie" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Изменить" + "value": "URL для открытия во внешнем браузере" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Promijeni" + "value": "URL-ovi za uvijek vanjsko otvaranje" } }, "ar": { "stringUnit": { "state": "translated", - "value": "تغيير" + "value": "عناوين URL للفتح خارجيًا دائمًا" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Endre" + "value": "URL-er som alltid åpnes eksternt" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Alterar" + "value": "URLs para Sempre Abrir Externamente" } }, "th": { "stringUnit": { "state": "translated", - "value": "เปลี่ยน" + "value": "URL ที่เปิดภายนอกเสมอ" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Değiştir" + "value": "Her Zaman Harici Olarak Açılacak URL'ler" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Змінити" + "value": "URL для завжди зовнішнього відкриття" } } } }, - "settings.automation.socketPassword.clear": { + "settings.browser.externalPatterns.subtitle": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Clear" + "value": "Applies to terminal link clicks and intercepted `open https://...` calls. One rule per line. Plain text matches any URL substring, or prefix with `re:` for regex (for example: openai.com/usage, re:^https?://[^/]*\\\\.example\\\\.com/(billing|usage))." } }, "ja": { "stringUnit": { "state": "translated", - "value": "クリア" + "value": "ターミナルのリンククリックおよびインターセプトされた`open https://...`呼び出しに適用されます。1行に1ルール。プレーンテキストはURL部分文字列に一致し、`re:`プレフィックスで正規表現を使用できます(例: openai.com/usage, re:^https?://[^/]*\\\\.example\\\\.com/(billing|usage))。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "清除" + "value": "适用于终端中的链接点击和拦截的 `open https://...` 调用。每行一条规则。纯文本匹配任意 URL 子串,或使用 `re:` 前缀表示正则表达式(例如:openai.com/usage、re:^https?://[^/]*\\\\.example\\\\.com/(billing|usage))。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "清除" + "value": "套用於終端機連結點擊和攔截的 `open https://...` 呼叫。每行一條規則。純文字會比對 URL 的任何子字串,或加上 `re:` 前綴使用正規表示式(例如:openai.com/usage、re:^https?://[^/]*\\\\.example\\\\.com/(billing|usage))。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "지우기" + "value": "터미널 링크 클릭 및 인터셉트된 `open https://...` 호출에 적용됩니다. 한 줄에 하나의 규칙. 일반 텍스트는 URL의 하위 문자열을 일치시키며, `re:` 접두사로 정규식을 사용할 수 있습니다 (예: openai.com/usage, re:^https?://[^/]*\\\\.example\\\\.com/(billing|usage))." } }, "de": { "stringUnit": { "state": "translated", - "value": "Löschen" + "value": "Gilt für Klicks auf Terminal-Links und abgefangene `open https://...`-Aufrufe. Eine Regel pro Zeile. Klartext stimmt mit jedem URL-Teilstring überein, oder verwenden Sie das Präfix `re:` für Regex (zum Beispiel: openai.com/usage, re:^https?://[^/]*\\\\.example\\\\.com/(billing|usage))." } }, "es": { "stringUnit": { "state": "translated", - "value": "Borrar" + "value": "Se aplica a clics en enlaces del terminal y llamadas interceptadas de `open https://...`. Una regla por línea. El texto plano coincide con cualquier subcadena de URL, o usa el prefijo `re:` para regex (por ejemplo: openai.com/usage, re:^https?://[^/]*\\\\.example\\\\.com/(billing|usage))." } }, "fr": { "stringUnit": { "state": "translated", - "value": "Effacer" + "value": "S'applique aux clics sur les liens du terminal et aux appels `open https://...` interceptés. Une règle par ligne. Le texte brut correspond à toute sous-chaîne d'URL, ou préfixez par `re:` pour une expression régulière (par exemple : openai.com/usage, re:^https?://[^/]*\\\\.example\\\\.com/(billing|usage))." } }, "it": { "stringUnit": { "state": "translated", - "value": "Cancella" + "value": "Si applica ai clic sui link nel terminale e alle chiamate intercettate `open https://...`. Una regola per riga. Il testo semplice corrisponde a qualsiasi sottostringa dell'URL, oppure usa il prefisso `re:` per le regex (ad esempio: openai.com/usage, re:^https?://[^/]*\\\\.example\\\\.com/(billing|usage))." } }, "da": { "stringUnit": { "state": "translated", - "value": "Ryd" + "value": "Gælder for terminallinksklik og opfangede `open https://...`-kald. Én regel pr. linje. Almindelig tekst matcher enhver URL-delstreng, eller brug `re:` som præfiks for regex (f.eks.: openai.com/usage, re:^https?://[^/]*\\.example\\.com/(billing|usage))." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Wyczyść" + "value": "Dotyczy kliknięć linków w terminalu i przechwyconych wywołań `open https://...`. Jedna reguła na wiersz. Zwykły tekst dopasowuje dowolny fragment URL, lub użyj prefiksu `re:` dla wyrażeń regularnych (na przykład: openai.com/usage, re:^https?://[^/]*\\\\.example\\\\.com/(billing|usage))." } }, "ru": { "stringUnit": { "state": "translated", - "value": "Очистить" + "value": "Применяется к нажатиям на ссылки в терминале и перехваченным вызовам `open https://...`. Одно правило на строку. Обычный текст совпадает с любой подстрокой URL, или используйте префикс `re:` для регулярных выражений (например: openai.com/usage, re:^https?://[^/]*\\\\.example\\\\.com/(billing|usage))." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Obriši" + "value": "Primjenjuje se na klikove linkova u terminalu i presretnute `open https://...` pozive. Jedno pravilo po redu. Običan tekst odgovara bilo kojem dijelu URL-a, ili dodajte prefiks `re:` za regex (na primjer: openai.com/usage, re:^https?://[^/]*\\\\.example\\\\.com/(billing|usage))." } }, "ar": { "stringUnit": { "state": "translated", - "value": "مسح" + "value": "ينطبق على نقرات الروابط في الطرفية واستدعاءات `open https://...` المعترضة. قاعدة واحدة لكل سطر. النص العادي يطابق أي جزء من URL، أو ابدأ بـ `re:` للتعبيرات النمطية (مثال: openai.com/usage, re:^https?://[^/]*\\\\.example\\\\.com/(billing|usage))." } }, "nb": { "stringUnit": { "state": "translated", - "value": "Fjern" + "value": "Gjelder for terminallenkeklikk og avlyttede `open https://...`-kall. Én regel per linje. Ren tekst matcher enhver del av URL-en, eller prefiks med `re:` for regulære uttrykk (for eksempel: openai.com/usage, re:^https?://[^/]*\\\\.example\\\\.com/(billing|usage))." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Limpar" + "value": "Aplica-se a cliques em links do terminal e chamadas interceptadas de `open https://...`. Uma regra por linha. Texto simples corresponde a qualquer substring de URL, ou prefixe com `re:` para regex (por exemplo: openai.com/usage, re:^https?://[^/]*\\\\.example\\\\.com/(billing|usage))." } }, "th": { "stringUnit": { "state": "translated", - "value": "ล้าง" + "value": "ใช้กับการคลิกลิงก์ในเทอร์มินัลและการดักจับคำสั่ง `open https://...` กฎหนึ่งข้อต่อบรรทัด ข้อความธรรมดาจะจับคู่กับส่วนใดก็ได้ของ URL หรือนำหน้าด้วย `re:` สำหรับ regex (ตัวอย่าง: openai.com/usage, re:^https?://[^/]*\\\\.example\\\\.com/(billing|usage))" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Temizle" + "value": "Terminal bağlantı tıklamalarına ve yakalanan `open https://...` çağrılarına uygulanır. Satır başına bir kural. Düz metin herhangi bir URL alt dizesiyle eşleşir veya regex için `re:` ön ekini kullanın (örneğin: openai.com/usage, re:^https?://[^/]*\\\\.example\\\\.com/(billing|usage))." } }, "uk": { "stringUnit": { "state": "translated", - "value": "Очистити" + "value": "Застосовується до кліків на посилання в терміналі та перехоплених викликів `open https://...`. Одне правило на рядок. Звичайний текст збігається з будь-якою частиною URL, або додайте префікс `re:` для регулярного виразу (наприклад: openai.com/usage, re:^https?://[^/]*\\.example\\.com/(billing|usage))." } } } }, - "settings.automation.socketPassword.clearFailed": { + "settings.browser.emptyImport.choose": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Failed to clear password (%@)." + "value": "Choose What to Import…" } }, "ja": { "stringUnit": { "state": "translated", - "value": "パスワードのクリアに失敗しました(%@)。" - } - }, - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "清除密码失败 (%@)。" + "value": "取り込む項目を選ぶ…" } }, - "zh-Hant": { + "uk": { "stringUnit": { "state": "translated", - "value": "清除密碼失敗(%@)。" + "value": "Вибрати, що імпортувати…" } }, "ko": { "stringUnit": { "state": "translated", - "value": "비밀번호 지우기 실패 (%@)." - } - }, - "de": { - "stringUnit": { - "state": "translated", - "value": "Passwort konnte nicht gelöscht werden (%@)." - } - }, - "es": { - "stringUnit": { - "state": "translated", - "value": "No se pudo borrar la contraseña (%@)." - } - }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "Impossible d'effacer le mot de passe (%@)." - } - }, - "it": { - "stringUnit": { - "state": "translated", - "value": "Impossibile cancellare la password (%@)." + "value": "가져올 항목 선택…" } - }, - "da": { + } + } + }, + "settings.browser.emptyImport.title": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Kunne ikke rydde adgangskode (%@)." + "value": "Import browser data" } }, - "pl": { + "ja": { "stringUnit": { "state": "translated", - "value": "Nie udało się wyczyścić hasła (%@)." + "value": "ブラウザーデータを取り込む" } }, - "ru": { + "uk": { "stringUnit": { "state": "translated", - "value": "Не удалось очистить пароль (%@)." + "value": "Імпорт даних браузера" } }, - "bs": { + "ko": { "stringUnit": { "state": "translated", - "value": "Nije uspjelo brisanje lozinke (%@)." + "value": "브라우저 데이터 가져오기" } - }, - "ar": { + } + } + }, + "settings.browser.reactGrabVersion": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "فشل مسح كلمة المرور (%@)." + "value": "React Grab Version" } }, - "nb": { + "ja": { "stringUnit": { "state": "translated", - "value": "Kunne ikke fjerne passord (%@)." + "value": "React Grabバージョン" } }, - "pt-BR": { + "ko": { "stringUnit": { "state": "translated", - "value": "Falha ao limpar a senha (%@)." + "value": "React Grab 버전" } - }, - "th": { + } + } + }, + "settings.browser.reactGrabVersion.subtitle": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "ไม่สามารถล้างรหัสผ่านได้ (%@)" + "value": "Pinned npm version of react-grab injected by the toolbar button (Cmd+Shift+G). Only versions with a known integrity hash are accepted." } }, - "tr": { + "ja": { "stringUnit": { "state": "translated", - "value": "Parola temizlenemedi (%@)." + "value": "ツールバーボタン(Cmd+Shift+G)で注入されるreact-grabのnpmバージョン。既知の整合性ハッシュを持つバージョンのみ使用可能です。" } }, - "uk": { + "ko": { "stringUnit": { "state": "translated", - "value": "Не вдалося очистити пароль (%@)." + "value": "도구 모음 버튼(Cmd+Shift+G)으로 주입되는 react-grab의 고정된 npm 버전입니다. 알려진 무결성 해시가 있는 버전만 허용됩니다." } } } }, - "settings.automation.socketPassword.cleared": { + "settings.browser.history": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Password cleared." + "value": "Browsing History" } }, "ja": { "stringUnit": { "state": "translated", - "value": "パスワードをクリアしました。" + "value": "ブラウザ履歴" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "密码已清除。" + "value": "浏览历史" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "密碼已清除。" + "value": "瀏覽記錄" } }, "ko": { "stringUnit": { "state": "translated", - "value": "비밀번호가 지워졌습니다." + "value": "탐색 기록" } }, "de": { "stringUnit": { "state": "translated", - "value": "Passwort gelöscht." + "value": "Browserverlauf" } }, "es": { "stringUnit": { "state": "translated", - "value": "Contraseña borrada." + "value": "Historial de navegación" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Mot de passe effacé." + "value": "Historique de navigation" } }, "it": { "stringUnit": { "state": "translated", - "value": "Password cancellata." + "value": "Cronologia di navigazione" } }, "da": { "stringUnit": { "state": "translated", - "value": "Adgangskode ryddet." + "value": "Browserhistorik" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Hasło wyczyszczone." + "value": "Historia przeglądania" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Пароль очищен." + "value": "История просмотра" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Lozinka obrisana." + "value": "Historija pregledanja" } }, "ar": { "stringUnit": { "state": "translated", - "value": "تم مسح كلمة المرور." + "value": "سجل التصفح" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Passord fjernet." + "value": "Nettleserhistorikk" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Senha removida." + "value": "Histórico de Navegação" } }, "th": { "stringUnit": { "state": "translated", - "value": "ล้างรหัสผ่านแล้ว" + "value": "ประวัติการท่องเว็บ" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Parola temizlendi." + "value": "Tarama Geçmişi" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Пароль очищено." + "value": "Історія перегляду" } } } }, - "settings.automation.socketPassword.enterFirst": { + "settings.browser.import": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Enter a password first." + "value": "Import Browser Data" } }, "ja": { "stringUnit": { "state": "translated", - "value": "まずパスワードを入力してください。" + "value": "ブラウザーデータを取り込む" } }, - "zh-Hans": { + "uk": { "stringUnit": { "state": "translated", - "value": "请先输入密码。" + "value": "Імпорт даних браузера" } }, - "zh-Hant": { + "ko": { "stringUnit": { "state": "translated", - "value": "請先輸入密碼。" + "value": "브라우저 데이터 가져오기" + } + } + } + }, + "settings.browser.import.choose": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Choose…" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "選択…" + } + }, + "uk": { + "stringUnit": { + "state": "translated", + "value": "Вибрати…" } }, "ko": { "stringUnit": { "state": "translated", - "value": "먼저 비밀번호를 입력하세요." + "value": "선택…" + } + } + } + }, + "settings.browser.import.refresh": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Refresh" } }, - "de": { + "ja": { "stringUnit": { "state": "translated", - "value": "Geben Sie zuerst ein Passwort ein." + "value": "再読み込み" } }, - "es": { + "uk": { "stringUnit": { "state": "translated", - "value": "Introduce una contraseña primero." + "value": "Оновити" } }, - "fr": { + "ko": { "stringUnit": { "state": "translated", - "value": "Saisissez d'abord un mot de passe." + "value": "새로고침" + } + } + } + }, + "settings.browser.import.hint.note.hidden": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "The blank-tab import hint is hidden. Turn it back on here any time." } }, - "it": { + "ja": { "stringUnit": { "state": "translated", - "value": "Inserisci prima una password." + "value": "空タブのインポート案内は非表示です。ここでいつでも再表示できます。" } }, - "da": { + "uk": { "stringUnit": { "state": "translated", - "value": "Indtast en adgangskode først." + "value": "Підказка імпорту на порожній вкладці прихована. Увімкніть її тут у будь-який час." } }, - "pl": { + "ko": { "stringUnit": { "state": "translated", - "value": "Najpierw wprowadź hasło." + "value": "빈 탭 가져오기 힌트가 숨겨져 있습니다. 여기서 언제든 다시 켤 수 있습니다." + } + } + } + }, + "settings.browser.import.hint.note.settingsOnly": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Blank tabs are currently using Settings only mode from the debug window." } }, - "ru": { + "ja": { "stringUnit": { "state": "translated", - "value": "Сначала введите пароль." + "value": "現在、空タブはデバッグウィンドウの「設定のみ」モードになっています。" } }, - "bs": { + "uk": { "stringUnit": { "state": "translated", - "value": "Prvo unesite lozinku." + "value": "Порожні вкладки зараз використовують режим «Тільки налаштування» з вікна налагодження." } }, - "ar": { + "ko": { "stringUnit": { "state": "translated", - "value": "أدخل كلمة مرور أولاً." + "value": "빈 탭이 현재 디버그 창의 설정 전용 모드를 사용하고 있습니다." + } + } + } + }, + "settings.browser.import.hint.note.visible": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Blank browser tabs can show this import suggestion. Hide or re-enable it here." } }, - "nb": { + "ja": { "stringUnit": { "state": "translated", - "value": "Skriv inn et passord først." + "value": "空のブラウザータブにこのインポート案内を表示できます。ここで非表示や再表示を切り替えられます。" } }, - "pt-BR": { + "uk": { "stringUnit": { "state": "translated", - "value": "Insira uma senha primeiro." + "value": "Порожні вкладки браузера можуть показувати пропозицію імпорту. Сховайте або увімкніть її тут." } }, - "th": { + "ko": { "stringUnit": { "state": "translated", - "value": "ป้อนรหัสผ่านก่อน" + "value": "빈 브라우저 탭에 가져오기 제안을 표시할 수 있습니다. 여기서 숨기거나 다시 활성화하세요." + } + } + } + }, + "settings.browser.import.hint.show": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Show import hint on blank browser tabs" } }, - "tr": { + "ja": { "stringUnit": { "state": "translated", - "value": "Önce bir parola girin." + "value": "空のブラウザータブにインポート案内を表示" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Спочатку введіть пароль." + "value": "Показувати підказку імпорту на порожніх вкладках браузера" + } + }, + "ko": { + "stringUnit": { + "state": "translated", + "value": "빈 브라우저 탭에 가져오기 힌트 표시" } } } }, - "settings.automation.socketPassword.placeholder": { + "settings.browser.history.clearButton": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Password" + "value": "Clear History…" } }, "ja": { "stringUnit": { "state": "translated", - "value": "パスワード" + "value": "履歴をクリア…" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "密码" + "value": "清除历史记录..." } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "密碼" + "value": "清除記錄..." } }, "ko": { "stringUnit": { "state": "translated", - "value": "비밀번호" + "value": "기록 지우기…" } }, "de": { "stringUnit": { "state": "translated", - "value": "Passwort" + "value": "Verlauf löschen …" } }, "es": { "stringUnit": { "state": "translated", - "value": "Contraseña" + "value": "Borrar historial…" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Mot de passe" + "value": "Effacer l'historique..." } }, "it": { "stringUnit": { "state": "translated", - "value": "Password" + "value": "Cancella cronologia…" } }, "da": { "stringUnit": { "state": "translated", - "value": "Adgangskode" + "value": "Ryd historik…" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Hasło" + "value": "Wyczyść historię…" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Пароль" + "value": "Очистить историю..." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Lozinka" + "value": "Obriši historiju…" } }, "ar": { "stringUnit": { "state": "translated", - "value": "كلمة المرور" + "value": "مسح السجل…" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Passord" + "value": "Tøm historikk …" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Senha" + "value": "Limpar Histórico…" } }, "th": { "stringUnit": { "state": "translated", - "value": "รหัสผ่าน" + "value": "ล้างประวัติ..." } }, "tr": { "stringUnit": { "state": "translated", - "value": "Parola" + "value": "Geçmişi Temizle…" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Пароль" + "value": "Очистити історію…" } } } }, - "settings.automation.socketPassword.saveFailed": { + "settings.browser.history.clearDialog.cancel": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Failed to save password (%@)." + "value": "Cancel" } }, "ja": { "stringUnit": { "state": "translated", - "value": "パスワードの保存に失敗しました(%@)。" + "value": "キャンセル" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "保存密码失败 (%@)。" + "value": "取消" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "儲存密碼失敗(%@)。" + "value": "取消" } }, "ko": { "stringUnit": { "state": "translated", - "value": "비밀번호 저장 실패 (%@)." + "value": "취소" } }, "de": { "stringUnit": { "state": "translated", - "value": "Passwort konnte nicht gespeichert werden (%@)." + "value": "Abbrechen" } }, "es": { "stringUnit": { "state": "translated", - "value": "No se pudo guardar la contraseña (%@)." + "value": "Cancelar" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Impossible d'enregistrer le mot de passe (%@)." + "value": "Annuler" } }, "it": { "stringUnit": { "state": "translated", - "value": "Impossibile salvare la password (%@)." + "value": "Annulla" } }, "da": { "stringUnit": { "state": "translated", - "value": "Kunne ikke gemme adgangskode (%@)." + "value": "Annuller" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Nie udało się zapisać hasła (%@)." + "value": "Anuluj" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Не удалось сохранить пароль (%@)." + "value": "Отменить" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Nije uspjelo spremanje lozinke (%@)." + "value": "Otkaži" } }, "ar": { "stringUnit": { "state": "translated", - "value": "فشل حفظ كلمة المرور (%@)." + "value": "إلغاء" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Kunne ikke lagre passord (%@)." + "value": "Avbryt" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Falha ao salvar a senha (%@)." + "value": "Cancelar" } }, "th": { "stringUnit": { "state": "translated", - "value": "ไม่สามารถบันทึกรหัสผ่านได้ (%@)" + "value": "ยกเลิก" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Parola kaydedilemedi (%@)." + "value": "Vazgeç" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Не вдалося зберегти пароль (%@)." + "value": "Скасувати" } } } }, - "settings.automation.socketPassword.saved": { + "settings.browser.history.clearDialog.confirm": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Password saved." + "value": "Clear History" } }, "ja": { "stringUnit": { "state": "translated", - "value": "パスワードを保存しました。" + "value": "履歴をクリア" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "密码已保存。" + "value": "清除历史记录" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "密碼已儲存。" + "value": "清除記錄" } }, "ko": { "stringUnit": { "state": "translated", - "value": "비밀번호가 저장되었습니다." + "value": "기록 지우기" } }, "de": { "stringUnit": { "state": "translated", - "value": "Passwort gespeichert." + "value": "Verlauf löschen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Contraseña guardada." + "value": "Borrar historial" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Mot de passe enregistré." + "value": "Effacer l'historique" } }, "it": { "stringUnit": { "state": "translated", - "value": "Password salvata." + "value": "Cancella cronologia" } }, "da": { "stringUnit": { "state": "translated", - "value": "Adgangskode gemt." + "value": "Ryd historik" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Hasło zapisane." + "value": "Wyczyść historię" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Пароль сохранен." + "value": "Очистить историю" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Lozinka spremljena." + "value": "Obriši historiju" } }, "ar": { "stringUnit": { "state": "translated", - "value": "تم حفظ كلمة المرور." + "value": "مسح السجل" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Passord lagret." + "value": "Tøm historikk" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Senha salva." + "value": "Limpar Histórico" } }, "th": { "stringUnit": { "state": "translated", - "value": "บันทึกรหัสผ่านแล้ว" + "value": "ล้างประวัติ" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Parola kaydedildi." + "value": "Geçmişi Temizle" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Пароль збережено." + "value": "Очистити історію" } } } }, - "settings.automation.socketPassword.set": { + "settings.browser.history.clearDialog.message": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Set" + "value": "This removes visited-page suggestions from the browser omnibar." } }, "ja": { "stringUnit": { "state": "translated", - "value": "設定" + "value": "ブラウザのオムニバーから訪問済みページの候補が削除されます。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "设置" + "value": "这将从浏览器地址栏中移除已访问页面的建议。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "設定" + "value": "這會移除瀏覽器網址列中已造訪頁面的建議。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "설정" + "value": "브라우저 옴니바에서 방문 페이지 제안을 제거합니다." } }, "de": { "stringUnit": { "state": "translated", - "value": "Festlegen" + "value": "Dies entfernt Vorschläge für besuchte Seiten aus der Browser-Adressleiste." } }, "es": { "stringUnit": { "state": "translated", - "value": "Establecer" + "value": "Esto elimina las sugerencias de páginas visitadas de la barra de direcciones del navegador." } }, "fr": { "stringUnit": { "state": "translated", - "value": "Définir" + "value": "Cela supprime les suggestions de pages visitées de la barre d'adresse du navigateur." } }, "it": { "stringUnit": { "state": "translated", - "value": "Imposta" + "value": "Questa operazione rimuove i suggerimenti delle pagine visitate dalla barra degli indirizzi del browser." } }, "da": { "stringUnit": { "state": "translated", - "value": "Angiv" + "value": "Dette fjerner besøgte sideforslag fra browserens omnibar." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Ustaw" + "value": "Spowoduje to usunięcie podpowiedzi odwiedzonych stron z paska adresu przeglądarki." } }, "ru": { "stringUnit": { "state": "translated", - "value": "Установить" + "value": "Это удалит подсказки посещенных страниц из адресной строки браузера." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Postavi" + "value": "Ovo uklanja prijedloge posjećenih stranica iz omnibar preglednika." } }, "ar": { "stringUnit": { "state": "translated", - "value": "تعيين" + "value": "يؤدي هذا إلى إزالة اقتراحات الصفحات المزارة من شريط عنوان المتصفح." } }, "nb": { "stringUnit": { "state": "translated", - "value": "Angi" + "value": "Dette fjerner forslag basert på besøkte sider fra nettleserens adressefelt." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Definir" + "value": "Isto remove as sugestões de páginas visitadas da barra de endereço do navegador." } }, "th": { "stringUnit": { "state": "translated", - "value": "ตั้งค่า" + "value": "การดำเนินการนี้จะลบคำแนะนำหน้าที่เยี่ยมชมจากแถบที่อยู่เบราว์เซอร์" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Ayarla" + "value": "Bu, tarayıcı çok amaçlı çubuğundan ziyaret edilen sayfa önerilerini kaldırır." } }, "uk": { "stringUnit": { "state": "translated", - "value": "Встановити" + "value": "Це видалить підказки відвіданих сторінок з адресного рядка браузера." } } } }, - "settings.automation.socketPassword.subtitleSet": { + "settings.browser.history.clearDialog.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Stored in Application Support." + "value": "Clear browser history?" } }, "ja": { "stringUnit": { "state": "translated", - "value": "Application Supportに保存済み。" + "value": "ブラウザ履歴をクリアしますか?" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "存储在应用程序支持目录中。" + "value": "清除浏览器历史记录?" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "儲存於 Application Support。" + "value": "要清除瀏覽記錄嗎?" } }, "ko": { "stringUnit": { "state": "translated", - "value": "Application Support에 저장됨." + "value": "브라우저 기록을 지우시겠습니까?" } }, "de": { "stringUnit": { "state": "translated", - "value": "Gespeichert in Application Support." + "value": "Browserverlauf löschen?" } }, "es": { "stringUnit": { "state": "translated", - "value": "Almacenada en Application Support." + "value": "¿Borrar historial del navegador?" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Stocké dans Application Support." + "value": "Effacer l'historique du navigateur ?" } }, "it": { "stringUnit": { "state": "translated", - "value": "Memorizzata nel Supporto Applicazioni." + "value": "Cancellare la cronologia del browser?" } }, "da": { "stringUnit": { "state": "translated", - "value": "Gemt i Application Support." + "value": "Ryd browserhistorik?" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Przechowywane w Application Support." + "value": "Wyczyścić historię przeglądarki?" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Хранится в Application Support." + "value": "Очистить историю браузера?" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Pohranjena u Application Support." + "value": "Obrisati historiju preglednika?" } }, "ar": { "stringUnit": { "state": "translated", - "value": "مخزنة في Application Support." + "value": "مسح سجل المتصفح؟" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Lagret i Application Support." + "value": "Tømme nettleserhistorikk?" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Armazenada em Application Support." + "value": "Limpar histórico do navegador?" } }, "th": { "stringUnit": { "state": "translated", - "value": "จัดเก็บใน Application Support" + "value": "ล้างประวัติเบราว์เซอร์หรือไม่?" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Uygulama Desteği klasöründe saklanır." + "value": "Tarayıcı geçmişi temizlensin mi?" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Збережено в Application Support." + "value": "Очистити історію браузера?" } } } }, - "settings.automation.socketPassword.subtitleUnset": { + "settings.browser.history.subtitleEmpty": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "No password set. External clients will be blocked until one is configured." + "value": "No saved pages yet." } }, "ja": { "stringUnit": { "state": "translated", - "value": "パスワードが設定されていません。設定するまで外部クライアントはブロックされます。" + "value": "保存済みのページはまだありません。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "未设置密码。外部客户端将被阻止,直到配置密码为止。" + "value": "尚无已保存的页面。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "尚未設定密碼。外部用戶端將被封鎖,直到設定密碼為止。" + "value": "尚無已儲存的頁面。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "비밀번호가 설정되지 않았습니다. 비밀번호를 구성하기 전까지 외부 클라이언트가 차단됩니다." + "value": "아직 저장된 페이지가 없습니다." } }, "de": { "stringUnit": { "state": "translated", - "value": "Kein Passwort festgelegt. Externe Clients werden blockiert, bis eines konfiguriert ist." + "value": "Noch keine gespeicherten Seiten." } }, "es": { "stringUnit": { "state": "translated", - "value": "No se ha establecido contraseña. Los clientes externos serán bloqueados hasta que se configure una." + "value": "Aún no hay páginas guardadas." } }, "fr": { "stringUnit": { "state": "translated", - "value": "Aucun mot de passe défini. Les clients externes seront bloqués tant qu'un mot de passe n'aura pas été configuré." + "value": "Aucune page enregistrée pour le moment." } }, "it": { "stringUnit": { "state": "translated", - "value": "Nessuna password impostata. I client esterni verranno bloccati finché non ne viene configurata una." + "value": "Nessuna pagina salvata." } }, "da": { "stringUnit": { "state": "translated", - "value": "Ingen adgangskode angivet. Eksterne klienter blokeres, indtil en er konfigureret." + "value": "Ingen gemte sider endnu." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Hasło nie jest ustawione. Klienty zewnętrzne będą blokowane, dopóki nie zostanie skonfigurowane." + "value": "Brak zapisanych stron." } }, "ru": { "stringUnit": { "state": "translated", - "value": "Пароль не установлен. Внешние клиенты будут заблокированы, пока он не будет настроен." + "value": "Сохраненных страниц пока нет." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Lozinka nije postavljena. Vanjski klijenti će biti blokirani dok se ne konfiguriše." + "value": "Još nema sačuvanih stranica." } }, "ar": { "stringUnit": { "state": "translated", - "value": "لم يتم تعيين كلمة مرور. سيتم حظر العملاء الخارجيين حتى يتم تكوين واحدة." + "value": "لا توجد صفحات محفوظة بعد." } }, "nb": { "stringUnit": { "state": "translated", - "value": "Ingen passord angitt. Eksterne klienter vil bli blokkert inntil et passord er konfigurert." + "value": "Ingen lagrede sider ennå." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Nenhuma senha definida. Clientes externos serão bloqueados até que uma seja configurada." + "value": "Nenhuma página salva ainda." } }, "th": { "stringUnit": { "state": "translated", - "value": "ยังไม่ได้ตั้งรหัสผ่าน ไคลเอ็นต์ภายนอกจะถูกบล็อกจนกว่าจะกำหนดค่า" + "value": "ยังไม่มีหน้าที่บันทึก" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Parola ayarlanmadı. Bir parola yapılandırılana kadar harici istemciler engellenecek." + "value": "Henüz kayıtlı sayfa yok." } }, "uk": { "stringUnit": { "state": "translated", - "value": "Пароль не встановлено. Зовнішні клієнти будуть заблоковані, поки його не налаштувати." + "value": "Збережених сторінок ще немає." } } } }, - "settings.blendMode.behindWindow": { + "settings.browser.history.subtitleMany": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Behind Window" + "value": "%lld saved pages appear in omnibar suggestions." } }, "ja": { "stringUnit": { "state": "translated", - "value": "ウインドウの背面" + "value": "%lld件の保存済みページがオムニバーの候補に表示されます。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "窗口后方" + "value": "%lld 个已保存页面显示在地址栏建议中。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "視窗後方" + "value": "%lld 個已儲存頁面會出現在網址列建議中。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "윈도우 뒤" + "value": "%lld개의 저장된 페이지가 옴니바 제안에 표시됩니다." } }, "de": { "stringUnit": { "state": "translated", - "value": "Hinter dem Fenster" + "value": "%lld gespeicherte Seiten erscheinen in den Adressleisten-Vorschlägen." } }, "es": { "stringUnit": { "state": "translated", - "value": "Detrás de la ventana" + "value": "%lld páginas guardadas aparecen en las sugerencias de la barra de direcciones." } }, "fr": { "stringUnit": { "state": "translated", - "value": "Derrière la fenêtre" + "value": "%lld pages enregistrées apparaissent dans les suggestions de la barre d'adresse." } }, "it": { "stringUnit": { "state": "translated", - "value": "Dietro la finestra" + "value": "%lld pagine salvate appaiono nei suggerimenti della barra degli indirizzi." } }, "da": { "stringUnit": { "state": "translated", - "value": "Bag vindue" + "value": "%lld gemte sider vises i omnibar-forslag." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Za oknem" + "value": "%lld zapisanych stron pojawia się w podpowiedziach paska adresu." } }, "ru": { "stringUnit": { "state": "translated", - "value": "За окном" + "value": "Сохраненных страниц: %lld. Отображаются в подсказках адресной строки." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Iza prozora" + "value": "%lld sačuvanih stranica se pojavljuje u prijedlozima omnibara." } }, "ar": { "stringUnit": { "state": "translated", - "value": "خلف النافذة" + "value": "%lld صفحة محفوظة تظهر في اقتراحات شريط العنوان." } }, "nb": { "stringUnit": { "state": "translated", - "value": "Bak vinduet" + "value": "%lld lagrede sider vises i adressefeltforslag." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Atrás da Janela" + "value": "%lld páginas salvas aparecem nas sugestões da barra de endereço." } }, "th": { "stringUnit": { "state": "translated", - "value": "ด้านหลังหน้าต่าง" + "value": "%lld หน้าที่บันทึกจะปรากฏในคำแนะนำแถบที่อยู่" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Pencerenin Arkası" + "value": "%lld kayıtlı sayfa çok amaçlı çubuk önerilerinde görünür." } }, "uk": { "stringUnit": { "state": "translated", - "value": "За вікном" + "value": "%lld збережених сторінок з'являються у підказках адресного рядка." } } } }, - "settings.blendMode.withinWindow": { + "settings.browser.history.subtitleOne": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Within Window" + "value": "1 saved page appears in omnibar suggestions." } }, "ja": { "stringUnit": { "state": "translated", - "value": "ウインドウ内" + "value": "1件の保存済みページがオムニバーの候補に表示されます。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "窗口内部" + "value": "1 个已保存页面显示在地址栏建议中。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "視窗內" + "value": "1 個已儲存頁面會出現在網址列建議中。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "윈도우 내" + "value": "1개의 저장된 페이지가 옴니바 제안에 표시됩니다." } }, "de": { "stringUnit": { "state": "translated", - "value": "Innerhalb des Fensters" + "value": "1 gespeicherte Seite erscheint in den Adressleisten-Vorschlägen." } }, "es": { "stringUnit": { "state": "translated", - "value": "Dentro de la ventana" + "value": "1 página guardada aparece en las sugerencias de la barra de direcciones." } }, "fr": { "stringUnit": { "state": "translated", - "value": "Dans la fenêtre" + "value": "1 page enregistrée apparaît dans les suggestions de la barre d'adresse." } }, "it": { "stringUnit": { "state": "translated", - "value": "All'interno della finestra" + "value": "1 pagina salvata appare nei suggerimenti della barra degli indirizzi." } }, "da": { "stringUnit": { "state": "translated", - "value": "Inden i vindue" + "value": "1 gemt side vises i omnibar-forslag." } }, "pl": { "stringUnit": { "state": "translated", - "value": "W oknie" + "value": "1 zapisana strona pojawia się w podpowiedziach paska adresu." } }, "ru": { "stringUnit": { "state": "translated", - "value": "Внутри окна" + "value": "1 сохраненная страница отображается в подсказках адресной строки." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Unutar prozora" + "value": "1 sačuvana stranica se pojavljuje u prijedlozima omnibara." } }, "ar": { "stringUnit": { "state": "translated", - "value": "داخل النافذة" + "value": "صفحة محفوظة واحدة تظهر في اقتراحات شريط العنوان." } }, "nb": { "stringUnit": { "state": "translated", - "value": "Inni vinduet" + "value": "1 lagret side vises i adressefeltforslag." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Dentro da Janela" + "value": "1 página salva aparece nas sugestões da barra de endereço." } }, "th": { "stringUnit": { "state": "translated", - "value": "ภายในหน้าต่าง" + "value": "1 หน้าที่บันทึกจะปรากฏในคำแนะนำแถบที่อยู่" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Pencere İçinde" + "value": "1 kayıtlı sayfa çok amaçlı çubuk önerilerinde görünür." } }, "uk": { "stringUnit": { "state": "translated", - "value": "Усередині вікна" + "value": "1 збережена сторінка з'являється у підказках адресного рядка." } } } }, - "settings.browser.externalPatterns": { + "settings.browser.hostWhitelist": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "URLs to Always Open Externally" + "value": "Hosts to Open in Embedded Browser" } }, "ja": { "stringUnit": { "state": "translated", - "value": "常に外部で開くURL" + "value": "内蔵ブラウザで開くホスト" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "始终在外部打开的 URL" + "value": "在内嵌浏览器中打开的主机" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "一律在外部開啟的 URL" + "value": "在內建瀏覽器中開啟的主機" } }, "ko": { "stringUnit": { "state": "translated", - "value": "항상 외부에서 열 URL" + "value": "내장 브라우저에서 열 호스트" } }, "de": { "stringUnit": { "state": "translated", - "value": "URLs, die immer extern geöffnet werden" + "value": "Hosts, die im integrierten Browser geöffnet werden" } }, "es": { "stringUnit": { "state": "translated", - "value": "URLs para abrir siempre externamente" + "value": "Hosts para abrir en el navegador integrado" } }, "fr": { "stringUnit": { "state": "translated", - "value": "URL à toujours ouvrir dans un navigateur externe" + "value": "Hôtes à ouvrir dans le navigateur intégré" } }, "it": { "stringUnit": { "state": "translated", - "value": "URL da aprire sempre esternamente" + "value": "Host da aprire nel browser integrato" } }, "da": { "stringUnit": { "state": "translated", - "value": "URL'er der altid åbnes eksternt" + "value": "Værter der åbnes i den indlejrede browser" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Adresy URL otwierane zawsze zewnętrznie" + "value": "Hosty do otwierania we wbudowanej przeglądarce" } }, "ru": { "stringUnit": { "state": "translated", - "value": "URL для открытия во внешнем браузере" + "value": "Хосты для открытия во встроенном браузере" } }, "bs": { "stringUnit": { "state": "translated", - "value": "URL-ovi za uvijek vanjsko otvaranje" + "value": "Hostovi za otvaranje u ugrađenom pregledniku" } }, "ar": { "stringUnit": { "state": "translated", - "value": "عناوين URL للفتح خارجيًا دائمًا" + "value": "المضيفون للفتح في المتصفح المضمّن" } }, "nb": { "stringUnit": { "state": "translated", - "value": "URL-er som alltid åpnes eksternt" + "value": "Verter som åpnes i innebygd nettleser" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "URLs para Sempre Abrir Externamente" + "value": "Hosts para Abrir no Navegador Integrado" } }, "th": { "stringUnit": { "state": "translated", - "value": "URL ที่เปิดภายนอกเสมอ" + "value": "โฮสต์ที่เปิดในเบราว์เซอร์ในตัว" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Her Zaman Harici Olarak Açılacak URL'ler" + "value": "Gömülü Tarayıcıda Açılacak Ana Bilgisayarlar" } }, "uk": { "stringUnit": { "state": "translated", - "value": "URL для завжди зовнішнього відкриття" + "value": "Хости для відкриття у вбудованому браузері" } } } }, - "settings.browser.externalPatterns.subtitle": { + "settings.browser.hostWhitelist.subtitle": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Applies to terminal link clicks and intercepted `open https://...` calls. One rule per line. Plain text matches any URL substring, or prefix with `re:` for regex (for example: openai.com/usage, re:^https?://[^/]*\\\\.example\\\\.com/(billing|usage))." + "value": "Applies to terminal link clicks and intercepted `open https://...` calls. Only these hosts open in cmux. Others open in your default browser. One host or wildcard per line (for example: example.com, *.internal.example). Leave empty to open all hosts in cmux." } }, "ja": { "stringUnit": { "state": "translated", - "value": "ターミナルのリンククリックおよびインターセプトされた`open https://...`呼び出しに適用されます。1行に1ルール。プレーンテキストはURL部分文字列に一致し、`re:`プレフィックスで正規表現を使用できます(例: openai.com/usage, re:^https?://[^/]*\\\\.example\\\\.com/(billing|usage))。" + "value": "ターミナルのリンククリックおよびインターセプトされた`open https://...`呼び出しに適用されます。これらのホストのみcmuxで開きます。その他はデフォルトブラウザで開きます。1行に1つのホストまたはワイルドカード(例: example.com, *.internal.example)。空欄にするとすべてのホストをcmuxで開きます。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "适用于终端中的链接点击和拦截的 `open https://...` 调用。每行一条规则。纯文本匹配任意 URL 子串,或使用 `re:` 前缀表示正则表达式(例如:openai.com/usage、re:^https?://[^/]*\\\\.example\\\\.com/(billing|usage))。" + "value": "适用于终端中的链接点击和拦截的 `open https://...` 调用。仅这些主机在 cmux 中打开,其他主机在默认浏览器中打开。每行一个主机或通配符(例如:example.com、*.internal.example)。留空则在 cmux 中打开所有主机。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "套用於終端機連結點擊和攔截的 `open https://...` 呼叫。每行一條規則。純文字會比對 URL 的任何子字串,或加上 `re:` 前綴使用正規表示式(例如:openai.com/usage、re:^https?://[^/]*\\\\.example\\\\.com/(billing|usage))。" + "value": "套用於終端機連結點擊和攔截的 `open https://...` 呼叫。僅這些主機會在 cmux 中開啟,其他主機會在您的預設瀏覽器中開啟。每行一個主機或萬用字元(例如:example.com、*.internal.example)。留空則在 cmux 中開啟所有主機。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "터미널 링크 클릭 및 인터셉트된 `open https://...` 호출에 적용됩니다. 한 줄에 하나의 규칙. 일반 텍스트는 URL의 하위 문자열을 일치시키며, `re:` 접두사로 정규식을 사용할 수 있습니다 (예: openai.com/usage, re:^https?://[^/]*\\\\.example\\\\.com/(billing|usage))." + "value": "터미널 링크 클릭 및 인터셉트된 `open https://...` 호출에 적용됩니다. 이 호스트만 cmux에서 열립니다. 나머지는 기본 브라우저에서 열립니다. 한 줄에 하나의 호스트 또는 와일드카드 (예: example.com, *.internal.example). 비워두면 모든 호스트가 cmux에서 열립니다." } }, "de": { "stringUnit": { "state": "translated", - "value": "Gilt für Klicks auf Terminal-Links und abgefangene `open https://...`-Aufrufe. Eine Regel pro Zeile. Klartext stimmt mit jedem URL-Teilstring überein, oder verwenden Sie das Präfix `re:` für Regex (zum Beispiel: openai.com/usage, re:^https?://[^/]*\\\\.example\\\\.com/(billing|usage))." + "value": "Gilt für Klicks auf Terminal-Links und abgefangene `open https://...`-Aufrufe. Nur diese Hosts werden in cmux geöffnet. Andere werden in Ihrem Standardbrowser geöffnet. Ein Host oder Platzhalter pro Zeile (zum Beispiel: example.com, *.internal.example). Leer lassen, um alle Hosts in cmux zu öffnen." } }, "es": { "stringUnit": { "state": "translated", - "value": "Se aplica a clics en enlaces del terminal y llamadas interceptadas de `open https://...`. Una regla por línea. El texto plano coincide con cualquier subcadena de URL, o usa el prefijo `re:` para regex (por ejemplo: openai.com/usage, re:^https?://[^/]*\\\\.example\\\\.com/(billing|usage))." + "value": "Se aplica a clics en enlaces del terminal y llamadas interceptadas de `open https://...`. Solo estos hosts se abren en cmux. Los demás se abren en tu navegador predeterminado. Un host o comodín por línea (por ejemplo: example.com, *.internal.example). Déjalo vacío para abrir todos los hosts en cmux." } }, "fr": { "stringUnit": { "state": "translated", - "value": "S'applique aux clics sur les liens du terminal et aux appels `open https://...` interceptés. Une règle par ligne. Le texte brut correspond à toute sous-chaîne d'URL, ou préfixez par `re:` pour une expression régulière (par exemple : openai.com/usage, re:^https?://[^/]*\\\\.example\\\\.com/(billing|usage))." + "value": "S'applique aux clics sur les liens du terminal et aux appels `open https://...` interceptés. Seuls ces hôtes s'ouvrent dans cmux. Les autres s'ouvrent dans votre navigateur par défaut. Un hôte ou caractère générique par ligne (par exemple : example.com, *.internal.example). Laissez vide pour ouvrir tous les hôtes dans cmux." } }, "it": { "stringUnit": { "state": "translated", - "value": "Si applica ai clic sui link nel terminale e alle chiamate intercettate `open https://...`. Una regola per riga. Il testo semplice corrisponde a qualsiasi sottostringa dell'URL, oppure usa il prefisso `re:` per le regex (ad esempio: openai.com/usage, re:^https?://[^/]*\\\\.example\\\\.com/(billing|usage))." + "value": "Si applica ai clic sui link nel terminale e alle chiamate intercettate `open https://...`. Solo questi host si aprono in cmux. Gli altri si aprono nel browser predefinito. Un host o wildcard per riga (ad esempio: example.com, *.internal.example). Lascia vuoto per aprire tutti gli host in cmux." } }, "da": { "stringUnit": { "state": "translated", - "value": "Gælder for terminallinksklik og opfangede `open https://...`-kald. Én regel pr. linje. Almindelig tekst matcher enhver URL-delstreng, eller brug `re:` som præfiks for regex (f.eks.: openai.com/usage, re:^https?://[^/]*\\.example\\.com/(billing|usage))." + "value": "Gælder for terminallinksklik og opfangede `open https://...`-kald. Kun disse værter åbnes i cmux. Andre åbnes i din standardbrowser. Én vært eller wildcard pr. linje (f.eks.: example.com, *.internal.example). Lad stå tomt for at åbne alle værter i cmux." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Dotyczy kliknięć linków w terminalu i przechwyconych wywołań `open https://...`. Jedna reguła na wiersz. Zwykły tekst dopasowuje dowolny fragment URL, lub użyj prefiksu `re:` dla wyrażeń regularnych (na przykład: openai.com/usage, re:^https?://[^/]*\\\\.example\\\\.com/(billing|usage))." + "value": "Dotyczy kliknięć linków w terminalu i przechwyconych wywołań `open https://...`. Tylko te hosty otwierają się w cmux. Pozostałe otwierają się w domyślnej przeglądarce. Jeden host lub wzorzec na wiersz (na przykład: example.com, *.internal.example). Pozostaw puste, aby otwierać wszystkie hosty w cmux." } }, "ru": { "stringUnit": { "state": "translated", - "value": "Применяется к нажатиям на ссылки в терминале и перехваченным вызовам `open https://...`. Одно правило на строку. Обычный текст совпадает с любой подстрокой URL, или используйте префикс `re:` для регулярных выражений (например: openai.com/usage, re:^https?://[^/]*\\\\.example\\\\.com/(billing|usage))." + "value": "Применяется к нажатиям на ссылки в терминале и перехваченным вызовам `open https://...`. Только эти хосты открываются в cmux. Остальные открываются в браузере по умолчанию. Один хост или шаблон на строку (например: example.com, *.internal.example). Оставьте пустым, чтобы открывать все хосты в cmux." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Primjenjuje se na klikove linkova u terminalu i presretnute `open https://...` pozive. Jedno pravilo po redu. Običan tekst odgovara bilo kojem dijelu URL-a, ili dodajte prefiks `re:` za regex (na primjer: openai.com/usage, re:^https?://[^/]*\\\\.example\\\\.com/(billing|usage))." + "value": "Primjenjuje se na klikove linkova u terminalu i presretnute `open https://...` pozive. Samo se ovi hostovi otvaraju u cmux. Ostali se otvaraju u podrazumijevanom pregledniku. Jedan host ili zamjenski znak po redu (na primjer: example.com, *.internal.example). Ostavite prazno da otvorite sve hostove u cmux." } }, "ar": { "stringUnit": { "state": "translated", - "value": "ينطبق على نقرات الروابط في الطرفية واستدعاءات `open https://...` المعترضة. قاعدة واحدة لكل سطر. النص العادي يطابق أي جزء من URL، أو ابدأ بـ `re:` للتعبيرات النمطية (مثال: openai.com/usage, re:^https?://[^/]*\\\\.example\\\\.com/(billing|usage))." + "value": "ينطبق على نقرات الروابط في الطرفية واستدعاءات `open https://...` المعترضة. فقط هؤلاء المضيفون يفتحون في cmux. البقية تفتح في متصفحك الافتراضي. مضيف واحد أو حرف بدل لكل سطر (مثال: example.com, *.internal.example). اتركه فارغًا لفتح جميع المضيفين في cmux." } }, "nb": { "stringUnit": { "state": "translated", - "value": "Gjelder for terminallenkeklikk og avlyttede `open https://...`-kall. Én regel per linje. Ren tekst matcher enhver del av URL-en, eller prefiks med `re:` for regulære uttrykk (for eksempel: openai.com/usage, re:^https?://[^/]*\\\\.example\\\\.com/(billing|usage))." + "value": "Gjelder for terminallenkeklikk og avlyttede `open https://...`-kall. Bare disse vertene åpnes i cmux. Andre åpnes i standard nettleser. Én vert eller jokertegn per linje (for eksempel: example.com, *.internal.example). La stå tom for å åpne alle verter i cmux." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Aplica-se a cliques em links do terminal e chamadas interceptadas de `open https://...`. Uma regra por linha. Texto simples corresponde a qualquer substring de URL, ou prefixe com `re:` para regex (por exemplo: openai.com/usage, re:^https?://[^/]*\\\\.example\\\\.com/(billing|usage))." + "value": "Aplica-se a cliques em links do terminal e chamadas interceptadas de `open https://...`. Apenas estes hosts abrem no cmux. Outros abrem no seu navegador padrão. Um host ou curinga por linha (por exemplo: example.com, *.internal.example). Deixe vazio para abrir todos os hosts no cmux." } }, "th": { "stringUnit": { "state": "translated", - "value": "ใช้กับการคลิกลิงก์ในเทอร์มินัลและการดักจับคำสั่ง `open https://...` กฎหนึ่งข้อต่อบรรทัด ข้อความธรรมดาจะจับคู่กับส่วนใดก็ได้ของ URL หรือนำหน้าด้วย `re:` สำหรับ regex (ตัวอย่าง: openai.com/usage, re:^https?://[^/]*\\\\.example\\\\.com/(billing|usage))" + "value": "ใช้กับการคลิกลิงก์ในเทอร์มินัลและการดักจับคำสั่ง `open https://...` เฉพาะโฮสต์เหล่านี้เท่านั้นที่จะเปิดใน cmux โฮสต์อื่นจะเปิดในเบราว์เซอร์เริ่มต้นของคุณ โฮสต์หรือ wildcard หนึ่งรายการต่อบรรทัด (ตัวอย่าง: example.com, *.internal.example) เว้นว่างเพื่อเปิดโฮสต์ทั้งหมดใน cmux" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Terminal bağlantı tıklamalarına ve yakalanan `open https://...` çağrılarına uygulanır. Satır başına bir kural. Düz metin herhangi bir URL alt dizesiyle eşleşir veya regex için `re:` ön ekini kullanın (örneğin: openai.com/usage, re:^https?://[^/]*\\\\.example\\\\.com/(billing|usage))." + "value": "Terminal bağlantı tıklamalarına ve yakalanan `open https://...` çağrılarına uygulanır. Yalnızca bu ana bilgisayarlar cmux'ta açılır. Diğerleri varsayılan tarayıcınızda açılır. Satır başına bir ana bilgisayar veya joker karakter (örneğin: example.com, *.internal.example). Tüm ana bilgisayarları cmux'ta açmak için boş bırakın." } }, "uk": { "stringUnit": { "state": "translated", - "value": "Застосовується до кліків на посилання в терміналі та перехоплених викликів `open https://...`. Одне правило на рядок. Звичайний текст збігається з будь-якою частиною URL, або додайте префікс `re:` для регулярного виразу (наприклад: openai.com/usage, re:^https?://[^/]*\\.example\\.com/(billing|usage))." + "value": "Застосовується до кліків на посилання в терміналі та перехоплених викликів `open https://...`. Тільки ці хости відкриваються в cmux. Інші відкриваються у стандартному браузері. Один хост або шаблон на рядок (наприклад: example.com, *.internal.example). Залиште порожнім, щоб відкривати всі хости в cmux." } } } }, - "settings.browser.emptyImport.choose": { + "settings.browser.httpAllowlist": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Choose What to Import…" + "value": "HTTP Hosts Allowed in Embedded Browser" } }, "ja": { "stringUnit": { "state": "translated", - "value": "取り込む項目を選ぶ…" + "value": "内蔵ブラウザで許可するHTTPホスト" } }, - "uk": { + "zh-Hans": { "stringUnit": { "state": "translated", - "value": "Вибрати, що імпортувати…" + "value": "内嵌浏览器中允许的 HTTP 主机" + } + }, + "zh-Hant": { + "stringUnit": { + "state": "translated", + "value": "允許在內建瀏覽器中使用的 HTTP 主機" } }, "ko": { "stringUnit": { "state": "translated", - "value": "가져올 항목 선택…" + "value": "내장 브라우저에서 허용할 HTTP 호스트" } - } - } - }, - "settings.browser.emptyImport.title": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "de": { "stringUnit": { "state": "translated", - "value": "Import browser data" + "value": "HTTP-Hosts, die im integrierten Browser zugelassen sind" } }, - "ja": { + "es": { "stringUnit": { "state": "translated", - "value": "ブラウザーデータを取り込む" + "value": "Hosts HTTP permitidos en el navegador integrado" } }, - "uk": { + "fr": { "stringUnit": { "state": "translated", - "value": "Імпорт даних браузера" + "value": "Hôtes HTTP autorisés dans le navigateur intégré" } }, - "ko": { + "it": { "stringUnit": { "state": "translated", - "value": "브라우저 데이터 가져오기" + "value": "Host HTTP consentiti nel browser integrato" } - } - } - }, - "settings.browser.reactGrabVersion": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "da": { "stringUnit": { "state": "translated", - "value": "React Grab Version" + "value": "HTTP-værter tilladt i den indlejrede browser" } }, - "ja": { + "pl": { "stringUnit": { "state": "translated", - "value": "React Grabバージョン" + "value": "Hosty HTTP dozwolone we wbudowanej przeglądarce" } }, - "ko": { + "ru": { "stringUnit": { "state": "translated", - "value": "React Grab 버전" + "value": "HTTP-хосты, разрешенные во встроенном браузере" } - } - } - }, - "settings.browser.reactGrabVersion.subtitle": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "bs": { "stringUnit": { "state": "translated", - "value": "Pinned npm version of react-grab injected by the toolbar button (Cmd+Shift+G). Only versions with a known integrity hash are accepted." + "value": "HTTP hostovi dozvoljeni u ugrađenom pregledniku" } }, - "ja": { + "ar": { "stringUnit": { "state": "translated", - "value": "ツールバーボタン(Cmd+Shift+G)で注入されるreact-grabのnpmバージョン。既知の整合性ハッシュを持つバージョンのみ使用可能です。" + "value": "مضيفو HTTP المسموح بهم في المتصفح المضمّن" } }, - "ko": { + "nb": { "stringUnit": { "state": "translated", - "value": "도구 모음 버튼(Cmd+Shift+G)으로 주입되는 react-grab의 고정된 npm 버전입니다. 알려진 무결성 해시가 있는 버전만 허용됩니다." + "value": "HTTP-verter tillatt i innebygd nettleser" + } + }, + "pt-BR": { + "stringUnit": { + "state": "translated", + "value": "Hosts HTTP Permitidos no Navegador Integrado" + } + }, + "th": { + "stringUnit": { + "state": "translated", + "value": "โฮสต์ HTTP ที่อนุญาตในเบราว์เซอร์ในตัว" + } + }, + "tr": { + "stringUnit": { + "state": "translated", + "value": "Gömülü Tarayıcıda İzin Verilen HTTP Ana Bilgisayarları" + } + }, + "uk": { + "stringUnit": { + "state": "translated", + "value": "HTTP-хости, дозволені у вбудованому браузері" } } } }, - "settings.browser.history": { + "settings.browser.httpAllowlist.description": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Browsing History" + "value": "Controls which HTTP (non-HTTPS) hosts can open in cmux without a warning prompt. Defaults include localhost, *.localhost, 127.0.0.1, ::1, 0.0.0.0, and *.localtest.me." } }, "ja": { "stringUnit": { "state": "translated", - "value": "ブラウザ履歴" + "value": "警告プロンプトなしでcmuxで開けるHTTP(非HTTPS)ホストを制御します。デフォルトにはlocalhost、*.localhost、127.0.0.1、::1、0.0.0.0、*.localtest.meが含まれます。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "浏览历史" + "value": "控制哪些 HTTP(非 HTTPS)主机可以在 cmux 中打开而不显示警告提示。默认包括 localhost、*.localhost、127.0.0.1、::1、0.0.0.0 和 *.localtest.me。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "瀏覽記錄" + "value": "控制哪些 HTTP(非 HTTPS)主機可以在 cmux 中開啟而不顯示警告提示。預設包含 localhost、*.localhost、127.0.0.1、::1、0.0.0.0 和 *.localtest.me。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "탐색 기록" + "value": "cmux에서 경고 없이 열 수 있는 HTTP(비HTTPS) 호스트를 제어합니다. 기본값에는 localhost, *.localhost, 127.0.0.1, ::1, 0.0.0.0 및 *.localtest.me가 포함됩니다." } }, "de": { "stringUnit": { "state": "translated", - "value": "Browserverlauf" + "value": "Steuert, welche HTTP-Hosts (nicht HTTPS) ohne Warnhinweis in cmux geöffnet werden können. Standardmäßig enthalten: localhost, *.localhost, 127.0.0.1, ::1, 0.0.0.0 und *.localtest.me." } }, "es": { "stringUnit": { "state": "translated", - "value": "Historial de navegación" + "value": "Controla qué hosts HTTP (no HTTPS) pueden abrirse en cmux sin un mensaje de advertencia. Los valores predeterminados incluyen localhost, *.localhost, 127.0.0.1, ::1, 0.0.0.0 y *.localtest.me." } }, "fr": { "stringUnit": { "state": "translated", - "value": "Historique de navigation" + "value": "Contrôle quels hôtes HTTP (non HTTPS) peuvent s'ouvrir dans cmux sans avertissement. Les valeurs par défaut incluent localhost, *.localhost, 127.0.0.1, ::1, 0.0.0.0 et *.localtest.me." } }, "it": { "stringUnit": { "state": "translated", - "value": "Cronologia di navigazione" + "value": "Controlla quali host HTTP (non HTTPS) possono aprirsi in cmux senza un avviso. I valori predefiniti includono localhost, *.localhost, 127.0.0.1, ::1, 0.0.0.0 e *.localtest.me." } }, "da": { "stringUnit": { "state": "translated", - "value": "Browserhistorik" + "value": "Styrer hvilke HTTP-værter (ikke-HTTPS) der kan åbnes i cmux uden advarselsmeddelelse. Standardindstillinger inkluderer localhost, *.localhost, 127.0.0.1, ::1, 0.0.0.0 og *.localtest.me." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Historia przeglądania" + "value": "Określa, które hosty HTTP (inne niż HTTPS) mogą być otwierane w cmux bez ostrzeżenia. Domyślnie uwzględniono localhost, *.localhost, 127.0.0.1, ::1, 0.0.0.0 i *.localtest.me." } }, "ru": { "stringUnit": { "state": "translated", - "value": "История просмотра" + "value": "Определяет, какие HTTP (не HTTPS) хосты могут открываться в cmux без предупреждения. По умолчанию включены localhost, *.localhost, 127.0.0.1, ::1, 0.0.0.0 и *.localtest.me." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Historija pregledanja" + "value": "Kontroliše koji HTTP (ne-HTTPS) hostovi mogu biti otvoreni u cmux bez upozorenja. Podrazumijevani uključuju localhost, *.localhost, 127.0.0.1, ::1, 0.0.0.0 i *.localtest.me." } }, "ar": { "stringUnit": { "state": "translated", - "value": "سجل التصفح" + "value": "يتحكم في مضيفي HTTP (غير HTTPS) الذين يمكنهم الفتح في cmux بدون رسالة تحذير. الافتراضيات تشمل localhost و *.localhost و 127.0.0.1 و ::1 و 0.0.0.0 و *.localtest.me." } }, "nb": { "stringUnit": { "state": "translated", - "value": "Nettleserhistorikk" + "value": "Styrer hvilke HTTP-verter (ikke HTTPS) som kan åpnes i cmux uten advarselsmelding. Standardverdier inkluderer localhost, *.localhost, 127.0.0.1, ::1, 0.0.0.0 og *.localtest.me." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Histórico de Navegação" + "value": "Controla quais hosts HTTP (não HTTPS) podem abrir no cmux sem um aviso. Os padrões incluem localhost, *.localhost, 127.0.0.1, ::1, 0.0.0.0 e *.localtest.me." } }, "th": { "stringUnit": { "state": "translated", - "value": "ประวัติการท่องเว็บ" + "value": "ควบคุมว่าโฮสต์ HTTP (ไม่ใช่ HTTPS) ใดที่สามารถเปิดใน cmux โดยไม่ต้องแสดงคำเตือน ค่าเริ่มต้นรวมถึง localhost, *.localhost, 127.0.0.1, ::1, 0.0.0.0 และ *.localtest.me" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Tarama Geçmişi" + "value": "Hangi HTTP (HTTPS olmayan) ana bilgisayarlarının cmux'ta uyarı istemi olmadan açılabileceğini kontrol eder. Varsayılanlar localhost, *.localhost, 127.0.0.1, ::1, 0.0.0.0 ve *.localtest.me içerir." } }, "uk": { "stringUnit": { "state": "translated", - "value": "Історія перегляду" + "value": "Визначає, які HTTP (не HTTPS) хости можуть відкриватися в cmux без попередження. Типово включає localhost, *.localhost, 127.0.0.1, ::1, 0.0.0.0 та *.localtest.me." } } } }, - "settings.browser.import": { + "settings.browser.httpAllowlist.hint": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Import Browser Data" + "value": "One host or wildcard per line (for example: localhost, *.localhost, 127.0.0.1, ::1, 0.0.0.0, *.localtest.me)." } }, "ja": { "stringUnit": { "state": "translated", - "value": "ブラウザーデータを取り込む" + "value": "1行に1つのホストまたはワイルドカード(例: localhost, *.localhost, 127.0.0.1, ::1, 0.0.0.0, *.localtest.me)。" } }, - "uk": { + "zh-Hans": { "stringUnit": { "state": "translated", - "value": "Імпорт даних браузера" + "value": "每行一个主机或通配符(例如:localhost、*.localhost、127.0.0.1、::1、0.0.0.0、*.localtest.me)。" } }, - "ko": { + "zh-Hant": { "stringUnit": { "state": "translated", - "value": "브라우저 데이터 가져오기" + "value": "每行一個主機或萬用字元(例如:localhost、*.localhost、127.0.0.1、::1、0.0.0.0、*.localtest.me)。" } - } - } - }, - "settings.browser.import.choose": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "ko": { "stringUnit": { "state": "translated", - "value": "Choose…" + "value": "한 줄에 하나의 호스트 또는 와일드카드 (예: localhost, *.localhost, 127.0.0.1, ::1, 0.0.0.0, *.localtest.me)." } }, - "ja": { + "de": { "stringUnit": { "state": "translated", - "value": "選択…" + "value": "Ein Host oder Platzhalter pro Zeile (zum Beispiel: localhost, *.localhost, 127.0.0.1, ::1, 0.0.0.0, *.localtest.me)." } }, - "uk": { + "es": { "stringUnit": { "state": "translated", - "value": "Вибрати…" + "value": "Un host o comodín por línea (por ejemplo: localhost, *.localhost, 127.0.0.1, ::1, 0.0.0.0, *.localtest.me)." } }, - "ko": { + "fr": { "stringUnit": { "state": "translated", - "value": "선택…" + "value": "Un hôte ou caractère générique par ligne (par exemple : localhost, *.localhost, 127.0.0.1, ::1, 0.0.0.0, *.localtest.me)." } - } - } - }, - "settings.browser.import.refresh": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "it": { "stringUnit": { "state": "translated", - "value": "Refresh" + "value": "Un host o wildcard per riga (ad esempio: localhost, *.localhost, 127.0.0.1, ::1, 0.0.0.0, *.localtest.me)." } }, - "ja": { + "da": { "stringUnit": { "state": "translated", - "value": "再読み込み" + "value": "Én vært eller wildcard pr. linje (f.eks.: localhost, *.localhost, 127.0.0.1, ::1, 0.0.0.0, *.localtest.me)." } }, - "uk": { + "pl": { "stringUnit": { "state": "translated", - "value": "Оновити" + "value": "Jeden host lub wzorzec na wiersz (na przykład: localhost, *.localhost, 127.0.0.1, ::1, 0.0.0.0, *.localtest.me)." } }, - "ko": { + "ru": { "stringUnit": { "state": "translated", - "value": "새로고침" + "value": "Один хост или шаблон на строку (например: localhost, *.localhost, 127.0.0.1, ::1, 0.0.0.0, *.localtest.me)." } - } - } - }, - "settings.browser.import.hint.note.hidden": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "bs": { "stringUnit": { "state": "translated", - "value": "The blank-tab import hint is hidden. Turn it back on here any time." + "value": "Jedan host ili zamjenski znak po redu (na primjer: localhost, *.localhost, 127.0.0.1, ::1, 0.0.0.0, *.localtest.me)." } }, - "ja": { + "ar": { "stringUnit": { "state": "translated", - "value": "空タブのインポート案内は非表示です。ここでいつでも再表示できます。" + "value": "مضيف واحد أو حرف بدل لكل سطر (مثال: localhost, *.localhost, 127.0.0.1, ::1, 0.0.0.0, *.localtest.me)." } }, - "uk": { + "nb": { "stringUnit": { "state": "translated", - "value": "Підказка імпорту на порожній вкладці прихована. Увімкніть її тут у будь-який час." + "value": "Én vert eller jokertegn per linje (for eksempel: localhost, *.localhost, 127.0.0.1, ::1, 0.0.0.0, *.localtest.me)." } }, - "ko": { - "stringUnit": { - "state": "translated", - "value": "빈 탭 가져오기 힌트가 숨겨져 있습니다. 여기서 언제든 다시 켤 수 있습니다." - } - } - } - }, - "settings.browser.import.hint.note.settingsOnly": { - "extractionState": "manual", - "localizations": { - "en": { + "pt-BR": { "stringUnit": { "state": "translated", - "value": "Blank tabs are currently using Settings only mode from the debug window." + "value": "Um host ou curinga por linha (por exemplo: localhost, *.localhost, 127.0.0.1, ::1, 0.0.0.0, *.localtest.me)." } }, - "ja": { + "th": { "stringUnit": { "state": "translated", - "value": "現在、空タブはデバッグウィンドウの「設定のみ」モードになっています。" + "value": "โฮสต์หรือ wildcard หนึ่งรายการต่อบรรทัด (ตัวอย่าง: localhost, *.localhost, 127.0.0.1, ::1, 0.0.0.0, *.localtest.me)" } }, - "uk": { + "tr": { "stringUnit": { "state": "translated", - "value": "Порожні вкладки зараз використовують режим «Тільки налаштування» з вікна налагодження." + "value": "Satır başına bir ana bilgisayar veya joker karakter (örneğin: localhost, *.localhost, 127.0.0.1, ::1, 0.0.0.0, *.localtest.me)." } }, - "ko": { + "uk": { "stringUnit": { "state": "translated", - "value": "빈 탭이 현재 디버그 창의 설정 전용 모드를 사용하고 있습니다." + "value": "Один хост або шаблон на рядок (наприклад: localhost, *.localhost, 127.0.0.1, ::1, 0.0.0.0, *.localtest.me)." } } } }, - "settings.browser.import.hint.note.visible": { + "settings.browser.httpAllowlist.save": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Blank browser tabs can show this import suggestion. Hide or re-enable it here." + "value": "Save" } }, "ja": { "stringUnit": { "state": "translated", - "value": "空のブラウザータブにこのインポート案内を表示できます。ここで非表示や再表示を切り替えられます。" + "value": "保存" } }, - "uk": { + "zh-Hans": { "stringUnit": { "state": "translated", - "value": "Порожні вкладки браузера можуть показувати пропозицію імпорту. Сховайте або увімкніть її тут." + "value": "保存" } }, - "ko": { - "stringUnit": { - "state": "translated", - "value": "빈 브라우저 탭에 가져오기 제안을 표시할 수 있습니다. 여기서 숨기거나 다시 활성화하세요." - } - } - } - }, - "settings.browser.import.hint.show": { - "extractionState": "manual", - "localizations": { - "en": { + "zh-Hant": { "stringUnit": { "state": "translated", - "value": "Show import hint on blank browser tabs" + "value": "儲存" } }, - "ja": { + "ko": { "stringUnit": { "state": "translated", - "value": "空のブラウザータブにインポート案内を表示" + "value": "저장" } }, - "uk": { + "de": { "stringUnit": { "state": "translated", - "value": "Показувати підказку імпорту на порожніх вкладках браузера" + "value": "Speichern" } }, - "ko": { - "stringUnit": { - "state": "translated", - "value": "빈 브라우저 탭에 가져오기 힌트 표시" - } - } - } - }, - "settings.browser.history.clearButton": { - "extractionState": "manual", - "localizations": { - "en": { + "es": { "stringUnit": { "state": "translated", - "value": "Clear History…" + "value": "Guardar" } }, - "ja": { + "fr": { "stringUnit": { "state": "translated", - "value": "履歴をクリア…" + "value": "Enregistrer" } }, - "zh-Hans": { + "it": { "stringUnit": { "state": "translated", - "value": "清除历史记录..." + "value": "Salva" } }, - "zh-Hant": { + "da": { "stringUnit": { "state": "translated", - "value": "清除記錄..." + "value": "Gem" } }, - "ko": { + "pl": { "stringUnit": { "state": "translated", - "value": "기록 지우기…" + "value": "Zapisz" } }, - "de": { + "ru": { "stringUnit": { "state": "translated", - "value": "Verlauf löschen …" + "value": "Сохранить" } }, - "es": { + "bs": { "stringUnit": { "state": "translated", - "value": "Borrar historial…" + "value": "Spremi" } }, - "fr": { + "ar": { "stringUnit": { "state": "translated", - "value": "Effacer l'historique..." + "value": "حفظ" } }, - "it": { + "nb": { "stringUnit": { "state": "translated", - "value": "Cancella cronologia…" + "value": "Lagre" } }, - "da": { + "pt-BR": { "stringUnit": { "state": "translated", - "value": "Ryd historik…" + "value": "Salvar" } }, - "pl": { + "th": { "stringUnit": { "state": "translated", - "value": "Wyczyść historię…" + "value": "บันทึก" } }, - "ru": { + "tr": { "stringUnit": { "state": "translated", - "value": "Очистить историю..." + "value": "Kaydet" } }, - "bs": { + "uk": { "stringUnit": { "state": "translated", - "value": "Obriši historiju…" + "value": "Зберегти" } - }, - "ar": { + } + } + }, + "settings.betaFeatures.dock": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", "value": "Dock" } }, "ja": { "stringUnit": { "state": "translated", "value": "Dock" } } } }, + "settings.betaFeatures.dock.subtitleOff": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", "value": "Hides Dock from the right sidebar until you enable it here." } }, "ja": { "stringUnit": { "state": "translated", "value": "ここで有効にするまで、Dock を右サイドバーから隠します。" } } } }, + "settings.betaFeatures.dock.subtitleOn": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", "value": "Shows Dock in the right sidebar mode switcher for custom terminal controls." } }, "ja": { "stringUnit": { "state": "translated", "value": "Dock を右サイドバーのモード切り替えに表示し、カスタム端末コントロールを使えるようにします。" } } } }, + "settings.betaFeatures.warning": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", "value": "Dock is unstable and may change or break. Enable it only when you are testing it." } }, "ja": { "stringUnit": { "state": "translated", "value": "Dock は不安定で、変更されたり壊れたりする可能性があります。テストする場合だけ有効にしてください。" } } } }, + "settings.browser.enabled": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "مسح السجل…" + "value": "Enable cmux Browser" } }, - "nb": { + "ja": { "stringUnit": { "state": "translated", - "value": "Tøm historikk …" + "value": "cmuxブラウザを有効にする" } - }, - "pt-BR": { + } + } + }, + "settings.browser.enabled.subtitleOff": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Limpar Histórico…" + "value": "Browser tabs, terminal link clicks, and intercepted open commands are disabled. Links open in your default browser." } }, - "th": { + "ja": { "stringUnit": { "state": "translated", - "value": "ล้างประวัติ..." + "value": "ブラウザタブ、ターミナルのリンククリック、インターセプトされたopenコマンドは無効です。リンクはデフォルトブラウザで開きます。" } - }, - "tr": { + } + } + }, + "settings.browser.enabled.subtitleOn": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Geçmişi Temizle…" + "value": "Browser tabs, terminal link clicks, and intercepted open commands can use the embedded browser." } }, - "uk": { + "ja": { "stringUnit": { "state": "translated", - "value": "Очистити історію…" + "value": "ブラウザタブ、ターミナルのリンククリック、インターセプトされたopenコマンドで内蔵ブラウザを使用できます。" } } } }, - "settings.browser.history.clearDialog.cancel": { + "settings.browser.hiddenWebViewDiscard": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", "value": "Browser Memory Saver" } }, "ja": { "stringUnit": { "state": "translated", "value": "ブラウザメモリセーバー" } } } }, + "settings.browser.hiddenWebViewDiscard.subtitleOff": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", "value": "Hidden browser tabs keep page memory until closed." } }, "ja": { "stringUnit": { "state": "translated", "value": "非表示のブラウザタブは、閉じるまでページメモリを保持します。" } } } }, + "settings.browser.hiddenWebViewDiscard.subtitleOn": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", "value": "Hidden browser tabs release page memory after the delay below, then restore when shown again." } }, "ja": { "stringUnit": { "state": "translated", "value": "非表示のブラウザタブは下の遅延後にページメモリを解放し、再表示時に復元します。" } } } }, + "settings.browser.hiddenWebViewDiscardDelay": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", "value": "Memory Saver Delay" } }, "ja": { "stringUnit": { "state": "translated", "value": "メモリセーバーの遅延" } } } }, + "settings.browser.hiddenWebViewDiscardDelay.minutes": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", "value": "%lldm" } }, "ja": { "stringUnit": { "state": "translated", "value": "%lld分" } } } }, + "settings.browser.hiddenWebViewDiscardDelay.minutesSeconds": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", "value": "%lldm %llds" } }, "ja": { "stringUnit": { "state": "translated", "value": "%lld分%lld秒" } } } }, + "settings.browser.hiddenWebViewDiscardDelay.seconds": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", "value": "%llds" } }, "ja": { "stringUnit": { "state": "translated", "value": "%lld秒" } } } }, + "settings.browser.hiddenWebViewDiscardDelay.subtitle": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", "value": "How long a browser tab must stay hidden before cmux frees its page memory. Active downloads, popups, developer tools, fullscreen, and loading pages are skipped." } }, "ja": { "stringUnit": { "state": "translated", "value": "ブラウザタブが非表示になってから、cmux がページメモリを解放するまでの時間です。進行中のダウンロード、ポップアップ、開発者ツール、フルスクリーン、読み込み中のページは対象外です。" } } } }, + "settings.browser.interceptOpen": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Cancel" + "value": "Intercept open http(s) in Terminal" } }, "ja": { "stringUnit": { "state": "translated", - "value": "キャンセル" + "value": "ターミナルでopen http(s)をインターセプト" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "取消" + "value": "在终端中拦截 open http(s)" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "取消" + "value": "在終端機中攔截 open http(s)" } }, "ko": { "stringUnit": { "state": "translated", - "value": "취소" + "value": "터미널에서 open http(s) 인터셉트" } }, "de": { "stringUnit": { "state": "translated", - "value": "Abbrechen" + "value": "open http(s) im Terminal abfangen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Cancelar" + "value": "Interceptar open http(s) en Terminal" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Annuler" + "value": "Intercepter open http(s) dans le terminal" } }, "it": { "stringUnit": { "state": "translated", - "value": "Annulla" + "value": "Intercetta open http(s) nel terminale" } }, "da": { "stringUnit": { "state": "translated", - "value": "Annuller" + "value": "Opfang open http(s) i terminal" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Anuluj" + "value": "Przechwytuj open http(s) w terminalu" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Отменить" + "value": "Перехватывать open http(s) в терминале" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Otkaži" + "value": "Presretni open http(s) u Terminalu" } }, "ar": { "stringUnit": { "state": "translated", - "value": "إلغاء" + "value": "اعتراض open http(s) في الطرفية" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Avbryt" + "value": "Avlytt open http(s) i terminal" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Cancelar" + "value": "Interceptar open http(s) no Terminal" } }, "th": { "stringUnit": { "state": "translated", - "value": "ยกเลิก" + "value": "ดักจับ open http(s) ในเทอร์มินัล" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Vazgeç" + "value": "Terminalde open http(s) Komutlarını Yakala" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Скасувати" + "value": "Перехоплювати open http(s) у терміналі" } } } }, - "settings.browser.history.clearDialog.confirm": { + "settings.browser.interceptOpen.subtitle": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Clear History" + "value": "When off, `open https://...` and `open http://...` always use your default browser." } }, "ja": { "stringUnit": { "state": "translated", - "value": "履歴をクリア" + "value": "オフの場合、`open https://...`および`open http://...`は常にデフォルトブラウザを使用します。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "清除历史记录" + "value": "关闭后,`open https://...` 和 `open http://...` 始终使用默认浏览器。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "清除記錄" + "value": "關閉時,`open https://...` 和 `open http://...` 一律使用您的預設瀏覽器。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "기록 지우기" + "value": "비활성화하면 `open https://...` 및 `open http://...`가 항상 기본 브라우저를 사용합니다." } }, "de": { "stringUnit": { "state": "translated", - "value": "Verlauf löschen" + "value": "Wenn deaktiviert, verwenden `open https://...` und `open http://...` immer Ihren Standardbrowser." } }, "es": { "stringUnit": { "state": "translated", - "value": "Borrar historial" + "value": "Cuando está desactivado, `open https://...` y `open http://...` siempre usan tu navegador predeterminado." } }, "fr": { "stringUnit": { "state": "translated", - "value": "Effacer l'historique" + "value": "Lorsque désactivé, `open https://...` et `open http://...` utilisent toujours votre navigateur par défaut." } }, "it": { "stringUnit": { "state": "translated", - "value": "Cancella cronologia" + "value": "Quando disattivato, `open https://...` e `open http://...` usano sempre il browser predefinito." } }, "da": { "stringUnit": { "state": "translated", - "value": "Ryd historik" + "value": "Når deaktiveret, bruger `open https://...` og `open http://...` altid din standardbrowser." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Wyczyść historię" + "value": "Po wyłączeniu `open https://...` i `open http://...` zawsze używają domyślnej przeglądarki." } }, "ru": { "stringUnit": { "state": "translated", - "value": "Очистить историю" + "value": "При отключении `open https://...` и `open http://...` всегда используют браузер по умолчанию." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Obriši historiju" + "value": "Kada je isključeno, `open https://...` i `open http://...` uvijek koriste podrazumijevani preglednik." } }, "ar": { "stringUnit": { "state": "translated", - "value": "مسح السجل" + "value": "عند التعطيل، يستخدم `open https://...` و `open http://...` دائمًا متصفحك الافتراضي." } }, "nb": { "stringUnit": { "state": "translated", - "value": "Tøm historikk" + "value": "Når av, bruker `open https://...` og `open http://...` alltid standard nettleser." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Limpar Histórico" + "value": "Quando desativado, `open https://...` e `open http://...` sempre usam seu navegador padrão." } }, "th": { "stringUnit": { "state": "translated", - "value": "ล้างประวัติ" + "value": "เมื่อปิด `open https://...` และ `open http://...` จะใช้เบราว์เซอร์เริ่มต้นของคุณเสมอ" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Geçmişi Temizle" + "value": "Kapalıyken, `open https://...` ve `open http://...` her zaman varsayılan tarayıcınızı kullanır." } }, "uk": { "stringUnit": { "state": "translated", - "value": "Очистити історію" + "value": "Якщо вимкнено, `open https://...` та `open http://...` завжди використовують стандартний браузер." } } } }, - "settings.browser.history.clearDialog.message": { + "settings.browser.openTerminalLinks": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "This removes visited-page suggestions from the browser omnibar." + "value": "Open Terminal Links in cmux Browser" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ブラウザのオムニバーから訪問済みページの候補が削除されます。" + "value": "ターミナルのリンクをcmuxブラウザで開く" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "这将从浏览器地址栏中移除已访问页面的建议。" + "value": "在 cmux 浏览器中打开终端链接" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "這會移除瀏覽器網址列中已造訪頁面的建議。" + "value": "在 cmux 瀏覽器中開啟終端機連結" } }, "ko": { "stringUnit": { "state": "translated", - "value": "브라우저 옴니바에서 방문 페이지 제안을 제거합니다." + "value": "터미널 링크를 cmux 브라우저에서 열기" } }, "de": { "stringUnit": { "state": "translated", - "value": "Dies entfernt Vorschläge für besuchte Seiten aus der Browser-Adressleiste." + "value": "Terminal-Links im cmux-Browser öffnen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Esto elimina las sugerencias de páginas visitadas de la barra de direcciones del navegador." + "value": "Abrir enlaces del terminal en el navegador de cmux" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Cela supprime les suggestions de pages visitées de la barre d'adresse du navigateur." + "value": "Ouvrir les liens du terminal dans le navigateur cmux" } }, "it": { "stringUnit": { "state": "translated", - "value": "Questa operazione rimuove i suggerimenti delle pagine visitate dalla barra degli indirizzi del browser." + "value": "Apri link del terminale nel browser cmux" } }, "da": { "stringUnit": { "state": "translated", - "value": "Dette fjerner besøgte sideforslag fra browserens omnibar." + "value": "Åbn terminallinks i cmux-browser" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Spowoduje to usunięcie podpowiedzi odwiedzonych stron z paska adresu przeglądarki." + "value": "Otwieraj linki terminala w przeglądarce cmux" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Это удалит подсказки посещенных страниц из адресной строки браузера." + "value": "Открывать ссылки из терминала в браузере cmux" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Ovo uklanja prijedloge posjećenih stranica iz omnibar preglednika." + "value": "Otvori linkove terminala u cmux pregledniku" } }, "ar": { "stringUnit": { "state": "translated", - "value": "يؤدي هذا إلى إزالة اقتراحات الصفحات المزارة من شريط عنوان المتصفح." + "value": "فتح روابط الطرفية في متصفح cmux" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Dette fjerner forslag basert på besøkte sider fra nettleserens adressefelt." + "value": "Åpne terminallenker i cmux-nettleser" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Isto remove as sugestões de páginas visitadas da barra de endereço do navegador." + "value": "Abrir Links do Terminal no Navegador do cmux" } }, "th": { "stringUnit": { "state": "translated", - "value": "การดำเนินการนี้จะลบคำแนะนำหน้าที่เยี่ยมชมจากแถบที่อยู่เบราว์เซอร์" + "value": "เปิดลิงก์เทอร์มินัลในเบราว์เซอร์ cmux" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Bu, tarayıcı çok amaçlı çubuğundan ziyaret edilen sayfa önerilerini kaldırır." + "value": "Terminal Bağlantılarını cmux Tarayıcısında Aç" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Це видалить підказки відвіданих сторінок з адресного рядка браузера." + "value": "Відкривати посилання терміналу у браузері cmux" } } } }, - "settings.browser.history.clearDialog.title": { + "settings.browser.openTerminalLinks.subtitle": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Clear browser history?" + "value": "When off, links clicked in terminal output open in your default browser." } }, "ja": { "stringUnit": { "state": "translated", - "value": "ブラウザ履歴をクリアしますか?" + "value": "オフの場合、ターミナル出力のリンクはデフォルトブラウザで開きます。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "清除浏览器历史记录?" + "value": "关闭后,终端输出中点击的链接在默认浏览器中打开。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "要清除瀏覽記錄嗎?" + "value": "關閉時,終端機輸出中點擊的連結會在您的預設瀏覽器中開啟。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "브라우저 기록을 지우시겠습니까?" + "value": "비활성화하면 터미널 출력에서 클릭한 링크가 기본 브라우저에서 열립니다." } }, "de": { "stringUnit": { "state": "translated", - "value": "Browserverlauf löschen?" + "value": "Wenn deaktiviert, werden im Terminal angeklickte Links in Ihrem Standardbrowser geöffnet." } }, "es": { "stringUnit": { "state": "translated", - "value": "¿Borrar historial del navegador?" + "value": "Cuando está desactivado, los enlaces en la salida del terminal se abren en tu navegador predeterminado." } }, "fr": { "stringUnit": { "state": "translated", - "value": "Effacer l'historique du navigateur ?" + "value": "Lorsque désactivé, les liens cliqués dans la sortie du terminal s'ouvrent dans votre navigateur par défaut." } }, "it": { "stringUnit": { "state": "translated", - "value": "Cancellare la cronologia del browser?" + "value": "Quando disattivato, i link cliccati nell'output del terminale si aprono nel browser predefinito." } }, "da": { "stringUnit": { "state": "translated", - "value": "Ryd browserhistorik?" + "value": "Når deaktiveret, åbnes links, der klikkes i terminaloutput, i din standardbrowser." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Wyczyścić historię przeglądarki?" + "value": "Po wyłączeniu linki kliknięte w terminalu otwierają się w domyślnej przeglądarce." } }, "ru": { "stringUnit": { "state": "translated", - "value": "Очистить историю браузера?" + "value": "При отключении ссылки из терминала открываются в браузере по умолчанию." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Obrisati historiju preglednika?" + "value": "Kada je isključeno, linkovi kliknuti u izlazu terminala se otvaraju u podrazumijevanom pregledniku." } }, "ar": { "stringUnit": { "state": "translated", - "value": "مسح سجل المتصفح؟" + "value": "عند التعطيل، تفتح الروابط المنقورة في مخرجات الطرفية في متصفحك الافتراضي." } }, "nb": { "stringUnit": { "state": "translated", - "value": "Tømme nettleserhistorikk?" + "value": "Når av, åpnes lenker som klikkes i terminalutdata i standard nettleser." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Limpar histórico do navegador?" + "value": "Quando desativado, links clicados na saída do terminal abrem no seu navegador padrão." } }, "th": { "stringUnit": { "state": "translated", - "value": "ล้างประวัติเบราว์เซอร์หรือไม่?" + "value": "เมื่อปิด ลิงก์ที่คลิกในเอาต์พุตเทอร์มินัลจะเปิดในเบราว์เซอร์เริ่มต้นของคุณ" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Tarayıcı geçmişi temizlensin mi?" + "value": "Kapalıyken, terminal çıktısında tıklanan bağlantılar varsayılan tarayıcınızda açılır." } }, "uk": { "stringUnit": { "state": "translated", - "value": "Очистити історію браузера?" + "value": "Якщо вимкнено, посилання у виводі терміналу відкриваються у стандартному браузері." } } } }, - "settings.browser.history.subtitleEmpty": { + "settings.browser.searchEngine": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "No saved pages yet." + "value": "Default Search Engine" } }, "ja": { "stringUnit": { "state": "translated", - "value": "保存済みのページはまだありません。" + "value": "デフォルト検索エンジン" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "尚无已保存的页面。" + "value": "默认搜索引擎" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "尚無已儲存的頁面。" + "value": "預設搜尋引擎" } }, "ko": { "stringUnit": { "state": "translated", - "value": "아직 저장된 페이지가 없습니다." + "value": "기본 검색 엔진" } }, "de": { "stringUnit": { "state": "translated", - "value": "Noch keine gespeicherten Seiten." + "value": "Standardsuchmaschine" } }, "es": { "stringUnit": { "state": "translated", - "value": "Aún no hay páginas guardadas." + "value": "Motor de búsqueda predeterminado" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Aucune page enregistrée pour le moment." + "value": "Moteur de recherche par défaut" } }, "it": { "stringUnit": { "state": "translated", - "value": "Nessuna pagina salvata." + "value": "Motore di ricerca predefinito" } }, "da": { "stringUnit": { "state": "translated", - "value": "Ingen gemte sider endnu." + "value": "Standardsøgemaskine" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Brak zapisanych stron." + "value": "Domyślna wyszukiwarka" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Сохраненных страниц пока нет." + "value": "Поисковая система по умолчанию" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Još nema sačuvanih stranica." + "value": "Podrazumijevani pretraživač" } }, "ar": { "stringUnit": { "state": "translated", - "value": "لا توجد صفحات محفوظة بعد." + "value": "محرك البحث الافتراضي" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Ingen lagrede sider ennå." + "value": "Standard søkemotor" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Nenhuma página salva ainda." + "value": "Motor de Busca Padrão" } }, "th": { "stringUnit": { "state": "translated", - "value": "ยังไม่มีหน้าที่บันทึก" + "value": "เครื่องมือค้นหาเริ่มต้น" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Henüz kayıtlı sayfa yok." + "value": "Varsayılan Arama Motoru" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Збережених сторінок ще немає." + "value": "Стандартна пошукова система" } } } }, - "settings.browser.history.subtitleLoading": { + "settings.browser.searchEngine.subtitle": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Checking browsing history..." + "value": "Used by the browser address bar when input is not a URL." } }, "ja": { "stringUnit": { "state": "translated", - "value": "閲覧履歴を確認中..." + "value": "ブラウザのアドレスバーで入力がURLでない場合に使用されます。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "正在检查浏览历史记录..." + "value": "浏览器地址栏中输入非 URL 内容时使用。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "正在檢查瀏覽歷史記錄..." + "value": "當瀏覽器網址列的輸入不是 URL 時使用。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "방문 기록을 확인하는 중..." - } - }, - "km": { - "stringUnit": { - "state": "translated", - "value": "កំពុងពិនិត្យប្រវត្តិរុករក..." + "value": "입력이 URL이 아닌 경우 브라우저 주소 표시줄에서 사용됩니다." } }, "de": { "stringUnit": { "state": "translated", - "value": "Browserverlauf wird geprüft..." + "value": "Wird von der Browser-Adressleiste verwendet, wenn die Eingabe keine URL ist." } }, "es": { "stringUnit": { "state": "translated", - "value": "Comprobando el historial de navegación..." + "value": "Usado por la barra de direcciones del navegador cuando la entrada no es una URL." } }, "fr": { "stringUnit": { "state": "translated", - "value": "Vérification de l'historique de navigation..." + "value": "Utilisé par la barre d'adresse du navigateur lorsque la saisie n'est pas une URL." } }, "it": { "stringUnit": { "state": "translated", - "value": "Controllo della cronologia di navigazione..." + "value": "Utilizzato dalla barra degli indirizzi del browser quando l'input non è un URL." } }, "da": { "stringUnit": { "state": "translated", - "value": "Kontrollerer browserhistorik..." + "value": "Bruges af browserens adresselinje, når input ikke er en URL." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Sprawdzanie historii przeglądania..." + "value": "Używana przez pasek adresu przeglądarki, gdy dane wejściowe nie są adresem URL." } }, "ru": { "stringUnit": { "state": "translated", - "value": "Проверка истории браузера..." + "value": "Используется адресной строкой браузера, когда ввод не является URL." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Provjerava se historija pregledanja..." + "value": "Koristi se u adresnoj traci preglednika kada unos nije URL." } }, "ar": { "stringUnit": { "state": "translated", - "value": "جارٍ التحقق من سجل التصفح..." + "value": "يُستخدم بواسطة شريط عنوان المتصفح عندما لا يكون الإدخال URL." } }, "nb": { "stringUnit": { "state": "translated", - "value": "Sjekker nettleserhistorikk..." + "value": "Brukes av adressefeltet i nettleseren når inndataen ikke er en URL." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Verificando histórico de navegação..." + "value": "Usado pela barra de endereço do navegador quando a entrada não é uma URL." } }, "th": { "stringUnit": { "state": "translated", - "value": "กำลังตรวจสอบประวัติการท่องเว็บ..." + "value": "ใช้โดยแถบที่อยู่เบราว์เซอร์เมื่ออินพุตไม่ใช่ URL" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Tarama geçmişi kontrol ediliyor..." + "value": "Giriş bir URL olmadığında tarayıcı adres çubuğu tarafından kullanılır." } }, "uk": { "stringUnit": { "state": "translated", - "value": "Перевірка історії браузера..." + "value": "Використовується адресним рядком браузера, коли введення не є URL." } } } }, - "settings.browser.history.subtitleMany": { + "settings.browser.searchSuggestions": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "%lld saved pages appear in omnibar suggestions." + "value": "Show Search Suggestions" } }, "ja": { "stringUnit": { "state": "translated", - "value": "%lld件の保存済みページがオムニバーの候補に表示されます。" + "value": "検索候補を表示" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "%lld 个已保存页面显示在地址栏建议中。" + "value": "显示搜索建议" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "%lld 個已儲存頁面會出現在網址列建議中。" + "value": "顯示搜尋建議" } }, "ko": { "stringUnit": { "state": "translated", - "value": "%lld개의 저장된 페이지가 옴니바 제안에 표시됩니다." + "value": "검색 제안 표시" } }, "de": { "stringUnit": { "state": "translated", - "value": "%lld gespeicherte Seiten erscheinen in den Adressleisten-Vorschlägen." + "value": "Suchvorschläge anzeigen" } }, "es": { "stringUnit": { "state": "translated", - "value": "%lld páginas guardadas aparecen en las sugerencias de la barra de direcciones." + "value": "Mostrar sugerencias de búsqueda" } }, "fr": { "stringUnit": { "state": "translated", - "value": "%lld pages enregistrées apparaissent dans les suggestions de la barre d'adresse." + "value": "Afficher les suggestions de recherche" } }, "it": { "stringUnit": { "state": "translated", - "value": "%lld pagine salvate appaiono nei suggerimenti della barra degli indirizzi." + "value": "Mostra suggerimenti di ricerca" } }, "da": { "stringUnit": { "state": "translated", - "value": "%lld gemte sider vises i omnibar-forslag." + "value": "Vis søgeforslag" } }, "pl": { "stringUnit": { "state": "translated", - "value": "%lld zapisanych stron pojawia się w podpowiedziach paska adresu." + "value": "Pokaż podpowiedzi wyszukiwania" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Сохраненных страниц: %lld. Отображаются в подсказках адресной строки." + "value": "Показывать поисковые подсказки" } }, "bs": { "stringUnit": { "state": "translated", - "value": "%lld sačuvanih stranica se pojavljuje u prijedlozima omnibara." + "value": "Prikaži prijedloge pretrage" } }, "ar": { "stringUnit": { "state": "translated", - "value": "%lld صفحة محفوظة تظهر في اقتراحات شريط العنوان." + "value": "عرض اقتراحات البحث" } }, "nb": { "stringUnit": { "state": "translated", - "value": "%lld lagrede sider vises i adressefeltforslag." + "value": "Vis søkeforslag" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "%lld páginas salvas aparecem nas sugestões da barra de endereço." + "value": "Mostrar Sugestões de Pesquisa" } }, "th": { "stringUnit": { "state": "translated", - "value": "%lld หน้าที่บันทึกจะปรากฏในคำแนะนำแถบที่อยู่" + "value": "แสดงคำแนะนำการค้นหา" } }, "tr": { "stringUnit": { "state": "translated", - "value": "%lld kayıtlı sayfa çok amaçlı çubuk önerilerinde görünür." + "value": "Arama Önerilerini Göster" } }, "uk": { "stringUnit": { "state": "translated", - "value": "%lld збережених сторінок з'являються у підказках адресного рядка." + "value": "Показувати підказки пошуку" } } } }, - "settings.browser.history.subtitleOne": { + "settings.browser.theme": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "1 saved page appears in omnibar suggestions." + "value": "Browser Theme" } }, "ja": { "stringUnit": { "state": "translated", - "value": "1件の保存済みページがオムニバーの候補に表示されます。" + "value": "ブラウザテーマ" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "1 个已保存页面显示在地址栏建议中。" + "value": "浏览器主题" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "1 個已儲存頁面會出現在網址列建議中。" + "value": "瀏覽器主題" } }, "ko": { "stringUnit": { "state": "translated", - "value": "1개의 저장된 페이지가 옴니바 제안에 표시됩니다." + "value": "브라우저 테마" } }, "de": { "stringUnit": { "state": "translated", - "value": "1 gespeicherte Seite erscheint in den Adressleisten-Vorschlägen." + "value": "Browser-Design" } }, "es": { "stringUnit": { "state": "translated", - "value": "1 página guardada aparece en las sugerencias de la barra de direcciones." + "value": "Tema del navegador" } }, "fr": { "stringUnit": { "state": "translated", - "value": "1 page enregistrée apparaît dans les suggestions de la barre d'adresse." + "value": "Thème du navigateur" } }, "it": { "stringUnit": { "state": "translated", - "value": "1 pagina salvata appare nei suggerimenti della barra degli indirizzi." + "value": "Tema del browser" } }, "da": { "stringUnit": { "state": "translated", - "value": "1 gemt side vises i omnibar-forslag." + "value": "Browsertema" } }, "pl": { "stringUnit": { "state": "translated", - "value": "1 zapisana strona pojawia się w podpowiedziach paska adresu." + "value": "Motyw przeglądarki" } }, "ru": { "stringUnit": { "state": "translated", - "value": "1 сохраненная страница отображается в подсказках адресной строки." + "value": "Тема браузера" } }, "bs": { "stringUnit": { "state": "translated", - "value": "1 sačuvana stranica se pojavljuje u prijedlozima omnibara." + "value": "Tema preglednika" } }, "ar": { "stringUnit": { "state": "translated", - "value": "صفحة محفوظة واحدة تظهر في اقتراحات شريط العنوان." + "value": "مظهر المتصفح" } }, "nb": { "stringUnit": { "state": "translated", - "value": "1 lagret side vises i adressefeltforslag." + "value": "Nettlesertema" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "1 página salva aparece nas sugestões da barra de endereço." + "value": "Tema do Navegador" } }, "th": { "stringUnit": { "state": "translated", - "value": "1 หน้าที่บันทึกจะปรากฏในคำแนะนำแถบที่อยู่" + "value": "ธีมเบราว์เซอร์" } }, "tr": { "stringUnit": { "state": "translated", - "value": "1 kayıtlı sayfa çok amaçlı çubuk önerilerinde görünür." + "value": "Tarayıcı Teması" } }, "uk": { "stringUnit": { "state": "translated", - "value": "1 збережена сторінка з'являється у підказках адресного рядка." + "value": "Тема браузера" } } } }, - "settings.browser.hostWhitelist": { + "settings.browser.theme.subtitleForced": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Hosts to Open in Embedded Browser" + "value": "%@ forces that color scheme for compatible pages." } }, "ja": { "stringUnit": { "state": "translated", - "value": "内蔵ブラウザで開くホスト" + "value": "%@は対応ページにそのカラースキームを強制します。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "在内嵌浏览器中打开的主机" + "value": "%@ 为兼容页面强制使用该配色方案。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "在內建瀏覽器中開啟的主機" + "value": "%@ 會為相容的頁面強制套用該色彩配置。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "내장 브라우저에서 열 호스트" + "value": "%@은(는) 호환 페이지에 해당 색상 구성표를 강제 적용합니다." } }, "de": { "stringUnit": { "state": "translated", - "value": "Hosts, die im integrierten Browser geöffnet werden" + "value": "%@ erzwingt dieses Farbschema für kompatible Seiten." } }, "es": { "stringUnit": { "state": "translated", - "value": "Hosts para abrir en el navegador integrado" + "value": "%@ fuerza ese esquema de colores para las páginas compatibles." } }, "fr": { "stringUnit": { "state": "translated", - "value": "Hôtes à ouvrir dans le navigateur intégré" + "value": "%@ impose ce jeu de couleurs aux pages compatibles." } }, "it": { "stringUnit": { "state": "translated", - "value": "Host da aprire nel browser integrato" + "value": "%@ impone quello schema di colori per le pagine compatibili." } }, "da": { "stringUnit": { "state": "translated", - "value": "Værter der åbnes i den indlejrede browser" + "value": "%@ tvinger det farveskema for kompatible sider." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Hosty do otwierania we wbudowanej przeglądarce" + "value": "%@ wymusza ten schemat kolorów dla zgodnych stron." } }, "ru": { "stringUnit": { "state": "translated", - "value": "Хосты для открытия во встроенном браузере" + "value": "%@ принудительно применяет эту цветовую схему для совместимых страниц." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Hostovi za otvaranje u ugrađenom pregledniku" + "value": "%@ nameće tu shemu boja za kompatibilne stranice." } }, "ar": { "stringUnit": { "state": "translated", - "value": "المضيفون للفتح في المتصفح المضمّن" + "value": "%@ يفرض نظام الألوان هذا للصفحات المتوافقة." } }, "nb": { "stringUnit": { "state": "translated", - "value": "Verter som åpnes i innebygd nettleser" + "value": "%@ tvinger det fargeskjemaet for kompatible sider." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Hosts para Abrir no Navegador Integrado" + "value": "%@ força esse esquema de cores para páginas compatíveis." } }, "th": { "stringUnit": { "state": "translated", - "value": "โฮสต์ที่เปิดในเบราว์เซอร์ในตัว" + "value": "%@ บังคับใช้โทนสีนั้นสำหรับหน้าที่รองรับ" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Gömülü Tarayıcıda Açılacak Ana Bilgisayarlar" + "value": "%@ uyumlu sayfalar için bu renk şemasını zorlar." } }, "uk": { "stringUnit": { "state": "translated", - "value": "Хости для відкриття у вбудованому браузері" + "value": "%@ примусово встановлює цю кольорову схему для сумісних сторінок." } } } }, - "settings.browser.hostWhitelist.subtitle": { + "settings.browser.theme.subtitleSystem": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Applies to terminal link clicks and intercepted `open https://...` calls. Only these hosts open in cmux. Others open in your default browser. One host or wildcard per line (for example: example.com, *.internal.example). Leave empty to open all hosts in cmux." + "value": "System follows app and macOS appearance." } }, "ja": { "stringUnit": { "state": "translated", - "value": "ターミナルのリンククリックおよびインターセプトされた`open https://...`呼び出しに適用されます。これらのホストのみcmuxで開きます。その他はデフォルトブラウザで開きます。1行に1つのホストまたはワイルドカード(例: example.com, *.internal.example)。空欄にするとすべてのホストをcmuxで開きます。" + "value": "システムはアプリとmacOSの外観に従います。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "适用于终端中的链接点击和拦截的 `open https://...` 调用。仅这些主机在 cmux 中打开,其他主机在默认浏览器中打开。每行一个主机或通配符(例如:example.com、*.internal.example)。留空则在 cmux 中打开所有主机。" + "value": "系统跟随应用和 macOS 外观。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "套用於終端機連結點擊和攔截的 `open https://...` 呼叫。僅這些主機會在 cmux 中開啟,其他主機會在您的預設瀏覽器中開啟。每行一個主機或萬用字元(例如:example.com、*.internal.example)。留空則在 cmux 中開啟所有主機。" + "value": "「系統」會跟隨 App 和 macOS 外觀。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "터미널 링크 클릭 및 인터셉트된 `open https://...` 호출에 적용됩니다. 이 호스트만 cmux에서 열립니다. 나머지는 기본 브라우저에서 열립니다. 한 줄에 하나의 호스트 또는 와일드카드 (예: example.com, *.internal.example). 비워두면 모든 호스트가 cmux에서 열립니다." + "value": "시스템은 앱 및 macOS 외관을 따릅니다." } }, "de": { "stringUnit": { "state": "translated", - "value": "Gilt für Klicks auf Terminal-Links und abgefangene `open https://...`-Aufrufe. Nur diese Hosts werden in cmux geöffnet. Andere werden in Ihrem Standardbrowser geöffnet. Ein Host oder Platzhalter pro Zeile (zum Beispiel: example.com, *.internal.example). Leer lassen, um alle Hosts in cmux zu öffnen." + "value": "System folgt der App- und macOS-Darstellung." } }, "es": { "stringUnit": { "state": "translated", - "value": "Se aplica a clics en enlaces del terminal y llamadas interceptadas de `open https://...`. Solo estos hosts se abren en cmux. Los demás se abren en tu navegador predeterminado. Un host o comodín por línea (por ejemplo: example.com, *.internal.example). Déjalo vacío para abrir todos los hosts en cmux." + "value": "Sistema sigue la apariencia de la app y macOS." } }, "fr": { "stringUnit": { "state": "translated", - "value": "S'applique aux clics sur les liens du terminal et aux appels `open https://...` interceptés. Seuls ces hôtes s'ouvrent dans cmux. Les autres s'ouvrent dans votre navigateur par défaut. Un hôte ou caractère générique par ligne (par exemple : example.com, *.internal.example). Laissez vide pour ouvrir tous les hôtes dans cmux." + "value": "Système suit l'apparence de l'app et de macOS." } }, "it": { "stringUnit": { "state": "translated", - "value": "Si applica ai clic sui link nel terminale e alle chiamate intercettate `open https://...`. Solo questi host si aprono in cmux. Gli altri si aprono nel browser predefinito. Un host o wildcard per riga (ad esempio: example.com, *.internal.example). Lascia vuoto per aprire tutti gli host in cmux." + "value": "Sistema segue l'aspetto dell'app e di macOS." } }, "da": { "stringUnit": { "state": "translated", - "value": "Gælder for terminallinksklik og opfangede `open https://...`-kald. Kun disse værter åbnes i cmux. Andre åbnes i din standardbrowser. Én vært eller wildcard pr. linje (f.eks.: example.com, *.internal.example). Lad stå tomt for at åbne alle værter i cmux." + "value": "System følger app- og macOS-udseende." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Dotyczy kliknięć linków w terminalu i przechwyconych wywołań `open https://...`. Tylko te hosty otwierają się w cmux. Pozostałe otwierają się w domyślnej przeglądarce. Jeden host lub wzorzec na wiersz (na przykład: example.com, *.internal.example). Pozostaw puste, aby otwierać wszystkie hosty w cmux." + "value": "Systemowy podąża za wyglądem aplikacji i macOS." } }, "ru": { "stringUnit": { "state": "translated", - "value": "Применяется к нажатиям на ссылки в терминале и перехваченным вызовам `open https://...`. Только эти хосты открываются в cmux. Остальные открываются в браузере по умолчанию. Один хост или шаблон на строку (например: example.com, *.internal.example). Оставьте пустым, чтобы открывать все хосты в cmux." + "value": "Системная тема следует за оформлением приложения и macOS." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Primjenjuje se na klikove linkova u terminalu i presretnute `open https://...` pozive. Samo se ovi hostovi otvaraju u cmux. Ostali se otvaraju u podrazumijevanom pregledniku. Jedan host ili zamjenski znak po redu (na primjer: example.com, *.internal.example). Ostavite prazno da otvorite sve hostove u cmux." + "value": "Sistemski prati izgled aplikacije i macOS." } }, "ar": { "stringUnit": { "state": "translated", - "value": "ينطبق على نقرات الروابط في الطرفية واستدعاءات `open https://...` المعترضة. فقط هؤلاء المضيفون يفتحون في cmux. البقية تفتح في متصفحك الافتراضي. مضيف واحد أو حرف بدل لكل سطر (مثال: example.com, *.internal.example). اتركه فارغًا لفتح جميع المضيفين في cmux." + "value": "النظام يتبع مظهر التطبيق و macOS." } }, "nb": { "stringUnit": { "state": "translated", - "value": "Gjelder for terminallenkeklikk og avlyttede `open https://...`-kall. Bare disse vertene åpnes i cmux. Andre åpnes i standard nettleser. Én vert eller jokertegn per linje (for eksempel: example.com, *.internal.example). La stå tom for å åpne alle verter i cmux." + "value": "System følger app- og macOS-utseende." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Aplica-se a cliques em links do terminal e chamadas interceptadas de `open https://...`. Apenas estes hosts abrem no cmux. Outros abrem no seu navegador padrão. Um host ou curinga por linha (por exemplo: example.com, *.internal.example). Deixe vazio para abrir todos os hosts no cmux." + "value": "Sistema segue a aparência do app e do macOS." } }, "th": { "stringUnit": { "state": "translated", - "value": "ใช้กับการคลิกลิงก์ในเทอร์มินัลและการดักจับคำสั่ง `open https://...` เฉพาะโฮสต์เหล่านี้เท่านั้นที่จะเปิดใน cmux โฮสต์อื่นจะเปิดในเบราว์เซอร์เริ่มต้นของคุณ โฮสต์หรือ wildcard หนึ่งรายการต่อบรรทัด (ตัวอย่าง: example.com, *.internal.example) เว้นว่างเพื่อเปิดโฮสต์ทั้งหมดใน cmux" + "value": "ระบบจะตามธีมแอปและรูปลักษณ์ macOS" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Terminal bağlantı tıklamalarına ve yakalanan `open https://...` çağrılarına uygulanır. Yalnızca bu ana bilgisayarlar cmux'ta açılır. Diğerleri varsayılan tarayıcınızda açılır. Satır başına bir ana bilgisayar veya joker karakter (örneğin: example.com, *.internal.example). Tüm ana bilgisayarları cmux'ta açmak için boş bırakın." + "value": "Sistem, uygulama ve macOS görünümünü takip eder." } }, "uk": { "stringUnit": { "state": "translated", - "value": "Застосовується до кліків на посилання в терміналі та перехоплених викликів `open https://...`. Тільки ці хости відкриваються в cmux. Інші відкриваються у стандартному браузері. Один хост або шаблон на рядок (наприклад: example.com, *.internal.example). Залиште порожнім, щоб відкривати всі хости в cmux." + "value": "Системна слідує за програмою та зовнішнім виглядом macOS." } } } }, - "settings.browser.httpAllowlist": { + "settings.material.contentBackground": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "HTTP Hosts Allowed in Embedded Browser" + "value": "Content Background" } }, "ja": { "stringUnit": { "state": "translated", - "value": "内蔵ブラウザで許可するHTTPホスト" + "value": "コンテンツ背景" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "内嵌浏览器中允许的 HTTP 主机" + "value": "内容背景" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "允許在內建瀏覽器中使用的 HTTP 主機" + "value": "內容背景" } }, "ko": { "stringUnit": { "state": "translated", - "value": "내장 브라우저에서 허용할 HTTP 호스트" + "value": "콘텐츠 배경" } }, "de": { "stringUnit": { "state": "translated", - "value": "HTTP-Hosts, die im integrierten Browser zugelassen sind" + "value": "Inhaltshintergrund" } }, "es": { "stringUnit": { "state": "translated", - "value": "Hosts HTTP permitidos en el navegador integrado" + "value": "Fondo de contenido" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Hôtes HTTP autorisés dans le navigateur intégré" + "value": "Arrière-plan du contenu" } }, "it": { "stringUnit": { "state": "translated", - "value": "Host HTTP consentiti nel browser integrato" + "value": "Sfondo contenuto" } }, "da": { "stringUnit": { "state": "translated", - "value": "HTTP-værter tilladt i den indlejrede browser" + "value": "Indholdsbaggrund" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Hosty HTTP dozwolone we wbudowanej przeglądarce" + "value": "Tło zawartości" } }, "ru": { "stringUnit": { "state": "translated", - "value": "HTTP-хосты, разрешенные во встроенном браузере" + "value": "Фон содержимого" } }, "bs": { "stringUnit": { "state": "translated", - "value": "HTTP hostovi dozvoljeni u ugrađenom pregledniku" + "value": "Pozadina sadržaja" } }, "ar": { "stringUnit": { "state": "translated", - "value": "مضيفو HTTP المسموح بهم في المتصفح المضمّن" + "value": "خلفية المحتوى" } }, "nb": { "stringUnit": { "state": "translated", - "value": "HTTP-verter tillatt i innebygd nettleser" + "value": "Innholdsbakgrunn" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Hosts HTTP Permitidos no Navegador Integrado" + "value": "Fundo de Conteúdo" } }, "th": { "stringUnit": { "state": "translated", - "value": "โฮสต์ HTTP ที่อนุญาตในเบราว์เซอร์ในตัว" + "value": "พื้นหลังเนื้อหา" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Gömülü Tarayıcıda İzin Verilen HTTP Ana Bilgisayarları" + "value": "İçerik Arka Planı" } }, "uk": { "stringUnit": { "state": "translated", - "value": "HTTP-хости, дозволені у вбудованому браузері" + "value": "Фон вмісту" } } } }, - "settings.browser.httpAllowlist.description": { + "settings.material.fullScreenUI": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Controls which HTTP (non-HTTPS) hosts can open in cmux without a warning prompt. Defaults include localhost, *.localhost, 127.0.0.1, ::1, 0.0.0.0, and *.localtest.me." + "value": "Full Screen UI" } }, "ja": { "stringUnit": { "state": "translated", - "value": "警告プロンプトなしでcmuxで開けるHTTP(非HTTPS)ホストを制御します。デフォルトにはlocalhost、*.localhost、127.0.0.1、::1、0.0.0.0、*.localtest.meが含まれます。" + "value": "フルスクリーンUI" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "控制哪些 HTTP(非 HTTPS)主机可以在 cmux 中打开而不显示警告提示。默认包括 localhost、*.localhost、127.0.0.1、::1、0.0.0.0 和 *.localtest.me。" + "value": "全屏 UI" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "控制哪些 HTTP(非 HTTPS)主機可以在 cmux 中開啟而不顯示警告提示。預設包含 localhost、*.localhost、127.0.0.1、::1、0.0.0.0 和 *.localtest.me。" + "value": "全螢幕 UI" } }, "ko": { "stringUnit": { "state": "translated", - "value": "cmux에서 경고 없이 열 수 있는 HTTP(비HTTPS) 호스트를 제어합니다. 기본값에는 localhost, *.localhost, 127.0.0.1, ::1, 0.0.0.0 및 *.localtest.me가 포함됩니다." + "value": "전체 화면 UI" } }, "de": { "stringUnit": { "state": "translated", - "value": "Steuert, welche HTTP-Hosts (nicht HTTPS) ohne Warnhinweis in cmux geöffnet werden können. Standardmäßig enthalten: localhost, *.localhost, 127.0.0.1, ::1, 0.0.0.0 und *.localtest.me." + "value": "Vollbild-UI" } }, "es": { "stringUnit": { "state": "translated", - "value": "Controla qué hosts HTTP (no HTTPS) pueden abrirse en cmux sin un mensaje de advertencia. Los valores predeterminados incluyen localhost, *.localhost, 127.0.0.1, ::1, 0.0.0.0 y *.localtest.me." + "value": "Interfaz a pantalla completa" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Contrôle quels hôtes HTTP (non HTTPS) peuvent s'ouvrir dans cmux sans avertissement. Les valeurs par défaut incluent localhost, *.localhost, 127.0.0.1, ::1, 0.0.0.0 et *.localtest.me." + "value": "Interface plein écran" } }, "it": { "stringUnit": { "state": "translated", - "value": "Controlla quali host HTTP (non HTTPS) possono aprirsi in cmux senza un avviso. I valori predefiniti includono localhost, *.localhost, 127.0.0.1, ::1, 0.0.0.0 e *.localtest.me." + "value": "UI a schermo intero" } }, "da": { "stringUnit": { "state": "translated", - "value": "Styrer hvilke HTTP-værter (ikke-HTTPS) der kan åbnes i cmux uden advarselsmeddelelse. Standardindstillinger inkluderer localhost, *.localhost, 127.0.0.1, ::1, 0.0.0.0 og *.localtest.me." + "value": "Fuldskærms-UI" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Określa, które hosty HTTP (inne niż HTTPS) mogą być otwierane w cmux bez ostrzeżenia. Domyślnie uwzględniono localhost, *.localhost, 127.0.0.1, ::1, 0.0.0.0 i *.localtest.me." + "value": "Pełnoekranowy interfejs" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Определяет, какие HTTP (не HTTPS) хосты могут открываться в cmux без предупреждения. По умолчанию включены localhost, *.localhost, 127.0.0.1, ::1, 0.0.0.0 и *.localtest.me." + "value": "Полноэкранный интерфейс" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Kontroliše koji HTTP (ne-HTTPS) hostovi mogu biti otvoreni u cmux bez upozorenja. Podrazumijevani uključuju localhost, *.localhost, 127.0.0.1, ::1, 0.0.0.0 i *.localtest.me." + "value": "UI punog ekrana" } }, "ar": { "stringUnit": { "state": "translated", - "value": "يتحكم في مضيفي HTTP (غير HTTPS) الذين يمكنهم الفتح في cmux بدون رسالة تحذير. الافتراضيات تشمل localhost و *.localhost و 127.0.0.1 و ::1 و 0.0.0.0 و *.localtest.me." + "value": "واجهة ملء الشاشة" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Styrer hvilke HTTP-verter (ikke HTTPS) som kan åpnes i cmux uten advarselsmelding. Standardverdier inkluderer localhost, *.localhost, 127.0.0.1, ::1, 0.0.0.0 og *.localtest.me." + "value": "Fullskjerm-UI" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Controla quais hosts HTTP (não HTTPS) podem abrir no cmux sem um aviso. Os padrões incluem localhost, *.localhost, 127.0.0.1, ::1, 0.0.0.0 e *.localtest.me." + "value": "Interface em Tela Cheia" } }, "th": { "stringUnit": { "state": "translated", - "value": "ควบคุมว่าโฮสต์ HTTP (ไม่ใช่ HTTPS) ใดที่สามารถเปิดใน cmux โดยไม่ต้องแสดงคำเตือน ค่าเริ่มต้นรวมถึง localhost, *.localhost, 127.0.0.1, ::1, 0.0.0.0 และ *.localtest.me" + "value": "UI เต็มหน้าจอ" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Hangi HTTP (HTTPS olmayan) ana bilgisayarlarının cmux'ta uyarı istemi olmadan açılabileceğini kontrol eder. Varsayılanlar localhost, *.localhost, 127.0.0.1, ::1, 0.0.0.0 ve *.localtest.me içerir." + "value": "Tam Ekran Kullanıcı Arayüzü" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Визначає, які HTTP (не HTTPS) хости можуть відкриватися в cmux без попередження. Типово включає localhost, *.localhost, 127.0.0.1, ::1, 0.0.0.0 та *.localtest.me." + "value": "Повноекранний інтерфейс" } } } }, - "settings.browser.httpAllowlist.hint": { + "settings.material.headerView": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "One host or wildcard per line (for example: localhost, *.localhost, 127.0.0.1, ::1, 0.0.0.0, *.localtest.me)." + "value": "Header View" } }, "ja": { "stringUnit": { "state": "translated", - "value": "1行に1つのホストまたはワイルドカード(例: localhost, *.localhost, 127.0.0.1, ::1, 0.0.0.0, *.localtest.me)。" + "value": "ヘッダビュー" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "每行一个主机或通配符(例如:localhost、*.localhost、127.0.0.1、::1、0.0.0.0、*.localtest.me)。" + "value": "头部视图" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "每行一個主機或萬用字元(例如:localhost、*.localhost、127.0.0.1、::1、0.0.0.0、*.localtest.me)。" + "value": "標題列" } }, "ko": { "stringUnit": { "state": "translated", - "value": "한 줄에 하나의 호스트 또는 와일드카드 (예: localhost, *.localhost, 127.0.0.1, ::1, 0.0.0.0, *.localtest.me)." + "value": "헤더 뷰" } }, "de": { "stringUnit": { "state": "translated", - "value": "Ein Host oder Platzhalter pro Zeile (zum Beispiel: localhost, *.localhost, 127.0.0.1, ::1, 0.0.0.0, *.localtest.me)." + "value": "Kopfansicht" } }, "es": { "stringUnit": { "state": "translated", - "value": "Un host o comodín por línea (por ejemplo: localhost, *.localhost, 127.0.0.1, ::1, 0.0.0.0, *.localtest.me)." + "value": "Vista de encabezado" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Un hôte ou caractère générique par ligne (par exemple : localhost, *.localhost, 127.0.0.1, ::1, 0.0.0.0, *.localtest.me)." + "value": "Vue d'en-tête" } }, "it": { "stringUnit": { "state": "translated", - "value": "Un host o wildcard per riga (ad esempio: localhost, *.localhost, 127.0.0.1, ::1, 0.0.0.0, *.localtest.me)." + "value": "Vista intestazione" } }, "da": { "stringUnit": { "state": "translated", - "value": "Én vært eller wildcard pr. linje (f.eks.: localhost, *.localhost, 127.0.0.1, ::1, 0.0.0.0, *.localtest.me)." + "value": "Headervisning" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Jeden host lub wzorzec na wiersz (na przykład: localhost, *.localhost, 127.0.0.1, ::1, 0.0.0.0, *.localtest.me)." + "value": "Widok nagłówka" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Один хост или шаблон на строку (например: localhost, *.localhost, 127.0.0.1, ::1, 0.0.0.0, *.localtest.me)." + "value": "Заголовок" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Jedan host ili zamjenski znak po redu (na primjer: localhost, *.localhost, 127.0.0.1, ::1, 0.0.0.0, *.localtest.me)." + "value": "Zaglavlje" } }, "ar": { "stringUnit": { "state": "translated", - "value": "مضيف واحد أو حرف بدل لكل سطر (مثال: localhost, *.localhost, 127.0.0.1, ::1, 0.0.0.0, *.localtest.me)." + "value": "عرض الرأس" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Én vert eller jokertegn per linje (for eksempel: localhost, *.localhost, 127.0.0.1, ::1, 0.0.0.0, *.localtest.me)." + "value": "Topptekstvisning" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Um host ou curinga por linha (por exemplo: localhost, *.localhost, 127.0.0.1, ::1, 0.0.0.0, *.localtest.me)." + "value": "Cabeçalho" } }, "th": { "stringUnit": { "state": "translated", - "value": "โฮสต์หรือ wildcard หนึ่งรายการต่อบรรทัด (ตัวอย่าง: localhost, *.localhost, 127.0.0.1, ::1, 0.0.0.0, *.localtest.me)" + "value": "มุมมองส่วนหัว" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Satır başına bir ana bilgisayar veya joker karakter (örneğin: localhost, *.localhost, 127.0.0.1, ::1, 0.0.0.0, *.localtest.me)." + "value": "Başlık Görünümü" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Один хост або шаблон на рядок (наприклад: localhost, *.localhost, 127.0.0.1, ::1, 0.0.0.0, *.localtest.me)." + "value": "Заголовок" } } } }, - "settings.browser.httpAllowlist.save": { + "settings.material.hudWindow": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Save" + "value": "HUD Window" } }, "ja": { "stringUnit": { "state": "translated", - "value": "保存" + "value": "HUDウインドウ" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "保存" + "value": "HUD 窗口" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "儲存" + "value": "HUD 視窗" } }, "ko": { "stringUnit": { "state": "translated", - "value": "저장" + "value": "HUD 윈도우" } }, "de": { "stringUnit": { "state": "translated", - "value": "Speichern" + "value": "HUD-Fenster" } }, "es": { "stringUnit": { "state": "translated", - "value": "Guardar" + "value": "Ventana HUD" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Enregistrer" + "value": "Fenêtre HUD" } }, "it": { "stringUnit": { "state": "translated", - "value": "Salva" + "value": "Finestra HUD" } }, "da": { "stringUnit": { "state": "translated", - "value": "Gem" + "value": "HUD-vindue" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Zapisz" + "value": "Okno HUD" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Сохранить" + "value": "HUD-окно" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Spremi" + "value": "HUD prozor" } }, "ar": { "stringUnit": { "state": "translated", - "value": "حفظ" + "value": "نافذة HUD" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Lagre" + "value": "HUD-vindu" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Salvar" + "value": "Janela HUD" } }, "th": { "stringUnit": { "state": "translated", - "value": "บันทึก" + "value": "หน้าต่าง HUD" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Kaydet" + "value": "HUD Penceresi" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Зберегти" - } - } - } - }, - "settings.betaFeatures.dock": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", "value": "Dock" } }, "ja": { "stringUnit": { "state": "translated", "value": "Dock" } } } }, - "settings.betaFeatures.dock.subtitleOff": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", "value": "Hides Dock from the right sidebar until you enable it here." } }, "ja": { "stringUnit": { "state": "translated", "value": "ここで有効にするまで、Dock を右サイドバーから隠します。" } } } }, - "settings.betaFeatures.dock.subtitleOn": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", "value": "Shows Dock in the right sidebar mode switcher for custom terminal controls." } }, "ja": { "stringUnit": { "state": "translated", "value": "Dock を右サイドバーのモード切り替えに表示し、カスタム端末コントロールを使えるようにします。" } } } }, - "settings.betaFeatures.warning": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", "value": "Dock is unstable and may change or break. Enable it only when you are testing it." } }, "ja": { "stringUnit": { "state": "translated", "value": "Dock は不安定で、変更されたり壊れたりする可能性があります。テストする場合だけ有効にしてください。" } } } }, - "settings.browser.enabled": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Enable cmux Browser" - } - }, - "ja": { - "stringUnit": { - "state": "translated", - "value": "cmuxブラウザを有効にする" - } - } - } - }, - "settings.browser.enabled.subtitleOff": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Browser tabs, terminal link clicks, and intercepted open commands are disabled. Links open in your default browser." - } - }, - "ja": { - "stringUnit": { - "state": "translated", - "value": "ブラウザタブ、ターミナルのリンククリック、インターセプトされたopenコマンドは無効です。リンクはデフォルトブラウザで開きます。" - } - } - } - }, - "settings.browser.enabled.subtitleOn": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Browser tabs, terminal link clicks, and intercepted open commands can use the embedded browser." - } - }, - "ja": { - "stringUnit": { - "state": "translated", - "value": "ブラウザタブ、ターミナルのリンククリック、インターセプトされたopenコマンドで内蔵ブラウザを使用できます。" + "value": "HUD-вікно" } } } }, - "settings.browser.hiddenWebViewDiscard": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", "value": "Browser Memory Saver" } }, "ja": { "stringUnit": { "state": "translated", "value": "ブラウザメモリセーバー" } } } }, - "settings.browser.hiddenWebViewDiscard.subtitleOff": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", "value": "Hidden browser tabs keep page memory until closed." } }, "ja": { "stringUnit": { "state": "translated", "value": "非表示のブラウザタブは、閉じるまでページメモリを保持します。" } } } }, - "settings.browser.hiddenWebViewDiscard.subtitleOn": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", "value": "Hidden browser tabs release page memory after the delay below, then restore when shown again." } }, "ja": { "stringUnit": { "state": "translated", "value": "非表示のブラウザタブは下の遅延後にページメモリを解放し、再表示時に復元します。" } } } }, - "settings.browser.hiddenWebViewDiscardDelay": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", "value": "Memory Saver Delay" } }, "ja": { "stringUnit": { "state": "translated", "value": "メモリセーバーの遅延" } } } }, - "settings.browser.hiddenWebViewDiscardDelay.minutes": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", "value": "%lldm" } }, "ja": { "stringUnit": { "state": "translated", "value": "%lld分" } } } }, - "settings.browser.hiddenWebViewDiscardDelay.minutesSeconds": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", "value": "%lldm %llds" } }, "ja": { "stringUnit": { "state": "translated", "value": "%lld分%lld秒" } } } }, - "settings.browser.hiddenWebViewDiscardDelay.seconds": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", "value": "%llds" } }, "ja": { "stringUnit": { "state": "translated", "value": "%lld秒" } } } }, - "settings.browser.hiddenWebViewDiscardDelay.subtitle": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", "value": "How long a browser tab must stay hidden before cmux frees its page memory. Active downloads, popups, developer tools, fullscreen, and loading pages are skipped." } }, "ja": { "stringUnit": { "state": "translated", "value": "ブラウザタブが非表示になってから、cmux がページメモリを解放するまでの時間です。進行中のダウンロード、ポップアップ、開発者ツール、フルスクリーン、読み込み中のページは対象外です。" } } } }, - "settings.browser.interceptOpen": { + "settings.material.liquidGlass": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Intercept open http(s) in Terminal" + "value": "Liquid Glass (macOS 26+)" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ターミナルでopen http(s)をインターセプト" + "value": "Liquid Glass(macOS 26以降)" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "在终端中拦截 open http(s)" + "value": "Liquid Glass (macOS 26+)" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "在終端機中攔截 open http(s)" + "value": "Liquid Glass (macOS 26+)" } }, "ko": { "stringUnit": { "state": "translated", - "value": "터미널에서 open http(s) 인터셉트" + "value": "Liquid Glass (macOS 26+)" } }, "de": { "stringUnit": { "state": "translated", - "value": "open http(s) im Terminal abfangen" + "value": "Liquid Glass (macOS 26+)" } }, "es": { "stringUnit": { "state": "translated", - "value": "Interceptar open http(s) en Terminal" + "value": "Liquid Glass (macOS 26+)" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Intercepter open http(s) dans le terminal" + "value": "Liquid Glass (macOS 26+)" } }, "it": { "stringUnit": { "state": "translated", - "value": "Intercetta open http(s) nel terminale" + "value": "Liquid Glass (macOS 26+)" } }, "da": { "stringUnit": { "state": "translated", - "value": "Opfang open http(s) i terminal" + "value": "Liquid Glass (macOS 26+)" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Przechwytuj open http(s) w terminalu" + "value": "Liquid Glass (macOS 26+)" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Перехватывать open http(s) в терминале" + "value": "Liquid Glass (macOS 26+)" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Presretni open http(s) u Terminalu" + "value": "Liquid Glass (macOS 26+)" } }, "ar": { "stringUnit": { "state": "translated", - "value": "اعتراض open http(s) في الطرفية" + "value": "Liquid Glass (macOS 26+)" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Avlytt open http(s) i terminal" + "value": "Liquid Glass (macOS 26+)" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Interceptar open http(s) no Terminal" + "value": "Liquid Glass (macOS 26+)" } }, "th": { "stringUnit": { "state": "translated", - "value": "ดักจับ open http(s) ในเทอร์มินัล" + "value": "Liquid Glass (macOS 26+)" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Terminalde open http(s) Komutlarını Yakala" + "value": "Liquid Glass (macOS 26+)" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Перехоплювати open http(s) у терміналі" + "value": "Liquid Glass (macOS 26+)" } } } }, - "settings.browser.interceptOpen.subtitle": { + "settings.material.menu": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "When off, `open https://...` and `open http://...` always use your default browser." + "value": "Menu" } }, "ja": { "stringUnit": { "state": "translated", - "value": "オフの場合、`open https://...`および`open http://...`は常にデフォルトブラウザを使用します。" + "value": "メニュー" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "关闭后,`open https://...` 和 `open http://...` 始终使用默认浏览器。" + "value": "菜单" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "關閉時,`open https://...` 和 `open http://...` 一律使用您的預設瀏覽器。" + "value": "選單" } }, "ko": { "stringUnit": { "state": "translated", - "value": "비활성화하면 `open https://...` 및 `open http://...`가 항상 기본 브라우저를 사용합니다." + "value": "메뉴" } }, "de": { "stringUnit": { "state": "translated", - "value": "Wenn deaktiviert, verwenden `open https://...` und `open http://...` immer Ihren Standardbrowser." + "value": "Menü" } }, "es": { "stringUnit": { "state": "translated", - "value": "Cuando está desactivado, `open https://...` y `open http://...` siempre usan tu navegador predeterminado." + "value": "Menú" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Lorsque désactivé, `open https://...` et `open http://...` utilisent toujours votre navigateur par défaut." + "value": "Menu" } }, "it": { "stringUnit": { "state": "translated", - "value": "Quando disattivato, `open https://...` e `open http://...` usano sempre il browser predefinito." + "value": "Menu" } }, "da": { "stringUnit": { "state": "translated", - "value": "Når deaktiveret, bruger `open https://...` og `open http://...` altid din standardbrowser." + "value": "Menu" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Po wyłączeniu `open https://...` i `open http://...` zawsze używają domyślnej przeglądarki." + "value": "Menu" } }, "ru": { "stringUnit": { "state": "translated", - "value": "При отключении `open https://...` и `open http://...` всегда используют браузер по умолчанию." + "value": "Меню" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Kada je isključeno, `open https://...` i `open http://...` uvijek koriste podrazumijevani preglednik." + "value": "Meni" } }, "ar": { "stringUnit": { "state": "translated", - "value": "عند التعطيل، يستخدم `open https://...` و `open http://...` دائمًا متصفحك الافتراضي." + "value": "القائمة" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Når av, bruker `open https://...` og `open http://...` alltid standard nettleser." + "value": "Meny" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Quando desativado, `open https://...` e `open http://...` sempre usam seu navegador padrão." + "value": "Menu" } }, "th": { "stringUnit": { "state": "translated", - "value": "เมื่อปิด `open https://...` และ `open http://...` จะใช้เบราว์เซอร์เริ่มต้นของคุณเสมอ" + "value": "เมนู" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Kapalıyken, `open https://...` ve `open http://...` her zaman varsayılan tarayıcınızı kullanır." + "value": "Menü" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Якщо вимкнено, `open https://...` та `open http://...` завжди використовують стандартний браузер." + "value": "Меню" } } } }, - "settings.browser.openTerminalLinks": { + "settings.material.none": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Open Terminal Links in cmux Browser" + "value": "None" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ターミナルのリンクをcmuxブラウザで開く" + "value": "なし" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "在 cmux 浏览器中打开终端链接" + "value": "无" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "在 cmux 瀏覽器中開啟終端機連結" + "value": "無" } }, "ko": { "stringUnit": { "state": "translated", - "value": "터미널 링크를 cmux 브라우저에서 열기" + "value": "없음" } }, "de": { "stringUnit": { "state": "translated", - "value": "Terminal-Links im cmux-Browser öffnen" + "value": "Keine" } }, "es": { "stringUnit": { "state": "translated", - "value": "Abrir enlaces del terminal en el navegador de cmux" + "value": "Ninguno" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Ouvrir les liens du terminal dans le navigateur cmux" + "value": "Aucun" } }, "it": { "stringUnit": { "state": "translated", - "value": "Apri link del terminale nel browser cmux" + "value": "Nessuno" } }, "da": { "stringUnit": { "state": "translated", - "value": "Åbn terminallinks i cmux-browser" + "value": "Ingen" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Otwieraj linki terminala w przeglądarce cmux" + "value": "Brak" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Открывать ссылки из терминала в браузере cmux" + "value": "Нет" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Otvori linkove terminala u cmux pregledniku" + "value": "Ništa" } }, "ar": { "stringUnit": { "state": "translated", - "value": "فتح روابط الطرفية في متصفح cmux" + "value": "بدون" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Åpne terminallenker i cmux-nettleser" + "value": "Ingen" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Abrir Links do Terminal no Navegador do cmux" + "value": "Nenhum" } }, "th": { "stringUnit": { "state": "translated", - "value": "เปิดลิงก์เทอร์มินัลในเบราว์เซอร์ cmux" + "value": "ไม่มี" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Terminal Bağlantılarını cmux Tarayıcısında Aç" + "value": "Yok" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Відкривати посилання терміналу у браузері cmux" + "value": "Немає" } } } }, - "settings.browser.openTerminalLinks.subtitle": { + "settings.material.popover": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "When off, links clicked in terminal output open in your default browser." + "value": "Popover" } }, "ja": { "stringUnit": { "state": "translated", - "value": "オフの場合、ターミナル出力のリンクはデフォルトブラウザで開きます。" + "value": "ポップオーバー" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "关闭后,终端输出中点击的链接在默认浏览器中打开。" + "value": "弹出框" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "關閉時,終端機輸出中點擊的連結會在您的預設瀏覽器中開啟。" + "value": "彈出框" } }, "ko": { "stringUnit": { "state": "translated", - "value": "비활성화하면 터미널 출력에서 클릭한 링크가 기본 브라우저에서 열립니다." + "value": "팝오버" } }, "de": { "stringUnit": { "state": "translated", - "value": "Wenn deaktiviert, werden im Terminal angeklickte Links in Ihrem Standardbrowser geöffnet." + "value": "Popover" } }, "es": { "stringUnit": { "state": "translated", - "value": "Cuando está desactivado, los enlaces en la salida del terminal se abren en tu navegador predeterminado." + "value": "Popover" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Lorsque désactivé, les liens cliqués dans la sortie du terminal s'ouvrent dans votre navigateur par défaut." + "value": "Popover" } }, "it": { "stringUnit": { "state": "translated", - "value": "Quando disattivato, i link cliccati nell'output del terminale si aprono nel browser predefinito." + "value": "Popover" } }, "da": { "stringUnit": { "state": "translated", - "value": "Når deaktiveret, åbnes links, der klikkes i terminaloutput, i din standardbrowser." + "value": "Popover" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Po wyłączeniu linki kliknięte w terminalu otwierają się w domyślnej przeglądarce." + "value": "Wyskakujące okno" } }, "ru": { "stringUnit": { "state": "translated", - "value": "При отключении ссылки из терминала открываются в браузере по умолчанию." + "value": "Всплывающее окно" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Kada je isključeno, linkovi kliknuti u izlazu terminala se otvaraju u podrazumijevanom pregledniku." + "value": "Iskočni prozor" } }, "ar": { "stringUnit": { "state": "translated", - "value": "عند التعطيل، تفتح الروابط المنقورة في مخرجات الطرفية في متصفحك الافتراضي." + "value": "نافذة منبثقة" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Når av, åpnes lenker som klikkes i terminalutdata i standard nettleser." + "value": "Popover" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Quando desativado, links clicados na saída do terminal abrem no seu navegador padrão." + "value": "Popover" } }, "th": { "stringUnit": { "state": "translated", - "value": "เมื่อปิด ลิงก์ที่คลิกในเอาต์พุตเทอร์มินัลจะเปิดในเบราว์เซอร์เริ่มต้นของคุณ" + "value": "ป็อปโอเวอร์" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Kapalıyken, terminal çıktısında tıklanan bağlantılar varsayılan tarayıcınızda açılır." + "value": "Açılır Pencere" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Якщо вимкнено, посилання у виводі терміналу відкриваються у стандартному браузері." + "value": "Спливне вікно" } } } }, - "settings.browser.searchEngine": { + "settings.material.sheet": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Default Search Engine" + "value": "Sheet" } }, "ja": { "stringUnit": { "state": "translated", - "value": "デフォルト検索エンジン" + "value": "シート" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "默认搜索引擎" + "value": "工作表" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "預設搜尋引擎" + "value": "工作表" } }, "ko": { "stringUnit": { "state": "translated", - "value": "기본 검색 엔진" + "value": "시트" } }, "de": { "stringUnit": { "state": "translated", - "value": "Standardsuchmaschine" + "value": "Dialogblatt" } }, "es": { "stringUnit": { "state": "translated", - "value": "Motor de búsqueda predeterminado" + "value": "Hoja" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Moteur de recherche par défaut" + "value": "Feuille" } }, "it": { "stringUnit": { "state": "translated", - "value": "Motore di ricerca predefinito" + "value": "Foglio" } }, "da": { "stringUnit": { "state": "translated", - "value": "Standardsøgemaskine" + "value": "Ark" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Domyślna wyszukiwarka" + "value": "Arkusz" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Поисковая система по умолчанию" + "value": "Лист" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Podrazumijevani pretraživač" + "value": "List" } }, "ar": { "stringUnit": { "state": "translated", - "value": "محرك البحث الافتراضي" + "value": "ورقة" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Standard søkemotor" + "value": "Ark" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Motor de Busca Padrão" + "value": "Folha" } }, "th": { "stringUnit": { "state": "translated", - "value": "เครื่องมือค้นหาเริ่มต้น" + "value": "ชีท" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Varsayılan Arama Motoru" + "value": "Sayfa" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Стандартна пошукова система" + "value": "Аркуш" } } } }, - "settings.browser.searchEngine.subtitle": { + "settings.material.sidebar": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Used by the browser address bar when input is not a URL." + "value": "Sidebar" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ブラウザのアドレスバーで入力がURLでない場合に使用されます。" + "value": "サイドバー" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "浏览器地址栏中输入非 URL 内容时使用。" + "value": "侧边栏" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "當瀏覽器網址列的輸入不是 URL 時使用。" + "value": "側邊欄" } }, "ko": { "stringUnit": { "state": "translated", - "value": "입력이 URL이 아닌 경우 브라우저 주소 표시줄에서 사용됩니다." + "value": "사이드바" } }, "de": { "stringUnit": { "state": "translated", - "value": "Wird von der Browser-Adressleiste verwendet, wenn die Eingabe keine URL ist." + "value": "Seitenleiste" } }, "es": { "stringUnit": { "state": "translated", - "value": "Usado por la barra de direcciones del navegador cuando la entrada no es una URL." + "value": "Barra lateral" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Utilisé par la barre d'adresse du navigateur lorsque la saisie n'est pas une URL." + "value": "Barre latérale" } }, "it": { "stringUnit": { "state": "translated", - "value": "Utilizzato dalla barra degli indirizzi del browser quando l'input non è un URL." + "value": "Barra laterale" } }, "da": { "stringUnit": { "state": "translated", - "value": "Bruges af browserens adresselinje, når input ikke er en URL." + "value": "Sidebjælke" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Używana przez pasek adresu przeglądarki, gdy dane wejściowe nie są adresem URL." + "value": "Pasek boczny" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Используется адресной строкой браузера, когда ввод не является URL." + "value": "Боковая панель" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Koristi se u adresnoj traci preglednika kada unos nije URL." + "value": "Bočna traka" } }, "ar": { "stringUnit": { "state": "translated", - "value": "يُستخدم بواسطة شريط عنوان المتصفح عندما لا يكون الإدخال URL." + "value": "الشريط الجانبي" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Brukes av adressefeltet i nettleseren når inndataen ikke er en URL." + "value": "Sidepanel" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Usado pela barra de endereço do navegador quando a entrada não é uma URL." + "value": "Barra Lateral" } }, "th": { "stringUnit": { "state": "translated", - "value": "ใช้โดยแถบที่อยู่เบราว์เซอร์เมื่ออินพุตไม่ใช่ URL" + "value": "แถบด้านข้าง" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Giriş bir URL olmadığında tarayıcı adres çubuğu tarafından kullanılır." + "value": "Kenar Çubuğu" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Використовується адресним рядком браузера, коли введення не є URL." + "value": "Бічна панель" } } } }, - "settings.browser.searchSuggestions": { + "settings.material.toolTip": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Show Search Suggestions" + "value": "Tool Tip" } }, "ja": { "stringUnit": { "state": "translated", - "value": "検索候補を表示" + "value": "ツールチップ" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "显示搜索建议" + "value": "工具提示" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "顯示搜尋建議" + "value": "工具提示" } }, "ko": { "stringUnit": { "state": "translated", - "value": "검색 제안 표시" + "value": "도구 설명" } }, "de": { "stringUnit": { "state": "translated", - "value": "Suchvorschläge anzeigen" + "value": "Tooltip" } }, "es": { "stringUnit": { "state": "translated", - "value": "Mostrar sugerencias de búsqueda" + "value": "Descripción emergente" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Afficher les suggestions de recherche" + "value": "Info-bulle" } }, "it": { "stringUnit": { "state": "translated", - "value": "Mostra suggerimenti di ricerca" + "value": "Suggerimento" } }, "da": { "stringUnit": { "state": "translated", - "value": "Vis søgeforslag" + "value": "Værktøjstip" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Pokaż podpowiedzi wyszukiwania" + "value": "Podpowiedź" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Показывать поисковые подсказки" + "value": "Подсказка" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Prikaži prijedloge pretrage" + "value": "Opis alata" } }, "ar": { "stringUnit": { "state": "translated", - "value": "عرض اقتراحات البحث" + "value": "تلميح أداة" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Vis søkeforslag" + "value": "Verktøytips" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Mostrar Sugestões de Pesquisa" + "value": "Dica de Ferramenta" } }, "th": { "stringUnit": { "state": "translated", - "value": "แสดงคำแนะนำการค้นหา" + "value": "คำแนะนำเครื่องมือ" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Arama Önerilerini Göster" + "value": "Araç İpucu" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Показувати підказки пошуку" + "value": "Підказка" } } } }, - "settings.browser.theme": { + "settings.material.underWindow": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Browser Theme" + "value": "Under Window" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ブラウザテーマ" + "value": "ウインドウ下" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "浏览器主题" + "value": "窗口底部" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "瀏覽器主題" + "value": "視窗下方" } }, "ko": { "stringUnit": { "state": "translated", - "value": "브라우저 테마" + "value": "윈도우 아래" } }, "de": { "stringUnit": { "state": "translated", - "value": "Browser-Design" + "value": "Unter dem Fenster" } }, "es": { "stringUnit": { "state": "translated", - "value": "Tema del navegador" + "value": "Debajo de la ventana" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Thème du navigateur" + "value": "Sous la fenêtre" } }, "it": { "stringUnit": { "state": "translated", - "value": "Tema del browser" + "value": "Sotto la finestra" } }, "da": { "stringUnit": { "state": "translated", - "value": "Browsertema" + "value": "Under vindue" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Motyw przeglądarki" + "value": "Pod oknem" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Тема браузера" + "value": "Под окном" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Tema preglednika" + "value": "Ispod prozora" } }, "ar": { "stringUnit": { "state": "translated", - "value": "مظهر المتصفح" + "value": "تحت النافذة" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Nettlesertema" + "value": "Under vinduet" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Tema do Navegador" + "value": "Sob a Janela" } }, "th": { "stringUnit": { "state": "translated", - "value": "ธีมเบราว์เซอร์" + "value": "ใต้หน้าต่าง" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Tarayıcı Teması" + "value": "Pencere Altı" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Тема браузера" + "value": "Під вікном" } } } }, - "settings.browser.theme.subtitleForced": { + "settings.material.windowBackground": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "%@ forces that color scheme for compatible pages." + "value": "Window Background" } }, "ja": { "stringUnit": { "state": "translated", - "value": "%@は対応ページにそのカラースキームを強制します。" + "value": "ウインドウ背景" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "%@ 为兼容页面强制使用该配色方案。" + "value": "窗口背景" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "%@ 會為相容的頁面強制套用該色彩配置。" + "value": "視窗背景" } }, "ko": { "stringUnit": { "state": "translated", - "value": "%@은(는) 호환 페이지에 해당 색상 구성표를 강제 적용합니다." + "value": "윈도우 배경" } }, "de": { "stringUnit": { "state": "translated", - "value": "%@ erzwingt dieses Farbschema für kompatible Seiten." + "value": "Fensterhintergrund" } }, "es": { "stringUnit": { "state": "translated", - "value": "%@ fuerza ese esquema de colores para las páginas compatibles." + "value": "Fondo de ventana" } }, "fr": { "stringUnit": { "state": "translated", - "value": "%@ impose ce jeu de couleurs aux pages compatibles." + "value": "Arrière-plan de la fenêtre" } }, "it": { "stringUnit": { "state": "translated", - "value": "%@ impone quello schema di colori per le pagine compatibili." + "value": "Sfondo finestra" } }, "da": { "stringUnit": { "state": "translated", - "value": "%@ tvinger det farveskema for kompatible sider." + "value": "Vinduesbaggrund" } }, "pl": { "stringUnit": { "state": "translated", - "value": "%@ wymusza ten schemat kolorów dla zgodnych stron." + "value": "Tło okna" } }, "ru": { "stringUnit": { "state": "translated", - "value": "%@ принудительно применяет эту цветовую схему для совместимых страниц." + "value": "Фон окна" } }, "bs": { "stringUnit": { "state": "translated", - "value": "%@ nameće tu shemu boja za kompatibilne stranice." + "value": "Pozadina prozora" } }, "ar": { "stringUnit": { "state": "translated", - "value": "%@ يفرض نظام الألوان هذا للصفحات المتوافقة." + "value": "خلفية النافذة" } }, "nb": { "stringUnit": { "state": "translated", - "value": "%@ tvinger det fargeskjemaet for kompatible sider." + "value": "Vindubakgrunn" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "%@ força esse esquema de cores para páginas compatíveis." + "value": "Fundo da Janela" } }, "th": { "stringUnit": { "state": "translated", - "value": "%@ บังคับใช้โทนสีนั้นสำหรับหน้าที่รองรับ" + "value": "พื้นหลังหน้าต่าง" } }, "tr": { "stringUnit": { "state": "translated", - "value": "%@ uyumlu sayfalar için bu renk şemasını zorlar." + "value": "Pencere Arka Planı" } }, "uk": { "stringUnit": { "state": "translated", - "value": "%@ примусово встановлює цю кольорову схему для сумісних сторінок." + "value": "Фон вікна" } } } }, - "settings.browser.theme.subtitleSystem": { + "settings.preset.hudGlass": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "System follows app and macOS appearance." + "value": "HUD Glass" } }, "ja": { "stringUnit": { "state": "translated", - "value": "システムはアプリとmacOSの外観に従います。" + "value": "HUD Glass" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "系统跟随应用和 macOS 外观。" + "value": "HUD 玻璃" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "「系統」會跟隨 App 和 macOS 外觀。" + "value": "HUD 玻璃" } }, "ko": { "stringUnit": { "state": "translated", - "value": "시스템은 앱 및 macOS 외관을 따릅니다." + "value": "HUD 글래스" } }, "de": { "stringUnit": { "state": "translated", - "value": "System folgt der App- und macOS-Darstellung." + "value": "HUD Glass" } }, "es": { "stringUnit": { "state": "translated", - "value": "Sistema sigue la apariencia de la app y macOS." + "value": "HUD Glass" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Système suit l'apparence de l'app et de macOS." + "value": "HUD Glass" } }, "it": { "stringUnit": { "state": "translated", - "value": "Sistema segue l'aspetto dell'app e di macOS." + "value": "HUD Glass" } }, "da": { "stringUnit": { "state": "translated", - "value": "System følger app- og macOS-udseende." + "value": "HUD-glas" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Systemowy podąża za wyglądem aplikacji i macOS." + "value": "Szkło HUD" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Системная тема следует за оформлением приложения и macOS." + "value": "HUD Glass" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Sistemski prati izgled aplikacije i macOS." + "value": "HUD staklo" } }, "ar": { "stringUnit": { "state": "translated", - "value": "النظام يتبع مظهر التطبيق و macOS." + "value": "زجاج HUD" } }, "nb": { "stringUnit": { "state": "translated", - "value": "System følger app- og macOS-utseende." + "value": "HUD-glass" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Sistema segue a aparência do app e do macOS." + "value": "Vidro HUD" } }, "th": { "stringUnit": { "state": "translated", - "value": "ระบบจะตามธีมแอปและรูปลักษณ์ macOS" + "value": "HUD Glass" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Sistem, uygulama ve macOS görünümünü takip eder." + "value": "HUD Glass" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Системна слідує за програмою та зовнішнім виглядом macOS." + "value": "HUD Glass" } } } }, - "settings.material.contentBackground": { + "settings.preset.nativeSidebar": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Content Background" + "value": "Native Sidebar" } }, "ja": { "stringUnit": { "state": "translated", - "value": "コンテンツ背景" + "value": "ネイティブサイドバー" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "内容背景" + "value": "原生侧边栏" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "內容背景" + "value": "原生側邊欄" } }, "ko": { "stringUnit": { "state": "translated", - "value": "콘텐츠 배경" + "value": "기본 사이드바" } }, "de": { "stringUnit": { "state": "translated", - "value": "Inhaltshintergrund" + "value": "Native Seitenleiste" } }, "es": { "stringUnit": { "state": "translated", - "value": "Fondo de contenido" + "value": "Barra lateral nativa" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Arrière-plan du contenu" + "value": "Barre latérale native" } }, "it": { "stringUnit": { "state": "translated", - "value": "Sfondo contenuto" + "value": "Barra laterale nativa" } }, "da": { "stringUnit": { "state": "translated", - "value": "Indholdsbaggrund" + "value": "Indbygget sidebjælke" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Tło zawartości" + "value": "Natywny pasek boczny" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Фон содержимого" + "value": "Системная боковая панель" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Pozadina sadržaja" + "value": "Nativna bočna traka" } }, "ar": { "stringUnit": { "state": "translated", - "value": "خلفية المحتوى" + "value": "شريط جانبي أصلي" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Innholdsbakgrunn" + "value": "Innebygd sidepanel" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Fundo de Conteúdo" + "value": "Barra Lateral Nativa" } }, "th": { "stringUnit": { "state": "translated", - "value": "พื้นหลังเนื้อหา" + "value": "แถบด้านข้างแบบดั้งเดิม" } }, "tr": { "stringUnit": { "state": "translated", - "value": "İçerik Arka Planı" + "value": "Yerel Kenar Çubuğu" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Фон вмісту" + "value": "Рідна бічна панель" } } } }, - "settings.material.fullScreenUI": { + "settings.preset.popoverGlass": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Full Screen UI" + "value": "Popover Glass" } }, "ja": { "stringUnit": { "state": "translated", - "value": "フルスクリーンUI" + "value": "ポップオーバーGlass" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "全屏 UI" + "value": "弹出框玻璃" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "全螢幕 UI" + "value": "彈出框玻璃" } }, "ko": { "stringUnit": { "state": "translated", - "value": "전체 화면 UI" + "value": "팝오버 글래스" } }, "de": { "stringUnit": { "state": "translated", - "value": "Vollbild-UI" + "value": "Popover Glass" } }, "es": { "stringUnit": { "state": "translated", - "value": "Interfaz a pantalla completa" + "value": "Popover Glass" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Interface plein écran" + "value": "Popover Glass" } }, "it": { "stringUnit": { "state": "translated", - "value": "UI a schermo intero" + "value": "Popover Glass" } }, "da": { "stringUnit": { "state": "translated", - "value": "Fuldskærms-UI" + "value": "Popover-glas" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Pełnoekranowy interfejs" + "value": "Szkło wyskakujące" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Полноэкранный интерфейс" + "value": "Popover Glass" } }, "bs": { "stringUnit": { "state": "translated", - "value": "UI punog ekrana" + "value": "Iskočno staklo" } }, "ar": { "stringUnit": { "state": "translated", - "value": "واجهة ملء الشاشة" + "value": "زجاج منبثق" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Fullskjerm-UI" + "value": "Popover-glass" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Interface em Tela Cheia" + "value": "Vidro Popover" } }, "th": { "stringUnit": { "state": "translated", - "value": "UI เต็มหน้าจอ" + "value": "Popover Glass" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Tam Ekran Kullanıcı Arayüzü" + "value": "Açılır Pencere Glass" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Повноекранний інтерфейс" + "value": "Popover Glass" } } } }, - "settings.material.headerView": { + "settings.preset.raycastGray": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Header View" + "value": "Raycast Gray" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ヘッダビュー" + "value": "Raycast Gray" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "头部视图" + "value": "Raycast 灰" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "標題列" + "value": "Raycast 灰" } }, "ko": { "stringUnit": { "state": "translated", - "value": "헤더 뷰" + "value": "Raycast 그레이" } }, "de": { "stringUnit": { "state": "translated", - "value": "Kopfansicht" + "value": "Raycast Gray" } }, "es": { "stringUnit": { "state": "translated", - "value": "Vista de encabezado" + "value": "Raycast Gray" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Vue d'en-tête" + "value": "Raycast Gray" } }, "it": { "stringUnit": { "state": "translated", - "value": "Vista intestazione" + "value": "Raycast Gray" } }, "da": { "stringUnit": { "state": "translated", - "value": "Headervisning" + "value": "Raycast-grå" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Widok nagłówka" + "value": "Szary Raycast" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Заголовок" + "value": "Raycast Gray" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Zaglavlje" + "value": "Raycast siva" } }, "ar": { "stringUnit": { "state": "translated", - "value": "عرض الرأس" + "value": "رمادي Raycast" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Topptekstvisning" + "value": "Raycast-grå" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Cabeçalho" + "value": "Cinza Raycast" } }, "th": { "stringUnit": { "state": "translated", - "value": "มุมมองส่วนหัว" + "value": "Raycast Gray" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Başlık Görünümü" + "value": "Raycast Gri" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Заголовок" + "value": "Raycast Gray" } } } }, - "settings.material.hudWindow": { + "settings.preset.softBlur": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "HUD Window" + "value": "Soft Blur" } }, "ja": { "stringUnit": { "state": "translated", - "value": "HUDウインドウ" + "value": "ソフトブラー" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "HUD 窗口" + "value": "柔和模糊" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "HUD 視窗" + "value": "柔和模糊" } }, "ko": { "stringUnit": { "state": "translated", - "value": "HUD 윈도우" + "value": "소프트 블러" } }, "de": { "stringUnit": { "state": "translated", - "value": "HUD-Fenster" + "value": "Soft Blur" } }, "es": { "stringUnit": { "state": "translated", - "value": "Ventana HUD" + "value": "Soft Blur" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Fenêtre HUD" + "value": "Soft Blur" } }, "it": { "stringUnit": { "state": "translated", - "value": "Finestra HUD" + "value": "Soft Blur" } }, "da": { "stringUnit": { "state": "translated", - "value": "HUD-vindue" + "value": "Blød sløring" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Okno HUD" + "value": "Delikatne rozmycie" } }, "ru": { "stringUnit": { "state": "translated", - "value": "HUD-окно" + "value": "Soft Blur" } }, "bs": { "stringUnit": { "state": "translated", - "value": "HUD prozor" + "value": "Meko zamućenje" } }, "ar": { "stringUnit": { "state": "translated", - "value": "نافذة HUD" + "value": "ضبابية ناعمة" } }, "nb": { "stringUnit": { "state": "translated", - "value": "HUD-vindu" + "value": "Myk uskarphet" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Janela HUD" + "value": "Desfoque Suave" } }, "th": { "stringUnit": { "state": "translated", - "value": "หน้าต่าง HUD" + "value": "Soft Blur" } }, "tr": { "stringUnit": { "state": "translated", - "value": "HUD Penceresi" + "value": "Yumuşak Bulanıklık" } }, "uk": { "stringUnit": { "state": "translated", - "value": "HUD-вікно" + "value": "Soft Blur" } } } }, - "settings.material.liquidGlass": { + "settings.preset.underWindow": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Liquid Glass (macOS 26+)" + "value": "Under Window" } }, "ja": { "stringUnit": { "state": "translated", - "value": "Liquid Glass(macOS 26以降)" + "value": "ウインドウ下" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "Liquid Glass (macOS 26+)" + "value": "窗口底部" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "Liquid Glass (macOS 26+)" + "value": "視窗下方" } }, "ko": { "stringUnit": { "state": "translated", - "value": "Liquid Glass (macOS 26+)" + "value": "윈도우 아래" } }, "de": { "stringUnit": { "state": "translated", - "value": "Liquid Glass (macOS 26+)" + "value": "Under Window" } }, "es": { "stringUnit": { "state": "translated", - "value": "Liquid Glass (macOS 26+)" + "value": "Under Window" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Liquid Glass (macOS 26+)" + "value": "Under Window" } }, "it": { "stringUnit": { "state": "translated", - "value": "Liquid Glass (macOS 26+)" + "value": "Under Window" } }, "da": { "stringUnit": { "state": "translated", - "value": "Liquid Glass (macOS 26+)" + "value": "Under vindue" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Liquid Glass (macOS 26+)" + "value": "Pod oknem" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Liquid Glass (macOS 26+)" + "value": "Under Window" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Liquid Glass (macOS 26+)" + "value": "Ispod prozora" } }, "ar": { "stringUnit": { "state": "translated", - "value": "Liquid Glass (macOS 26+)" + "value": "تحت النافذة" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Liquid Glass (macOS 26+)" + "value": "Under vinduet" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Liquid Glass (macOS 26+)" + "value": "Sob a Janela" } }, "th": { "stringUnit": { "state": "translated", - "value": "Liquid Glass (macOS 26+)" + "value": "Under Window" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Liquid Glass (macOS 26+)" + "value": "Pencere Altı" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Liquid Glass (macOS 26+)" + "value": "Under Window" } } } }, - "settings.material.menu": { + "settings.reset.resetAll": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Menu" + "value": "Reset All Settings" } }, "ja": { "stringUnit": { "state": "translated", - "value": "メニュー" + "value": "すべての設定をリセット" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "菜单" + "value": "重置所有设置" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "選單" + "value": "重置所有設定" } }, "ko": { "stringUnit": { "state": "translated", - "value": "메뉴" + "value": "모든 설정 초기화" } }, "de": { "stringUnit": { "state": "translated", - "value": "Menü" + "value": "Alle Einstellungen zurücksetzen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Menú" + "value": "Restablecer todos los ajustes" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Menu" + "value": "Réinitialiser tous les réglages" } }, "it": { "stringUnit": { "state": "translated", - "value": "Menu" + "value": "Ripristina tutte le impostazioni" } }, "da": { "stringUnit": { "state": "translated", - "value": "Menu" + "value": "Nulstil alle indstillinger" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Menu" + "value": "Resetuj wszystkie ustawienia" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Меню" + "value": "Сбросить все настройки" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Meni" + "value": "Resetuj sve postavke" } }, "ar": { "stringUnit": { "state": "translated", - "value": "القائمة" + "value": "إعادة تعيين جميع الإعدادات" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Meny" + "value": "Tilbakestill alle innstillinger" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Menu" + "value": "Redefinir Todos os Ajustes" } }, "th": { "stringUnit": { "state": "translated", - "value": "เมนู" + "value": "รีเซ็ตการตั้งค่าทั้งหมด" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Menü" + "value": "Tüm Ayarları Sıfırla" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Меню" + "value": "Скинути всі налаштування" } } } }, - "settings.material.none": { + "settings.section.app": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "None" + "value": "App" } }, "ja": { "stringUnit": { "state": "translated", - "value": "なし" + "value": "アプリ" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "无" + "value": "应用" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "無" + "value": "App" } }, "ko": { "stringUnit": { "state": "translated", - "value": "없음" + "value": "앱" } }, "de": { "stringUnit": { "state": "translated", - "value": "Keine" + "value": "App" } }, "es": { "stringUnit": { "state": "translated", - "value": "Ninguno" + "value": "App" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Aucun" + "value": "App" } }, "it": { "stringUnit": { "state": "translated", - "value": "Nessuno" + "value": "App" } }, "da": { "stringUnit": { "state": "translated", - "value": "Ingen" + "value": "App" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Brak" + "value": "Aplikacja" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Нет" + "value": "Приложение" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Ništa" + "value": "Aplikacija" } }, "ar": { "stringUnit": { "state": "translated", - "value": "بدون" + "value": "التطبيق" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Ingen" + "value": "App" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Nenhum" + "value": "App" } }, "th": { "stringUnit": { "state": "translated", - "value": "ไม่มี" + "value": "แอป" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Yok" + "value": "Uygulama" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Немає" + "value": "Програма" } } } }, - "settings.material.popover": { + "settings.section.automation": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Popover" + "value": "Automation" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ポップオーバー" + "value": "オートメーション" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "弹出框" + "value": "自动化" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "彈出框" + "value": "自動化" } }, "ko": { "stringUnit": { "state": "translated", - "value": "팝오버" + "value": "자동화" } }, "de": { "stringUnit": { "state": "translated", - "value": "Popover" + "value": "Automatisierung" } }, "es": { "stringUnit": { "state": "translated", - "value": "Popover" + "value": "Automatización" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Popover" + "value": "Automatisation" } }, "it": { "stringUnit": { "state": "translated", - "value": "Popover" + "value": "Automazione" } }, "da": { "stringUnit": { "state": "translated", - "value": "Popover" + "value": "Automatisering" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Wyskakujące okno" + "value": "Automatyzacja" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Всплывающее окно" + "value": "Автоматизация" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Iskočni prozor" + "value": "Automatizacija" } }, "ar": { "stringUnit": { "state": "translated", - "value": "نافذة منبثقة" + "value": "الأتمتة" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Popover" + "value": "Automatisering" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Popover" + "value": "Automação" } }, "th": { "stringUnit": { "state": "translated", - "value": "ป็อปโอเวอร์" + "value": "ระบบอัตโนมัติ" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Açılır Pencere" + "value": "Otomasyon" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Спливне вікно" + "value": "Автоматизація" } } } }, - "settings.material.sheet": { + "settings.section.betaFeatures": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", "value": "Beta Features" } }, "ja": { "stringUnit": { "state": "translated", "value": "ベータ機能" } } } }, + "settings.section.browser": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Sheet" + "value": "Browser" } }, "ja": { "stringUnit": { "state": "translated", - "value": "シート" + "value": "ブラウザ" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "工作表" + "value": "浏览器" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "工作表" + "value": "瀏覽器" } }, "ko": { "stringUnit": { "state": "translated", - "value": "시트" + "value": "브라우저" } }, "de": { "stringUnit": { "state": "translated", - "value": "Dialogblatt" + "value": "Browser" } }, "es": { "stringUnit": { "state": "translated", - "value": "Hoja" + "value": "Navegador" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Feuille" + "value": "Navigateur" } }, "it": { "stringUnit": { "state": "translated", - "value": "Foglio" + "value": "Browser" } }, "da": { "stringUnit": { "state": "translated", - "value": "Ark" + "value": "Browser" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Arkusz" + "value": "Przeglądarka" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Лист" + "value": "Браузер" } }, "bs": { "stringUnit": { "state": "translated", - "value": "List" + "value": "Preglednik" } }, "ar": { "stringUnit": { "state": "translated", - "value": "ورقة" + "value": "المتصفح" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Ark" + "value": "Nettleser" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Folha" + "value": "Navegador" } }, "th": { "stringUnit": { "state": "translated", - "value": "ชีท" + "value": "เบราว์เซอร์" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Sayfa" + "value": "Tarayıcı" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Аркуш" + "value": "Браузер" } } } }, - "settings.material.sidebar": { + "settings.section.globalHotkey": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Sidebar" + "value": "Global Hotkey" } }, "ja": { "stringUnit": { "state": "translated", - "value": "サイドバー" + "value": "グローバルホットキー" + } + }, + "ko": { + "stringUnit": { + "state": "translated", + "value": "글로벌 단축키" + } + } + } + }, + "settings.section.keyboardShortcuts": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Keyboard Shortcuts" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "キーボードショートカット" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "侧边栏" + "value": "键盘快捷键" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "側邊欄" + "value": "鍵盤快速鍵" } }, "ko": { "stringUnit": { "state": "translated", - "value": "사이드바" + "value": "키보드 단축키" } }, "de": { "stringUnit": { "state": "translated", - "value": "Seitenleiste" + "value": "Tastaturkurzbefehle" } }, "es": { "stringUnit": { "state": "translated", - "value": "Barra lateral" + "value": "Atajos de teclado" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Barre latérale" + "value": "Raccourcis clavier" } }, "it": { "stringUnit": { "state": "translated", - "value": "Barra laterale" + "value": "Abbreviazioni da tastiera" } }, "da": { "stringUnit": { "state": "translated", - "value": "Sidebjælke" + "value": "Tastaturgenveje" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Pasek boczny" + "value": "Skróty klawiaturowe" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Боковая панель" + "value": "Сочетания клавиш" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Bočna traka" + "value": "Prečice na tastaturi" } }, "ar": { "stringUnit": { "state": "translated", - "value": "الشريط الجانبي" + "value": "اختصارات لوحة المفاتيح" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Sidepanel" + "value": "Tastatursnarveier" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Barra Lateral" + "value": "Atalhos de Teclado" } }, "th": { "stringUnit": { "state": "translated", - "value": "แถบด้านข้าง" + "value": "แป้นพิมพ์ลัด" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Kenar Çubuğu" + "value": "Klavye Kısayolları" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Бічна панель" + "value": "Комбінації клавіш" } } } }, - "settings.material.toolTip": { + "settings.section.settingsJSON": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Tool Tip" + "value": "cmux.json" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ツールチップ" + "value": "cmux.json" + } + }, + "ko": { + "stringUnit": { + "state": "translated", + "value": "cmux.json" + } + } + } + }, + "settings.section.reset": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Reset" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "リセット" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "工具提示" + "value": "重置" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "工具提示" + "value": "重置" } }, "ko": { "stringUnit": { "state": "translated", - "value": "도구 설명" + "value": "초기화" } }, "de": { "stringUnit": { "state": "translated", - "value": "Tooltip" + "value": "Zurücksetzen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Descripción emergente" + "value": "Restablecer" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Info-bulle" + "value": "Réinitialiser" } }, "it": { "stringUnit": { "state": "translated", - "value": "Suggerimento" + "value": "Ripristina" } }, "da": { "stringUnit": { "state": "translated", - "value": "Værktøjstip" + "value": "Nulstil" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Podpowiedź" + "value": "Resetuj" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Подсказка" + "value": "Сброс" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Opis alata" + "value": "Resetovanje" } }, "ar": { "stringUnit": { "state": "translated", - "value": "تلميح أداة" + "value": "إعادة التعيين" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Verktøytips" + "value": "Tilbakestill" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Dica de Ferramenta" + "value": "Redefinir" } }, "th": { "stringUnit": { "state": "translated", - "value": "คำแนะนำเครื่องมือ" + "value": "รีเซ็ต" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Araç İpucu" + "value": "Sıfırla" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Підказка" + "value": "Скидання" } } } }, - "settings.material.underWindow": { + "settings.section.workspaceColors": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Under Window" + "value": "Workspace Colors" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ウインドウ下" + "value": "ワークスペースカラー" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "窗口底部" + "value": "工作区颜色" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "視窗下方" + "value": "工作區顏色" } }, "ko": { "stringUnit": { "state": "translated", - "value": "윈도우 아래" + "value": "작업 공간 색상" } }, "de": { "stringUnit": { "state": "translated", - "value": "Unter dem Fenster" + "value": "Arbeitsbereichsfarben" } }, "es": { "stringUnit": { "state": "translated", - "value": "Debajo de la ventana" + "value": "Colores de espacios de trabajo" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Sous la fenêtre" + "value": "Couleurs des espaces de travail" } }, "it": { "stringUnit": { "state": "translated", - "value": "Sotto la finestra" + "value": "Colori area di lavoro" } }, "da": { "stringUnit": { "state": "translated", - "value": "Under vindue" + "value": "Arbejdsområdefarver" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Pod oknem" + "value": "Kolory przestrzeni roboczych" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Под окном" + "value": "Цвета рабочих пространств" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Ispod prozora" + "value": "Boje radnog prostora" } }, "ar": { "stringUnit": { "state": "translated", - "value": "تحت النافذة" + "value": "ألوان مساحة العمل" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Under vinduet" + "value": "Arbeidsområdefarger" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Sob a Janela" + "value": "Cores da Área de Trabalho" } }, "th": { "stringUnit": { "state": "translated", - "value": "ใต้หน้าต่าง" + "value": "สีเวิร์กสเปซ" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Pencere Altı" + "value": "Çalışma Alanı Renkleri" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Під вікном" + "value": "Кольори робочих областей" } } } }, - "settings.material.windowBackground": { + "settings.shortcuts.recordHint": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Window Background" + "value": "Click a shortcut value to record. Use X to unbind; it changes to restore after a clear." } }, "ja": { "stringUnit": { "state": "translated", - "value": "ウインドウ背景" + "value": "ショートカット値をクリックして記録します。X で割り当て解除でき、解除後は復元に変わります。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "窗口背景" + "value": "点击快捷键值以录制新快捷键。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "視窗背景" + "value": "按一下快速鍵值以錄製新的快速鍵。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "윈도우 배경" + "value": "단축키 값을 클릭하여 새 단축키를 기록하세요." } }, "de": { "stringUnit": { "state": "translated", - "value": "Fensterhintergrund" + "value": "Klicken Sie auf einen Kurzbefehlswert, um einen neuen Kurzbefehl aufzunehmen." } }, "es": { "stringUnit": { "state": "translated", - "value": "Fondo de ventana" + "value": "Haz clic en un valor de atajo para grabar un nuevo atajo." } }, "fr": { "stringUnit": { "state": "translated", - "value": "Arrière-plan de la fenêtre" + "value": "Cliquez sur une valeur de raccourci pour en enregistrer un nouveau." } }, "it": { "stringUnit": { "state": "translated", - "value": "Sfondo finestra" + "value": "Fai clic su un valore di scorciatoia per registrarne una nuova." } }, "da": { "stringUnit": { "state": "translated", - "value": "Vinduesbaggrund" + "value": "Klik på en genvejsværdi for at optage en ny genvej." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Tło okna" + "value": "Kliknij wartość skrótu, aby nagrać nowy skrót." } }, "ru": { "stringUnit": { "state": "translated", - "value": "Фон окна" + "value": "Нажмите на значение сочетания, чтобы записать новое." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Pozadina prozora" + "value": "Kliknite na vrijednost prečice da snimite novu prečicu." } }, "ar": { "stringUnit": { "state": "translated", - "value": "خلفية النافذة" + "value": "انقر على قيمة اختصار لتسجيل اختصار جديد." } }, "nb": { "stringUnit": { "state": "translated", - "value": "Vindubakgrunn" + "value": "Klikk på en snarveiverdi for å ta opp en ny snarvei." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Fundo da Janela" + "value": "Clique em um valor de atalho para gravar um novo atalho." } }, "th": { "stringUnit": { "state": "translated", - "value": "พื้นหลังหน้าต่าง" + "value": "คลิกค่าทางลัดเพื่อบันทึกทางลัดใหม่" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Pencere Arka Planı" + "value": "Yeni bir kısayol kaydetmek için bir kısayol değerine tıklayın." } }, "uk": { "stringUnit": { "state": "translated", - "value": "Фон вікна" + "value": "Натисніть на значення комбінації, щоб записати нову." } } } }, - "settings.preset.hudGlass": { + "settings.shortcuts.resetDefaults": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "HUD Glass" + "value": "Reset Default Shortcuts" } }, "ja": { "stringUnit": { "state": "translated", - "value": "HUD Glass" + "value": "デフォルトショートカットにリセット" + } + } + } + }, + "settings.shortcuts.resetDefaults.button": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Reset Defaults" } }, - "zh-Hans": { + "ja": { "stringUnit": { "state": "translated", - "value": "HUD 玻璃" + "value": "デフォルトにリセット" + } + } + } + }, + "settings.shortcuts.resetDefaults.subtitle": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Restore built-in shortcut values for shortcuts managed in app settings." } }, - "zh-Hant": { + "ja": { "stringUnit": { "state": "translated", - "value": "HUD 玻璃" + "value": "アプリ設定で管理しているショートカットを組み込み値に戻します。" + } + } + } + }, + "settings.globalHotkey.enable": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Enable System-Wide Hotkey" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "システム全体のホットキーを有効にする" } }, "ko": { "stringUnit": { "state": "translated", - "value": "HUD 글래스" + "value": "시스템 전체 단축키 활성화" + } + } + } + }, + "settings.globalHotkey.enable.subtitleOff": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Turn this on to show or hide all cmux windows from any app." } }, - "de": { + "ja": { "stringUnit": { "state": "translated", - "value": "HUD Glass" + "value": "どのアプリからでも cmux のすべてのウィンドウを表示または非表示にするにはオンにします。" } }, - "es": { + "ko": { "stringUnit": { "state": "translated", - "value": "HUD Glass" + "value": "이 옵션을 켜면 어떤 앱에서든 모든 cmux 윈도우를 표시하거나 숨길 수 있습니다." + } + } + } + }, + "settings.globalHotkey.enable.subtitleOn": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Press the shortcut from any app to show or hide all cmux windows." } }, - "fr": { + "ja": { "stringUnit": { "state": "translated", - "value": "HUD Glass" + "value": "どのアプリからでもこのショートカットで cmux のすべてのウィンドウを表示または非表示にできます。" } }, - "it": { + "ko": { "stringUnit": { "state": "translated", - "value": "HUD Glass" + "value": "어떤 앱에서든 단축키를 눌러 모든 cmux 윈도우를 표시하거나 숨깁니다." + } + } + } + }, + "settings.globalHotkey.note": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Use Command, Option, or Control with another key. No extra macOS permission is required." } }, - "da": { + "ja": { "stringUnit": { "state": "translated", - "value": "HUD-glas" + "value": "Command、Option、または Control と別のキーを組み合わせてください。追加の macOS 権限は不要です。" } }, - "pl": { + "ko": { "stringUnit": { "state": "translated", - "value": "Szkło HUD" + "value": "Command, Option 또는 Control과 다른 키를 함께 사용하세요. 추가 macOS 권한이 필요하지 않습니다." + } + } + } + }, + "settings.globalHotkey.shortcut": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Show/Hide All Windows" } }, - "ru": { + "ja": { "stringUnit": { "state": "translated", - "value": "HUD Glass" + "value": "すべてのウィンドウを表示/非表示" } }, - "bs": { + "ko": { "stringUnit": { "state": "translated", - "value": "HUD staklo" + "value": "모든 윈도우 표시/숨기기" + } + } + } + }, + "settings.shortcuts.chords": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Shortcut Chords" } }, - "ar": { + "ja": { "stringUnit": { "state": "translated", - "value": "زجاج HUD" + "value": "ショートカットコード" } }, - "nb": { + "ko": { "stringUnit": { "state": "translated", - "value": "HUD-glass" + "value": "단축키 조합" + } + } + } + }, + "settings.shortcuts.chords.docsButton": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Chord docs" } }, - "pt-BR": { + "ja": { "stringUnit": { "state": "translated", - "value": "Vidro HUD" + "value": "コードの説明" } }, - "th": { + "ko": { "stringUnit": { "state": "translated", - "value": "HUD Glass" + "value": "조합 문서" + } + } + } + }, + "settings.shortcuts.chords.subtitle": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Add tmux-style multi-step shortcuts in cmux.json, for example [\"ctrl+b\", \"c\"]." } }, - "tr": { + "ja": { "stringUnit": { "state": "translated", - "value": "HUD Glass" + "value": "cmux.json で tmux 風の2段階ショートカットを追加できます。例: [\"ctrl+b\", \"c\"]。" } }, - "uk": { + "ko": { "stringUnit": { "state": "translated", - "value": "HUD Glass" + "value": "cmux.json에서 tmux 스타일의 다단계 단축키를 추가할 수 있습니다. 예: [\"ctrl+b\", \"c\"]." } } } }, - "settings.preset.nativeSidebar": { + "settings.state.active": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Native Sidebar" + "value": "Active" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ネイティブサイドバー" + "value": "アクティブ" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "原生侧边栏" + "value": "活跃" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "原生側邊欄" + "value": "使用中" } }, "ko": { "stringUnit": { "state": "translated", - "value": "기본 사이드바" + "value": "활성" } }, "de": { "stringUnit": { "state": "translated", - "value": "Native Seitenleiste" + "value": "Aktiv" } }, "es": { "stringUnit": { "state": "translated", - "value": "Barra lateral nativa" + "value": "Activo" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Barre latérale native" + "value": "Actif" } }, "it": { "stringUnit": { "state": "translated", - "value": "Barra laterale nativa" + "value": "Attivo" } }, "da": { "stringUnit": { "state": "translated", - "value": "Indbygget sidebjælke" + "value": "Aktiv" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Natywny pasek boczny" + "value": "Aktywny" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Системная боковая панель" + "value": "Активное" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Nativna bočna traka" + "value": "Aktivno" } }, "ar": { "stringUnit": { "state": "translated", - "value": "شريط جانبي أصلي" + "value": "نشط" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Innebygd sidepanel" + "value": "Aktiv" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Barra Lateral Nativa" + "value": "Ativo" } }, "th": { "stringUnit": { "state": "translated", - "value": "แถบด้านข้างแบบดั้งเดิม" + "value": "ใช้งานอยู่" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Yerel Kenar Çubuğu" + "value": "Etkin" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Рідна бічна панель" + "value": "Активний" } } } }, - "settings.preset.popoverGlass": { + "settings.state.followWindow": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Popover Glass" + "value": "Follow Window" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ポップオーバーGlass" + "value": "ウインドウに追従" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "弹出框玻璃" + "value": "跟随窗口" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "彈出框玻璃" + "value": "跟隨視窗" } }, "ko": { "stringUnit": { "state": "translated", - "value": "팝오버 글래스" + "value": "윈도우 따르기" } }, "de": { "stringUnit": { "state": "translated", - "value": "Popover Glass" + "value": "Fenster folgen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Popover Glass" + "value": "Seguir ventana" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Popover Glass" + "value": "Suivre la fenêtre" } }, "it": { "stringUnit": { "state": "translated", - "value": "Popover Glass" + "value": "Segui finestra" } }, "da": { "stringUnit": { "state": "translated", - "value": "Popover-glas" + "value": "Følg vindue" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Szkło wyskakujące" + "value": "Podążaj za oknem" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Popover Glass" + "value": "Следовать за окном" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Iskočno staklo" + "value": "Prati prozor" } }, "ar": { "stringUnit": { "state": "translated", - "value": "زجاج منبثق" + "value": "متابعة النافذة" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Popover-glass" + "value": "Følg vindu" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Vidro Popover" + "value": "Seguir Janela" } }, "th": { "stringUnit": { "state": "translated", - "value": "Popover Glass" + "value": "ตามหน้าต่าง" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Açılır Pencere Glass" + "value": "Pencereyi Takip Et" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Popover Glass" + "value": "Відповідно до вікна" } } } }, - "settings.preset.raycastGray": { + "settings.state.inactive": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Raycast Gray" + "value": "Inactive" } }, "ja": { "stringUnit": { "state": "translated", - "value": "Raycast Gray" + "value": "非アクティブ" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "Raycast 灰" + "value": "不活跃" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "Raycast 灰" + "value": "非使用中" } }, "ko": { "stringUnit": { "state": "translated", - "value": "Raycast 그레이" + "value": "비활성" } }, "de": { "stringUnit": { "state": "translated", - "value": "Raycast Gray" + "value": "Inaktiv" } }, "es": { "stringUnit": { "state": "translated", - "value": "Raycast Gray" + "value": "Inactivo" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Raycast Gray" - } - }, - "it": { - "stringUnit": { - "state": "translated", - "value": "Raycast Gray" - } - }, - "da": { - "stringUnit": { - "state": "translated", - "value": "Raycast-grå" - } - }, - "pl": { - "stringUnit": { - "state": "translated", - "value": "Szary Raycast" - } - }, - "ru": { - "stringUnit": { - "state": "translated", - "value": "Raycast Gray" - } - }, - "bs": { - "stringUnit": { - "state": "translated", - "value": "Raycast siva" - } - }, - "ar": { - "stringUnit": { - "state": "translated", - "value": "رمادي Raycast" - } - }, - "nb": { - "stringUnit": { - "state": "translated", - "value": "Raycast-grå" - } - }, - "pt-BR": { - "stringUnit": { - "state": "translated", - "value": "Cinza Raycast" - } - }, - "th": { - "stringUnit": { - "state": "translated", - "value": "Raycast Gray" - } - }, - "tr": { - "stringUnit": { - "state": "translated", - "value": "Raycast Gri" - } - }, - "uk": { - "stringUnit": { - "state": "translated", - "value": "Raycast Gray" - } - } - } - }, - "settings.preset.softBlur": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Soft Blur" - } - }, - "ja": { - "stringUnit": { - "state": "translated", - "value": "ソフトブラー" - } - }, - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "柔和模糊" - } - }, - "zh-Hant": { - "stringUnit": { - "state": "translated", - "value": "柔和模糊" - } - }, - "ko": { - "stringUnit": { - "state": "translated", - "value": "소프트 블러" - } - }, - "de": { - "stringUnit": { - "state": "translated", - "value": "Soft Blur" - } - }, - "es": { - "stringUnit": { - "state": "translated", - "value": "Soft Blur" - } - }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "Soft Blur" - } - }, - "it": { - "stringUnit": { - "state": "translated", - "value": "Soft Blur" - } - }, - "da": { - "stringUnit": { - "state": "translated", - "value": "Blød sløring" - } - }, - "pl": { - "stringUnit": { - "state": "translated", - "value": "Delikatne rozmycie" - } - }, - "ru": { - "stringUnit": { - "state": "translated", - "value": "Soft Blur" - } - }, - "bs": { - "stringUnit": { - "state": "translated", - "value": "Meko zamućenje" - } - }, - "ar": { - "stringUnit": { - "state": "translated", - "value": "ضبابية ناعمة" - } - }, - "nb": { - "stringUnit": { - "state": "translated", - "value": "Myk uskarphet" - } - }, - "pt-BR": { - "stringUnit": { - "state": "translated", - "value": "Desfoque Suave" - } - }, - "th": { - "stringUnit": { - "state": "translated", - "value": "Soft Blur" - } - }, - "tr": { - "stringUnit": { - "state": "translated", - "value": "Yumuşak Bulanıklık" - } - }, - "uk": { - "stringUnit": { - "state": "translated", - "value": "Soft Blur" - } - } - } - }, - "settings.preset.underWindow": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Under Window" - } - }, - "ja": { - "stringUnit": { - "state": "translated", - "value": "ウインドウ下" - } - }, - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "窗口底部" - } - }, - "zh-Hant": { - "stringUnit": { - "state": "translated", - "value": "視窗下方" - } - }, - "ko": { - "stringUnit": { - "state": "translated", - "value": "윈도우 아래" - } - }, - "de": { - "stringUnit": { - "state": "translated", - "value": "Under Window" - } - }, - "es": { - "stringUnit": { - "state": "translated", - "value": "Under Window" - } - }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "Under Window" - } - }, - "it": { - "stringUnit": { - "state": "translated", - "value": "Under Window" - } - }, - "da": { - "stringUnit": { - "state": "translated", - "value": "Under vindue" - } - }, - "pl": { - "stringUnit": { - "state": "translated", - "value": "Pod oknem" - } - }, - "ru": { - "stringUnit": { - "state": "translated", - "value": "Under Window" - } - }, - "bs": { - "stringUnit": { - "state": "translated", - "value": "Ispod prozora" - } - }, - "ar": { - "stringUnit": { - "state": "translated", - "value": "تحت النافذة" - } - }, - "nb": { - "stringUnit": { - "state": "translated", - "value": "Under vinduet" - } - }, - "pt-BR": { - "stringUnit": { - "state": "translated", - "value": "Sob a Janela" - } - }, - "th": { - "stringUnit": { - "state": "translated", - "value": "Under Window" - } - }, - "tr": { - "stringUnit": { - "state": "translated", - "value": "Pencere Altı" - } - }, - "uk": { - "stringUnit": { - "state": "translated", - "value": "Under Window" - } - } - } - }, - "settings.reset.resetAll": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Reset All Settings" - } - }, - "ja": { - "stringUnit": { - "state": "translated", - "value": "すべての設定をリセット" - } - }, - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "重置所有设置" - } - }, - "zh-Hant": { - "stringUnit": { - "state": "translated", - "value": "重置所有設定" - } - }, - "ko": { - "stringUnit": { - "state": "translated", - "value": "모든 설정 초기화" - } - }, - "de": { - "stringUnit": { - "state": "translated", - "value": "Alle Einstellungen zurücksetzen" - } - }, - "es": { - "stringUnit": { - "state": "translated", - "value": "Restablecer todos los ajustes" - } - }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "Réinitialiser tous les réglages" - } - }, - "it": { - "stringUnit": { - "state": "translated", - "value": "Ripristina tutte le impostazioni" - } - }, - "da": { - "stringUnit": { - "state": "translated", - "value": "Nulstil alle indstillinger" - } - }, - "pl": { - "stringUnit": { - "state": "translated", - "value": "Resetuj wszystkie ustawienia" - } - }, - "ru": { - "stringUnit": { - "state": "translated", - "value": "Сбросить все настройки" - } - }, - "bs": { - "stringUnit": { - "state": "translated", - "value": "Resetuj sve postavke" - } - }, - "ar": { - "stringUnit": { - "state": "translated", - "value": "إعادة تعيين جميع الإعدادات" - } - }, - "nb": { - "stringUnit": { - "state": "translated", - "value": "Tilbakestill alle innstillinger" - } - }, - "pt-BR": { - "stringUnit": { - "state": "translated", - "value": "Redefinir Todos os Ajustes" - } - }, - "th": { - "stringUnit": { - "state": "translated", - "value": "รีเซ็ตการตั้งค่าทั้งหมด" - } - }, - "tr": { - "stringUnit": { - "state": "translated", - "value": "Tüm Ayarları Sıfırla" - } - }, - "uk": { - "stringUnit": { - "state": "translated", - "value": "Скинути всі налаштування" - } - } - } - }, - "settings.section.app": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "App" - } - }, - "ja": { - "stringUnit": { - "state": "translated", - "value": "アプリ" - } - }, - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "应用" - } - }, - "zh-Hant": { - "stringUnit": { - "state": "translated", - "value": "App" - } - }, - "ko": { - "stringUnit": { - "state": "translated", - "value": "앱" - } - }, - "de": { - "stringUnit": { - "state": "translated", - "value": "App" - } - }, - "es": { - "stringUnit": { - "state": "translated", - "value": "App" - } - }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "App" - } - }, - "it": { - "stringUnit": { - "state": "translated", - "value": "App" - } - }, - "da": { - "stringUnit": { - "state": "translated", - "value": "App" - } - }, - "pl": { - "stringUnit": { - "state": "translated", - "value": "Aplikacja" - } - }, - "ru": { - "stringUnit": { - "state": "translated", - "value": "Приложение" - } - }, - "bs": { - "stringUnit": { - "state": "translated", - "value": "Aplikacija" - } - }, - "ar": { - "stringUnit": { - "state": "translated", - "value": "التطبيق" - } - }, - "nb": { - "stringUnit": { - "state": "translated", - "value": "App" - } - }, - "pt-BR": { - "stringUnit": { - "state": "translated", - "value": "App" - } - }, - "th": { - "stringUnit": { - "state": "translated", - "value": "แอป" - } - }, - "tr": { - "stringUnit": { - "state": "translated", - "value": "Uygulama" - } - }, - "uk": { - "stringUnit": { - "state": "translated", - "value": "Програма" - } - } - } - }, - "settings.section.automation": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Automation" - } - }, - "ja": { - "stringUnit": { - "state": "translated", - "value": "オートメーション" - } - }, - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "自动化" - } - }, - "zh-Hant": { - "stringUnit": { - "state": "translated", - "value": "自動化" - } - }, - "ko": { - "stringUnit": { - "state": "translated", - "value": "자동화" - } - }, - "de": { - "stringUnit": { - "state": "translated", - "value": "Automatisierung" - } - }, - "es": { - "stringUnit": { - "state": "translated", - "value": "Automatización" - } - }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "Automatisation" - } - }, - "it": { - "stringUnit": { - "state": "translated", - "value": "Automazione" - } - }, - "da": { - "stringUnit": { - "state": "translated", - "value": "Automatisering" - } - }, - "pl": { - "stringUnit": { - "state": "translated", - "value": "Automatyzacja" - } - }, - "ru": { - "stringUnit": { - "state": "translated", - "value": "Автоматизация" - } - }, - "bs": { - "stringUnit": { - "state": "translated", - "value": "Automatizacija" - } - }, - "ar": { - "stringUnit": { - "state": "translated", - "value": "الأتمتة" - } - }, - "nb": { - "stringUnit": { - "state": "translated", - "value": "Automatisering" - } - }, - "pt-BR": { - "stringUnit": { - "state": "translated", - "value": "Automação" - } - }, - "th": { - "stringUnit": { - "state": "translated", - "value": "ระบบอัตโนมัติ" - } - }, - "tr": { - "stringUnit": { - "state": "translated", - "value": "Otomasyon" - } - }, - "uk": { - "stringUnit": { - "state": "translated", - "value": "Автоматизація" - } - } - } - }, - "settings.section.betaFeatures": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", "value": "Beta Features" } }, "ja": { "stringUnit": { "state": "translated", "value": "ベータ機能" } } } }, - "settings.section.browser": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Browser" - } - }, - "ja": { - "stringUnit": { - "state": "translated", - "value": "ブラウザ" - } - }, - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "浏览器" - } - }, - "zh-Hant": { - "stringUnit": { - "state": "translated", - "value": "瀏覽器" - } - }, - "ko": { - "stringUnit": { - "state": "translated", - "value": "브라우저" - } - }, - "de": { - "stringUnit": { - "state": "translated", - "value": "Browser" - } - }, - "es": { - "stringUnit": { - "state": "translated", - "value": "Navegador" - } - }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "Navigateur" - } - }, - "it": { - "stringUnit": { - "state": "translated", - "value": "Browser" - } - }, - "da": { - "stringUnit": { - "state": "translated", - "value": "Browser" - } - }, - "pl": { - "stringUnit": { - "state": "translated", - "value": "Przeglądarka" - } - }, - "ru": { - "stringUnit": { - "state": "translated", - "value": "Браузер" - } - }, - "bs": { - "stringUnit": { - "state": "translated", - "value": "Preglednik" - } - }, - "ar": { - "stringUnit": { - "state": "translated", - "value": "المتصفح" - } - }, - "nb": { - "stringUnit": { - "state": "translated", - "value": "Nettleser" - } - }, - "pt-BR": { - "stringUnit": { - "state": "translated", - "value": "Navegador" - } - }, - "th": { - "stringUnit": { - "state": "translated", - "value": "เบราว์เซอร์" - } - }, - "tr": { - "stringUnit": { - "state": "translated", - "value": "Tarayıcı" - } - }, - "uk": { - "stringUnit": { - "state": "translated", - "value": "Браузер" - } - } - } - }, - "settings.section.globalHotkey": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Global Hotkey" - } - }, - "ja": { - "stringUnit": { - "state": "translated", - "value": "グローバルホットキー" - } - }, - "ko": { - "stringUnit": { - "state": "translated", - "value": "글로벌 단축키" - } - } - } - }, - "settings.section.keyboardShortcuts": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Keyboard Shortcuts" - } - }, - "ja": { - "stringUnit": { - "state": "translated", - "value": "キーボードショートカット" - } - }, - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "键盘快捷键" - } - }, - "zh-Hant": { - "stringUnit": { - "state": "translated", - "value": "鍵盤快速鍵" - } - }, - "ko": { - "stringUnit": { - "state": "translated", - "value": "키보드 단축키" - } - }, - "de": { - "stringUnit": { - "state": "translated", - "value": "Tastaturkurzbefehle" - } - }, - "es": { - "stringUnit": { - "state": "translated", - "value": "Atajos de teclado" - } - }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "Raccourcis clavier" - } - }, - "it": { - "stringUnit": { - "state": "translated", - "value": "Abbreviazioni da tastiera" - } - }, - "da": { - "stringUnit": { - "state": "translated", - "value": "Tastaturgenveje" - } - }, - "pl": { - "stringUnit": { - "state": "translated", - "value": "Skróty klawiaturowe" - } - }, - "ru": { - "stringUnit": { - "state": "translated", - "value": "Сочетания клавиш" - } - }, - "bs": { - "stringUnit": { - "state": "translated", - "value": "Prečice na tastaturi" - } - }, - "ar": { - "stringUnit": { - "state": "translated", - "value": "اختصارات لوحة المفاتيح" - } - }, - "nb": { - "stringUnit": { - "state": "translated", - "value": "Tastatursnarveier" - } - }, - "pt-BR": { - "stringUnit": { - "state": "translated", - "value": "Atalhos de Teclado" - } - }, - "th": { - "stringUnit": { - "state": "translated", - "value": "แป้นพิมพ์ลัด" - } - }, - "tr": { - "stringUnit": { - "state": "translated", - "value": "Klavye Kısayolları" - } - }, - "uk": { - "stringUnit": { - "state": "translated", - "value": "Комбінації клавіш" - } - } - } - }, - "settings.section.settingsJSON": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "cmux.json" - } - }, - "ja": { - "stringUnit": { - "state": "translated", - "value": "cmux.json" - } - }, - "ko": { - "stringUnit": { - "state": "translated", - "value": "cmux.json" - } - } - } - }, - "settings.section.reset": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Reset" - } - }, - "ja": { - "stringUnit": { - "state": "translated", - "value": "リセット" - } - }, - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "重置" - } - }, - "zh-Hant": { - "stringUnit": { - "state": "translated", - "value": "重置" - } - }, - "ko": { - "stringUnit": { - "state": "translated", - "value": "초기화" - } - }, - "de": { - "stringUnit": { - "state": "translated", - "value": "Zurücksetzen" - } - }, - "es": { - "stringUnit": { - "state": "translated", - "value": "Restablecer" - } - }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "Réinitialiser" - } - }, - "it": { - "stringUnit": { - "state": "translated", - "value": "Ripristina" - } - }, - "da": { - "stringUnit": { - "state": "translated", - "value": "Nulstil" - } - }, - "pl": { - "stringUnit": { - "state": "translated", - "value": "Resetuj" - } - }, - "ru": { - "stringUnit": { - "state": "translated", - "value": "Сброс" - } - }, - "bs": { - "stringUnit": { - "state": "translated", - "value": "Resetovanje" - } - }, - "ar": { - "stringUnit": { - "state": "translated", - "value": "إعادة التعيين" - } - }, - "nb": { - "stringUnit": { - "state": "translated", - "value": "Tilbakestill" - } - }, - "pt-BR": { - "stringUnit": { - "state": "translated", - "value": "Redefinir" - } - }, - "th": { - "stringUnit": { - "state": "translated", - "value": "รีเซ็ต" - } - }, - "tr": { - "stringUnit": { - "state": "translated", - "value": "Sıfırla" - } - }, - "uk": { - "stringUnit": { - "state": "translated", - "value": "Скидання" - } - } - } - }, - "settings.section.workspaceColors": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Workspace Colors" - } - }, - "ja": { - "stringUnit": { - "state": "translated", - "value": "ワークスペースカラー" - } - }, - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "工作区颜色" - } - }, - "zh-Hant": { - "stringUnit": { - "state": "translated", - "value": "工作區顏色" - } - }, - "ko": { - "stringUnit": { - "state": "translated", - "value": "작업 공간 색상" - } - }, - "de": { - "stringUnit": { - "state": "translated", - "value": "Arbeitsbereichsfarben" - } - }, - "es": { - "stringUnit": { - "state": "translated", - "value": "Colores de espacios de trabajo" - } - }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "Couleurs des espaces de travail" - } - }, - "it": { - "stringUnit": { - "state": "translated", - "value": "Colori area di lavoro" - } - }, - "da": { - "stringUnit": { - "state": "translated", - "value": "Arbejdsområdefarver" - } - }, - "pl": { - "stringUnit": { - "state": "translated", - "value": "Kolory przestrzeni roboczych" - } - }, - "ru": { - "stringUnit": { - "state": "translated", - "value": "Цвета рабочих пространств" - } - }, - "bs": { - "stringUnit": { - "state": "translated", - "value": "Boje radnog prostora" - } - }, - "ar": { - "stringUnit": { - "state": "translated", - "value": "ألوان مساحة العمل" - } - }, - "nb": { - "stringUnit": { - "state": "translated", - "value": "Arbeidsområdefarger" - } - }, - "pt-BR": { - "stringUnit": { - "state": "translated", - "value": "Cores da Área de Trabalho" - } - }, - "th": { - "stringUnit": { - "state": "translated", - "value": "สีเวิร์กสเปซ" - } - }, - "tr": { - "stringUnit": { - "state": "translated", - "value": "Çalışma Alanı Renkleri" - } - }, - "uk": { - "stringUnit": { - "state": "translated", - "value": "Кольори робочих областей" - } - } - } - }, - "settings.shortcuts.recordHint": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Click a shortcut value to record. Use X to unbind; it changes to restore after a clear." - } - }, - "ja": { - "stringUnit": { - "state": "translated", - "value": "ショートカット値をクリックして記録します。X で割り当て解除でき、解除後は復元に変わります。" - } - }, - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "点击快捷键值以录制新快捷键。" - } - }, - "zh-Hant": { - "stringUnit": { - "state": "translated", - "value": "按一下快速鍵值以錄製新的快速鍵。" - } - }, - "ko": { - "stringUnit": { - "state": "translated", - "value": "단축키 값을 클릭하여 새 단축키를 기록하세요." - } - }, - "de": { - "stringUnit": { - "state": "translated", - "value": "Klicken Sie auf einen Kurzbefehlswert, um einen neuen Kurzbefehl aufzunehmen." - } - }, - "es": { - "stringUnit": { - "state": "translated", - "value": "Haz clic en un valor de atajo para grabar un nuevo atajo." - } - }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "Cliquez sur une valeur de raccourci pour en enregistrer un nouveau." - } - }, - "it": { - "stringUnit": { - "state": "translated", - "value": "Fai clic su un valore di scorciatoia per registrarne una nuova." - } - }, - "da": { - "stringUnit": { - "state": "translated", - "value": "Klik på en genvejsværdi for at optage en ny genvej." - } - }, - "pl": { - "stringUnit": { - "state": "translated", - "value": "Kliknij wartość skrótu, aby nagrać nowy skrót." - } - }, - "ru": { - "stringUnit": { - "state": "translated", - "value": "Нажмите на значение сочетания, чтобы записать новое." - } - }, - "bs": { - "stringUnit": { - "state": "translated", - "value": "Kliknite na vrijednost prečice da snimite novu prečicu." - } - }, - "ar": { - "stringUnit": { - "state": "translated", - "value": "انقر على قيمة اختصار لتسجيل اختصار جديد." - } - }, - "nb": { - "stringUnit": { - "state": "translated", - "value": "Klikk på en snarveiverdi for å ta opp en ny snarvei." - } - }, - "pt-BR": { - "stringUnit": { - "state": "translated", - "value": "Clique em um valor de atalho para gravar um novo atalho." - } - }, - "th": { - "stringUnit": { - "state": "translated", - "value": "คลิกค่าทางลัดเพื่อบันทึกทางลัดใหม่" - } - }, - "tr": { - "stringUnit": { - "state": "translated", - "value": "Yeni bir kısayol kaydetmek için bir kısayol değerine tıklayın." - } - }, - "uk": { - "stringUnit": { - "state": "translated", - "value": "Натисніть на значення комбінації, щоб записати нову." - } - } - } - }, - "settings.shortcuts.resetDefaults": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Reset Default Shortcuts" - } - }, - "ja": { - "stringUnit": { - "state": "translated", - "value": "デフォルトショートカットにリセット" - } - } - } - }, - "settings.shortcuts.resetDefaults.button": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Reset Defaults" - } - }, - "ja": { - "stringUnit": { - "state": "translated", - "value": "デフォルトにリセット" - } - } - } - }, - "settings.shortcuts.resetDefaults.subtitle": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Restore built-in shortcut values for shortcuts managed in app settings." - } - }, - "ja": { - "stringUnit": { - "state": "translated", - "value": "アプリ設定で管理しているショートカットを組み込み値に戻します。" - } - } - } - }, - "settings.globalHotkey.enable": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Enable System-Wide Hotkey" - } - }, - "ja": { - "stringUnit": { - "state": "translated", - "value": "システム全体のホットキーを有効にする" - } - }, - "ko": { - "stringUnit": { - "state": "translated", - "value": "시스템 전체 단축키 활성화" - } - } - } - }, - "settings.globalHotkey.enable.subtitleOff": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Turn this on to show or hide all cmux windows from any app." - } - }, - "ja": { - "stringUnit": { - "state": "translated", - "value": "どのアプリからでも cmux のすべてのウィンドウを表示または非表示にするにはオンにします。" - } - }, - "ko": { - "stringUnit": { - "state": "translated", - "value": "이 옵션을 켜면 어떤 앱에서든 모든 cmux 윈도우를 표시하거나 숨길 수 있습니다." - } - } - } - }, - "settings.globalHotkey.enable.subtitleOn": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Press the shortcut from any app to show or hide all cmux windows." - } - }, - "ja": { - "stringUnit": { - "state": "translated", - "value": "どのアプリからでもこのショートカットで cmux のすべてのウィンドウを表示または非表示にできます。" - } - }, - "ko": { - "stringUnit": { - "state": "translated", - "value": "어떤 앱에서든 단축키를 눌러 모든 cmux 윈도우를 표시하거나 숨깁니다." - } - } - } - }, - "settings.globalHotkey.note": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Use Command, Option, or Control with another key. No extra macOS permission is required." - } - }, - "ja": { - "stringUnit": { - "state": "translated", - "value": "Command、Option、または Control と別のキーを組み合わせてください。追加の macOS 権限は不要です。" - } - }, - "ko": { - "stringUnit": { - "state": "translated", - "value": "Command, Option 또는 Control과 다른 키를 함께 사용하세요. 추가 macOS 권한이 필요하지 않습니다." - } - } - } - }, - "settings.globalHotkey.shortcut": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Show/Hide All Windows" - } - }, - "ja": { - "stringUnit": { - "state": "translated", - "value": "すべてのウィンドウを表示/非表示" - } - }, - "ko": { - "stringUnit": { - "state": "translated", - "value": "모든 윈도우 표시/숨기기" - } - } - } - }, - "settings.shortcuts.chords": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Shortcut Chords" - } - }, - "ja": { - "stringUnit": { - "state": "translated", - "value": "ショートカットコード" - } - }, - "ko": { - "stringUnit": { - "state": "translated", - "value": "단축키 조합" - } - } - } - }, - "settings.shortcuts.chords.docsButton": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Chord docs" - } - }, - "ja": { - "stringUnit": { - "state": "translated", - "value": "コードの説明" - } - }, - "ko": { - "stringUnit": { - "state": "translated", - "value": "조합 문서" - } - } - } - }, - "settings.shortcuts.chords.subtitle": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Add tmux-style multi-step shortcuts in cmux.json, for example [\"ctrl+b\", \"c\"]." - } - }, - "ja": { - "stringUnit": { - "state": "translated", - "value": "cmux.json で tmux 風の2段階ショートカットを追加できます。例: [\"ctrl+b\", \"c\"]。" - } - }, - "ko": { - "stringUnit": { - "state": "translated", - "value": "cmux.json에서 tmux 스타일의 다단계 단축키를 추가할 수 있습니다. 예: [\"ctrl+b\", \"c\"]." - } - } - } - }, - "settings.state.active": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Active" - } - }, - "ja": { - "stringUnit": { - "state": "translated", - "value": "アクティブ" - } - }, - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "活跃" - } - }, - "zh-Hant": { - "stringUnit": { - "state": "translated", - "value": "使用中" - } - }, - "ko": { - "stringUnit": { - "state": "translated", - "value": "활성" - } - }, - "de": { - "stringUnit": { - "state": "translated", - "value": "Aktiv" - } - }, - "es": { - "stringUnit": { - "state": "translated", - "value": "Activo" - } - }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "Actif" - } - }, - "it": { - "stringUnit": { - "state": "translated", - "value": "Attivo" - } - }, - "da": { - "stringUnit": { - "state": "translated", - "value": "Aktiv" - } - }, - "pl": { - "stringUnit": { - "state": "translated", - "value": "Aktywny" - } - }, - "ru": { - "stringUnit": { - "state": "translated", - "value": "Активное" - } - }, - "bs": { - "stringUnit": { - "state": "translated", - "value": "Aktivno" - } - }, - "ar": { - "stringUnit": { - "state": "translated", - "value": "نشط" - } - }, - "nb": { - "stringUnit": { - "state": "translated", - "value": "Aktiv" - } - }, - "pt-BR": { - "stringUnit": { - "state": "translated", - "value": "Ativo" - } - }, - "th": { - "stringUnit": { - "state": "translated", - "value": "ใช้งานอยู่" - } - }, - "tr": { - "stringUnit": { - "state": "translated", - "value": "Etkin" - } - }, - "uk": { - "stringUnit": { - "state": "translated", - "value": "Активний" - } - } - } - }, - "settings.state.followWindow": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Follow Window" - } - }, - "ja": { - "stringUnit": { - "state": "translated", - "value": "ウインドウに追従" - } - }, - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "跟随窗口" - } - }, - "zh-Hant": { - "stringUnit": { - "state": "translated", - "value": "跟隨視窗" - } - }, - "ko": { - "stringUnit": { - "state": "translated", - "value": "윈도우 따르기" - } - }, - "de": { - "stringUnit": { - "state": "translated", - "value": "Fenster folgen" - } - }, - "es": { - "stringUnit": { - "state": "translated", - "value": "Seguir ventana" - } - }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "Suivre la fenêtre" - } - }, - "it": { - "stringUnit": { - "state": "translated", - "value": "Segui finestra" - } - }, - "da": { - "stringUnit": { - "state": "translated", - "value": "Følg vindue" - } - }, - "pl": { - "stringUnit": { - "state": "translated", - "value": "Podążaj za oknem" - } - }, - "ru": { - "stringUnit": { - "state": "translated", - "value": "Следовать за окном" - } - }, - "bs": { - "stringUnit": { - "state": "translated", - "value": "Prati prozor" - } - }, - "ar": { - "stringUnit": { - "state": "translated", - "value": "متابعة النافذة" - } - }, - "nb": { - "stringUnit": { - "state": "translated", - "value": "Følg vindu" - } - }, - "pt-BR": { - "stringUnit": { - "state": "translated", - "value": "Seguir Janela" - } - }, - "th": { - "stringUnit": { - "state": "translated", - "value": "ตามหน้าต่าง" - } - }, - "tr": { - "stringUnit": { - "state": "translated", - "value": "Pencereyi Takip Et" - } - }, - "uk": { - "stringUnit": { - "state": "translated", - "value": "Відповідно до вікна" - } - } - } - }, - "settings.state.inactive": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Inactive" - } - }, - "ja": { - "stringUnit": { - "state": "translated", - "value": "非アクティブ" - } - }, - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "不活跃" - } - }, - "zh-Hant": { - "stringUnit": { - "state": "translated", - "value": "非使用中" - } - }, - "ko": { - "stringUnit": { - "state": "translated", - "value": "비활성" - } - }, - "de": { - "stringUnit": { - "state": "translated", - "value": "Inaktiv" - } - }, - "es": { - "stringUnit": { - "state": "translated", - "value": "Inactivo" - } - }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "Inactif" + "value": "Inactif" } }, "it": { @@ -77579,125 +76165,6 @@ } } }, - "settings.search.alias.setting.app.watch-git-status": { - "extractionState": "manual", - "localizations": { - "ar": { - "stringUnit": { - "state": "translated", - "value": "sidebar.watchGitStatus git status branch watcher index lock حالة git فرع مراقبة الشريط الجانبي" - } - }, - "bs": { - "stringUnit": { - "state": "translated", - "value": "sidebar.watchGitStatus git status branch watcher index lock git status grana bočna traka" - } - }, - "da": { - "stringUnit": { - "state": "translated", - "value": "sidebar.watchGitStatus git status branch watcher index lock git-status gren sidepanel" - } - }, - "de": { - "stringUnit": { - "state": "translated", - "value": "sidebar.watchGitStatus git status branch watcher index lock git-status branch seitenleiste" - } - }, - "en": { - "stringUnit": { - "state": "translated", - "value": "sidebar.watchGitStatus git status branch watcher index lock" - } - }, - "es": { - "stringUnit": { - "state": "translated", - "value": "sidebar.watchGitStatus git status branch watcher index lock estado git rama barra lateral" - } - }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "sidebar.watchGitStatus git status branch watcher index lock état git branche barre latérale" - } - }, - "it": { - "stringUnit": { - "state": "translated", - "value": "sidebar.watchGitStatus git status branch watcher index lock stato git ramo barra laterale" - } - }, - "ja": { - "stringUnit": { - "state": "translated", - "value": "sidebar.watchGitStatus git status branch watcher index lock git 状態 ブランチ 監視 index lock" - } - }, - "ko": { - "stringUnit": { - "state": "translated", - "value": "sidebar.watchGitStatus git status branch watcher index lock git 상태 브랜치 사이드바" - } - }, - "nb": { - "stringUnit": { - "state": "translated", - "value": "sidebar.watchGitStatus git status branch watcher index lock git-status gren sidepanel" - } - }, - "pl": { - "stringUnit": { - "state": "translated", - "value": "sidebar.watchGitStatus git status branch watcher index lock status git gałąź pasek boczny" - } - }, - "pt-BR": { - "stringUnit": { - "state": "translated", - "value": "sidebar.watchGitStatus git status branch watcher index lock status git branch barra lateral" - } - }, - "ru": { - "stringUnit": { - "state": "translated", - "value": "sidebar.watchGitStatus git status branch watcher index lock состояние git ветка боковая панель" - } - }, - "th": { - "stringUnit": { - "state": "translated", - "value": "sidebar.watchGitStatus git status branch watcher index lock สถานะ git สาขา แถบด้านข้าง" - } - }, - "tr": { - "stringUnit": { - "state": "translated", - "value": "sidebar.watchGitStatus git status branch watcher index lock git durumu dal kenar çubuğu" - } - }, - "uk": { - "stringUnit": { - "state": "translated", - "value": "sidebar.watchGitStatus git status branch watcher index lock стан git гілка бічна панель" - } - }, - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "sidebar.watchGitStatus git status branch watcher index lock git 状态 分支 侧边栏" - } - }, - "zh-Hant": { - "stringUnit": { - "state": "translated", - "value": "sidebar.watchGitStatus git status branch watcher index lock git 狀態 分支 側邊欄" - } - } - } - }, "settings.search.alias.setting.app.open-pr-links": { "extractionState": "manual", "localizations": { @@ -79744,10 +78211,6 @@ } } }, - "settings.search.alias.setting.automation.subagent-notifications": { - "extractionState": "manual", - "localizations": {"ar":{"stringUnit":{"state":"translated","value":"automation.suppressSubagentNotifications وكيل فرعي متداخل طفل codex claude hook إشعارات"}},"bs":{"stringUnit":{"state":"translated","value":"automation.suppressSubagentNotifications podagent ugniježđen dječiji agent codex claude hook obavještenja"}},"da":{"stringUnit":{"state":"translated","value":"automation.suppressSubagentNotifications underagent indlejret børneagent codex claude hooks notifikationer"}},"de":{"stringUnit":{"state":"translated","value":"automation.suppressSubagentNotifications unteragent verschachtelt kindagent codex claude hooks benachrichtigungen"}},"en":{"stringUnit":{"state":"translated","value":"automation.suppressSubagentNotifications subagent nested child agent codex claude hooks notifications"}},"es":{"stringUnit":{"state":"translated","value":"automation.suppressSubagentNotifications subagente anidado agente secundario codex claude hooks notificaciones"}},"fr":{"stringUnit":{"state":"translated","value":"automation.suppressSubagentNotifications sous-agent imbriqué agent enfant codex claude hooks notifications"}},"it":{"stringUnit":{"state":"translated","value":"automation.suppressSubagentNotifications sottoagente annidato agente figlio codex claude hook notifiche"}},"ja":{"stringUnit":{"state":"translated","value":"automation.suppressSubagentNotifications サブエージェント ネスト 子エージェント codex claude フック 通知"}},"ko":{"stringUnit":{"state":"translated","value":"automation.suppressSubagentNotifications 하위 에이전트 중첩 자식 에이전트 codex claude 훅 알림"}},"nb":{"stringUnit":{"state":"translated","value":"automation.suppressSubagentNotifications underagent innebygd barneagent codex claude hooks varsler"}},"pl":{"stringUnit":{"state":"translated","value":"automation.suppressSubagentNotifications podagent zagnieżdżony agent podrzędny codex claude hooki powiadomienia"}},"pt-BR":{"stringUnit":{"state":"translated","value":"automation.suppressSubagentNotifications subagente aninhado agente filho codex claude hooks notificações"}},"ru":{"stringUnit":{"state":"translated","value":"automation.suppressSubagentNotifications подагент вложенный дочерний агент codex claude hooks уведомления"}},"th":{"stringUnit":{"state":"translated","value":"automation.suppressSubagentNotifications เอเจนต์ย่อย ซ้อน เอเจนต์ลูก codex claude hook การแจ้งเตือน"}},"tr":{"stringUnit":{"state":"translated","value":"automation.suppressSubagentNotifications alt ajan iç içe çocuk ajan codex claude hook bildirimler"}},"uk":{"stringUnit":{"state":"translated","value":"automation.suppressSubagentNotifications підагент вкладений дочірній агент codex claude hooks сповіщення"}},"zh-Hans":{"stringUnit":{"state":"translated","value":"automation.suppressSubagentNotifications 子代理 嵌套 子级代理 codex claude hooks 通知"}},"zh-Hant":{"stringUnit":{"state":"translated","value":"automation.suppressSubagentNotifications 子代理 巢狀 子級代理 codex claude hooks 通知"}}} - }, "settings.search.alias.setting.automation.cursor": { "extractionState": "manual", "localizations": { @@ -83114,23457 +81577,24409 @@ } } }, - "settings.search.prompt": { + "settings.search.prompt": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Search" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "検索" + } + } + } + }, + "settings.search.noResults": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "No Results" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "結果なし" + } + } + } + }, + "settings.workspaceColors.base": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Base: %@" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "ベース: %@" + } + }, + "zh-Hans": { + "stringUnit": { + "state": "translated", + "value": "基础色:%@" + } + }, + "zh-Hant": { + "stringUnit": { + "state": "translated", + "value": "基底:%@" + } + }, + "ko": { + "stringUnit": { + "state": "translated", + "value": "기본: %@" + } + }, + "de": { + "stringUnit": { + "state": "translated", + "value": "Basis: %@" + } + }, + "es": { + "stringUnit": { + "state": "translated", + "value": "Base: %@" + } + }, + "fr": { + "stringUnit": { + "state": "translated", + "value": "Base : %@" + } + }, + "it": { + "stringUnit": { + "state": "translated", + "value": "Base: %@" + } + }, + "da": { + "stringUnit": { + "state": "translated", + "value": "Base: %@" + } + }, + "pl": { + "stringUnit": { + "state": "translated", + "value": "Bazowy: %@" + } + }, + "ru": { + "stringUnit": { + "state": "translated", + "value": "Базовый: %@" + } + }, + "bs": { + "stringUnit": { + "state": "translated", + "value": "Osnovna: %@" + } + }, + "ar": { + "stringUnit": { + "state": "translated", + "value": "الأساس: %@" + } + }, + "nb": { + "stringUnit": { + "state": "translated", + "value": "Basis: %@" + } + }, + "pt-BR": { + "stringUnit": { + "state": "translated", + "value": "Base: %@" + } + }, + "th": { + "stringUnit": { + "state": "translated", + "value": "ฐาน: %@" + } + }, + "tr": { + "stringUnit": { + "state": "translated", + "value": "Temel: %@" + } + }, + "uk": { + "stringUnit": { + "state": "translated", + "value": "Базовий: %@" + } + } + } + }, + "settings.workspaceColors.customColors": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Custom Colors" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "カスタムカラー" + } + }, + "zh-Hans": { + "stringUnit": { + "state": "translated", + "value": "自定义颜色" + } + }, + "zh-Hant": { + "stringUnit": { + "state": "translated", + "value": "自訂顏色" + } + }, + "ko": { + "stringUnit": { + "state": "translated", + "value": "사용자 지정 색상" + } + }, + "de": { + "stringUnit": { + "state": "translated", + "value": "Benutzerdefinierte Farben" + } + }, + "es": { + "stringUnit": { + "state": "translated", + "value": "Colores personalizados" + } + }, + "fr": { + "stringUnit": { + "state": "translated", + "value": "Couleurs personnalisées" + } + }, + "it": { + "stringUnit": { + "state": "translated", + "value": "Colori personalizzati" + } + }, + "da": { + "stringUnit": { + "state": "translated", + "value": "Brugerdefinerede farver" + } + }, + "pl": { + "stringUnit": { + "state": "translated", + "value": "Własne kolory" + } + }, + "ru": { + "stringUnit": { + "state": "translated", + "value": "Пользовательские цвета" + } + }, + "bs": { + "stringUnit": { + "state": "translated", + "value": "Prilagođene boje" + } + }, + "ar": { + "stringUnit": { + "state": "translated", + "value": "ألوان مخصصة" + } + }, + "nb": { + "stringUnit": { + "state": "translated", + "value": "Egendefinerte farger" + } + }, + "pt-BR": { + "stringUnit": { + "state": "translated", + "value": "Cores Personalizadas" + } + }, + "th": { + "stringUnit": { + "state": "translated", + "value": "สีที่กำหนดเอง" + } + }, + "tr": { + "stringUnit": { + "state": "translated", + "value": "Özel Renkler" + } + }, + "uk": { + "stringUnit": { + "state": "translated", + "value": "Власні кольори" + } + } + } + }, + "settings.workspaceColors.customEntry": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Named palette entry." + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "名前付きのパレット項目です。" + } + }, + "ko": { + "stringUnit": { + "state": "translated", + "value": "이름이 지정된 팔레트 항목." + } + } + } + }, + "settings.workspaceColors.dictionaryNote": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Edit cmux.json to add or remove named colors. \"Choose Custom Color...\" still adds local Custom N entries." + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "名前付きカラーの追加や削除は cmux.json を編集してください。「カスタムカラーを選択…」は引き続きローカルの Custom N エントリを追加します。" + } + }, + "ko": { + "stringUnit": { + "state": "translated", + "value": "cmux.json을 편집하여 이름이 지정된 색상을 추가하거나 제거하세요. \"사용자 지정 색상 선택...\"으로 로컬 Custom N 항목을 추가할 수 있습니다." + } + } + } + }, + "settings.workspaceColors.emptyPalette": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "No palette entries. Add colors in cmux.json or use \"Choose Custom Color...\" from a workspace context menu." + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "パレット項目はありません。cmux.json でカラーを追加するか、ワークスペースのコンテキストメニューから「カスタムカラーを選択…」を使ってください。" + } + }, + "ko": { + "stringUnit": { + "state": "translated", + "value": "팔레트 항목이 없습니다. cmux.json에서 색상을 추가하거나 워크스페이스 컨텍스트 메뉴의 \"사용자 지정 색상 선택...\"을 사용하세요." + } + } + } + }, + "settings.workspaceColors.indicator": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Workspace Color Indicator" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "ワークスペースカラーインジケーター" + } + }, + "zh-Hans": { + "stringUnit": { + "state": "translated", + "value": "工作区颜色指示器" + } + }, + "zh-Hant": { + "stringUnit": { + "state": "translated", + "value": "工作區顏色指示器" + } + }, + "ko": { + "stringUnit": { + "state": "translated", + "value": "작업 공간 색상 표시기" + } + }, + "de": { + "stringUnit": { + "state": "translated", + "value": "Arbeitsbereichsfarb-Indikator" + } + }, + "es": { + "stringUnit": { + "state": "translated", + "value": "Indicador de color del espacio de trabajo" + } + }, + "fr": { + "stringUnit": { + "state": "translated", + "value": "Indicateur de couleur d'espace de travail" + } + }, + "it": { + "stringUnit": { + "state": "translated", + "value": "Indicatore colore area di lavoro" + } + }, + "da": { + "stringUnit": { + "state": "translated", + "value": "Arbejdsområdefarveindikator" + } + }, + "pl": { + "stringUnit": { + "state": "translated", + "value": "Wskaźnik koloru przestrzeni roboczej" + } + }, + "ru": { + "stringUnit": { + "state": "translated", + "value": "Индикатор цвета рабочего пространства" + } + }, + "bs": { + "stringUnit": { + "state": "translated", + "value": "Indikator boje radnog prostora" + } + }, + "ar": { + "stringUnit": { + "state": "translated", + "value": "مؤشر لون مساحة العمل" + } + }, + "nb": { + "stringUnit": { + "state": "translated", + "value": "Arbeidsområdefarge-indikator" + } + }, + "pt-BR": { + "stringUnit": { + "state": "translated", + "value": "Indicador de Cor da Área de Trabalho" + } + }, + "th": { + "stringUnit": { + "state": "translated", + "value": "ตัวบ่งชี้สีเวิร์กสเปซ" + } + }, + "tr": { + "stringUnit": { + "state": "translated", + "value": "Çalışma Alanı Renk Göstergesi" + } + }, + "uk": { + "stringUnit": { + "state": "translated", + "value": "Індикатор кольору робочої області" + } + } + } + }, + "settings.workspaceColors.noCustomColors": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Search" + "value": "Custom colors: none yet. Use \"Choose Custom Color...\" from a workspace context menu." } }, "ja": { "stringUnit": { "state": "translated", - "value": "検索" + "value": "カスタムカラー: まだありません。ワークスペースのコンテキストメニューから「カスタムカラーを選択…」を使用してください。" + } + }, + "zh-Hans": { + "stringUnit": { + "state": "translated", + "value": "自定义颜色:暂无。请从工作区右键菜单中使用「选取自定义颜色...」。" + } + }, + "zh-Hant": { + "stringUnit": { + "state": "translated", + "value": "自訂顏色:尚無。請從工作區右鍵選單中使用「選擇自訂顏色...」。" + } + }, + "ko": { + "stringUnit": { + "state": "translated", + "value": "사용자 지정 색상: 아직 없습니다. 작업 공간 컨텍스트 메뉴에서 \"사용자 지정 색상 선택...\"을 사용하세요." + } + }, + "de": { + "stringUnit": { + "state": "translated", + "value": "Benutzerdefinierte Farben: noch keine. Verwenden Sie 'Eigene Farbe wählen ...' im Kontextmenü eines Arbeitsbereichs." + } + }, + "es": { + "stringUnit": { + "state": "translated", + "value": "Colores personalizados: ninguno aún. Usa \"Elegir color personalizado…\" desde el menú contextual de un espacio de trabajo." + } + }, + "fr": { + "stringUnit": { + "state": "translated", + "value": "Couleurs personnalisées : aucune pour le moment. Utilisez « Choisir une couleur personnalisée... » depuis le menu contextuel d'un espace de travail." + } + }, + "it": { + "stringUnit": { + "state": "translated", + "value": "Colori personalizzati: nessuno. Usa \"Scegli colore personalizzato...\" dal menu contestuale di un'area di lavoro." + } + }, + "da": { + "stringUnit": { + "state": "translated", + "value": "Brugerdefinerede farver: ingen endnu. Brug \"Vælg brugerdefineret farve...\" fra en arbejdsområdekontekstmenu." + } + }, + "pl": { + "stringUnit": { + "state": "translated", + "value": "Własne kolory: jeszcze żadnych. Użyj „Wybierz własny kolor…” z menu kontekstowego przestrzeni roboczej." + } + }, + "ru": { + "stringUnit": { + "state": "translated", + "value": "Пользовательские цвета: пока нет. Используйте «Выбрать пользовательский цвет...» из контекстного меню рабочего пространства." + } + }, + "bs": { + "stringUnit": { + "state": "translated", + "value": "Prilagođene boje: još nema. Koristite \"Odaberi prilagođenu boju...\" iz kontekstnog menija radnog prostora." + } + }, + "ar": { + "stringUnit": { + "state": "translated", + "value": "ألوان مخصصة: لا يوجد بعد. استخدم \"اختيار لون مخصص...\" من قائمة سياق مساحة العمل." + } + }, + "nb": { + "stringUnit": { + "state": "translated", + "value": "Egendefinerte farger: ingen ennå. Bruk «Velg egendefinert farge ...» fra en arbeidsområde-kontekstmeny." + } + }, + "pt-BR": { + "stringUnit": { + "state": "translated", + "value": "Cores personalizadas: nenhuma ainda. Use \"Escolher Cor Personalizada...\" no menu de contexto de uma área de trabalho." + } + }, + "th": { + "stringUnit": { + "state": "translated", + "value": "สีที่กำหนดเอง: ยังไม่มี ใช้ \"เลือกสีที่กำหนดเอง...\" จากเมนูบริบทเวิร์กสเปซ" + } + }, + "tr": { + "stringUnit": { + "state": "translated", + "value": "Özel renkler: henüz yok. Bir çalışma alanı bağlam menüsünden \"Özel Renk Seç...\" seçeneğini kullanın." + } + }, + "uk": { + "stringUnit": { + "state": "translated", + "value": "Власні кольори: ще немає. Використовуйте «Вибрати власний колір...» з контекстного меню робочої області." } } } }, - "settings.search.noResults": { + "settings.workspaceColors.paletteNote": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "No Results" + "value": "Customize the workspace color palette used by Sidebar > Workspace Color. \"Choose Custom Color...\" entries are persisted below." } }, "ja": { "stringUnit": { "state": "translated", - "value": "結果なし" + "value": "サイドバー > ワークスペースカラーで使用するカラーパレットをカスタマイズできます。「カスタムカラーを選択…」のエントリは以下に保存されます。" + } + }, + "zh-Hans": { + "stringUnit": { + "state": "translated", + "value": "自定义「侧边栏 > 工作区颜色」中使用的工作区调色板。「选取自定义颜色...」的条目将保存在下方。" + } + }, + "zh-Hant": { + "stringUnit": { + "state": "translated", + "value": "自訂側邊欄 > 工作區顏色使用的色板。「選擇自訂顏色...」的項目會保存在下方。" + } + }, + "ko": { + "stringUnit": { + "state": "translated", + "value": "사이드바 > 작업 공간 색상에서 사용하는 작업 공간 색상 팔레트를 사용자 지정합니다. \"사용자 지정 색상 선택...\" 항목은 아래에 저장됩니다." + } + }, + "de": { + "stringUnit": { + "state": "translated", + "value": "Passen Sie die Arbeitsbereichs-Farbpalette an, die unter Seitenleiste > Arbeitsbereichsfarbe verwendet wird. Einträge unter 'Eigene Farbe wählen ...' werden unten gespeichert." + } + }, + "es": { + "stringUnit": { + "state": "translated", + "value": "Personaliza la paleta de colores de espacios de trabajo usada en Barra lateral > Color del espacio de trabajo. Las entradas de \"Elegir color personalizado…\" se guardan a continuación." + } + }, + "fr": { + "stringUnit": { + "state": "translated", + "value": "Personnalisez la palette de couleurs utilisée par Barre latérale > Couleur de l'espace de travail. Les entrées « Choisir une couleur personnalisée... » sont enregistrées ci-dessous." + } + }, + "it": { + "stringUnit": { + "state": "translated", + "value": "Personalizza la palette di colori utilizzata da Barra laterale > Colore area di lavoro. Le voci \"Scegli colore personalizzato...\" vengono salvate qui sotto." + } + }, + "da": { + "stringUnit": { + "state": "translated", + "value": "Tilpas arbejdsområdets farvepalette, der bruges af Sidebjælke > Arbejdsområdefarve. \"Vælg brugerdefineret farve...\"-poster gemmes nedenfor." + } + }, + "pl": { + "stringUnit": { + "state": "translated", + "value": "Dostosuj paletę kolorów przestrzeni roboczej używaną przez Pasek boczny > Kolor przestrzeni roboczej. Wpisy „Wybierz własny kolor…” są zapisywane poniżej." + } + }, + "ru": { + "stringUnit": { + "state": "translated", + "value": "Настройте палитру цветов рабочих пространств, используемую в Боковая панель > Цвет рабочего пространства. Записи «Выбрать пользовательский цвет...» сохраняются ниже." + } + }, + "bs": { + "stringUnit": { + "state": "translated", + "value": "Prilagodite paletu boja radnog prostora koju koristi Bočna traka > Boja radnog prostora. Unosi \"Odaberi prilagođenu boju...\" su trajno sačuvani ispod." + } + }, + "ar": { + "stringUnit": { + "state": "translated", + "value": "تخصيص لوحة ألوان مساحة العمل المستخدمة بواسطة الشريط الجانبي > لون مساحة العمل. إدخالات \"اختيار لون مخصص...\" تُحفظ أدناه." + } + }, + "nb": { + "stringUnit": { + "state": "translated", + "value": "Tilpass arbeidsområdefargepaletten som brukes av Sidepanel > Arbeidsområdefarge. «Velg egendefinert farge ...»-oppføringer lagres nedenfor." + } + }, + "pt-BR": { + "stringUnit": { + "state": "translated", + "value": "Personalize a paleta de cores usada em Barra Lateral > Cor da Área de Trabalho. Entradas de \"Escolher Cor Personalizada...\" são salvas abaixo." + } + }, + "th": { + "stringUnit": { + "state": "translated", + "value": "ปรับแต่งจานสีเวิร์กสเปซที่ใช้ใน แถบด้านข้าง > สีเวิร์กสเปซ รายการ \"เลือกสีที่กำหนดเอง...\" จะถูกบันทึกด้านล่าง" + } + }, + "tr": { + "stringUnit": { + "state": "translated", + "value": "Kenar Çubuğu > Çalışma Alanı Rengi tarafından kullanılan çalışma alanı renk paletini özelleştirin. \"Özel Renk Seç...\" girişleri aşağıda saklanır." + } + }, + "uk": { + "stringUnit": { + "state": "translated", + "value": "Налаштуйте палітру кольорів робочих областей, яка використовується в Бічна панель > Колір робочої області. Записи «Вибрати власний колір...» зберігаються нижче." } } } }, - "settings.workspaceColors.base": { + "settings.workspaceColors.remove": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Base: %@" + "value": "Remove" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ベース: %@" + "value": "削除" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "基础色:%@" + "value": "移除" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "基底:%@" + "value": "移除" } }, "ko": { "stringUnit": { "state": "translated", - "value": "기본: %@" + "value": "제거" } }, "de": { "stringUnit": { "state": "translated", - "value": "Basis: %@" + "value": "Entfernen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Base: %@" + "value": "Eliminar" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Base : %@" + "value": "Supprimer" } }, "it": { "stringUnit": { "state": "translated", - "value": "Base: %@" + "value": "Rimuovi" } }, "da": { "stringUnit": { "state": "translated", - "value": "Base: %@" + "value": "Fjern" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Bazowy: %@" + "value": "Usuń" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Базовый: %@" + "value": "Удалить" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Osnovna: %@" + "value": "Ukloni" } }, "ar": { "stringUnit": { "state": "translated", - "value": "الأساس: %@" + "value": "إزالة" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Basis: %@" + "value": "Fjern" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Base: %@" + "value": "Remover" } }, "th": { "stringUnit": { "state": "translated", - "value": "ฐาน: %@" + "value": "ลบ" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Temel: %@" + "value": "Kaldır" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Базовий: %@" + "value": "Видалити" } } } }, - "settings.workspaceColors.customColors": { + "settings.workspaceColors.resetPalette": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Custom Colors" + "value": "Reset Palette" } }, "ja": { "stringUnit": { "state": "translated", - "value": "カスタムカラー" + "value": "パレットをリセット" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "自定义颜色" + "value": "重置调色板" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "自訂顏色" + "value": "重置色板" } }, "ko": { "stringUnit": { "state": "translated", - "value": "사용자 지정 색상" + "value": "팔레트 초기화" } }, "de": { "stringUnit": { "state": "translated", - "value": "Benutzerdefinierte Farben" + "value": "Palette zurücksetzen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Colores personalizados" + "value": "Restablecer paleta" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Couleurs personnalisées" + "value": "Réinitialiser la palette" } }, "it": { "stringUnit": { "state": "translated", - "value": "Colori personalizzati" + "value": "Ripristina palette" } }, "da": { "stringUnit": { "state": "translated", - "value": "Brugerdefinerede farver" + "value": "Nulstil palette" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Własne kolory" + "value": "Resetuj paletę" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Пользовательские цвета" + "value": "Сбросить палитру" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Prilagođene boje" + "value": "Resetuj paletu" } }, "ar": { "stringUnit": { "state": "translated", - "value": "ألوان مخصصة" + "value": "إعادة تعيين اللوحة" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Egendefinerte farger" + "value": "Tilbakestill palett" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Cores Personalizadas" + "value": "Redefinir Paleta" } }, "th": { "stringUnit": { "state": "translated", - "value": "สีที่กำหนดเอง" + "value": "รีเซ็ตจานสี" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Özel Renkler" + "value": "Paleti Sıfırla" + } + }, + "uk": { + "stringUnit": { + "state": "translated", + "value": "Скинути палітру" + } + } + } + }, + "settings.workspaceColors.resetPalette.button": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Reset" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "リセット" + } + }, + "zh-Hans": { + "stringUnit": { + "state": "translated", + "value": "重置" + } + }, + "zh-Hant": { + "stringUnit": { + "state": "translated", + "value": "重置" + } + }, + "ko": { + "stringUnit": { + "state": "translated", + "value": "초기화" + } + }, + "de": { + "stringUnit": { + "state": "translated", + "value": "Zurücksetzen" + } + }, + "es": { + "stringUnit": { + "state": "translated", + "value": "Restablecer" + } + }, + "fr": { + "stringUnit": { + "state": "translated", + "value": "Réinitialiser" + } + }, + "it": { + "stringUnit": { + "state": "translated", + "value": "Ripristina" + } + }, + "da": { + "stringUnit": { + "state": "translated", + "value": "Nulstil" + } + }, + "pl": { + "stringUnit": { + "state": "translated", + "value": "Resetuj" + } + }, + "ru": { + "stringUnit": { + "state": "translated", + "value": "Сбросить" + } + }, + "bs": { + "stringUnit": { + "state": "translated", + "value": "Resetuj" + } + }, + "ar": { + "stringUnit": { + "state": "translated", + "value": "إعادة تعيين" + } + }, + "nb": { + "stringUnit": { + "state": "translated", + "value": "Tilbakestill" + } + }, + "pt-BR": { + "stringUnit": { + "state": "translated", + "value": "Redefinir" + } + }, + "th": { + "stringUnit": { + "state": "translated", + "value": "รีเซ็ต" + } + }, + "tr": { + "stringUnit": { + "state": "translated", + "value": "Sıfırla" + } + }, + "uk": { + "stringUnit": { + "state": "translated", + "value": "Скинути" + } + } + } + }, + "settings.workspaceColors.resetPalette.subtitle": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Restore built-in defaults and clear all custom colors." + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "組み込みのデフォルトに戻し、すべてのカスタムカラーをクリアします。" + } + }, + "zh-Hans": { + "stringUnit": { + "state": "translated", + "value": "恢复内置默认值并清除所有自定义颜色。" + } + }, + "zh-Hant": { + "stringUnit": { + "state": "translated", + "value": "恢復內建預設值並清除所有自訂顏色。" + } + }, + "ko": { + "stringUnit": { + "state": "translated", + "value": "기본 제공 값을 복원하고 모든 사용자 지정 색상을 지웁니다." + } + }, + "de": { + "stringUnit": { + "state": "translated", + "value": "Integrierte Standardeinstellungen wiederherstellen und alle benutzerdefinierten Farben löschen." + } + }, + "es": { + "stringUnit": { + "state": "translated", + "value": "Restaurar los valores predeterminados y borrar todos los colores personalizados." + } + }, + "fr": { + "stringUnit": { + "state": "translated", + "value": "Restaurer les valeurs par défaut et effacer toutes les couleurs personnalisées." + } + }, + "it": { + "stringUnit": { + "state": "translated", + "value": "Ripristina i valori predefiniti e cancella tutti i colori personalizzati." + } + }, + "da": { + "stringUnit": { + "state": "translated", + "value": "Gendan indbyggede standardindstillinger og ryd alle brugerdefinerede farver." + } + }, + "pl": { + "stringUnit": { + "state": "translated", + "value": "Przywróć wbudowane wartości domyślne i wyczyść wszystkie własne kolory." + } + }, + "ru": { + "stringUnit": { + "state": "translated", + "value": "Восстановить встроенные значения по умолчанию и удалить все пользовательские цвета." } }, - "uk": { + "bs": { "stringUnit": { "state": "translated", - "value": "Власні кольори" + "value": "Vrati ugrađene podrazumijevane vrijednosti i obriši sve prilagođene boje." } - } - } - }, - "settings.workspaceColors.customEntry": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "ar": { "stringUnit": { "state": "translated", - "value": "Named palette entry." + "value": "استعادة الإعدادات الافتراضية المدمجة ومسح جميع الألوان المخصصة." } }, - "ja": { + "nb": { "stringUnit": { "state": "translated", - "value": "名前付きのパレット項目です。" + "value": "Gjenopprett innebygde standardverdier og fjern alle egendefinerte farger." } }, - "ko": { + "pt-BR": { "stringUnit": { "state": "translated", - "value": "이름이 지정된 팔레트 항목." + "value": "Restaurar padrões integrados e limpar todas as cores personalizadas." } - } - } - }, - "settings.workspaceColors.dictionaryNote": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "th": { "stringUnit": { "state": "translated", - "value": "Edit cmux.json to add or remove named colors. \"Choose Custom Color...\" still adds local Custom N entries." + "value": "คืนค่าเริ่มต้นในตัวและล้างสีที่กำหนดเองทั้งหมด" } }, - "ja": { + "tr": { "stringUnit": { "state": "translated", - "value": "名前付きカラーの追加や削除は cmux.json を編集してください。「カスタムカラーを選択…」は引き続きローカルの Custom N エントリを追加します。" + "value": "Yerleşik varsayılanları geri yükle ve tüm özel renkleri temizle." } }, - "ko": { + "uk": { "stringUnit": { "state": "translated", - "value": "cmux.json을 편집하여 이름이 지정된 색상을 추가하거나 제거하세요. \"사용자 지정 색상 선택...\"으로 로컬 Custom N 항목을 추가할 수 있습니다." + "value": "Відновити вбудовані стандартні значення та очистити всі власні кольори." } } } }, - "settings.workspaceColors.emptyPalette": { + "settings.workspaceColors.resetPalette.subtitleV2": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "No palette entries. Add colors in cmux.json or use \"Choose Custom Color...\" from a workspace context menu." + "value": "Restore the built-in palette and remove extra named colors." } }, "ja": { "stringUnit": { "state": "translated", - "value": "パレット項目はありません。cmux.json でカラーを追加するか、ワークスペースのコンテキストメニューから「カスタムカラーを選択…」を使ってください。" + "value": "組み込みパレットを復元し、追加した名前付きカラーを削除します。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "팔레트 항목이 없습니다. cmux.json에서 색상을 추가하거나 워크스페이스 컨텍스트 메뉴의 \"사용자 지정 색상 선택...\"을 사용하세요." + "value": "기본 팔레트를 복원하고 추가된 이름 있는 색상을 제거합니다." } } } }, - "settings.workspaceColors.indicator": { + "shortcut.closeWindow.label": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Workspace Color Indicator" + "value": "Close Window" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ワークスペースカラーインジケーター" + "value": "ウインドウを閉じる" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "工作区颜色指示器" + "value": "关闭窗口" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "工作區顏色指示器" + "value": "關閉視窗" } }, "ko": { "stringUnit": { "state": "translated", - "value": "작업 공간 색상 표시기" + "value": "윈도우 닫기" } }, "de": { "stringUnit": { "state": "translated", - "value": "Arbeitsbereichsfarb-Indikator" + "value": "Fenster schließen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Indicador de color del espacio de trabajo" + "value": "Cerrar ventana" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Indicateur de couleur d'espace de travail" + "value": "Fermer la fenêtre" } }, "it": { "stringUnit": { "state": "translated", - "value": "Indicatore colore area di lavoro" + "value": "Chiudi finestra" } }, "da": { "stringUnit": { "state": "translated", - "value": "Arbejdsområdefarveindikator" + "value": "Luk vindue" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Wskaźnik koloru przestrzeni roboczej" + "value": "Zamknij okno" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Индикатор цвета рабочего пространства" + "value": "Закрыть окно" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Indikator boje radnog prostora" + "value": "Zatvori prozor" } }, "ar": { "stringUnit": { "state": "translated", - "value": "مؤشر لون مساحة العمل" + "value": "إغلاق النافذة" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Arbeidsområdefarge-indikator" + "value": "Lukk vindu" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Indicador de Cor da Área de Trabalho" + "value": "Fechar Janela" } }, "th": { "stringUnit": { "state": "translated", - "value": "ตัวบ่งชี้สีเวิร์กสเปซ" + "value": "ปิดหน้าต่าง" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Çalışma Alanı Renk Göstergesi" + "value": "Pencereyi Kapat" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Індикатор кольору робочої області" + "value": "Закрити вікно" } } } }, - "settings.workspaceColors.noCustomColors": { + "shortcut.closeWorkspace.label": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Custom colors: none yet. Use \"Choose Custom Color...\" from a workspace context menu." + "value": "Close Workspace" } }, "ja": { "stringUnit": { "state": "translated", - "value": "カスタムカラー: まだありません。ワークスペースのコンテキストメニューから「カスタムカラーを選択…」を使用してください。" + "value": "ワークスペースを閉じる" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "自定义颜色:暂无。请从工作区右键菜单中使用「选取自定义颜色...」。" + "value": "关闭工作区" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "自訂顏色:尚無。請從工作區右鍵選單中使用「選擇自訂顏色...」。" + "value": "關閉工作區" } }, "ko": { "stringUnit": { "state": "translated", - "value": "사용자 지정 색상: 아직 없습니다. 작업 공간 컨텍스트 메뉴에서 \"사용자 지정 색상 선택...\"을 사용하세요." + "value": "작업 공간 닫기" } }, "de": { "stringUnit": { "state": "translated", - "value": "Benutzerdefinierte Farben: noch keine. Verwenden Sie 'Eigene Farbe wählen ...' im Kontextmenü eines Arbeitsbereichs." + "value": "Arbeitsbereich schließen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Colores personalizados: ninguno aún. Usa \"Elegir color personalizado…\" desde el menú contextual de un espacio de trabajo." + "value": "Cerrar espacio de trabajo" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Couleurs personnalisées : aucune pour le moment. Utilisez « Choisir une couleur personnalisée... » depuis le menu contextuel d'un espace de travail." + "value": "Fermer l'espace de travail" } }, "it": { "stringUnit": { "state": "translated", - "value": "Colori personalizzati: nessuno. Usa \"Scegli colore personalizzato...\" dal menu contestuale di un'area di lavoro." + "value": "Chiudi area di lavoro" } }, "da": { "stringUnit": { "state": "translated", - "value": "Brugerdefinerede farver: ingen endnu. Brug \"Vælg brugerdefineret farve...\" fra en arbejdsområdekontekstmenu." + "value": "Luk arbejdsområde" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Własne kolory: jeszcze żadnych. Użyj „Wybierz własny kolor…” z menu kontekstowego przestrzeni roboczej." + "value": "Zamknij przestrzeń roboczą" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Пользовательские цвета: пока нет. Используйте «Выбрать пользовательский цвет...» из контекстного меню рабочего пространства." + "value": "Закрыть рабочее пространство" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Prilagođene boje: još nema. Koristite \"Odaberi prilagođenu boju...\" iz kontekstnog menija radnog prostora." + "value": "Zatvori radni prostor" } }, "ar": { "stringUnit": { "state": "translated", - "value": "ألوان مخصصة: لا يوجد بعد. استخدم \"اختيار لون مخصص...\" من قائمة سياق مساحة العمل." + "value": "إغلاق مساحة العمل" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Egendefinerte farger: ingen ennå. Bruk «Velg egendefinert farge ...» fra en arbeidsområde-kontekstmeny." + "value": "Lukk arbeidsområde" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Cores personalizadas: nenhuma ainda. Use \"Escolher Cor Personalizada...\" no menu de contexto de uma área de trabalho." + "value": "Fechar Área de Trabalho" } }, "th": { "stringUnit": { "state": "translated", - "value": "สีที่กำหนดเอง: ยังไม่มี ใช้ \"เลือกสีที่กำหนดเอง...\" จากเมนูบริบทเวิร์กสเปซ" + "value": "ปิดเวิร์กสเปซ" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Özel renkler: henüz yok. Bir çalışma alanı bağlam menüsünden \"Özel Renk Seç...\" seçeneğini kullanın." + "value": "Çalışma Alanını Kapat" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Власні кольори: ще немає. Використовуйте «Вибрати власний колір...» з контекстного меню робочої області." + "value": "Закрити робочу область" } } } }, - "settings.workspaceColors.paletteNote": { + "shortcut.flashFocusedPanel.label": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Customize the workspace color palette used by Sidebar > Workspace Color. \"Choose Custom Color...\" entries are persisted below." + "value": "Flash Focused Panel" } }, "ja": { "stringUnit": { "state": "translated", - "value": "サイドバー > ワークスペースカラーで使用するカラーパレットをカスタマイズできます。「カスタムカラーを選択…」のエントリは以下に保存されます。" + "value": "フォーカスペインを強調" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "自定义「侧边栏 > 工作区颜色」中使用的工作区调色板。「选取自定义颜色...」的条目将保存在下方。" + "value": "闪烁聚焦面板" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "自訂側邊欄 > 工作區顏色使用的色板。「選擇自訂顏色...」的項目會保存在下方。" + "value": "閃爍聚焦面板" } }, "ko": { "stringUnit": { "state": "translated", - "value": "사이드바 > 작업 공간 색상에서 사용하는 작업 공간 색상 팔레트를 사용자 지정합니다. \"사용자 지정 색상 선택...\" 항목은 아래에 저장됩니다." + "value": "포커스된 패널 깜빡이기" } }, "de": { "stringUnit": { "state": "translated", - "value": "Passen Sie die Arbeitsbereichs-Farbpalette an, die unter Seitenleiste > Arbeitsbereichsfarbe verwendet wird. Einträge unter 'Eigene Farbe wählen ...' werden unten gespeichert." + "value": "Fokussierten Bereich hervorheben" } }, "es": { "stringUnit": { "state": "translated", - "value": "Personaliza la paleta de colores de espacios de trabajo usada en Barra lateral > Color del espacio de trabajo. Las entradas de \"Elegir color personalizado…\" se guardan a continuación." + "value": "Resaltar panel enfocado" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Personnalisez la palette de couleurs utilisée par Barre latérale > Couleur de l'espace de travail. Les entrées « Choisir une couleur personnalisée... » sont enregistrées ci-dessous." + "value": "Flasher le panneau actif" } }, "it": { "stringUnit": { "state": "translated", - "value": "Personalizza la palette di colori utilizzata da Barra laterale > Colore area di lavoro. Le voci \"Scegli colore personalizzato...\" vengono salvate qui sotto." + "value": "Evidenzia pannello attivo" } }, "da": { "stringUnit": { "state": "translated", - "value": "Tilpas arbejdsområdets farvepalette, der bruges af Sidebjælke > Arbejdsområdefarve. \"Vælg brugerdefineret farve...\"-poster gemmes nedenfor." + "value": "Fremhæv fokuseret panel" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Dostosuj paletę kolorów przestrzeni roboczej używaną przez Pasek boczny > Kolor przestrzeni roboczej. Wpisy „Wybierz własny kolor…” są zapisywane poniżej." + "value": "Podświetl aktywny panel" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Настройте палитру цветов рабочих пространств, используемую в Боковая панель > Цвет рабочего пространства. Записи «Выбрать пользовательский цвет...» сохраняются ниже." + "value": "Подсветить активную панель" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Prilagodite paletu boja radnog prostora koju koristi Bočna traka > Boja radnog prostora. Unosi \"Odaberi prilagođenu boju...\" su trajno sačuvani ispod." + "value": "Označi fokusirani panel" } }, "ar": { "stringUnit": { "state": "translated", - "value": "تخصيص لوحة ألوان مساحة العمل المستخدمة بواسطة الشريط الجانبي > لون مساحة العمل. إدخالات \"اختيار لون مخصص...\" تُحفظ أدناه." + "value": "وميض اللوحة المركّزة" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Tilpass arbeidsområdefargepaletten som brukes av Sidepanel > Arbeidsområdefarge. «Velg egendefinert farge ...»-oppføringer lagres nedenfor." + "value": "Blink fokusert panel" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Personalize a paleta de cores usada em Barra Lateral > Cor da Área de Trabalho. Entradas de \"Escolher Cor Personalizada...\" são salvas abaixo." + "value": "Piscar Painel em Foco" } }, "th": { "stringUnit": { "state": "translated", - "value": "ปรับแต่งจานสีเวิร์กสเปซที่ใช้ใน แถบด้านข้าง > สีเวิร์กสเปซ รายการ \"เลือกสีที่กำหนดเอง...\" จะถูกบันทึกด้านล่าง" + "value": "กะพริบแผงที่โฟกัส" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Kenar Çubuğu > Çalışma Alanı Rengi tarafından kullanılan çalışma alanı renk paletini özelleştirin. \"Özel Renk Seç...\" girişleri aşağıda saklanır." + "value": "Odaklanılan Paneli Yanıp Söndür" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Налаштуйте палітру кольорів робочих областей, яка використовується в Бічна панель > Колір робочої області. Записи «Вибрати власний колір...» зберігаються нижче." + "value": "Підсвітити активну панель" } } } }, - "settings.workspaceColors.remove": { + "shortcut.focusPaneDown.label": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Remove" + "value": "Focus Pane Down" } }, "ja": { "stringUnit": { "state": "translated", - "value": "削除" + "value": "下のペインにフォーカス" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "移除" + "value": "聚焦下方面板" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "移除" + "value": "聚焦下方面板" } }, "ko": { "stringUnit": { "state": "translated", - "value": "제거" + "value": "아래쪽 패널로 포커스" } }, "de": { "stringUnit": { "state": "translated", - "value": "Entfernen" + "value": "Bereich unten fokussieren" } }, "es": { "stringUnit": { "state": "translated", - "value": "Eliminar" + "value": "Enfocar panel inferior" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Supprimer" + "value": "Activer le panneau du bas" } }, "it": { "stringUnit": { "state": "translated", - "value": "Rimuovi" + "value": "Sposta focus pannello in basso" } }, "da": { "stringUnit": { "state": "translated", - "value": "Fjern" + "value": "Fokuser panel nedad" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Usuń" + "value": "Fokus na panel poniżej" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Удалить" + "value": "Фокус на панель снизу" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Ukloni" + "value": "Fokusiraj panel dolje" } }, "ar": { "stringUnit": { "state": "translated", - "value": "إزالة" + "value": "التركيز على اللوحة أسفل" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Fjern" + "value": "Fokuser panel ned" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Remover" + "value": "Focar Painel Abaixo" } }, "th": { "stringUnit": { "state": "translated", - "value": "ลบ" + "value": "โฟกัสบานหน้าต่างด้านล่าง" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Kaldır" + "value": "Aşağıdaki Bölmeye Odaklan" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Видалити" + "value": "Фокус на панель внизу" } } } }, - "settings.workspaceColors.resetPalette": { + "shortcut.focusPaneLeft.label": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Reset Palette" + "value": "Focus Pane Left" } }, "ja": { "stringUnit": { "state": "translated", - "value": "パレットをリセット" + "value": "左のペインにフォーカス" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "重置调色板" + "value": "聚焦左侧面板" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "重置色板" + "value": "聚焦左側面板" } }, "ko": { "stringUnit": { "state": "translated", - "value": "팔레트 초기화" + "value": "왼쪽 패널로 포커스" } }, "de": { "stringUnit": { "state": "translated", - "value": "Palette zurücksetzen" + "value": "Bereich links fokussieren" } }, "es": { "stringUnit": { "state": "translated", - "value": "Restablecer paleta" + "value": "Enfocar panel izquierdo" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Réinitialiser la palette" + "value": "Activer le panneau de gauche" } }, "it": { "stringUnit": { "state": "translated", - "value": "Ripristina palette" + "value": "Sposta focus pannello a sinistra" } }, "da": { "stringUnit": { "state": "translated", - "value": "Nulstil palette" + "value": "Fokuser panel til venstre" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Resetuj paletę" + "value": "Fokus na panel po lewej" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Сбросить палитру" + "value": "Фокус на панель слева" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Resetuj paletu" + "value": "Fokusiraj panel lijevo" } }, "ar": { "stringUnit": { "state": "translated", - "value": "إعادة تعيين اللوحة" + "value": "التركيز على اللوحة يسار" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Tilbakestill palett" + "value": "Fokuser panel venstre" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Redefinir Paleta" + "value": "Focar Painel à Esquerda" } }, "th": { "stringUnit": { "state": "translated", - "value": "รีเซ็ตจานสี" + "value": "โฟกัสบานหน้าต่างด้านซ้าย" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Paleti Sıfırla" + "value": "Soldaki Bölmeye Odaklan" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Скинути палітру" + "value": "Фокус на панель зліва" } } } }, - "settings.workspaceColors.resetPalette.button": { + "shortcut.focusPaneRight.label": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Reset" + "value": "Focus Pane Right" } }, "ja": { "stringUnit": { "state": "translated", - "value": "リセット" + "value": "右のペインにフォーカス" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "重置" + "value": "聚焦右侧面板" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "重置" + "value": "聚焦右側面板" } }, "ko": { "stringUnit": { "state": "translated", - "value": "초기화" + "value": "오른쪽 패널로 포커스" } }, "de": { "stringUnit": { "state": "translated", - "value": "Zurücksetzen" + "value": "Bereich rechts fokussieren" } }, "es": { "stringUnit": { "state": "translated", - "value": "Restablecer" + "value": "Enfocar panel derecho" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Réinitialiser" + "value": "Activer le panneau de droite" } }, "it": { "stringUnit": { "state": "translated", - "value": "Ripristina" + "value": "Sposta focus pannello a destra" } }, "da": { "stringUnit": { "state": "translated", - "value": "Nulstil" + "value": "Fokuser panel til højre" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Resetuj" + "value": "Fokus na panel po prawej" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Сбросить" + "value": "Фокус на панель справа" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Resetuj" + "value": "Fokusiraj panel desno" } }, "ar": { "stringUnit": { "state": "translated", - "value": "إعادة تعيين" + "value": "التركيز على اللوحة يمين" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Tilbakestill" + "value": "Fokuser panel høyre" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Redefinir" + "value": "Focar Painel à Direita" } }, "th": { "stringUnit": { "state": "translated", - "value": "รีเซ็ต" + "value": "โฟกัสบานหน้าต่างด้านขวา" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Sıfırla" + "value": "Sağdaki Bölmeye Odaklan" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Скинути" + "value": "Фокус на панель справа" } } } }, - "settings.workspaceColors.resetPalette.subtitle": { + "shortcut.focusPaneUp.label": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Restore built-in defaults and clear all custom colors." + "value": "Focus Pane Up" } }, "ja": { "stringUnit": { "state": "translated", - "value": "組み込みのデフォルトに戻し、すべてのカスタムカラーをクリアします。" + "value": "上のペインにフォーカス" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "恢复内置默认值并清除所有自定义颜色。" + "value": "聚焦上方面板" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "恢復內建預設值並清除所有自訂顏色。" + "value": "聚焦上方面板" } }, "ko": { "stringUnit": { "state": "translated", - "value": "기본 제공 값을 복원하고 모든 사용자 지정 색상을 지웁니다." + "value": "위쪽 패널로 포커스" } }, "de": { "stringUnit": { "state": "translated", - "value": "Integrierte Standardeinstellungen wiederherstellen und alle benutzerdefinierten Farben löschen." + "value": "Bereich oben fokussieren" } }, "es": { "stringUnit": { "state": "translated", - "value": "Restaurar los valores predeterminados y borrar todos los colores personalizados." + "value": "Enfocar panel superior" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Restaurer les valeurs par défaut et effacer toutes les couleurs personnalisées." + "value": "Activer le panneau du haut" } }, "it": { "stringUnit": { "state": "translated", - "value": "Ripristina i valori predefiniti e cancella tutti i colori personalizzati." + "value": "Sposta focus pannello in alto" } }, "da": { "stringUnit": { "state": "translated", - "value": "Gendan indbyggede standardindstillinger og ryd alle brugerdefinerede farver." + "value": "Fokuser panel opad" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Przywróć wbudowane wartości domyślne i wyczyść wszystkie własne kolory." + "value": "Fokus na panel powyżej" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Восстановить встроенные значения по умолчанию и удалить все пользовательские цвета." + "value": "Фокус на панель сверху" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Vrati ugrađene podrazumijevane vrijednosti i obriši sve prilagođene boje." + "value": "Fokusiraj panel gore" } }, "ar": { "stringUnit": { "state": "translated", - "value": "استعادة الإعدادات الافتراضية المدمجة ومسح جميع الألوان المخصصة." + "value": "التركيز على اللوحة أعلى" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Gjenopprett innebygde standardverdier og fjern alle egendefinerte farger." + "value": "Fokuser panel opp" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Restaurar padrões integrados e limpar todas as cores personalizadas." + "value": "Focar Painel Acima" } }, "th": { "stringUnit": { "state": "translated", - "value": "คืนค่าเริ่มต้นในตัวและล้างสีที่กำหนดเองทั้งหมด" + "value": "โฟกัสบานหน้าต่างด้านบน" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Yerleşik varsayılanları geri yükle ve tüm özel renkleri temizle." + "value": "Yukarıdaki Bölmeye Odaklan" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Відновити вбудовані стандартні значення та очистити всі власні кольори." - } - } - } - }, - "settings.workspaceColors.resetPalette.subtitleV2": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Restore the built-in palette and remove extra named colors." - } - }, - "ja": { - "stringUnit": { - "state": "translated", - "value": "組み込みパレットを復元し、追加した名前付きカラーを削除します。" - } - }, - "ko": { - "stringUnit": { - "state": "translated", - "value": "기본 팔레트를 복원하고 추가된 이름 있는 색상을 제거합니다." + "value": "Фокус на панель зверху" } } } }, - "shortcut.closeWindow.label": { + "shortcut.jumpToUnread.label": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Close Window" + "value": "Jump to Latest Unread" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ウインドウを閉じる" + "value": "最新の未読にジャンプ" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "关闭窗口" + "value": "跳转到最新未读" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "關閉視窗" + "value": "跳至最新未讀" } }, "ko": { "stringUnit": { "state": "translated", - "value": "윈도우 닫기" + "value": "최신 읽지 않은 항목으로 이동" } }, "de": { "stringUnit": { "state": "translated", - "value": "Fenster schließen" + "value": "Zur letzten ungelesenen springen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Cerrar ventana" + "value": "Ir a la última no leída" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Fermer la fenêtre" + "value": "Aller au dernier message non lu" } }, "it": { "stringUnit": { "state": "translated", - "value": "Chiudi finestra" + "value": "Vai all'ultimo non letto" } }, "da": { "stringUnit": { "state": "translated", - "value": "Luk vindue" + "value": "Gå til seneste ulæste" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Zamknij okno" + "value": "Przejdź do najnowszego nieprzeczytanego" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Закрыть окно" + "value": "Перейти к последнему непрочитанному" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Zatvori prozor" + "value": "Skoči na najnovije nepročitano" } }, "ar": { "stringUnit": { "state": "translated", - "value": "إغلاق النافذة" + "value": "الانتقال إلى أحدث غير مقروء" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Lukk vindu" + "value": "Gå til siste uleste" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Fechar Janela" + "value": "Ir para Última Não Lida" } }, "th": { "stringUnit": { "state": "translated", - "value": "ปิดหน้าต่าง" + "value": "ข้ามไปยังรายการยังไม่อ่านล่าสุด" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Pencereyi Kapat" + "value": "Son Okunmamışa Atla" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Закрити вікно" + "value": "Перейти до останнього непрочитаного" } } } }, - "shortcut.closeWorkspace.label": { + "shortcut.toggleUnread.label": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Close Workspace" + "value": "Toggle Unread" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ワークスペースを閉じる" + "value": "未読を切り替え" + } + } + } + }, + "shortcut.markOldestUnreadAndJumpNext.label": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Mark as Oldest Unread and Jump to Next Latest Unread" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "最古の未読としてマークして次の最新未読にジャンプ" + } + } + } + }, + "shortcut.newSurface.label": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "New Surface" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "新規サーフェス" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "关闭工作区" + "value": "新建 Surface" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "關閉工作區" + "value": "新增 Surface" } }, "ko": { "stringUnit": { "state": "translated", - "value": "작업 공간 닫기" + "value": "새 화면" } }, "de": { "stringUnit": { "state": "translated", - "value": "Arbeitsbereich schließen" + "value": "Neue Oberfläche" } }, "es": { "stringUnit": { "state": "translated", - "value": "Cerrar espacio de trabajo" + "value": "Nueva superficie" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Fermer l'espace de travail" + "value": "Nouvelle surface" } }, "it": { "stringUnit": { "state": "translated", - "value": "Chiudi area di lavoro" + "value": "Nuova superficie" } }, "da": { "stringUnit": { "state": "translated", - "value": "Luk arbejdsområde" + "value": "Ny overflade" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Zamknij przestrzeń roboczą" + "value": "Nowa powierzchnia" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Закрыть рабочее пространство" + "value": "Новая поверхность" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Zatvori radni prostor" + "value": "Nova površina" } }, "ar": { "stringUnit": { "state": "translated", - "value": "إغلاق مساحة العمل" + "value": "سطح جديد" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Lukk arbeidsområde" + "value": "Ny flate" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Fechar Área de Trabalho" + "value": "Nova Superfície" } }, "th": { "stringUnit": { "state": "translated", - "value": "ปิดเวิร์กสเปซ" + "value": "พื้นผิวใหม่" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Çalışma Alanını Kapat" + "value": "Yeni Yüzey" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Закрити робочу область" + "value": "Нова поверхня" } } } }, - "shortcut.flashFocusedPanel.label": { + "shortcut.newWindow.label": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Flash Focused Panel" + "value": "New Window" } }, "ja": { "stringUnit": { "state": "translated", - "value": "フォーカスペインを強調" + "value": "新規ウインドウ" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "闪烁聚焦面板" + "value": "新建窗口" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "閃爍聚焦面板" + "value": "新增視窗" } }, "ko": { "stringUnit": { "state": "translated", - "value": "포커스된 패널 깜빡이기" + "value": "새 윈도우" } }, "de": { "stringUnit": { "state": "translated", - "value": "Fokussierten Bereich hervorheben" + "value": "Neues Fenster" } }, "es": { "stringUnit": { "state": "translated", - "value": "Resaltar panel enfocado" + "value": "Nueva ventana" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Flasher le panneau actif" + "value": "Nouvelle fenêtre" } }, "it": { "stringUnit": { "state": "translated", - "value": "Evidenzia pannello attivo" + "value": "Nuova finestra" } }, "da": { "stringUnit": { "state": "translated", - "value": "Fremhæv fokuseret panel" + "value": "Nyt vindue" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Podświetl aktywny panel" + "value": "Nowe okno" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Подсветить активную панель" + "value": "Новое окно" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Označi fokusirani panel" + "value": "Novi prozor" } }, "ar": { "stringUnit": { "state": "translated", - "value": "وميض اللوحة المركّزة" + "value": "نافذة جديدة" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Blink fokusert panel" + "value": "Nytt vindu" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Piscar Painel em Foco" + "value": "Nova Janela" } }, "th": { "stringUnit": { "state": "translated", - "value": "กะพริบแผงที่โฟกัส" + "value": "หน้าต่างใหม่" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Odaklanılan Paneli Yanıp Söndür" + "value": "Yeni Pencere" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Підсвітити активну панель" + "value": "Нове вікно" } } } }, - "shortcut.focusPaneDown.label": { + "shortcut.newWorkspace.label": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Focus Pane Down" + "value": "New Workspace" } }, "ja": { "stringUnit": { "state": "translated", - "value": "下のペインにフォーカス" + "value": "新規ワークスペース" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "聚焦下方面板" + "value": "新建工作区" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "聚焦下方面板" + "value": "新增工作區" } }, "ko": { "stringUnit": { "state": "translated", - "value": "아래쪽 패널로 포커스" + "value": "새 작업 공간" } }, "de": { "stringUnit": { "state": "translated", - "value": "Bereich unten fokussieren" + "value": "Neuer Arbeitsbereich" } }, "es": { "stringUnit": { "state": "translated", - "value": "Enfocar panel inferior" + "value": "Nuevo espacio de trabajo" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Activer le panneau du bas" + "value": "Nouvel espace de travail" } }, "it": { "stringUnit": { "state": "translated", - "value": "Sposta focus pannello in basso" + "value": "Nuova area di lavoro" } }, "da": { "stringUnit": { "state": "translated", - "value": "Fokuser panel nedad" + "value": "Nyt arbejdsområde" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Fokus na panel poniżej" + "value": "Nowa przestrzeń robocza" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Фокус на панель снизу" + "value": "Новое рабочее пространство" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Fokusiraj panel dolje" + "value": "Novi radni prostor" } }, "ar": { "stringUnit": { "state": "translated", - "value": "التركيز على اللوحة أسفل" + "value": "مساحة عمل جديدة" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Fokuser panel ned" + "value": "Nytt arbeidsområde" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Focar Painel Abaixo" + "value": "Nova Área de Trabalho" } }, "th": { "stringUnit": { "state": "translated", - "value": "โฟกัสบานหน้าต่างด้านล่าง" + "value": "เวิร์กสเปซใหม่" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Aşağıdaki Bölmeye Odaklan" + "value": "Yeni Çalışma Alanı" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Фокус на панель внизу" + "value": "Нова робоча область" } } } }, - "shortcut.focusPaneLeft.label": { + "shortcut.nextSurface.label": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Focus Pane Left" + "value": "Next Surface" } }, "ja": { "stringUnit": { "state": "translated", - "value": "左のペインにフォーカス" + "value": "次のサーフェス" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "聚焦左侧面板" + "value": "下一个 Surface" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "聚焦左側面板" + "value": "下一個 Surface" } }, "ko": { "stringUnit": { "state": "translated", - "value": "왼쪽 패널로 포커스" + "value": "다음 화면" } }, "de": { "stringUnit": { "state": "translated", - "value": "Bereich links fokussieren" + "value": "Nächste Oberfläche" } }, "es": { "stringUnit": { "state": "translated", - "value": "Enfocar panel izquierdo" + "value": "Siguiente superficie" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Activer le panneau de gauche" + "value": "Surface suivante" } }, "it": { "stringUnit": { "state": "translated", - "value": "Sposta focus pannello a sinistra" + "value": "Superficie successiva" } }, "da": { "stringUnit": { "state": "translated", - "value": "Fokuser panel til venstre" + "value": "Næste overflade" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Fokus na panel po lewej" + "value": "Następna powierzchnia" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Фокус на панель слева" + "value": "Следующая поверхность" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Fokusiraj panel lijevo" + "value": "Sljedeća površina" } }, "ar": { "stringUnit": { "state": "translated", - "value": "التركيز على اللوحة يسار" + "value": "السطح التالي" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Fokuser panel venstre" + "value": "Neste flate" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Focar Painel à Esquerda" + "value": "Próxima Superfície" } }, "th": { "stringUnit": { "state": "translated", - "value": "โฟกัสบานหน้าต่างด้านซ้าย" + "value": "พื้นผิวถัดไป" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Soldaki Bölmeye Odaklan" + "value": "Sonraki Yüzey" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Фокус на панель зліва" + "value": "Наступна поверхня" } } } }, - "shortcut.focusPaneRight.label": { + "shortcut.nextWorkspace.label": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Focus Pane Right" + "value": "Next Workspace" } }, "ja": { "stringUnit": { "state": "translated", - "value": "右のペインにフォーカス" + "value": "次のワークスペース" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "聚焦右侧面板" + "value": "下一个工作区" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "聚焦右側面板" + "value": "下一個工作區" } }, "ko": { "stringUnit": { "state": "translated", - "value": "오른쪽 패널로 포커스" + "value": "다음 작업 공간" } }, "de": { "stringUnit": { "state": "translated", - "value": "Bereich rechts fokussieren" + "value": "Nächster Arbeitsbereich" } }, "es": { "stringUnit": { "state": "translated", - "value": "Enfocar panel derecho" + "value": "Siguiente espacio de trabajo" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Activer le panneau de droite" + "value": "Espace de travail suivant" } }, "it": { "stringUnit": { "state": "translated", - "value": "Sposta focus pannello a destra" + "value": "Area di lavoro successiva" } }, "da": { "stringUnit": { "state": "translated", - "value": "Fokuser panel til højre" + "value": "Næste arbejdsområde" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Fokus na panel po prawej" + "value": "Następna przestrzeń robocza" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Фокус на панель справа" + "value": "Следующее рабочее пространство" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Fokusiraj panel desno" + "value": "Sljedeći radni prostor" } }, "ar": { "stringUnit": { "state": "translated", - "value": "التركيز على اللوحة يمين" + "value": "مساحة العمل التالية" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Fokuser panel høyre" + "value": "Neste arbeidsområde" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Focar Painel à Direita" + "value": "Próxima Área de Trabalho" } }, "th": { "stringUnit": { "state": "translated", - "value": "โฟกัสบานหน้าต่างด้านขวา" + "value": "เวิร์กสเปซถัดไป" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Sağdaki Bölmeye Odaklan" + "value": "Sonraki Çalışma Alanı" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Фокус на панель справа" + "value": "Наступна робоча область" } } } }, - "shortcut.focusPaneUp.label": { + "shortcut.openBrowser.label": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Focus Pane Up" + "value": "Open Browser" } }, "ja": { "stringUnit": { "state": "translated", - "value": "上のペインにフォーカス" + "value": "ブラウザを開く" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "聚焦上方面板" + "value": "打开浏览器" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "聚焦上方面板" + "value": "開啟瀏覽器" } }, "ko": { "stringUnit": { "state": "translated", - "value": "위쪽 패널로 포커스" + "value": "브라우저 열기" } }, "de": { "stringUnit": { "state": "translated", - "value": "Bereich oben fokussieren" + "value": "Browser öffnen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Enfocar panel superior" + "value": "Abrir navegador" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Activer le panneau du haut" + "value": "Ouvrir le navigateur" } }, "it": { "stringUnit": { "state": "translated", - "value": "Sposta focus pannello in alto" + "value": "Apri browser" } }, "da": { "stringUnit": { "state": "translated", - "value": "Fokuser panel opad" + "value": "Åbn browser" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Fokus na panel powyżej" + "value": "Otwórz przeglądarkę" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Фокус на панель сверху" + "value": "Открыть браузер" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Fokusiraj panel gore" + "value": "Otvori preglednik" } }, "ar": { "stringUnit": { "state": "translated", - "value": "التركيز على اللوحة أعلى" + "value": "فتح المتصفح" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Fokuser panel opp" + "value": "Åpne nettleser" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Focar Painel Acima" + "value": "Abrir Navegador" } }, "th": { "stringUnit": { "state": "translated", - "value": "โฟกัสบานหน้าต่างด้านบน" + "value": "เปิดเบราว์เซอร์" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Yukarıdaki Bölmeye Odaklan" + "value": "Tarayıcıyı Aç" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Фокус на панель зверху" + "value": "Відкрити браузер" } } } }, - "shortcut.jumpToUnread.label": { + "shortcut.openFolder.label": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Jump to Latest Unread" + "value": "Open Folder" } }, "ja": { "stringUnit": { "state": "translated", - "value": "最新の未読にジャンプ" + "value": "フォルダを開く" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "跳转到最新未读" + "value": "打开文件夹" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "跳至最新未讀" + "value": "開啟資料夾" } }, "ko": { "stringUnit": { "state": "translated", - "value": "최신 읽지 않은 항목으로 이동" + "value": "폴더 열기" } }, "de": { "stringUnit": { "state": "translated", - "value": "Zur letzten ungelesenen springen" + "value": "Ordner öffnen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Ir a la última no leída" + "value": "Abrir carpeta" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Aller au dernier message non lu" + "value": "Ouvrir un dossier" } }, "it": { "stringUnit": { "state": "translated", - "value": "Vai all'ultimo non letto" + "value": "Apri cartella" } }, "da": { "stringUnit": { "state": "translated", - "value": "Gå til seneste ulæste" + "value": "Åbn mappe" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Przejdź do najnowszego nieprzeczytanego" + "value": "Otwórz folder" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Перейти к последнему непрочитанному" + "value": "Открыть папку" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Skoči na najnovije nepročitano" + "value": "Otvori folder" } }, "ar": { "stringUnit": { "state": "translated", - "value": "الانتقال إلى أحدث غير مقروء" + "value": "فتح مجلد" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Gå til siste uleste" + "value": "Åpne mappe" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Ir para Última Não Lida" + "value": "Abrir Pasta" } }, "th": { "stringUnit": { "state": "translated", - "value": "ข้ามไปยังรายการยังไม่อ่านล่าสุด" + "value": "เปิดโฟลเดอร์" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Son Okunmamışa Atla" + "value": "Klasör Aç" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Перейти до останнього непрочитаного" + "value": "Відкрити теку" } } } }, - "shortcut.toggleUnread.label": { + "shortcut.key.tab": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Toggle Unread" + "value": "Tab" } }, "ja": { "stringUnit": { "state": "translated", - "value": "未読を切り替え" + "value": "Tab" + } + }, + "ko": { + "stringUnit": { + "state": "translated", + "value": "Tab" } } } }, - "shortcut.markOldestUnreadAndJumpNext.label": { + "shortcut.key.space": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Mark as Oldest Unread and Jump to Next Latest Unread" + "value": "Space" } }, "ja": { "stringUnit": { "state": "translated", - "value": "最古の未読としてマークして次の最新未読にジャンプ" + "value": "スペース" } } } }, - "shortcut.newSurface.label": { + "shortcut.pressShortcut.prompt": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "New Surface" + "value": "Press shortcut…" } }, "ja": { "stringUnit": { "state": "translated", - "value": "新規サーフェス" + "value": "ショートカットを入力…" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "新建 Surface" + "value": "请按快捷键..." } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "新增 Surface" + "value": "請按快速鍵..." } }, "ko": { "stringUnit": { "state": "translated", - "value": "새 화면" + "value": "단축키를 누르세요…" } }, "de": { "stringUnit": { "state": "translated", - "value": "Neue Oberfläche" + "value": "Tastenkürzel drücken …" } }, "es": { "stringUnit": { "state": "translated", - "value": "Nueva superficie" + "value": "Pulsa un atajo…" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Nouvelle surface" + "value": "Appuyez sur un raccourci..." } }, "it": { "stringUnit": { "state": "translated", - "value": "Nuova superficie" + "value": "Premi la scorciatoia…" } }, "da": { "stringUnit": { "state": "translated", - "value": "Ny overflade" + "value": "Tryk genvej…" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Nowa powierzchnia" + "value": "Naciśnij skrót…" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Новая поверхность" + "value": "Нажмите сочетание клавиш..." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Nova površina" + "value": "Pritisnite prečicu…" } }, "ar": { "stringUnit": { "state": "translated", - "value": "سطح جديد" + "value": "اضغط الاختصار…" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Ny flate" + "value": "Trykk snarvei …" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Nova Superfície" + "value": "Pressione o atalho…" } }, "th": { "stringUnit": { "state": "translated", - "value": "พื้นผิวใหม่" + "value": "กดแป้นพิมพ์ลัด..." } }, "tr": { "stringUnit": { "state": "translated", - "value": "Yeni Yüzey" + "value": "Kısayola basın…" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Нова поверхня" + "value": "Натисніть комбінацію…" } } } }, - "shortcut.newWindow.label": { + "shortcut.unbound.displayValue": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "New Window" + "value": "None" } }, "ja": { "stringUnit": { "state": "translated", - "value": "新規ウインドウ" + "value": "なし" } - }, - "zh-Hans": { + } + } + }, + "shortcut.recorder.pendingChord": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "新建窗口" + "value": "%@ …" } }, - "zh-Hant": { + "ja": { "stringUnit": { "state": "translated", - "value": "新增視窗" + "value": "%@ …" } }, "ko": { "stringUnit": { "state": "translated", - "value": "새 윈도우" + "value": "%@ …" } - }, - "de": { + } + } + }, + "shortcut.recorder.clear": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Neues Fenster" + "value": "Unbind" } }, - "es": { + "ja": { "stringUnit": { "state": "translated", - "value": "Nueva ventana" + "value": "割り当て解除" } - }, - "fr": { + } + } + }, + "shortcut.recorder.clear.help": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Nouvelle fenêtre" + "value": "Unbind shortcut" } }, - "it": { + "ja": { "stringUnit": { "state": "translated", - "value": "Nuova finestra" + "value": "ショートカットの割り当てを解除" } - }, - "da": { + } + } + }, + "shortcut.recorder.restore": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Nyt vindue" + "value": "Restore" } }, - "pl": { + "ja": { "stringUnit": { "state": "translated", - "value": "Nowe okno" + "value": "復元" } - }, - "ru": { + } + } + }, + "shortcut.recorder.restore.help": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Новое окно" + "value": "Restore previous shortcut" } }, - "bs": { + "ja": { "stringUnit": { "state": "translated", - "value": "Novi prozor" + "value": "前のショートカットを復元" } - }, - "ar": { + } + } + }, + "shortcut.recorder.error.bareKeyNotAllowed": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "نافذة جديدة" + "value": "Shortcuts must include ⌘ ⌥ ⌃ or ⇧" } }, - "nb": { + "ja": { "stringUnit": { "state": "translated", - "value": "Nytt vindu" + "value": "ショートカットには ⌘ ⌥ ⌃ または ⇧ を含める必要があります" } - }, - "pt-BR": { + } + } + }, + "shortcut.recorder.error.conflictsWithAction": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Nova Janela" + "value": "This shortcut conflicts with %@ (%@)." } }, - "th": { + "ja": { "stringUnit": { "state": "translated", - "value": "หน้าต่างใหม่" + "value": "このショートカットは %@(%@)と競合しています。" } - }, - "tr": { + } + } + }, + "shortcut.recorder.error.conflictsWithAction.swap": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Yeni Pencere" + "value": "This shortcut conflicts with %@ (%@). Swap shortcuts?" } }, - "uk": { + "ja": { "stringUnit": { "state": "translated", - "value": "Нове вікно" + "value": "このショートカットは %@(%@)と競合しています。ショートカットを入れ替えますか?" } } } }, - "shortcut.newWorkspace.label": { + "shortcut.recorder.error.numberedShortcutRequiresDigit": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "New Workspace" + "value": "Use a digit from 1 through 9." } }, "ja": { "stringUnit": { "state": "translated", - "value": "新規ワークスペース" + "value": "1 から 9 の数字を使ってください。" } - }, - "zh-Hans": { + } + } + }, + "shortcut.recorder.error.reservedBySystem": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "新建工作区" + "value": "This keystroke is reserved by macOS." } }, - "zh-Hant": { + "ja": { "stringUnit": { "state": "translated", - "value": "新增工作區" + "value": "このキー入力は macOS によって予約されています。" } - }, - "ko": { + } + } + }, + "shortcut.recorder.error.systemWideHotkeyRequiresModifier": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "새 작업 공간" + "value": "System-wide hotkeys must include Command, Option, or Control." } }, - "de": { + "ja": { "stringUnit": { "state": "translated", - "value": "Neuer Arbeitsbereich" + "value": "システム全体のホットキーには Command、Option、または Control を含める必要があります。" + } + } + } + }, + "shortcut.recorder.swap": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Swap" } }, - "es": { + "ja": { "stringUnit": { "state": "translated", - "value": "Nuevo espacio de trabajo" + "value": "入れ替え" + } + } + } + }, + "shortcut.recorder.undo": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Undo" } }, - "fr": { + "ja": { "stringUnit": { "state": "translated", - "value": "Nouvel espace de travail" + "value": "元に戻す" + } + } + } + }, + "shortcut.key.mediaBrightnessDown": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Brightness Down" } }, - "it": { + "ja": { "stringUnit": { "state": "translated", - "value": "Nuova area di lavoro" + "value": "画面の明るさを下げる" + } + } + } + }, + "shortcut.key.mediaBrightnessUp": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Brightness Up" } }, - "da": { + "ja": { "stringUnit": { "state": "translated", - "value": "Nyt arbejdsområde" + "value": "画面の明るさを上げる" + } + } + } + }, + "shortcut.key.mediaMute": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Mute" } }, - "pl": { + "ja": { "stringUnit": { "state": "translated", - "value": "Nowa przestrzeń robocza" + "value": "消音" + } + } + } + }, + "shortcut.key.mediaNext": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Next Track" } }, - "ru": { + "ja": { + "stringUnit": { + "state": "translated", + "value": "次のトラック" + } + } + } + }, + "shortcut.key.mediaPlayPause": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Новое рабочее пространство" + "value": "Play/Pause" } }, - "bs": { + "ja": { "stringUnit": { "state": "translated", - "value": "Novi radni prostor" + "value": "再生/一時停止" } - }, - "ar": { + } + } + }, + "shortcut.key.mediaPrevious": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "مساحة عمل جديدة" + "value": "Previous Track" } }, - "nb": { + "ja": { "stringUnit": { "state": "translated", - "value": "Nytt arbeidsområde" + "value": "前のトラック" } - }, - "pt-BR": { + } + } + }, + "shortcut.key.mediaVolumeDown": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Nova Área de Trabalho" + "value": "Volume Down" } }, - "th": { + "ja": { "stringUnit": { "state": "translated", - "value": "เวิร์กสเปซใหม่" + "value": "音量を下げる" } - }, - "tr": { + } + } + }, + "shortcut.key.mediaVolumeUp": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Yeni Çalışma Alanı" + "value": "Volume Up" } }, - "uk": { + "ja": { "stringUnit": { "state": "translated", - "value": "Нова робоча область" + "value": "音量を上げる" } } } }, - "shortcut.nextSurface.label": { + "shortcut.previousSurface.label": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Next Surface" + "value": "Previous Surface" } }, "ja": { "stringUnit": { "state": "translated", - "value": "次のサーフェス" + "value": "前のサーフェス" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "下一个 Surface" + "value": "上一个 Surface" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "下一個 Surface" + "value": "上一個 Surface" } }, "ko": { "stringUnit": { "state": "translated", - "value": "다음 화면" + "value": "이전 화면" } }, "de": { "stringUnit": { "state": "translated", - "value": "Nächste Oberfläche" + "value": "Vorherige Oberfläche" } }, "es": { "stringUnit": { "state": "translated", - "value": "Siguiente superficie" + "value": "Superficie anterior" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Surface suivante" + "value": "Surface précédente" } }, "it": { "stringUnit": { "state": "translated", - "value": "Superficie successiva" + "value": "Superficie precedente" } }, "da": { "stringUnit": { "state": "translated", - "value": "Næste overflade" + "value": "Forrige overflade" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Następna powierzchnia" + "value": "Poprzednia powierzchnia" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Следующая поверхность" + "value": "Предыдущая поверхность" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Sljedeća površina" + "value": "Prethodna površina" } }, "ar": { "stringUnit": { "state": "translated", - "value": "السطح التالي" + "value": "السطح السابق" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Neste flate" + "value": "Forrige flate" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Próxima Superfície" + "value": "Superfície Anterior" } }, "th": { "stringUnit": { "state": "translated", - "value": "พื้นผิวถัดไป" + "value": "พื้นผิวก่อนหน้า" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Sonraki Yüzey" + "value": "Önceki Yüzey" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Наступна поверхня" + "value": "Попередня поверхня" } } } }, - "shortcut.nextWorkspace.label": { + "shortcut.previousWorkspace.label": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Next Workspace" + "value": "Previous Workspace" } }, "ja": { "stringUnit": { "state": "translated", - "value": "次のワークスペース" + "value": "前のワークスペース" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "下一个工作区" + "value": "上一个工作区" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "下一個工作區" + "value": "上一個工作區" } }, "ko": { "stringUnit": { "state": "translated", - "value": "다음 작업 공간" + "value": "이전 작업 공간" } }, "de": { "stringUnit": { "state": "translated", - "value": "Nächster Arbeitsbereich" + "value": "Vorheriger Arbeitsbereich" } }, "es": { "stringUnit": { "state": "translated", - "value": "Siguiente espacio de trabajo" + "value": "Espacio de trabajo anterior" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Espace de travail suivant" + "value": "Espace de travail précédent" } }, "it": { "stringUnit": { "state": "translated", - "value": "Area di lavoro successiva" + "value": "Area di lavoro precedente" } }, "da": { "stringUnit": { "state": "translated", - "value": "Næste arbejdsområde" + "value": "Forrige arbejdsområde" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Następna przestrzeń robocza" + "value": "Poprzednia przestrzeń robocza" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Следующее рабочее пространство" + "value": "Предыдущее рабочее пространство" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Sljedeći radni prostor" + "value": "Prethodni radni prostor" } }, "ar": { "stringUnit": { "state": "translated", - "value": "مساحة العمل التالية" + "value": "مساحة العمل السابقة" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Neste arbeidsområde" + "value": "Forrige arbeidsområde" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Próxima Área de Trabalho" + "value": "Área de Trabalho Anterior" } }, "th": { "stringUnit": { "state": "translated", - "value": "เวิร์กสเปซถัดไป" + "value": "เวิร์กสเปซก่อนหน้า" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Sonraki Çalışma Alanı" + "value": "Önceki Çalışma Alanı" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Наступна робоча область" + "value": "Попередня робоча область" } } } }, - "shortcut.openBrowser.label": { + "shortcut.saveFilePreview.label": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Open Browser" + "value": "Save File Preview" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ブラウザを開く" + "value": "ファイルプレビューを保存" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "打开浏览器" + "value": "保存文件预览" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "開啟瀏覽器" + "value": "儲存檔案預覽" } }, "ko": { "stringUnit": { "state": "translated", - "value": "브라우저 열기" + "value": "파일 미리보기 저장" } }, "de": { "stringUnit": { "state": "translated", - "value": "Browser öffnen" + "value": "Dateivorschau speichern" } }, "es": { "stringUnit": { "state": "translated", - "value": "Abrir navegador" + "value": "Guardar vista previa del archivo" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Ouvrir le navigateur" + "value": "Enregistrer l’aperçu du fichier" } }, "it": { "stringUnit": { "state": "translated", - "value": "Apri browser" + "value": "Salva anteprima file" } }, "da": { "stringUnit": { "state": "translated", - "value": "Åbn browser" + "value": "Gem filforhåndsvisning" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Otwórz przeglądarkę" + "value": "Zapisz podgląd pliku" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Открыть браузер" + "value": "Сохранить предпросмотр файла" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Otvori preglednik" + "value": "Spremi pregled datoteke" } }, "ar": { "stringUnit": { "state": "translated", - "value": "فتح المتصفح" + "value": "حفظ معاينة الملف" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Åpne nettleser" + "value": "Lagre filforhåndsvisning" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Abrir Navegador" + "value": "Salvar prévia do arquivo" } }, "th": { "stringUnit": { "state": "translated", - "value": "เปิดเบราว์เซอร์" + "value": "บันทึกตัวอย่างไฟล์" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Tarayıcıyı Aç" + "value": "Dosya önizlemesini kaydet" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Відкрити браузер" + "value": "Зберегти попередній перегляд файлу" } } } }, - "shortcut.openFolder.label": { + "shortcut.renameTab.label": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Open Folder" + "value": "Rename Tab" } }, "ja": { "stringUnit": { "state": "translated", - "value": "フォルダを開く" + "value": "タブ名を変更" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "打开文件夹" + "value": "重命名标签页" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "開啟資料夾" + "value": "重新命名標籤頁" } }, "ko": { "stringUnit": { "state": "translated", - "value": "폴더 열기" + "value": "탭 이름 변경" } }, "de": { "stringUnit": { "state": "translated", - "value": "Ordner öffnen" + "value": "Tab umbenennen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Abrir carpeta" + "value": "Renombrar pestaña" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Ouvrir un dossier" + "value": "Renommer l'onglet" } }, "it": { "stringUnit": { "state": "translated", - "value": "Apri cartella" + "value": "Rinomina scheda" } }, "da": { "stringUnit": { "state": "translated", - "value": "Åbn mappe" + "value": "Omdøb fane" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Otwórz folder" + "value": "Zmień nazwę karty" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Открыть папку" + "value": "Переименовать вкладку" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Otvori folder" + "value": "Preimenuj tab" } }, "ar": { "stringUnit": { "state": "translated", - "value": "فتح مجلد" + "value": "إعادة تسمية اللسان" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Åpne mappe" + "value": "Gi fanen nytt navn" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Abrir Pasta" + "value": "Renomear Aba" } }, "th": { "stringUnit": { "state": "translated", - "value": "เปิดโฟลเดอร์" + "value": "เปลี่ยนชื่อแท็บ" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Klasör Aç" + "value": "Sekmeyi Yeniden Adlandır" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Відкрити теку" - } - } - } - }, - "shortcut.key.tab": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Tab" - } - }, - "ja": { - "stringUnit": { - "state": "translated", - "value": "Tab" - } - }, - "ko": { - "stringUnit": { - "state": "translated", - "value": "Tab" - } - } - } - }, - "shortcut.key.space": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Space" - } - }, - "ja": { - "stringUnit": { - "state": "translated", - "value": "スペース" + "value": "Перейменувати вкладку" } } } }, - "shortcut.pressShortcut.prompt": { + "shortcut.renameWorkspace.label": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Press shortcut…" + "value": "Rename Workspace" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ショートカットを入力…" + "value": "ワークスペース名を変更" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "请按快捷键..." + "value": "重命名工作区" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "請按快速鍵..." + "value": "重新命名工作區" } }, "ko": { "stringUnit": { "state": "translated", - "value": "단축키를 누르세요…" + "value": "작업 공간 이름 변경" } }, "de": { "stringUnit": { "state": "translated", - "value": "Tastenkürzel drücken …" + "value": "Arbeitsbereich umbenennen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Pulsa un atajo…" + "value": "Renombrar espacio de trabajo" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Appuyez sur un raccourci..." + "value": "Renommer l'espace de travail" } }, "it": { "stringUnit": { "state": "translated", - "value": "Premi la scorciatoia…" + "value": "Rinomina area di lavoro" } }, "da": { "stringUnit": { "state": "translated", - "value": "Tryk genvej…" + "value": "Omdøb arbejdsområde" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Naciśnij skrót…" + "value": "Zmień nazwę przestrzeni roboczej" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Нажмите сочетание клавиш..." + "value": "Переименовать рабочее пространство" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Pritisnite prečicu…" + "value": "Preimenuj radni prostor" } }, "ar": { "stringUnit": { "state": "translated", - "value": "اضغط الاختصار…" + "value": "إعادة تسمية مساحة العمل" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Trykk snarvei …" + "value": "Gi arbeidsområdet nytt navn" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Pressione o atalho…" + "value": "Renomear Área de Trabalho" } }, "th": { "stringUnit": { "state": "translated", - "value": "กดแป้นพิมพ์ลัด..." + "value": "เปลี่ยนชื่อเวิร์กสเปซ" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Kısayola basın…" + "value": "Çalışma Alanını Yeniden Adlandır" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Натисніть комбінацію…" + "value": "Перейменувати робочу область" } } } }, - "shortcut.unbound.displayValue": { + "shortcut.reopenPreviousSession.label": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "None" + "value": "Reopen Previous Session" } }, "ja": { "stringUnit": { "state": "translated", - "value": "なし" + "value": "前回のセッションを再度開く" } } } }, - "shortcut.recorder.pendingChord": { + "shortcut.selectSurfaceByNumber.label": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "%@ …" + "value": "Select Surface 1…9" } }, "ja": { "stringUnit": { "state": "translated", - "value": "%@ …" + "value": "サーフェス 1…9 を選択" + } + }, + "uk": { + "stringUnit": { + "state": "translated", + "value": "Вибрати поверхню 1…9" } }, "ko": { "stringUnit": { "state": "translated", - "value": "%@ …" + "value": "서피스 1…9 선택" } } } }, - "shortcut.recorder.clear": { + "shortcut.selectWorkspaceByNumber.label": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Unbind" + "value": "Select Workspace 1…9" } }, "ja": { "stringUnit": { "state": "translated", - "value": "割り当て解除" + "value": "ワークスペース 1…9 を選択" } - } - } - }, - "shortcut.recorder.clear.help": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "uk": { "stringUnit": { "state": "translated", - "value": "Unbind shortcut" + "value": "Вибрати робочу область 1…9" } }, - "ja": { + "ko": { "stringUnit": { "state": "translated", - "value": "ショートカットの割り当てを解除" + "value": "워크스페이스 1…9 선택" } } } }, - "shortcut.recorder.restore": { + "shortcut.resetWorkspaceColor.label": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Restore" + "value": "Reset Workspace Color" } }, "ja": { "stringUnit": { "state": "translated", - "value": "復元" + "value": "ワークスペース色をリセット" } } } }, - "shortcut.recorder.restore.help": { + "shortcut.setWorkspaceColorRed.label": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Restore previous shortcut" + "value": "Workspace Color: Red" } }, "ja": { "stringUnit": { "state": "translated", - "value": "前のショートカットを復元" + "value": "ワークスペース色: 赤" } } } }, - "shortcut.recorder.error.bareKeyNotAllowed": { + "shortcut.setWorkspaceColorCrimson.label": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Shortcuts must include ⌘ ⌥ ⌃ or ⇧" + "value": "Workspace Color: Crimson" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ショートカットには ⌘ ⌥ ⌃ または ⇧ を含める必要があります" + "value": "ワークスペース色: クリムゾン" } } } }, - "shortcut.recorder.error.conflictsWithAction": { + "shortcut.setWorkspaceColorOrange.label": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "This shortcut conflicts with %@ (%@)." + "value": "Workspace Color: Orange" } }, "ja": { "stringUnit": { "state": "translated", - "value": "このショートカットは %@(%@)と競合しています。" + "value": "ワークスペース色: オレンジ" } } } }, - "shortcut.recorder.error.conflictsWithAction.swap": { + "shortcut.setWorkspaceColorAmber.label": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "This shortcut conflicts with %@ (%@). Swap shortcuts?" + "value": "Workspace Color: Amber" } }, "ja": { "stringUnit": { "state": "translated", - "value": "このショートカットは %@(%@)と競合しています。ショートカットを入れ替えますか?" + "value": "ワークスペース色: アンバー" } } } }, - "shortcut.recorder.error.numberedShortcutRequiresDigit": { + "shortcut.setWorkspaceColorOlive.label": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Use a digit from 1 through 9." + "value": "Workspace Color: Olive" } }, "ja": { "stringUnit": { "state": "translated", - "value": "1 から 9 の数字を使ってください。" + "value": "ワークスペース色: オリーブ" } } } }, - "shortcut.recorder.error.reservedBySystem": { + "shortcut.setWorkspaceColorGreen.label": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "This keystroke is reserved by macOS." + "value": "Workspace Color: Green" } }, "ja": { "stringUnit": { "state": "translated", - "value": "このキー入力は macOS によって予約されています。" + "value": "ワークスペース色: 緑" } } } }, - "shortcut.recorder.error.systemWideHotkeyRequiresModifier": { + "shortcut.setWorkspaceColorTeal.label": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "System-wide hotkeys must include Command, Option, or Control." + "value": "Workspace Color: Teal" } }, "ja": { "stringUnit": { "state": "translated", - "value": "システム全体のホットキーには Command、Option、または Control を含める必要があります。" + "value": "ワークスペース色: ティール" } } } }, - "shortcut.recorder.swap": { + "shortcut.setWorkspaceColorAqua.label": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Swap" + "value": "Workspace Color: Aqua" } }, "ja": { "stringUnit": { "state": "translated", - "value": "入れ替え" + "value": "ワークスペース色: アクア" } } } }, - "shortcut.recorder.undo": { + "shortcut.setWorkspaceColorBlue.label": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Undo" + "value": "Workspace Color: Blue" } }, "ja": { "stringUnit": { "state": "translated", - "value": "元に戻す" + "value": "ワークスペース色: 青" } } } }, - "shortcut.key.mediaBrightnessDown": { + "shortcut.showBrowserJSConsole.label": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Brightness Down" + "value": "Show Browser JavaScript Console" } }, "ja": { "stringUnit": { "state": "translated", - "value": "画面の明るさを下げる" + "value": "ブラウザ JavaScript コンソールを表示" } - } - } - }, - "shortcut.key.mediaBrightnessUp": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "zh-Hans": { "stringUnit": { "state": "translated", - "value": "Brightness Up" + "value": "显示浏览器 JavaScript 控制台" } }, - "ja": { + "zh-Hant": { "stringUnit": { "state": "translated", - "value": "画面の明るさを上げる" + "value": "顯示瀏覽器 JavaScript 主控台" } - } - } - }, - "shortcut.key.mediaMute": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "ko": { "stringUnit": { "state": "translated", - "value": "Mute" + "value": "브라우저 JavaScript 콘솔 표시" } }, - "ja": { + "de": { "stringUnit": { "state": "translated", - "value": "消音" + "value": "Browser-JavaScript-Konsole anzeigen" } - } - } - }, - "shortcut.key.mediaNext": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "es": { "stringUnit": { "state": "translated", - "value": "Next Track" + "value": "Mostrar consola de JavaScript del navegador" } }, - "ja": { + "fr": { "stringUnit": { "state": "translated", - "value": "次のトラック" + "value": "Afficher la console JavaScript du navigateur" } - } - } - }, - "shortcut.key.mediaPlayPause": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "it": { "stringUnit": { "state": "translated", - "value": "Play/Pause" + "value": "Mostra console JavaScript del browser" + } + }, + "da": { + "stringUnit": { + "state": "translated", + "value": "Vis browser JavaScript-konsol" + } + }, + "pl": { + "stringUnit": { + "state": "translated", + "value": "Pokaż konsolę JavaScript przeglądarki" + } + }, + "ru": { + "stringUnit": { + "state": "translated", + "value": "Показать консоль JavaScript в браузере" + } + }, + "bs": { + "stringUnit": { + "state": "translated", + "value": "Prikaži JavaScript konzolu preglednika" + } + }, + "ar": { + "stringUnit": { + "state": "translated", + "value": "عرض وحدة تحكم JavaScript للمتصفح" + } + }, + "nb": { + "stringUnit": { + "state": "translated", + "value": "Vis JavaScript-konsoll i nettleser" + } + }, + "pt-BR": { + "stringUnit": { + "state": "translated", + "value": "Mostrar Console JavaScript do Navegador" + } + }, + "th": { + "stringUnit": { + "state": "translated", + "value": "แสดงคอนโซล JavaScript ของเบราว์เซอร์" + } + }, + "tr": { + "stringUnit": { + "state": "translated", + "value": "Tarayıcı JavaScript Konsolunu Göster" } }, - "ja": { + "uk": { "stringUnit": { "state": "translated", - "value": "再生/一時停止" + "value": "Показати консоль JavaScript браузера" } } } }, - "shortcut.key.mediaPrevious": { + "shortcut.toggleReactGrab.label": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Previous Track" + "value": "Toggle React Grab" } }, "ja": { "stringUnit": { "state": "translated", - "value": "前のトラック" - } - } - } - }, - "shortcut.key.mediaVolumeDown": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Volume Down" + "value": "React Grabの切り替え" } }, - "ja": { + "zh-Hans": { "stringUnit": { "state": "translated", - "value": "音量を下げる" + "value": "切换 React Grab" } - } - } - }, - "shortcut.key.mediaVolumeUp": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "zh-Hant": { "stringUnit": { "state": "translated", - "value": "Volume Up" + "value": "切換 React Grab" } }, - "ja": { + "ko": { "stringUnit": { "state": "translated", - "value": "音量を上げる" + "value": "React Grab 전환" } } } }, - "shortcut.previousSurface.label": { + "shortcut.showNotifications.label": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Previous Surface" + "value": "Show Notifications" } }, "ja": { "stringUnit": { "state": "translated", - "value": "前のサーフェス" + "value": "通知を表示" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "上一个 Surface" + "value": "显示通知" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "上一個 Surface" + "value": "顯示通知" } }, "ko": { "stringUnit": { "state": "translated", - "value": "이전 화면" + "value": "알림 표시" } }, "de": { "stringUnit": { "state": "translated", - "value": "Vorherige Oberfläche" + "value": "Benachrichtigungen anzeigen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Superficie anterior" + "value": "Mostrar notificaciones" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Surface précédente" + "value": "Afficher les notifications" } }, "it": { "stringUnit": { "state": "translated", - "value": "Superficie precedente" + "value": "Mostra notifiche" } }, "da": { "stringUnit": { "state": "translated", - "value": "Forrige overflade" + "value": "Vis notifikationer" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Poprzednia powierzchnia" + "value": "Pokaż powiadomienia" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Предыдущая поверхность" + "value": "Показать уведомления" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Prethodna površina" + "value": "Prikaži obavještenja" } }, "ar": { "stringUnit": { "state": "translated", - "value": "السطح السابق" + "value": "عرض الإشعارات" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Forrige flate" + "value": "Vis varsler" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Superfície Anterior" + "value": "Mostrar Notificações" } }, "th": { "stringUnit": { "state": "translated", - "value": "พื้นผิวก่อนหน้า" + "value": "แสดงการแจ้งเตือน" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Önceki Yüzey" + "value": "Bildirimleri Göster" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Попередня поверхня" + "value": "Показати сповіщення" } } } }, - "shortcut.previousWorkspace.label": { + "shortcut.splitBrowserDown.label": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Previous Workspace" + "value": "Split Browser Down" } }, "ja": { "stringUnit": { "state": "translated", - "value": "前のワークスペース" + "value": "ブラウザを下に分割" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "上一个工作区" + "value": "向下拆分浏览器" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "上一個工作區" + "value": "向下分割瀏覽器" } }, "ko": { "stringUnit": { "state": "translated", - "value": "이전 작업 공간" + "value": "브라우저를 아래로 분할" } }, "de": { "stringUnit": { "state": "translated", - "value": "Vorheriger Arbeitsbereich" + "value": "Browser nach unten teilen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Espacio de trabajo anterior" + "value": "Dividir navegador hacia abajo" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Espace de travail précédent" + "value": "Diviser le navigateur vers le bas" } }, "it": { "stringUnit": { "state": "translated", - "value": "Area di lavoro precedente" + "value": "Dividi browser in basso" } }, "da": { "stringUnit": { "state": "translated", - "value": "Forrige arbejdsområde" + "value": "Opdel browser nedad" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Poprzednia przestrzeń robocza" + "value": "Podziel przeglądarkę w dół" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Предыдущее рабочее пространство" + "value": "Разделить браузер вниз" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Prethodni radni prostor" + "value": "Podijeli preglednik dolje" } }, "ar": { "stringUnit": { "state": "translated", - "value": "مساحة العمل السابقة" + "value": "تقسيم المتصفح للأسفل" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Forrige arbeidsområde" + "value": "Del nettleser ned" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Área de Trabalho Anterior" + "value": "Dividir Navegador para Baixo" } }, "th": { "stringUnit": { "state": "translated", - "value": "เวิร์กสเปซก่อนหน้า" + "value": "แยกเบราว์เซอร์ลงล่าง" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Önceki Çalışma Alanı" + "value": "Tarayıcıyı Aşağı Böl" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Попередня робоча область" + "value": "Розділити браузер вниз" } } } }, - "shortcut.saveFilePreview.label": { + "shortcut.splitBrowserRight.label": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Save File Preview" + "value": "Split Browser Right" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ファイルプレビューを保存" + "value": "ブラウザを右に分割" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "保存文件预览" + "value": "向右拆分浏览器" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "儲存檔案預覽" + "value": "向右分割瀏覽器" } }, "ko": { "stringUnit": { "state": "translated", - "value": "파일 미리보기 저장" + "value": "브라우저를 오른쪽으로 분할" } }, "de": { "stringUnit": { "state": "translated", - "value": "Dateivorschau speichern" + "value": "Browser nach rechts teilen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Guardar vista previa del archivo" + "value": "Dividir navegador a la derecha" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Enregistrer l’aperçu du fichier" + "value": "Diviser le navigateur à droite" } }, "it": { "stringUnit": { "state": "translated", - "value": "Salva anteprima file" + "value": "Dividi browser a destra" } }, "da": { "stringUnit": { "state": "translated", - "value": "Gem filforhåndsvisning" + "value": "Opdel browser til højre" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Zapisz podgląd pliku" + "value": "Podziel przeglądarkę w prawo" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Сохранить предпросмотр файла" + "value": "Разделить браузер вправо" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Spremi pregled datoteke" + "value": "Podijeli preglednik desno" } }, "ar": { "stringUnit": { "state": "translated", - "value": "حفظ معاينة الملف" + "value": "تقسيم المتصفح لليمين" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Lagre filforhåndsvisning" + "value": "Del nettleser til høyre" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Salvar prévia do arquivo" + "value": "Dividir Navegador à Direita" } }, "th": { "stringUnit": { "state": "translated", - "value": "บันทึกตัวอย่างไฟล์" + "value": "แยกเบราว์เซอร์ไปทางขวา" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Dosya önizlemesini kaydet" + "value": "Tarayıcıyı Sağa Böl" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Зберегти попередній перегляд файлу" + "value": "Розділити браузер праворуч" } } } }, - "shortcut.renameTab.label": { + "shortcut.splitDown.label": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Rename Tab" + "value": "Split Down" } }, "ja": { "stringUnit": { "state": "translated", - "value": "タブ名を変更" + "value": "下に分割" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "重命名标签页" + "value": "向下拆分" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "重新命名標籤頁" + "value": "向下分割" } }, "ko": { "stringUnit": { "state": "translated", - "value": "탭 이름 변경" + "value": "아래로 분할" } }, "de": { "stringUnit": { "state": "translated", - "value": "Tab umbenennen" + "value": "Nach unten teilen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Renombrar pestaña" + "value": "Dividir hacia abajo" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Renommer l'onglet" + "value": "Diviser vers le bas" } }, "it": { "stringUnit": { "state": "translated", - "value": "Rinomina scheda" + "value": "Dividi in basso" } }, "da": { "stringUnit": { "state": "translated", - "value": "Omdøb fane" + "value": "Opdel nedad" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Zmień nazwę karty" + "value": "Podziel w dół" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Переименовать вкладку" + "value": "Разделить вниз" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Preimenuj tab" + "value": "Podijeli dolje" } }, "ar": { "stringUnit": { "state": "translated", - "value": "إعادة تسمية اللسان" + "value": "تقسيم للأسفل" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Gi fanen nytt navn" + "value": "Del ned" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Renomear Aba" + "value": "Dividir para Baixo" } }, "th": { "stringUnit": { "state": "translated", - "value": "เปลี่ยนชื่อแท็บ" + "value": "แยกลงล่าง" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Sekmeyi Yeniden Adlandır" + "value": "Aşağı Böl" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Перейменувати вкладку" + "value": "Розділити вниз" } } } }, - "shortcut.renameWorkspace.label": { + "shortcut.equalizeSplits.label": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Rename Workspace" + "value": "Equalize Splits" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ワークスペース名を変更" + "value": "分割を均等にする" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "重命名工作区" + "value": "均分面板" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "重新命名工作區" + "value": "均等分割" } }, "ko": { "stringUnit": { "state": "translated", - "value": "작업 공간 이름 변경" + "value": "분할 균등화" } }, "de": { "stringUnit": { "state": "translated", - "value": "Arbeitsbereich umbenennen" + "value": "Teilungen angleichen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Renombrar espacio de trabajo" + "value": "Igualar divisiones" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Renommer l'espace de travail" + "value": "Égaliser les divisions" } }, "it": { "stringUnit": { "state": "translated", - "value": "Rinomina area di lavoro" + "value": "Equalizza divisioni" } }, "da": { "stringUnit": { "state": "translated", - "value": "Omdøb arbejdsområde" + "value": "Udlign opdelinger" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Zmień nazwę przestrzeni roboczej" + "value": "Wyrównaj podziały" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Переименовать рабочее пространство" + "value": "Выровнять разделение" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Preimenuj radni prostor" + "value": "Izjednači podjele" } }, "ar": { "stringUnit": { "state": "translated", - "value": "إعادة تسمية مساحة العمل" + "value": "تسوية التقسيمات" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Gi arbeidsområdet nytt navn" + "value": "Gjør delinger like" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Renomear Área de Trabalho" + "value": "Equalizar Divisões" } }, "th": { "stringUnit": { "state": "translated", - "value": "เปลี่ยนชื่อเวิร์กสเปซ" + "value": "ปรับขนาดช่องแยกให้เท่ากัน" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Çalışma Alanını Yeniden Adlandır" + "value": "Bölmeleri Eşitle" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Перейменувати робочу область" + "value": "Вирівняти розділення" } } } }, - "shortcut.reopenPreviousSession.label": { + "shortcut.splitRight.label": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Reopen Previous Session" + "value": "Split Right" } }, "ja": { "stringUnit": { "state": "translated", - "value": "前回のセッションを再度開く" + "value": "右に分割" } - } - } - }, - "shortcut.selectSurfaceByNumber.label": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "zh-Hans": { "stringUnit": { "state": "translated", - "value": "Select Surface 1…9" + "value": "向右拆分" } }, - "ja": { + "zh-Hant": { "stringUnit": { "state": "translated", - "value": "サーフェス 1…9 を選択" + "value": "向右分割" } }, - "uk": { + "ko": { "stringUnit": { "state": "translated", - "value": "Вибрати поверхню 1…9" + "value": "오른쪽으로 분할" } }, - "ko": { + "de": { "stringUnit": { "state": "translated", - "value": "서피스 1…9 선택" + "value": "Nach rechts teilen" } - } - } - }, - "shortcut.selectWorkspaceByNumber.label": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "es": { "stringUnit": { "state": "translated", - "value": "Select Workspace 1…9" + "value": "Dividir a la derecha" } }, - "ja": { + "fr": { "stringUnit": { "state": "translated", - "value": "ワークスペース 1…9 を選択" + "value": "Diviser à droite" } }, - "uk": { + "it": { "stringUnit": { "state": "translated", - "value": "Вибрати робочу область 1…9" + "value": "Dividi a destra" } }, - "ko": { + "da": { "stringUnit": { "state": "translated", - "value": "워크스페이스 1…9 선택" + "value": "Opdel til højre" } - } - } - }, - "shortcut.resetWorkspaceColor.label": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "pl": { "stringUnit": { "state": "translated", - "value": "Reset Workspace Color" + "value": "Podziel w prawo" } }, - "ja": { + "ru": { "stringUnit": { "state": "translated", - "value": "ワークスペース色をリセット" + "value": "Разделить вправо" } - } - } - }, - "shortcut.setWorkspaceColorRed.label": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "bs": { "stringUnit": { "state": "translated", - "value": "Workspace Color: Red" + "value": "Podijeli desno" } }, - "ja": { + "ar": { "stringUnit": { "state": "translated", - "value": "ワークスペース色: 赤" + "value": "تقسيم لليمين" } - } - } - }, - "shortcut.setWorkspaceColorCrimson.label": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "nb": { "stringUnit": { "state": "translated", - "value": "Workspace Color: Crimson" + "value": "Del til høyre" } }, - "ja": { + "pt-BR": { "stringUnit": { "state": "translated", - "value": "ワークスペース色: クリムゾン" + "value": "Dividir à Direita" } - } - } - }, - "shortcut.setWorkspaceColorOrange.label": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "th": { "stringUnit": { "state": "translated", - "value": "Workspace Color: Orange" + "value": "แยกไปทางขวา" } }, - "ja": { + "tr": { "stringUnit": { "state": "translated", - "value": "ワークスペース色: オレンジ" + "value": "Sağa Böl" + } + }, + "uk": { + "stringUnit": { + "state": "translated", + "value": "Розділити праворуч" } } } }, - "shortcut.setWorkspaceColorAmber.label": { + "shortcut.toggleBrowserDevTools.label": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Workspace Color: Amber" + "value": "Toggle Browser Developer Tools" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ワークスペース色: アンバー" + "value": "ブラウザデベロッパツールを切替" } - } - } - }, - "shortcut.setWorkspaceColorOlive.label": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "zh-Hans": { "stringUnit": { "state": "translated", - "value": "Workspace Color: Olive" + "value": "切换浏览器开发者工具" } }, - "ja": { + "zh-Hant": { "stringUnit": { "state": "translated", - "value": "ワークスペース色: オリーブ" + "value": "切換瀏覽器開發者工具" } - } - } - }, - "shortcut.setWorkspaceColorGreen.label": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "ko": { "stringUnit": { "state": "translated", - "value": "Workspace Color: Green" + "value": "브라우저 개발자 도구 전환" } }, - "ja": { + "de": { "stringUnit": { "state": "translated", - "value": "ワークスペース色: 緑" + "value": "Browser-Entwicklerwerkzeuge ein-/ausblenden" } - } - } - }, - "shortcut.setWorkspaceColorTeal.label": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "es": { "stringUnit": { "state": "translated", - "value": "Workspace Color: Teal" + "value": "Alternar herramientas de desarrollo del navegador" } }, - "ja": { + "fr": { "stringUnit": { "state": "translated", - "value": "ワークスペース色: ティール" + "value": "Afficher/masquer les outils de développement du navigateur" } - } - } - }, - "shortcut.setWorkspaceColorAqua.label": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "it": { "stringUnit": { "state": "translated", - "value": "Workspace Color: Aqua" + "value": "Attiva/Disattiva Strumenti sviluppatore browser" } }, - "ja": { + "da": { "stringUnit": { "state": "translated", - "value": "ワークスペース色: アクア" + "value": "Slå browserudviklerværktøjer til/fra" } - } - } - }, - "shortcut.setWorkspaceColorBlue.label": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "pl": { "stringUnit": { "state": "translated", - "value": "Workspace Color: Blue" + "value": "Przełącz narzędzia deweloperskie przeglądarki" } }, - "ja": { + "ru": { "stringUnit": { "state": "translated", - "value": "ワークスペース色: 青" + "value": "Инструменты разработчика браузера" + } + }, + "bs": { + "stringUnit": { + "state": "translated", + "value": "Prebaci razvojne alate preglednika" + } + }, + "ar": { + "stringUnit": { + "state": "translated", + "value": "تبديل أدوات المطور للمتصفح" + } + }, + "nb": { + "stringUnit": { + "state": "translated", + "value": "Slå utviklerverktøy i nettleser av/på" + } + }, + "pt-BR": { + "stringUnit": { + "state": "translated", + "value": "Alternar Ferramentas do Desenvolvedor do Navegador" + } + }, + "th": { + "stringUnit": { + "state": "translated", + "value": "สลับเครื่องมือนักพัฒนาเบราว์เซอร์" + } + }, + "tr": { + "stringUnit": { + "state": "translated", + "value": "Tarayıcı Geliştirici Araçlarını Aç/Kapat" + } + }, + "uk": { + "stringUnit": { + "state": "translated", + "value": "Перемкнути інструменти розробника браузера" } } } }, - "shortcut.showBrowserJSConsole.label": { + "shortcut.togglePaneZoom.label": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Show Browser JavaScript Console" + "value": "Toggle Pane Zoom" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ブラウザ JavaScript コンソールを表示" + "value": "ペインズームを切替" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "显示浏览器 JavaScript 控制台" + "value": "切换面板缩放" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "顯示瀏覽器 JavaScript 主控台" + "value": "切換面板縮放" } }, "ko": { "stringUnit": { "state": "translated", - "value": "브라우저 JavaScript 콘솔 표시" + "value": "패널 확대/축소 전환" } }, "de": { "stringUnit": { "state": "translated", - "value": "Browser-JavaScript-Konsole anzeigen" + "value": "Bereichszoom umschalten" } }, "es": { "stringUnit": { "state": "translated", - "value": "Mostrar consola de JavaScript del navegador" + "value": "Alternar zoom del panel" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Afficher la console JavaScript du navigateur" + "value": "Activer/désactiver le zoom du panneau" } }, "it": { "stringUnit": { "state": "translated", - "value": "Mostra console JavaScript del browser" + "value": "Attiva/Disattiva zoom pannello" } }, "da": { "stringUnit": { "state": "translated", - "value": "Vis browser JavaScript-konsol" + "value": "Slå panelzoom til/fra" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Pokaż konsolę JavaScript przeglądarki" + "value": "Przełącz powiększenie panelu" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Показать консоль JavaScript в браузере" + "value": "Масштаб панели" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Prikaži JavaScript konzolu preglednika" + "value": "Prebaci uvećanje panela" } }, "ar": { "stringUnit": { "state": "translated", - "value": "عرض وحدة تحكم JavaScript للمتصفح" + "value": "تبديل تكبير اللوحة" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Vis JavaScript-konsoll i nettleser" + "value": "Slå panelzoom av/på" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Mostrar Console JavaScript do Navegador" + "value": "Alternar Zoom do Painel" } }, "th": { "stringUnit": { "state": "translated", - "value": "แสดงคอนโซล JavaScript ของเบราว์เซอร์" + "value": "สลับการซูมบานหน้าต่าง" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Tarayıcı JavaScript Konsolunu Göster" + "value": "Bölme Yakınlaştırmasını Aç/Kapat" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Показати консоль JavaScript браузера" + "value": "Перемкнути масштаб панелі" } } } }, - "shortcut.toggleReactGrab.label": { + "fileExplorer.empty": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Toggle React Grab" + "value": "No folder open" } }, "ja": { "stringUnit": { "state": "translated", - "value": "React Grabの切り替え" - } - }, - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "切换 React Grab" - } - }, - "zh-Hant": { - "stringUnit": { - "state": "translated", - "value": "切換 React Grab" + "value": "フォルダが開かれていません" } }, "ko": { "stringUnit": { "state": "translated", - "value": "React Grab 전환" + "value": "열린 폴더 없음" } } } }, - "shortcut.showNotifications.label": { + "fileExplorer.contextMenu.copyPath": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Show Notifications" + "value": "Copy Path" } }, "ja": { "stringUnit": { "state": "translated", - "value": "通知を表示" - } - }, - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "显示通知" - } - }, - "zh-Hant": { - "stringUnit": { - "state": "translated", - "value": "顯示通知" + "value": "パスをコピー" } - }, - "ko": { + } + } + }, + "fileExplorer.contextMenu.copyRelativePath": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "알림 표시" + "value": "Copy Relative Path" } }, - "de": { + "ja": { "stringUnit": { "state": "translated", - "value": "Benachrichtigungen anzeigen" + "value": "相対パスをコピー" } - }, - "es": { + } + } + }, + "fileExplorer.contextMenu.insertPath": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Mostrar notificaciones" + "value": "Insert Path" } }, - "fr": { + "ja": { "stringUnit": { "state": "translated", - "value": "Afficher les notifications" + "value": "パスを挿入" } - }, - "it": { + } + } + }, + "fileExplorer.contextMenu.insertRelativePath": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Mostra notifiche" + "value": "Insert Relative Path" } }, - "da": { + "ja": { "stringUnit": { "state": "translated", - "value": "Vis notifikationer" + "value": "相対パスを挿入" } - }, - "pl": { + } + } + }, + "fileExplorer.contextMenu.openDefault": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Pokaż powiadomienia" + "value": "Open in Default Editor" } }, - "ru": { + "ja": { "stringUnit": { "state": "translated", - "value": "Показать уведомления" + "value": "デフォルトのエディタで開く" } - }, - "bs": { + } + } + }, + "fileExplorer.contextMenu.openInCmux": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Prikaži obavještenja" + "value": "Open in cmux" } }, - "ar": { + "ja": { "stringUnit": { "state": "translated", - "value": "عرض الإشعارات" + "value": "cmuxで開く" } - }, - "nb": { + } + } + }, + "fileExplorer.contextMenu.revealInFinder": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Vis varsler" + "value": "Reveal in Finder" } }, - "pt-BR": { + "ja": { "stringUnit": { "state": "translated", - "value": "Mostrar Notificações" + "value": "Finderで表示" } - }, - "th": { + } + } + }, + "fileExplorer.error.unavailable": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "แสดงการแจ้งเตือน" + "value": "File explorer is not available" } }, - "tr": { + "ja": { "stringUnit": { "state": "translated", - "value": "Bildirimleri Göster" + "value": "ファイルエクスプローラーは利用できません" } }, - "uk": { + "ko": { "stringUnit": { "state": "translated", - "value": "Показати сповіщення" + "value": "파일 탐색기를 사용할 수 없습니다" } } } }, - "shortcut.splitBrowserDown.label": { + "fileExplorer.status.sshHomeFailed": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Split Browser Down" + "value": "Unable to resolve SSH home: %@" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ブラウザを下に分割" - } - }, - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "向下拆分浏览器" + "value": "SSH のホームを解決できません: %@" } - }, - "zh-Hant": { + } + } + }, + "fileExplorer.status.sshResolvingHome": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "向下分割瀏覽器" + "value": "Resolving remote home..." } }, - "ko": { + "ja": { "stringUnit": { "state": "translated", - "value": "브라우저를 아래로 분할" + "value": "リモートのホームを解決中..." } - }, - "de": { + } + } + }, + "fileExplorer.status.sshUnavailable": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Browser nach unten teilen" + "value": "SSH files unavailable" } }, - "es": { + "ja": { "stringUnit": { "state": "translated", - "value": "Dividir navegador hacia abajo" + "value": "SSH ファイルを利用できません" } - }, - "fr": { + } + } + }, + "fileExplorer.status.sshUnavailableWithDetail": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Diviser le navigateur vers le bas" + "value": "SSH files unavailable: %@" } }, - "it": { + "ja": { "stringUnit": { "state": "translated", - "value": "Dividi browser in basso" + "value": "SSH ファイルを利用できません: %@" } - }, - "da": { + } + } + }, + "fileExplorer.search.empty": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Opdel browser nedad" + "value": "Type to search" } }, - "pl": { + "ja": { "stringUnit": { "state": "translated", - "value": "Podziel przeglądarkę w dół" + "value": "入力して検索" } - }, - "ru": { + } + } + }, + "fileExplorer.search.failed": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Разделить браузер вниз" + "value": "Search failed: %@" } }, - "bs": { + "ja": { "stringUnit": { "state": "translated", - "value": "Podijeli preglednik dolje" + "value": "検索に失敗しました: %@" } - }, - "ar": { + } + } + }, + "fileExplorer.search.limit": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "تقسيم المتصفح للأسفل" + "value": "First %d matches" } }, - "nb": { + "ja": { "stringUnit": { "state": "translated", - "value": "Del nettleser ned" + "value": "最初の%d件" } - }, - "pt-BR": { + } + } + }, + "fileExplorer.search.matches": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Dividir Navegador para Baixo" + "value": "%d matches" } }, - "th": { + "ja": { "stringUnit": { "state": "translated", - "value": "แยกเบราว์เซอร์ลงล่าง" + "value": "%d件" } - }, - "tr": { + } + } + }, + "fileExplorer.search.noMatches": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Tarayıcıyı Aşağı Böl" + "value": "No matches" } }, - "uk": { + "ja": { "stringUnit": { "state": "translated", - "value": "Розділити браузер вниз" + "value": "一致なし" } } } }, - "shortcut.splitBrowserRight.label": { + "fileExplorer.search.placeholder": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Split Browser Right" + "value": "Search files" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ブラウザを右に分割" + "value": "ファイルを検索" } - }, - "zh-Hans": { + } + } + }, + "fileExplorer.search.rgExited": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "向右拆分浏览器" + "value": "rg exited with status %d" } }, - "zh-Hant": { + "ja": { "stringUnit": { "state": "translated", - "value": "向右分割瀏覽器" + "value": "rg がステータス %d で終了しました" } - }, - "ko": { + } + } + }, + "fileExplorer.search.rgNotInstalled": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "브라우저를 오른쪽으로 분할" + "value": "ripgrep (rg) is not installed or is not on PATH." } }, - "de": { + "ja": { "stringUnit": { "state": "translated", - "value": "Browser nach rechts teilen" + "value": "ripgrep (rg) がインストールされていないか、PATH にありません。" } - }, - "es": { + } + } + }, + "fileExplorer.search.searching": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Dividir navegador a la derecha" + "value": "%d matches, searching" } }, - "fr": { + "ja": { "stringUnit": { "state": "translated", - "value": "Diviser le navigateur à droite" + "value": "%d件、検索中" } - }, - "it": { + } + } + }, + "fileExplorer.search.rgConfiguredPathNotExecutable": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Dividi browser a destra" + "value": "Configured ripgrep path is not executable: %@" } }, - "da": { + "ja": { "stringUnit": { "state": "translated", - "value": "Opdel browser til højre" + "value": "設定されたripgrepパスは実行できません: %@" } }, - "pl": { + "ko": { "stringUnit": { "state": "translated", - "value": "Podziel przeglądarkę w prawo" + "value": "설정된 ripgrep 경로를 실행할 수 없습니다: %@" } - }, - "ru": { + } + } + }, + "fileExplorer.search.unsupported": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Разделить браузер вправо" + "value": "Local folders only" } }, - "bs": { + "ja": { "stringUnit": { "state": "translated", - "value": "Podijeli preglednik desno" + "value": "ローカルフォルダのみ" } - }, - "ar": { + } + } + }, + "titlebar.fileExplorer.accessibilityLabel": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "تقسيم المتصفح لليمين" + "value": "Toggle File Explorer" } }, - "nb": { + "ja": { "stringUnit": { "state": "translated", - "value": "Del nettleser til høyre" + "value": "ファイルエクスプローラーを切替" } }, - "pt-BR": { + "ko": { "stringUnit": { "state": "translated", - "value": "Dividir Navegador à Direita" + "value": "파일 탐색기 토글" } - }, - "th": { + } + } + }, + "titlebar.fileExplorer.tooltip": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "แยกเบราว์เซอร์ไปทางขวา" + "value": "Show or hide the file explorer" } }, - "tr": { + "ja": { "stringUnit": { "state": "translated", - "value": "Tarayıcıyı Sağa Böl" + "value": "ファイルエクスプローラーの表示/非表示" } }, - "uk": { + "ko": { "stringUnit": { "state": "translated", - "value": "Розділити браузер праворуч" + "value": "파일 탐색기 표시 또는 숨기기" } } } }, - "shortcut.splitDown.label": { + "shortcut.toggleTerminalCopyMode.label": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Split Down" + "value": "Toggle Terminal Copy Mode" } }, "ja": { "stringUnit": { "state": "translated", - "value": "下に分割" + "value": "ターミナルコピーモードを切替" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "向下拆分" + "value": "切换终端复制模式" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "向下分割" + "value": "切換終端機複製模式" } }, "ko": { "stringUnit": { "state": "translated", - "value": "아래로 분할" + "value": "터미널 복사 모드 전환" } }, "de": { "stringUnit": { "state": "translated", - "value": "Nach unten teilen" + "value": "Terminal-Kopiermodus umschalten" } }, "es": { "stringUnit": { "state": "translated", - "value": "Dividir hacia abajo" + "value": "Alternar modo de copia del terminal" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Diviser vers le bas" + "value": "Activer/désactiver le mode copie du terminal" } }, "it": { "stringUnit": { "state": "translated", - "value": "Dividi in basso" + "value": "Attiva/Disattiva modalità copia terminale" } }, "da": { "stringUnit": { "state": "translated", - "value": "Opdel nedad" + "value": "Slå terminalkopiertilstand til/fra" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Podziel w dół" + "value": "Przełącz tryb kopiowania terminala" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Разделить вниз" + "value": "Режим копирования терминала" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Podijeli dolje" + "value": "Prebaci režim kopiranja terminala" } }, "ar": { "stringUnit": { "state": "translated", - "value": "تقسيم للأسفل" + "value": "تبديل وضع النسخ في الطرفية" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Del ned" + "value": "Slå terminalkopieringsmodus av/på" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Dividir para Baixo" + "value": "Alternar Modo de Cópia do Terminal" } }, "th": { "stringUnit": { "state": "translated", - "value": "แยกลงล่าง" + "value": "สลับโหมดคัดลอกเทอร์มินัล" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Aşağı Böl" + "value": "Terminal Kopyalama Modunu Aç/Kapat" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Розділити вниз" + "value": "Перемкнути режим копіювання терміналу" } } } }, - "shortcut.equalizeSplits.label": { + "sidebar.closeWorkspace.tooltip": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Equalize Splits" + "value": "Close Workspace" } }, "ja": { "stringUnit": { "state": "translated", - "value": "分割を均等にする" + "value": "ワークスペースを閉じる" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "均分面板" + "value": "关闭工作区" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "均等分割" + "value": "關閉工作區" } }, "ko": { "stringUnit": { "state": "translated", - "value": "분할 균등화" + "value": "작업 공간 닫기" } }, "de": { "stringUnit": { "state": "translated", - "value": "Teilungen angleichen" + "value": "Arbeitsbereich schließen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Igualar divisiones" + "value": "Cerrar espacio de trabajo" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Égaliser les divisions" + "value": "Fermer l'espace de travail" } }, "it": { "stringUnit": { "state": "translated", - "value": "Equalizza divisioni" + "value": "Chiudi area di lavoro" } }, "da": { "stringUnit": { "state": "translated", - "value": "Udlign opdelinger" + "value": "Luk arbejdsområde" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Wyrównaj podziały" + "value": "Zamknij przestrzeń roboczą" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Выровнять разделение" + "value": "Закрыть рабочее пространство" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Izjednači podjele" + "value": "Zatvori radni prostor" } }, "ar": { "stringUnit": { "state": "translated", - "value": "تسوية التقسيمات" + "value": "إغلاق مساحة العمل" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Gjør delinger like" + "value": "Lukk arbeidsområde" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Equalizar Divisões" + "value": "Fechar Área de Trabalho" + } + }, + "th": { + "stringUnit": { + "state": "translated", + "value": "ปิดเวิร์กสเปซ" + } + }, + "tr": { + "stringUnit": { + "state": "translated", + "value": "Çalışma Alanını Kapat" + } + }, + "uk": { + "stringUnit": { + "state": "translated", + "value": "Закрити робочу область" + } + } + } + }, + "sidebar.pinnedWorkspaceProtected.tooltip": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Pinned workspace. Closing requires confirmation." } }, - "th": { + "ja": { "stringUnit": { "state": "translated", - "value": "ปรับขนาดช่องแยกให้เท่ากัน" + "value": "ピン留めされたワークスペースです。閉じるには確認が必要です。" } }, - "tr": { + "uk": { "stringUnit": { "state": "translated", - "value": "Bölmeleri Eşitle" + "value": "Закріплена робоча область. Закриття потребує підтвердження." } }, - "uk": { + "ko": { "stringUnit": { "state": "translated", - "value": "Вирівняти розділення" + "value": "고정된 워크스페이스입니다. 닫으려면 확인이 필요합니다." } } } }, - "shortcut.splitRight.label": { + "sidebar.folderIcon.dragHint": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Split Right" + "value": "Drag to open in Finder or another app" } }, "ja": { "stringUnit": { "state": "translated", - "value": "右に分割" + "value": "ドラッグしてFinderまたは他のアプリで開く" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "向右拆分" + "value": "拖拽以在访达或其他应用中打开" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "向右分割" + "value": "拖曳以在 Finder 或其他 App 中開啟" } }, "ko": { "stringUnit": { "state": "translated", - "value": "오른쪽으로 분할" + "value": "Finder 또는 다른 앱으로 드래그하여 열기" } }, "de": { "stringUnit": { "state": "translated", - "value": "Nach rechts teilen" + "value": "Ziehen, um im Finder oder einer anderen App zu öffnen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Dividir a la derecha" + "value": "Arrastra para abrir en Finder u otra app" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Diviser à droite" + "value": "Glissez pour ouvrir dans le Finder ou une autre app" } }, "it": { "stringUnit": { "state": "translated", - "value": "Dividi a destra" + "value": "Trascina per aprire nel Finder o in un'altra app" } }, "da": { "stringUnit": { "state": "translated", - "value": "Opdel til højre" + "value": "Træk for at åbne i Finder eller et andet program" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Podziel w prawo" + "value": "Przeciągnij, aby otworzyć w Finderze lub innej aplikacji" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Разделить вправо" + "value": "Перетащите, чтобы открыть в Finder или другом приложении" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Podijeli desno" + "value": "Prevucite za otvaranje u Finderu ili drugoj aplikaciji" } }, "ar": { "stringUnit": { "state": "translated", - "value": "تقسيم لليمين" + "value": "اسحب للفتح في Finder أو تطبيق آخر" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Del til høyre" + "value": "Dra for å åpne i Finder eller en annen app" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Dividir à Direita" + "value": "Arraste para abrir no Finder ou em outro app" } }, "th": { "stringUnit": { "state": "translated", - "value": "แยกไปทางขวา" + "value": "ลากเพื่อเปิดใน Finder หรือแอปอื่น" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Sağa Böl" + "value": "Finder'da veya başka bir uygulamada açmak için sürükleyin" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Розділити праворуч" + "value": "Перетягніть, щоб відкрити у Finder або іншій програмі" } } } }, - "shortcut.toggleBrowserDevTools.label": { + "sidebar.indicator.leftRail": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Toggle Browser Developer Tools" + "value": "Left Rail" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ブラウザデベロッパツールを切替" + "value": "左レール" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "切换浏览器开发者工具" + "value": "左侧导轨" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "切換瀏覽器開發者工具" + "value": "左側軌道" } }, "ko": { "stringUnit": { "state": "translated", - "value": "브라우저 개발자 도구 전환" + "value": "왼쪽 레일" } }, "de": { "stringUnit": { "state": "translated", - "value": "Browser-Entwicklerwerkzeuge ein-/ausblenden" + "value": "Linke Leiste" } }, "es": { "stringUnit": { "state": "translated", - "value": "Alternar herramientas de desarrollo del navegador" + "value": "Barra izquierda" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Afficher/masquer les outils de développement du navigateur" + "value": "Rail gauche" } }, "it": { "stringUnit": { "state": "translated", - "value": "Attiva/Disattiva Strumenti sviluppatore browser" + "value": "Barra sinistra" } }, "da": { "stringUnit": { "state": "translated", - "value": "Slå browserudviklerværktøjer til/fra" + "value": "Venstre skinne" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Przełącz narzędzia deweloperskie przeglądarki" + "value": "Lewa listwa" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Инструменты разработчика браузера" + "value": "Левая полоса" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Prebaci razvojne alate preglednika" + "value": "Lijeva traka" } }, "ar": { "stringUnit": { "state": "translated", - "value": "تبديل أدوات المطور للمتصفح" + "value": "شريط أيسر" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Slå utviklerverktøy i nettleser av/på" + "value": "Venstre skinne" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Alternar Ferramentas do Desenvolvedor do Navegador" + "value": "Trilho Esquerdo" } }, "th": { "stringUnit": { "state": "translated", - "value": "สลับเครื่องมือนักพัฒนาเบราว์เซอร์" + "value": "แถบด้านซ้าย" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Tarayıcı Geliştirici Araçlarını Aç/Kapat" + "value": "Sol Şerit" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Перемкнути інструменти розробника браузера" + "value": "Лівий рейл" } } } }, - "shortcut.togglePaneZoom.label": { + "sidebar.indicator.solidFill": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Toggle Pane Zoom" + "value": "Solid Fill" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ペインズームを切替" + "value": "ソリッドフィル" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "切换面板缩放" + "value": "纯色填充" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "切換面板縮放" + "value": "實心填充" } }, "ko": { "stringUnit": { "state": "translated", - "value": "패널 확대/축소 전환" + "value": "단색 채우기" } }, "de": { "stringUnit": { "state": "translated", - "value": "Bereichszoom umschalten" + "value": "Farbfüllung" } }, "es": { "stringUnit": { "state": "translated", - "value": "Alternar zoom del panel" + "value": "Relleno sólido" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Activer/désactiver le zoom du panneau" + "value": "Remplissage uni" } }, "it": { "stringUnit": { "state": "translated", - "value": "Attiva/Disattiva zoom pannello" + "value": "Riempimento solido" } }, "da": { "stringUnit": { "state": "translated", - "value": "Slå panelzoom til/fra" + "value": "Solid udfyldning" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Przełącz powiększenie panelu" + "value": "Jednolite wypełnienie" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Масштаб панели" + "value": "Сплошная заливка" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Prebaci uvećanje panela" + "value": "Puna ispuna" } }, "ar": { "stringUnit": { "state": "translated", - "value": "تبديل تكبير اللوحة" + "value": "تعبئة صلبة" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Slå panelzoom av/på" + "value": "Heldekkende fyll" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Alternar Zoom do Painel" + "value": "Preenchimento Sólido" } }, "th": { "stringUnit": { "state": "translated", - "value": "สลับการซูมบานหน้าต่าง" + "value": "พื้นทึบ" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Bölme Yakınlaştırmasını Aç/Kapat" + "value": "Düz Dolgu" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Перемкнути масштаб панелі" + "value": "Суцільне заповнення" } } } }, - "fileExplorer.empty": { + "sidebar.metadata.showLess": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "No folder open" + "value": "Show less" } }, "ja": { "stringUnit": { "state": "translated", - "value": "フォルダが開かれていません" + "value": "表示を減らす" } }, - "ko": { - "stringUnit": { - "state": "translated", - "value": "열린 폴더 없음" - } - } - } - }, - "fileExplorer.contextMenu.copyPath": { - "extractionState": "manual", - "localizations": { - "en": { + "zh-Hans": { "stringUnit": { "state": "translated", - "value": "Copy Path" + "value": "收起" } }, - "ja": { + "zh-Hant": { "stringUnit": { "state": "translated", - "value": "パスをコピー" + "value": "顯示較少" } - } - } - }, - "fileExplorer.contextMenu.copyRelativePath": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "ko": { "stringUnit": { "state": "translated", - "value": "Copy Relative Path" + "value": "간략히 보기" } }, - "ja": { + "de": { "stringUnit": { "state": "translated", - "value": "相対パスをコピー" + "value": "Weniger anzeigen" } - } - } - }, - "fileExplorer.contextMenu.insertPath": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "es": { "stringUnit": { "state": "translated", - "value": "Insert Path" + "value": "Mostrar menos" } }, - "ja": { + "fr": { "stringUnit": { "state": "translated", - "value": "パスを挿入" + "value": "Afficher moins" } - } - } - }, - "fileExplorer.contextMenu.insertRelativePath": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "it": { "stringUnit": { "state": "translated", - "value": "Insert Relative Path" + "value": "Mostra meno" } }, - "ja": { + "da": { "stringUnit": { "state": "translated", - "value": "相対パスを挿入" + "value": "Vis mindre" } - } - } - }, - "fileExplorer.contextMenu.openDefault": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "pl": { "stringUnit": { "state": "translated", - "value": "Open in Default Editor" + "value": "Pokaż mniej" } }, - "ja": { + "ru": { "stringUnit": { "state": "translated", - "value": "デフォルトのエディタで開く" + "value": "Показать меньше" } - } - } - }, - "fileExplorer.contextMenu.openInCmux": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "bs": { "stringUnit": { "state": "translated", - "value": "Open in cmux" + "value": "Prikaži manje" } }, - "ja": { + "ar": { "stringUnit": { "state": "translated", - "value": "cmuxで開く" + "value": "عرض أقل" } - } - } - }, - "fileExplorer.contextMenu.revealInFinder": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "nb": { "stringUnit": { "state": "translated", - "value": "Reveal in Finder" + "value": "Vis mindre" } }, - "ja": { + "pt-BR": { "stringUnit": { "state": "translated", - "value": "Finderで表示" + "value": "Mostrar menos" } - } - } - }, - "fileExplorer.error.unavailable": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "th": { "stringUnit": { "state": "translated", - "value": "File explorer is not available" + "value": "แสดงน้อยลง" } }, - "ja": { + "tr": { "stringUnit": { "state": "translated", - "value": "ファイルエクスプローラーは利用できません" + "value": "Daha az göster" } }, - "ko": { + "uk": { "stringUnit": { "state": "translated", - "value": "파일 탐색기를 사용할 수 없습니다" + "value": "Менше" } } } }, - "fileExplorer.status.sshHomeFailed": { + "sidebar.metadata.showLessDetails": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Unable to resolve SSH home: %@" + "value": "Show less details" } }, "ja": { "stringUnit": { "state": "translated", - "value": "SSH のホームを解決できません: %@" + "value": "詳細を折りたたむ" } - } - } - }, - "fileExplorer.status.sshResolvingHome": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "zh-Hans": { "stringUnit": { "state": "translated", - "value": "Resolving remote home..." + "value": "收起详细信息" } }, - "ja": { + "zh-Hant": { "stringUnit": { "state": "translated", - "value": "リモートのホームを解決中..." + "value": "顯示較少詳細資訊" } - } - } - }, - "fileExplorer.status.sshUnavailable": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "ko": { "stringUnit": { "state": "translated", - "value": "SSH files unavailable" + "value": "세부 정보 접기" } }, - "ja": { + "de": { "stringUnit": { "state": "translated", - "value": "SSH ファイルを利用できません" + "value": "Weniger Details anzeigen" } - } - } - }, - "fileExplorer.status.sshUnavailableWithDetail": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "es": { "stringUnit": { "state": "translated", - "value": "SSH files unavailable: %@" + "value": "Mostrar menos detalles" } }, - "ja": { + "fr": { "stringUnit": { "state": "translated", - "value": "SSH ファイルを利用できません: %@" + "value": "Afficher moins de détails" } - } - } - }, - "fileExplorer.search.empty": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "it": { "stringUnit": { "state": "translated", - "value": "Type to search" + "value": "Mostra meno dettagli" } }, - "ja": { + "da": { "stringUnit": { "state": "translated", - "value": "入力して検索" + "value": "Vis færre detaljer" } - } - } - }, - "fileExplorer.search.failed": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "pl": { "stringUnit": { "state": "translated", - "value": "Search failed: %@" + "value": "Pokaż mniej szczegółów" } }, - "ja": { + "ru": { "stringUnit": { "state": "translated", - "value": "検索に失敗しました: %@" + "value": "Показать меньше подробностей" } - } - } - }, - "fileExplorer.search.limit": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "bs": { "stringUnit": { "state": "translated", - "value": "First %d matches" + "value": "Prikaži manje detalja" } }, - "ja": { + "ar": { "stringUnit": { "state": "translated", - "value": "最初の%d件" + "value": "عرض تفاصيل أقل" } - } - } - }, - "fileExplorer.search.matches": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "nb": { "stringUnit": { "state": "translated", - "value": "%d matches" + "value": "Vis færre detaljer" } }, - "ja": { + "pt-BR": { "stringUnit": { "state": "translated", - "value": "%d件" + "value": "Mostrar menos detalhes" } - } - } - }, - "fileExplorer.search.noMatches": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "th": { "stringUnit": { "state": "translated", - "value": "No matches" + "value": "แสดงรายละเอียดน้อยลง" } }, - "ja": { + "tr": { "stringUnit": { "state": "translated", - "value": "一致なし" + "value": "Daha az ayrıntı göster" + } + }, + "uk": { + "stringUnit": { + "state": "translated", + "value": "Менше деталей" } } } }, - "fileExplorer.search.placeholder": { + "sidebar.metadata.showMore": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Search files" + "value": "Show more" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ファイルを検索" + "value": "さらに表示" } - } - } - }, - "fileExplorer.search.rgExited": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "zh-Hans": { "stringUnit": { "state": "translated", - "value": "rg exited with status %d" + "value": "展开" } }, - "ja": { + "zh-Hant": { "stringUnit": { "state": "translated", - "value": "rg がステータス %d で終了しました" + "value": "顯示更多" } - } - } - }, - "fileExplorer.search.rgNotInstalled": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "ko": { "stringUnit": { "state": "translated", - "value": "ripgrep (rg) is not installed or is not on PATH." + "value": "더 보기" } }, - "ja": { + "de": { "stringUnit": { "state": "translated", - "value": "ripgrep (rg) がインストールされていないか、PATH にありません。" + "value": "Mehr anzeigen" } - } - } - }, - "fileExplorer.search.searching": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "es": { "stringUnit": { "state": "translated", - "value": "%d matches, searching" + "value": "Mostrar más" } }, - "ja": { + "fr": { "stringUnit": { "state": "translated", - "value": "%d件、検索中" + "value": "Afficher plus" } - } - } - }, - "fileExplorer.search.rgConfiguredPathNotExecutable": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "it": { "stringUnit": { "state": "translated", - "value": "Configured ripgrep path is not executable: %@" + "value": "Mostra di più" } }, - "ja": { + "da": { "stringUnit": { "state": "translated", - "value": "設定されたripgrepパスは実行できません: %@" + "value": "Vis mere" } }, - "ko": { + "pl": { "stringUnit": { "state": "translated", - "value": "설정된 ripgrep 경로를 실행할 수 없습니다: %@" + "value": "Pokaż więcej" } - } - } - }, - "fileExplorer.search.unsupported": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "ru": { "stringUnit": { "state": "translated", - "value": "Local folders only" + "value": "Показать больше" } }, - "ja": { + "bs": { "stringUnit": { "state": "translated", - "value": "ローカルフォルダのみ" + "value": "Prikaži više" } - } - } - }, - "titlebar.fileExplorer.accessibilityLabel": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "ar": { "stringUnit": { "state": "translated", - "value": "Toggle File Explorer" + "value": "عرض المزيد" } }, - "ja": { + "nb": { "stringUnit": { "state": "translated", - "value": "ファイルエクスプローラーを切替" + "value": "Vis mer" } }, - "ko": { + "pt-BR": { "stringUnit": { - "state": "translated", - "value": "파일 탐색기 토글" - } - } - } - }, - "titlebar.fileExplorer.tooltip": { - "extractionState": "manual", - "localizations": { - "en": { + "state": "translated", + "value": "Mostrar mais" + } + }, + "th": { "stringUnit": { "state": "translated", - "value": "Show or hide the file explorer" + "value": "แสดงเพิ่มเติม" } }, - "ja": { + "tr": { "stringUnit": { "state": "translated", - "value": "ファイルエクスプローラーの表示/非表示" + "value": "Daha fazla göster" } }, - "ko": { + "uk": { "stringUnit": { "state": "translated", - "value": "파일 탐색기 표시 또는 숨기기" + "value": "Більше" } } } }, - "shortcut.toggleTerminalCopyMode.label": { + "sidebar.metadata.showMoreDetails": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Toggle Terminal Copy Mode" + "value": "Show more details" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ターミナルコピーモードを切替" + "value": "詳細を展開" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "切换终端复制模式" + "value": "展开详细信息" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "切換終端機複製模式" + "value": "顯示更多詳細資訊" } }, "ko": { "stringUnit": { "state": "translated", - "value": "터미널 복사 모드 전환" + "value": "세부 정보 펼치기" } }, "de": { "stringUnit": { "state": "translated", - "value": "Terminal-Kopiermodus umschalten" + "value": "Mehr Details anzeigen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Alternar modo de copia del terminal" + "value": "Mostrar más detalles" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Activer/désactiver le mode copie du terminal" + "value": "Afficher plus de détails" } }, "it": { "stringUnit": { "state": "translated", - "value": "Attiva/Disattiva modalità copia terminale" + "value": "Mostra più dettagli" } }, "da": { "stringUnit": { "state": "translated", - "value": "Slå terminalkopiertilstand til/fra" + "value": "Vis flere detaljer" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Przełącz tryb kopiowania terminala" + "value": "Pokaż więcej szczegółów" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Режим копирования терминала" + "value": "Показать больше подробностей" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Prebaci režim kopiranja terminala" + "value": "Prikaži više detalja" } }, "ar": { "stringUnit": { "state": "translated", - "value": "تبديل وضع النسخ في الطرفية" + "value": "عرض تفاصيل أكثر" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Slå terminalkopieringsmodus av/på" + "value": "Vis flere detaljer" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Alternar Modo de Cópia do Terminal" + "value": "Mostrar mais detalhes" } }, "th": { "stringUnit": { "state": "translated", - "value": "สลับโหมดคัดลอกเทอร์มินัล" + "value": "แสดงรายละเอียดเพิ่มเติม" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Terminal Kopyalama Modunu Aç/Kapat" + "value": "Daha fazla ayrıntı göster" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Перемкнути режим копіювання терміналу" + "value": "Більше деталей" } } } }, - "sidebar.closeWorkspace.tooltip": { + "sidebar.pathMenu.macintoshHD": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Close Workspace" + "value": "Macintosh HD" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ワークスペースを閉じる" + "value": "Macintosh HD" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "关闭工作区" + "value": "Macintosh HD" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "關閉工作區" + "value": "Macintosh HD" } }, "ko": { "stringUnit": { "state": "translated", - "value": "작업 공간 닫기" + "value": "Macintosh HD" } }, "de": { "stringUnit": { "state": "translated", - "value": "Arbeitsbereich schließen" + "value": "Macintosh HD" } }, "es": { "stringUnit": { "state": "translated", - "value": "Cerrar espacio de trabajo" + "value": "Macintosh HD" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Fermer l'espace de travail" + "value": "Macintosh HD" } }, "it": { "stringUnit": { "state": "translated", - "value": "Chiudi area di lavoro" + "value": "Macintosh HD" } }, "da": { "stringUnit": { "state": "translated", - "value": "Luk arbejdsområde" + "value": "Macintosh HD" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Zamknij przestrzeń roboczą" + "value": "Macintosh HD" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Закрыть рабочее пространство" + "value": "Macintosh HD" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Zatvori radni prostor" + "value": "Macintosh HD" } }, "ar": { "stringUnit": { "state": "translated", - "value": "إغلاق مساحة العمل" + "value": "Macintosh HD" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Lukk arbeidsområde" + "value": "Macintosh HD" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Fechar Área de Trabalho" + "value": "Macintosh HD" } }, "th": { "stringUnit": { "state": "translated", - "value": "ปิดเวิร์กสเปซ" + "value": "Macintosh HD" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Çalışma Alanını Kapat" + "value": "Macintosh HD" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Закрити робочу область" + "value": "Macintosh HD" } } } }, - "sidebar.pinnedWorkspaceProtected.tooltip": { + "sidebar.port.label": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Pinned workspace. Closing requires confirmation." + "value": ":%lld" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ピン留めされたワークスペースです。閉じるには確認が必要です。" + "value": ":%lld" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Закріплена робоча область. Закриття потребує підтвердження." + "value": ":%lld" } }, "ko": { "stringUnit": { "state": "translated", - "value": "고정된 워크스페이스입니다. 닫으려면 확인이 필요합니다." + "value": ":%lld" } } } }, - "sidebar.folderIcon.dragHint": { + "sidebar.port.openTooltip": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Drag to open in Finder or another app" + "value": "Open localhost:%lld" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ドラッグしてFinderまたは他のアプリで開く" + "value": "localhost:%lldを開く" + } + }, + "uk": { + "stringUnit": { + "state": "translated", + "value": "Відкрити localhost:%lld" + } + }, + "ko": { + "stringUnit": { + "state": "translated", + "value": "localhost:%lld 열기" + } + } + } + }, + "sidebar.pullRequest.openTooltip": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Open %1$@ #%2$lld" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "%1$@ #%2$lldを開く" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "拖拽以在访达或其他应用中打开" + "value": "打开 %1$@ #%2$lld" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "拖曳以在 Finder 或其他 App 中開啟" + "value": "開啟 %1$@ #%2$lld" } }, "ko": { "stringUnit": { "state": "translated", - "value": "Finder 또는 다른 앱으로 드래그하여 열기" + "value": "%1$@ #%2$lld 열기" } }, "de": { "stringUnit": { "state": "translated", - "value": "Ziehen, um im Finder oder einer anderen App zu öffnen" + "value": "%1$@ #%2$lld öffnen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Arrastra para abrir en Finder u otra app" + "value": "Abrir %1$@ #%2$lld" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Glissez pour ouvrir dans le Finder ou une autre app" + "value": "Ouvrir %1$@ #%2$lld" } }, "it": { "stringUnit": { "state": "translated", - "value": "Trascina per aprire nel Finder o in un'altra app" + "value": "Apri %1$@ #%2$lld" } }, "da": { "stringUnit": { "state": "translated", - "value": "Træk for at åbne i Finder eller et andet program" + "value": "Åbn %1$@ #%2$lld" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Przeciągnij, aby otworzyć w Finderze lub innej aplikacji" + "value": "Otwórz %1$@ #%2$lld" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Перетащите, чтобы открыть в Finder или другом приложении" + "value": "Открыть %1$@ #%2$lld" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Prevucite za otvaranje u Finderu ili drugoj aplikaciji" + "value": "Otvori %1$@ #%2$lld" } }, "ar": { "stringUnit": { "state": "translated", - "value": "اسحب للفتح في Finder أو تطبيق آخر" + "value": "فتح %1$@ #%2$lld" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Dra for å åpne i Finder eller en annen app" + "value": "Åpne %1$@ #%2$lld" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Arraste para abrir no Finder ou em outro app" + "value": "Abrir %1$@ #%2$lld" } }, "th": { "stringUnit": { "state": "translated", - "value": "ลากเพื่อเปิดใน Finder หรือแอปอื่น" + "value": "เปิด %1$@ #%2$lld" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Finder'da veya başka bir uygulamada açmak için sürükleyin" + "value": "%1$@ #%2$lld Aç" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Перетягніть, щоб відкрити у Finder або іншій програмі" + "value": "Відкрити %1$@ #%2$lld" } } } }, - "sidebar.indicator.leftRail": { + "sidebar.pullRequest.statusClosed": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Left Rail" + "value": "closed" } }, "ja": { "stringUnit": { "state": "translated", - "value": "左レール" + "value": "クローズ" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "左侧导轨" + "value": "已关闭" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "左側軌道" + "value": "已關閉" } }, "ko": { "stringUnit": { "state": "translated", - "value": "왼쪽 레일" + "value": "닫힘" } }, "de": { "stringUnit": { "state": "translated", - "value": "Linke Leiste" + "value": "geschlossen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Barra izquierda" + "value": "cerrado" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Rail gauche" + "value": "fermée" } }, "it": { "stringUnit": { "state": "translated", - "value": "Barra sinistra" + "value": "chiusa" } }, "da": { "stringUnit": { "state": "translated", - "value": "Venstre skinne" + "value": "lukket" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Lewa listwa" + "value": "zamknięty" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Левая полоса" + "value": "закрыт" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Lijeva traka" + "value": "zatvoren" } }, "ar": { "stringUnit": { "state": "translated", - "value": "شريط أيسر" + "value": "مغلق" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Venstre skinne" + "value": "lukket" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Trilho Esquerdo" + "value": "fechado" } }, "th": { "stringUnit": { "state": "translated", - "value": "แถบด้านซ้าย" + "value": "ปิดแล้ว" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Sol Şerit" + "value": "kapalı" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Лівий рейл" + "value": "закритий" } } } }, - "sidebar.indicator.solidFill": { + "sidebar.pullRequest.statusMerged": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Solid Fill" + "value": "merged" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ソリッドフィル" + "value": "マージ済み" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "纯色填充" + "value": "已合并" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "實心填充" + "value": "已合併" } }, "ko": { "stringUnit": { "state": "translated", - "value": "단색 채우기" + "value": "병합됨" } }, "de": { "stringUnit": { "state": "translated", - "value": "Farbfüllung" + "value": "zusammengeführt" } }, "es": { "stringUnit": { "state": "translated", - "value": "Relleno sólido" + "value": "fusionado" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Remplissage uni" + "value": "fusionnée" } }, "it": { "stringUnit": { "state": "translated", - "value": "Riempimento solido" + "value": "unita" } }, "da": { "stringUnit": { "state": "translated", - "value": "Solid udfyldning" + "value": "sammenlagt" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Jednolite wypełnienie" + "value": "scalony" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Сплошная заливка" + "value": "объединен" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Puna ispuna" + "value": "spojen" } }, "ar": { "stringUnit": { "state": "translated", - "value": "تعبئة صلبة" + "value": "مدمج" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Heldekkende fyll" + "value": "sammenslått" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Preenchimento Sólido" + "value": "mesclado" } }, "th": { "stringUnit": { "state": "translated", - "value": "พื้นทึบ" + "value": "ผสานแล้ว" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Düz Dolgu" + "value": "birleştirildi" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Суцільне заповнення" + "value": "злитий" } } } }, - "sidebar.metadata.showLess": { + "sidebar.pullRequest.statusOpen": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Show less" + "value": "open" } }, "ja": { "stringUnit": { "state": "translated", - "value": "表示を減らす" + "value": "オープン" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "收起" + "value": "打开" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "顯示較少" + "value": "開啟" } }, "ko": { "stringUnit": { "state": "translated", - "value": "간략히 보기" + "value": "열림" } }, "de": { "stringUnit": { "state": "translated", - "value": "Weniger anzeigen" + "value": "offen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Mostrar menos" + "value": "abierto" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Afficher moins" + "value": "ouverte" } }, "it": { "stringUnit": { "state": "translated", - "value": "Mostra meno" + "value": "aperta" } }, "da": { "stringUnit": { "state": "translated", - "value": "Vis mindre" + "value": "åben" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Pokaż mniej" + "value": "otwarty" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Показать меньше" + "value": "открыт" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Prikaži manje" + "value": "otvoren" } }, "ar": { "stringUnit": { "state": "translated", - "value": "عرض أقل" + "value": "مفتوح" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Vis mindre" + "value": "åpen" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Mostrar menos" + "value": "aberto" } }, "th": { "stringUnit": { "state": "translated", - "value": "แสดงน้อยลง" + "value": "เปิด" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Daha az göster" + "value": "açık" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Менше" + "value": "відкритий" } } } }, - "sidebar.metadata.showLessDetails": { + "sidebar.workspace.accessibilityHint": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Show less details" + "value": "Activate to focus this workspace. Drag to reorder, or use Move Up and Move Down actions." } }, "ja": { "stringUnit": { "state": "translated", - "value": "詳細を折りたたむ" + "value": "アクティブにしてこのワークスペースにフォーカスします。ドラッグで並べ替え、または「上に移動」「下に移動」アクションを使用します。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "收起详细信息" + "value": "激活以聚焦此工作区。拖拽以重新排序,或使用上移和下移操作。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "顯示較少詳細資訊" + "value": "啟用以聚焦此工作區。拖曳以重新排序,或使用上移和下移動作。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "세부 정보 접기" + "value": "이 작업 공간에 포커스하려면 활성화하세요. 드래그하여 순서를 변경하거나 위로 이동 및 아래로 이동 동작을 사용하세요." } }, "de": { "stringUnit": { "state": "translated", - "value": "Weniger Details anzeigen" + "value": "Aktivieren, um diesen Arbeitsbereich zu fokussieren. Ziehen zum Umordnen oder verwenden Sie die Aktionen 'Nach oben' und 'Nach unten'." } }, "es": { "stringUnit": { "state": "translated", - "value": "Mostrar menos detalles" + "value": "Activa para enfocar este espacio de trabajo. Arrastra para reordenar, o usa las acciones Mover hacia arriba y Mover hacia abajo." } }, "fr": { "stringUnit": { "state": "translated", - "value": "Afficher moins de détails" + "value": "Activez pour accéder à cet espace de travail. Glissez pour réordonner, ou utilisez les actions Déplacer vers le haut et Déplacer vers le bas." } }, "it": { "stringUnit": { "state": "translated", - "value": "Mostra meno dettagli" + "value": "Attiva per portare il focus su questa area di lavoro. Trascina per riordinare oppure usa le azioni Sposta in alto e Sposta in basso." } }, "da": { "stringUnit": { "state": "translated", - "value": "Vis færre detaljer" + "value": "Aktiver for at fokusere dette arbejdsområde. Træk for at omarrangere, eller brug handlingerne Flyt op og Flyt ned." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Pokaż mniej szczegółów" + "value": "Aktywuj, aby ustawić fokus na tej przestrzeni roboczej. Przeciągnij, aby zmienić kolejność, lub użyj akcji Przenieś w górę i Przenieś w dół." } }, "ru": { "stringUnit": { "state": "translated", - "value": "Показать меньше подробностей" + "value": "Активируйте для перехода к этому рабочему пространству. Перетащите для изменения порядка или используйте действия «Переместить вверх» и «Переместить вниз»." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Prikaži manje detalja" + "value": "Aktivirajte za fokusiranje ovog radnog prostora. Prevucite za preraspoređivanje ili koristite akcije Pomjeri gore i Pomjeri dolje." } }, "ar": { "stringUnit": { "state": "translated", - "value": "عرض تفاصيل أقل" + "value": "فعّل للتركيز على مساحة العمل هذه. اسحب لإعادة الترتيب، أو استخدم إجراءات نقل للأعلى ونقل للأسفل." } }, "nb": { "stringUnit": { "state": "translated", - "value": "Vis færre detaljer" + "value": "Aktiver for å fokusere dette arbeidsområdet. Dra for å omorganisere, eller bruk Flytt opp og Flytt ned." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Mostrar menos detalhes" + "value": "Ative para focar nesta área de trabalho. Arraste para reordenar ou use as ações Mover para Cima e Mover para Baixo." } }, "th": { "stringUnit": { "state": "translated", - "value": "แสดงรายละเอียดน้อยลง" + "value": "เปิดใช้งานเพื่อโฟกัสเวิร์กสเปซนี้ ลากเพื่อจัดเรียงใหม่ หรือใช้การกระทำเลื่อนขึ้นและเลื่อนลง" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Daha az ayrıntı göster" + "value": "Bu çalışma alanına odaklanmak için etkinleştirin. Yeniden sıralamak için sürükleyin veya Yukarı Taşı ve Aşağı Taşı eylemlerini kullanın." } }, "uk": { "stringUnit": { "state": "translated", - "value": "Менше деталей" + "value": "Активуйте, щоб сфокусувати цю робочу область. Перетягніть для зміни порядку або використовуйте дії «Перемістити вгору» та «Перемістити вниз»." } } } }, - "sidebar.metadata.showMore": { + "sidebar.remote.badge": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Show more" + "value": "SSH" } }, "ja": { "stringUnit": { "state": "translated", - "value": "さらに表示" + "value": "SSH" } }, - "zh-Hans": { + "uk": { "stringUnit": { "state": "translated", - "value": "展开" + "value": "SSH" } }, - "zh-Hant": { + "ko": { "stringUnit": { "state": "translated", - "value": "顯示更多" + "value": "SSH" } - }, - "ko": { + } + } + }, + "remote.status.connected": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "더 보기" + "value": "Connected" } }, - "de": { + "ja": { "stringUnit": { "state": "translated", - "value": "Mehr anzeigen" + "value": "接続済み" } }, - "es": { + "uk": { "stringUnit": { "state": "translated", - "value": "Mostrar más" + "value": "Підключено" } }, - "fr": { + "ko": { "stringUnit": { "state": "translated", - "value": "Afficher plus" + "value": "연결됨" } - }, - "it": { + } + } + }, + "remote.status.connecting": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Mostra di più" + "value": "Connecting" } }, - "da": { + "ja": { "stringUnit": { "state": "translated", - "value": "Vis mere" + "value": "接続中" } }, - "pl": { + "uk": { "stringUnit": { "state": "translated", - "value": "Pokaż więcej" + "value": "Підключення" } }, - "ru": { + "ko": { "stringUnit": { "state": "translated", - "value": "Показать больше" + "value": "연결 중" } - }, - "bs": { + } + } + }, + "remote.status.reconnecting": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Prikaži više" + "value": "Reconnecting" } }, - "ar": { + "ja": { "stringUnit": { "state": "translated", - "value": "عرض المزيد" + "value": "再接続中" } }, - "nb": { + "uk": { "stringUnit": { "state": "translated", - "value": "Vis mer" + "value": "Повторне підключення" } }, - "pt-BR": { + "ko": { "stringUnit": { "state": "translated", - "value": "Mostrar mais" + "value": "다시 연결 중" } - }, - "th": { + } + } + }, + "remote.status.disconnected": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "แสดงเพิ่มเติม" + "value": "Disconnected" } }, - "tr": { + "ja": { "stringUnit": { "state": "translated", - "value": "Daha fazla göster" + "value": "切断済み" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Більше" + "value": "Відключено" + } + }, + "ko": { + "stringUnit": { + "state": "translated", + "value": "연결 해제됨" } } } }, - "sidebar.metadata.showMoreDetails": { + "remote.status.error": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Show more details" + "value": "Error" } }, "ja": { "stringUnit": { "state": "translated", - "value": "詳細を展開" + "value": "エラー" } }, - "zh-Hans": { + "uk": { "stringUnit": { "state": "translated", - "value": "展开详细信息" + "value": "Помилка" } }, - "zh-Hant": { + "ko": { "stringUnit": { "state": "translated", - "value": "顯示更多詳細資訊" + "value": "오류" } - }, - "ko": { + } + } + }, + "sidebar.remote.subtitle": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "세부 정보 펼치기" + "value": "SSH • %@" } }, - "de": { + "ja": { "stringUnit": { "state": "translated", - "value": "Mehr Details anzeigen" + "value": "SSH • %@" } }, - "es": { + "uk": { "stringUnit": { "state": "translated", - "value": "Mostrar más detalles" + "value": "SSH • %@" } }, - "fr": { + "ko": { "stringUnit": { "state": "translated", - "value": "Afficher plus de détails" + "value": "SSH • %@" } - }, - "it": { + } + } + }, + "sidebar.remote.subtitleFallback": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Mostra più dettagli" + "value": "SSH workspace" } }, - "da": { + "ja": { "stringUnit": { "state": "translated", - "value": "Vis flere detaljer" + "value": "SSH ワークスペース" } }, - "pl": { + "uk": { "stringUnit": { "state": "translated", - "value": "Pokaż więcej szczegółów" + "value": "SSH робоча область" } }, - "ru": { + "ko": { "stringUnit": { "state": "translated", - "value": "Показать больше подробностей" + "value": "SSH 워크스페이스" + } + } + } + }, + "sidebar.remote.help.connected": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "SSH connected to %@" } }, - "bs": { + "ja": { "stringUnit": { "state": "translated", - "value": "Prikaži više detalja" + "value": "SSH は %@ に接続済み" } }, - "ar": { + "uk": { "stringUnit": { "state": "translated", - "value": "عرض تفاصيل أكثر" + "value": "SSH підключено до %@" } }, - "nb": { + "ko": { "stringUnit": { "state": "translated", - "value": "Vis flere detaljer" + "value": "%@에 SSH 연결됨" } - }, - "pt-BR": { + } + } + }, + "sidebar.remote.help.connecting": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Mostrar mais detalhes" + "value": "SSH connecting to %@" } }, - "th": { + "ja": { "stringUnit": { "state": "translated", - "value": "แสดงรายละเอียดเพิ่มเติม" + "value": "SSH は %@ に接続中" } }, - "tr": { + "uk": { "stringUnit": { "state": "translated", - "value": "Daha fazla ayrıntı göster" + "value": "SSH підключення до %@" } }, - "uk": { + "ko": { "stringUnit": { "state": "translated", - "value": "Більше деталей" + "value": "%@에 SSH 연결 중" } } } }, - "sidebar.pathMenu.macintoshHD": { + "sidebar.remote.help.reconnecting": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Macintosh HD" + "value": "SSH reconnecting to %@" } }, "ja": { "stringUnit": { "state": "translated", - "value": "Macintosh HD" + "value": "SSH は %@ に再接続中" } }, - "zh-Hans": { + "uk": { "stringUnit": { "state": "translated", - "value": "Macintosh HD" + "value": "SSH повторно підключається до %@" } }, - "zh-Hant": { + "ko": { "stringUnit": { "state": "translated", - "value": "Macintosh HD" + "value": "%@에 SSH 다시 연결 중" } - }, - "ko": { + } + } + }, + "sidebar.remote.help.error": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Macintosh HD" + "value": "SSH error for %@" } }, - "de": { + "ja": { "stringUnit": { "state": "translated", - "value": "Macintosh HD" + "value": "%@ の SSH エラー" } }, - "es": { + "uk": { "stringUnit": { "state": "translated", - "value": "Macintosh HD" + "value": "Помилка SSH для %@" } }, - "fr": { + "ko": { "stringUnit": { "state": "translated", - "value": "Macintosh HD" + "value": "%@에 대한 SSH 오류" } - }, - "it": { + } + } + }, + "sidebar.remote.help.errorWithDetail": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Macintosh HD" + "value": "SSH error for %@: %@" } }, - "da": { + "ja": { "stringUnit": { "state": "translated", - "value": "Macintosh HD" + "value": "%@ の SSH エラー: %@" } }, - "pl": { + "uk": { "stringUnit": { "state": "translated", - "value": "Macintosh HD" + "value": "Помилка SSH для %@: %@" } }, - "ru": { + "ko": { "stringUnit": { "state": "translated", - "value": "Macintosh HD" + "value": "%@에 대한 SSH 오류: %@" } - }, - "bs": { + } + } + }, + "sidebar.remote.help.disconnected": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Macintosh HD" + "value": "SSH disconnected from %@" } }, - "ar": { + "ja": { "stringUnit": { "state": "translated", - "value": "Macintosh HD" + "value": "SSH は %@ から切断済み" } }, - "nb": { + "uk": { "stringUnit": { "state": "translated", - "value": "Macintosh HD" + "value": "SSH відключено від %@" } }, - "pt-BR": { + "ko": { "stringUnit": { "state": "translated", - "value": "Macintosh HD" + "value": "%@에서 SSH 연결 해제됨" } - }, - "th": { + } + } + }, + "sidebar.remote.help.targetFallback": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Macintosh HD" + "value": "remote host" } }, - "tr": { + "ja": { "stringUnit": { "state": "translated", - "value": "Macintosh HD" + "value": "リモートホスト" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Macintosh HD" + "value": "віддалений хост" + } + }, + "ko": { + "stringUnit": { + "state": "translated", + "value": "원격 호스트" } } } }, - "sidebar.port.label": { + "sidebar.activeTabIndicator.leftRail": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": ":%lld" + "value": "Left Rail" } }, "ja": { "stringUnit": { "state": "translated", - "value": ":%lld" + "value": "左レール" } }, "uk": { "stringUnit": { "state": "translated", - "value": ":%lld" + "value": "Лівий рейл" } }, "ko": { "stringUnit": { "state": "translated", - "value": ":%lld" + "value": "왼쪽 레일" } } } }, - "sidebar.port.openTooltip": { + "sidebar.activeTabIndicator.solidFill": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Open localhost:%lld" + "value": "Solid Fill" } }, "ja": { "stringUnit": { "state": "translated", - "value": "localhost:%lldを開く" + "value": "塗りつぶし" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Відкрити localhost:%lld" + "value": "Суцільне заповнення" } }, "ko": { "stringUnit": { "state": "translated", - "value": "localhost:%lld 열기" + "value": "단색 채우기" } } } }, - "sidebar.pullRequest.openTooltip": { + "sidebar.workspace.moveDownAction": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Open %1$@ #%2$lld" + "value": "Move Down" } }, "ja": { "stringUnit": { "state": "translated", - "value": "%1$@ #%2$lldを開く" + "value": "下に移動" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "打开 %1$@ #%2$lld" + "value": "下移" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "開啟 %1$@ #%2$lld" + "value": "下移" } }, "ko": { "stringUnit": { "state": "translated", - "value": "%1$@ #%2$lld 열기" + "value": "아래로 이동" } }, "de": { "stringUnit": { "state": "translated", - "value": "%1$@ #%2$lld öffnen" + "value": "Nach unten bewegen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Abrir %1$@ #%2$lld" + "value": "Mover hacia abajo" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Ouvrir %1$@ #%2$lld" + "value": "Déplacer vers le bas" } }, "it": { "stringUnit": { "state": "translated", - "value": "Apri %1$@ #%2$lld" + "value": "Sposta in basso" } }, "da": { "stringUnit": { "state": "translated", - "value": "Åbn %1$@ #%2$lld" + "value": "Flyt ned" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Otwórz %1$@ #%2$lld" + "value": "Przenieś w dół" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Открыть %1$@ #%2$lld" + "value": "Переместить вниз" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Otvori %1$@ #%2$lld" + "value": "Pomjeri dolje" } }, "ar": { "stringUnit": { "state": "translated", - "value": "فتح %1$@ #%2$lld" + "value": "نقل للأسفل" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Åpne %1$@ #%2$lld" + "value": "Flytt ned" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Abrir %1$@ #%2$lld" + "value": "Mover para Baixo" } }, "th": { "stringUnit": { "state": "translated", - "value": "เปิด %1$@ #%2$lld" + "value": "เลื่อนลง" } }, "tr": { "stringUnit": { "state": "translated", - "value": "%1$@ #%2$lld Aç" + "value": "Aşağı Taşı" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Відкрити %1$@ #%2$lld" + "value": "Перемістити вниз" } } } }, - "sidebar.pullRequest.statusClosed": { + "sidebar.workspace.moveUpAction": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "closed" + "value": "Move Up" } }, "ja": { "stringUnit": { "state": "translated", - "value": "クローズ" + "value": "上に移動" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "已关闭" + "value": "上移" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "已關閉" + "value": "上移" } }, "ko": { "stringUnit": { "state": "translated", - "value": "닫힘" + "value": "위로 이동" } }, "de": { "stringUnit": { "state": "translated", - "value": "geschlossen" + "value": "Nach oben bewegen" } }, "es": { "stringUnit": { "state": "translated", - "value": "cerrado" + "value": "Mover hacia arriba" } }, "fr": { "stringUnit": { "state": "translated", - "value": "fermée" + "value": "Déplacer vers le haut" } }, "it": { "stringUnit": { "state": "translated", - "value": "chiusa" + "value": "Sposta in alto" } }, "da": { "stringUnit": { "state": "translated", - "value": "lukket" + "value": "Flyt op" } }, "pl": { "stringUnit": { "state": "translated", - "value": "zamknięty" + "value": "Przenieś w górę" } }, "ru": { "stringUnit": { "state": "translated", - "value": "закрыт" + "value": "Переместить вверх" } }, "bs": { "stringUnit": { "state": "translated", - "value": "zatvoren" + "value": "Pomjeri gore" } }, "ar": { "stringUnit": { "state": "translated", - "value": "مغلق" + "value": "نقل للأعلى" } }, "nb": { "stringUnit": { "state": "translated", - "value": "lukket" + "value": "Flytt opp" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "fechado" + "value": "Mover para Cima" } }, "th": { "stringUnit": { "state": "translated", - "value": "ปิดแล้ว" + "value": "เลื่อนขึ้น" } }, "tr": { "stringUnit": { "state": "translated", - "value": "kapalı" + "value": "Yukarı Taşı" } }, "uk": { "stringUnit": { "state": "translated", - "value": "закритий" + "value": "Перемістити вгору" } } } }, - "sidebar.pullRequest.statusMerged": { + "socketControl.allowAll.description": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "merged" + "value": "Allow any local process and user to connect with no auth. Unsafe." } }, "ja": { "stringUnit": { "state": "translated", - "value": "マージ済み" + "value": "認証なしで任意のローカルプロセスおよびユーザーの接続を許可します。安全ではありません。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "已合并" + "value": "允许任何本地进程和用户无需认证即可连接。不安全。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "已合併" + "value": "允許任何本機程序和使用者連線,無需驗證。不安全。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "병합됨" + "value": "인증 없이 모든 로컬 프로세스 및 사용자의 연결을 허용합니다. 안전하지 않습니다." } }, "de": { "stringUnit": { "state": "translated", - "value": "zusammengeführt" + "value": "Jeden lokalen Prozess und Benutzer ohne Authentifizierung verbinden lassen. Unsicher." } }, "es": { "stringUnit": { "state": "translated", - "value": "fusionado" + "value": "Permitir que cualquier proceso y usuario local se conecte sin autenticación. Inseguro." } }, "fr": { "stringUnit": { "state": "translated", - "value": "fusionnée" + "value": "Autoriser tout processus et utilisateur local à se connecter sans authentification. Non sécurisé." } }, "it": { "stringUnit": { "state": "translated", - "value": "unita" + "value": "Consenti a qualsiasi processo e utente locale di connettersi senza autenticazione. Non sicuro." } }, "da": { "stringUnit": { "state": "translated", - "value": "sammenlagt" + "value": "Tillad enhver lokal proces og bruger at forbinde uden autentifikation. Usikkert." } }, "pl": { "stringUnit": { "state": "translated", - "value": "scalony" + "value": "Zezwól dowolnemu lokalnemu procesowi i użytkownikowi na połączenie bez uwierzytelniania. Niebezpieczne." } }, "ru": { "stringUnit": { "state": "translated", - "value": "объединен" + "value": "Разрешить подключение любому локальному процессу и пользователю без авторизации. Небезопасно." } }, "bs": { "stringUnit": { "state": "translated", - "value": "spojen" + "value": "Dozvolite bilo kojem lokalnom procesu i korisniku da se poveže bez autentikacije. Nesigurno." } }, "ar": { "stringUnit": { "state": "translated", - "value": "مدمج" + "value": "السماح لأي عملية ومستخدم محلي بالاتصال بدون مصادقة. غير آمن." } }, "nb": { "stringUnit": { "state": "translated", - "value": "sammenslått" + "value": "Tillat enhver lokal prosess og bruker å koble til uten autentisering. Usikkert." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "mesclado" + "value": "Permitir que qualquer processo e usuário local se conecte sem autenticação. Inseguro." } }, "th": { "stringUnit": { "state": "translated", - "value": "ผสานแล้ว" + "value": "อนุญาตให้กระบวนการในเครื่องและผู้ใช้ทุกคนเชื่อมต่อโดยไม่ต้องยืนยันตัวตน ไม่ปลอดภัย" } }, "tr": { "stringUnit": { "state": "translated", - "value": "birleştirildi" + "value": "Herhangi bir yerel işlem ve kullanıcının kimlik doğrulama olmadan bağlanmasına izin ver. Güvensiz." } }, "uk": { "stringUnit": { "state": "translated", - "value": "злитий" + "value": "Дозволити будь-якому локальному процесу та користувачу підключатися без автентифікації. Небезпечно." } } } }, - "sidebar.pullRequest.statusOpen": { + "socketControl.allowAll.name": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "open" + "value": "Full open access" } }, "ja": { "stringUnit": { "state": "translated", - "value": "オープン" + "value": "完全オープンアクセス" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "打开" + "value": "完全开放访问" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "開啟" + "value": "完全開放存取" } }, "ko": { "stringUnit": { "state": "translated", - "value": "열림" + "value": "전체 개방 접근" } }, "de": { "stringUnit": { "state": "translated", - "value": "offen" + "value": "Vollständiger offener Zugriff" } }, "es": { "stringUnit": { "state": "translated", - "value": "abierto" + "value": "Acceso abierto completo" } }, "fr": { "stringUnit": { "state": "translated", - "value": "ouverte" + "value": "Accès ouvert complet" } }, "it": { "stringUnit": { "state": "translated", - "value": "aperta" + "value": "Accesso aperto completo" } }, "da": { "stringUnit": { "state": "translated", - "value": "åben" + "value": "Fuld åben adgang" } }, "pl": { "stringUnit": { "state": "translated", - "value": "otwarty" + "value": "Pełny otwarty dostęp" } }, "ru": { "stringUnit": { "state": "translated", - "value": "открыт" + "value": "Полный открытый доступ" } }, "bs": { "stringUnit": { "state": "translated", - "value": "otvoren" + "value": "Potpuni otvoreni pristup" } }, "ar": { "stringUnit": { "state": "translated", - "value": "مفتوح" + "value": "وصول مفتوح كامل" } }, "nb": { "stringUnit": { "state": "translated", - "value": "åpen" + "value": "Full åpen tilgang" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "aberto" + "value": "Acesso aberto total" } }, "th": { "stringUnit": { "state": "translated", - "value": "เปิด" + "value": "การเข้าถึงเปิดแบบเต็ม" } }, "tr": { "stringUnit": { "state": "translated", - "value": "açık" + "value": "Tam açık erişim" } }, "uk": { "stringUnit": { "state": "translated", - "value": "відкритий" + "value": "Повний відкритий доступ" } } } }, - "sidebar.workspace.accessibilityHint": { + "socketControl.automation.description": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Activate to focus this workspace. Drag to reorder, or use Move Up and Move Down actions." + "value": "Allow external local automation clients from this macOS user (no ancestry check)." } }, "ja": { "stringUnit": { "state": "translated", - "value": "アクティブにしてこのワークスペースにフォーカスします。ドラッグで並べ替え、または「上に移動」「下に移動」アクションを使用します。" + "value": "この macOS ユーザーからの外部ローカル自動化クライアントを許可します(プロセス系譜チェックなし)。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "激活以聚焦此工作区。拖拽以重新排序,或使用上移和下移操作。" + "value": "允许当前 macOS 用户的外部本地自动化客户端连接(不检查进程来源)。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "啟用以聚焦此工作區。拖曳以重新排序,或使用上移和下移動作。" + "value": "允許此 macOS 使用者的外部本機自動化用戶端(不檢查來源)。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "이 작업 공간에 포커스하려면 활성화하세요. 드래그하여 순서를 변경하거나 위로 이동 및 아래로 이동 동작을 사용하세요." + "value": "이 macOS 사용자의 외부 로컬 자동화 클라이언트를 허용합니다 (출처 확인 없음)." } }, "de": { "stringUnit": { "state": "translated", - "value": "Aktivieren, um diesen Arbeitsbereich zu fokussieren. Ziehen zum Umordnen oder verwenden Sie die Aktionen 'Nach oben' und 'Nach unten'." + "value": "Externe lokale Automatisierungs-Clients dieses macOS-Benutzers zulassen (keine Abstammungsprüfung)." } }, "es": { "stringUnit": { "state": "translated", - "value": "Activa para enfocar este espacio de trabajo. Arrastra para reordenar, o usa las acciones Mover hacia arriba y Mover hacia abajo." + "value": "Permitir clientes de automatización locales externos de este usuario de macOS (sin verificación de ascendencia)." } }, "fr": { "stringUnit": { "state": "translated", - "value": "Activez pour accéder à cet espace de travail. Glissez pour réordonner, ou utilisez les actions Déplacer vers le haut et Déplacer vers le bas." + "value": "Autoriser les clients d'automatisation locaux externes de cet utilisateur macOS (sans vérification de parenté)." } }, "it": { "stringUnit": { "state": "translated", - "value": "Attiva per portare il focus su questa area di lavoro. Trascina per riordinare oppure usa le azioni Sposta in alto e Sposta in basso." + "value": "Consenti ai client di automazione locale esterni di questo utente macOS (senza controllo di discendenza)." } }, "da": { "stringUnit": { "state": "translated", - "value": "Aktiver for at fokusere dette arbejdsområde. Træk for at omarrangere, eller brug handlingerne Flyt op og Flyt ned." + "value": "Tillad eksterne lokale automatiseringsklienter fra denne macOS-bruger (ingen herkomstkontrol)." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Aktywuj, aby ustawić fokus na tej przestrzeni roboczej. Przeciągnij, aby zmienić kolejność, lub użyj akcji Przenieś w górę i Przenieś w dół." + "value": "Zezwól zewnętrznym lokalnym klientom automatyzacji od tego użytkownika macOS (bez sprawdzania pochodzenia)." } }, "ru": { "stringUnit": { "state": "translated", - "value": "Активируйте для перехода к этому рабочему пространству. Перетащите для изменения порядка или используйте действия «Переместить вверх» и «Переместить вниз»." + "value": "Разрешить внешним клиентам автоматизации от текущего пользователя macOS (без проверки происхождения)." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Aktivirajte za fokusiranje ovog radnog prostora. Prevucite za preraspoređivanje ili koristite akcije Pomjeri gore i Pomjeri dolje." + "value": "Dozvolite vanjskim lokalnim klijentima automatizacije od ovog macOS korisnika (bez provjere porijekla)." } }, "ar": { "stringUnit": { "state": "translated", - "value": "فعّل للتركيز على مساحة العمل هذه. اسحب لإعادة الترتيب، أو استخدم إجراءات نقل للأعلى ونقل للأسفل." + "value": "السماح لعملاء الأتمتة المحليين الخارجيين من مستخدم macOS هذا (بدون فحص النسب)." } }, "nb": { "stringUnit": { "state": "translated", - "value": "Aktiver for å fokusere dette arbeidsområdet. Dra for å omorganisere, eller bruk Flytt opp og Flytt ned." + "value": "Tillat eksterne lokale automatiseringsklienter fra denne macOS-brukeren (ingen opphavskontroll)." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Ative para focar nesta área de trabalho. Arraste para reordenar ou use as ações Mover para Cima e Mover para Baixo." + "value": "Permitir clientes de automação locais externos deste usuário macOS (sem verificação de ancestralidade)." } }, "th": { "stringUnit": { "state": "translated", - "value": "เปิดใช้งานเพื่อโฟกัสเวิร์กสเปซนี้ ลากเพื่อจัดเรียงใหม่ หรือใช้การกระทำเลื่อนขึ้นและเลื่อนลง" + "value": "อนุญาตไคลเอ็นต์ระบบอัตโนมัติภายนอกจากผู้ใช้ macOS นี้ (ไม่ตรวจสอบสายสืบทอด)" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Bu çalışma alanına odaklanmak için etkinleştirin. Yeniden sıralamak için sürükleyin veya Yukarı Taşı ve Aşağı Taşı eylemlerini kullanın." + "value": "Bu macOS kullanıcısından gelen harici yerel otomasyon istemcilerine izin ver (soy denetimi yok)." } }, "uk": { "stringUnit": { "state": "translated", - "value": "Активуйте, щоб сфокусувати цю робочу область. Перетягніть для зміни порядку або використовуйте дії «Перемістити вгору» та «Перемістити вниз»." + "value": "Дозволити зовнішнім локальним клієнтам автоматизації від цього користувача macOS (без перевірки походження)." } } } }, - "sidebar.remote.badge": { + "socketControl.automation.name": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "SSH" + "value": "Automation mode" } }, "ja": { "stringUnit": { "state": "translated", - "value": "SSH" + "value": "自動化モード" } }, - "uk": { + "zh-Hans": { "stringUnit": { "state": "translated", - "value": "SSH" + "value": "自动化模式" } }, - "ko": { - "stringUnit": { - "state": "translated", - "value": "SSH" - } - } - } - }, - "remote.status.connected": { - "extractionState": "manual", - "localizations": { - "en": { + "zh-Hant": { "stringUnit": { "state": "translated", - "value": "Connected" + "value": "自動化模式" } }, - "ja": { + "ko": { "stringUnit": { "state": "translated", - "value": "接続済み" + "value": "자동화 모드" } }, - "uk": { + "de": { "stringUnit": { "state": "translated", - "value": "Підключено" + "value": "Automatisierungsmodus" } }, - "ko": { - "stringUnit": { - "state": "translated", - "value": "연결됨" - } - } - } - }, - "remote.status.connecting": { - "extractionState": "manual", - "localizations": { - "en": { + "es": { "stringUnit": { "state": "translated", - "value": "Connecting" + "value": "Modo de automatización" } }, - "ja": { + "fr": { "stringUnit": { "state": "translated", - "value": "接続中" + "value": "Mode automatisation" } }, - "uk": { + "it": { "stringUnit": { "state": "translated", - "value": "Підключення" + "value": "Modalità automazione" } }, - "ko": { - "stringUnit": { - "state": "translated", - "value": "연결 중" - } - } - } - }, - "remote.status.reconnecting": { - "extractionState": "manual", - "localizations": { - "en": { + "da": { "stringUnit": { "state": "translated", - "value": "Reconnecting" + "value": "Automatiseringstilstand" } }, - "ja": { + "pl": { "stringUnit": { "state": "translated", - "value": "再接続中" + "value": "Tryb automatyzacji" } }, - "uk": { + "ru": { "stringUnit": { "state": "translated", - "value": "Повторне підключення" + "value": "Режим автоматизации" } }, - "ko": { - "stringUnit": { - "state": "translated", - "value": "다시 연결 중" - } - } - } - }, - "remote.status.disconnected": { - "extractionState": "manual", - "localizations": { - "en": { + "bs": { "stringUnit": { "state": "translated", - "value": "Disconnected" + "value": "Režim automatizacije" } }, - "ja": { + "ar": { "stringUnit": { "state": "translated", - "value": "切断済み" + "value": "وضع الأتمتة" } }, - "uk": { + "nb": { "stringUnit": { "state": "translated", - "value": "Відключено" + "value": "Automatiseringsmodus" } }, - "ko": { - "stringUnit": { - "state": "translated", - "value": "연결 해제됨" - } - } - } - }, - "remote.status.error": { - "extractionState": "manual", - "localizations": { - "en": { + "pt-BR": { "stringUnit": { "state": "translated", - "value": "Error" + "value": "Modo de automação" } }, - "ja": { + "th": { "stringUnit": { "state": "translated", - "value": "エラー" + "value": "โหมดระบบอัตโนมัติ" } }, - "uk": { + "tr": { "stringUnit": { "state": "translated", - "value": "Помилка" + "value": "Otomasyon modu" } }, - "ko": { + "uk": { "stringUnit": { "state": "translated", - "value": "오류" + "value": "Режим автоматизації" } } } }, - "sidebar.remote.subtitle": { + "socketControl.cmuxOnly.description": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "SSH • %@" + "value": "Only processes started inside cmux terminals can send commands." } }, "ja": { "stringUnit": { "state": "translated", - "value": "SSH • %@" + "value": "cmux ターミナル内で起動したプロセスのみがコマンドを送信できます。" } }, - "uk": { + "zh-Hans": { "stringUnit": { "state": "translated", - "value": "SSH • %@" + "value": "仅允许在 cmux 终端内启动的进程发送命令。" } }, - "ko": { - "stringUnit": { - "state": "translated", - "value": "SSH • %@" - } - } - } - }, - "sidebar.remote.subtitleFallback": { - "extractionState": "manual", - "localizations": { - "en": { + "zh-Hant": { "stringUnit": { "state": "translated", - "value": "SSH workspace" + "value": "僅在 cmux 終端機內啟動的程序可以傳送指令。" } }, - "ja": { + "ko": { "stringUnit": { "state": "translated", - "value": "SSH ワークスペース" + "value": "cmux 터미널 내에서 시작된 프로세스만 명령을 보낼 수 있습니다." } }, - "uk": { + "de": { "stringUnit": { "state": "translated", - "value": "SSH робоча область" + "value": "Nur Prozesse, die in cmux-Terminals gestartet wurden, können Befehle senden." } }, - "ko": { + "es": { "stringUnit": { "state": "translated", - "value": "SSH 워크스페이스" + "value": "Solo los procesos iniciados dentro de terminales de cmux pueden enviar comandos." } - } - } - }, - "sidebar.remote.help.connected": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "fr": { "stringUnit": { "state": "translated", - "value": "SSH connected to %@" + "value": "Seuls les processus lancés dans les terminaux cmux peuvent envoyer des commandes." } }, - "ja": { + "it": { "stringUnit": { "state": "translated", - "value": "SSH は %@ に接続済み" + "value": "Solo i processi avviati nei terminali cmux possono inviare comandi." } }, - "uk": { + "da": { "stringUnit": { "state": "translated", - "value": "SSH підключено до %@" + "value": "Kun processer startet i cmux-terminaler kan sende kommandoer." } }, - "ko": { + "pl": { "stringUnit": { "state": "translated", - "value": "%@에 SSH 연결됨" + "value": "Tylko procesy uruchomione wewnątrz terminali cmux mogą wysyłać polecenia." } - } - } - }, - "sidebar.remote.help.connecting": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "ru": { "stringUnit": { "state": "translated", - "value": "SSH connecting to %@" + "value": "Только процессы, запущенные в терминалах cmux, могут отправлять команды." } }, - "ja": { + "bs": { "stringUnit": { "state": "translated", - "value": "SSH は %@ に接続中" + "value": "Samo procesi pokrenuti unutar cmux terminala mogu slati naredbe." } }, - "uk": { + "ar": { "stringUnit": { "state": "translated", - "value": "SSH підключення до %@" + "value": "فقط العمليات التي بدأت داخل طرفيات cmux يمكنها إرسال الأوامر." } }, - "ko": { + "nb": { "stringUnit": { "state": "translated", - "value": "%@에 SSH 연결 중" + "value": "Bare prosesser startet innenfor cmux-terminaler kan sende kommandoer." } - } - } - }, - "sidebar.remote.help.reconnecting": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "pt-BR": { "stringUnit": { "state": "translated", - "value": "SSH reconnecting to %@" + "value": "Apenas processos iniciados dentro de terminais do cmux podem enviar comandos." } }, - "ja": { + "th": { "stringUnit": { "state": "translated", - "value": "SSH は %@ に再接続中" + "value": "เฉพาะกระบวนการที่เริ่มต้นภายในเทอร์มินัล cmux เท่านั้นที่สามารถส่งคำสั่งได้" } }, - "uk": { + "tr": { "stringUnit": { "state": "translated", - "value": "SSH повторно підключається до %@" + "value": "Yalnızca cmux terminalleri içinden başlatılan işlemler komut gönderebilir." } }, - "ko": { + "uk": { "stringUnit": { "state": "translated", - "value": "%@에 SSH 다시 연결 중" + "value": "Тільки процеси, запущені в терміналах cmux, можуть надсилати команди." } } } }, - "sidebar.remote.help.error": { + "socket.surfaceSplitOff.error.appDelegateUnavailable": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "SSH error for %@" + "value": "AppDelegate not available" } }, "ja": { "stringUnit": { "state": "translated", - "value": "%@ の SSH エラー" + "value": "AppDelegateを利用できません" } - }, - "uk": { + } + } + }, + "socket.surfaceSplitOff.error.invalidDirection": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Помилка SSH для %@" + "value": "Missing or invalid direction (left|right|up|down)" } }, - "ko": { + "ja": { "stringUnit": { "state": "translated", - "value": "%@에 대한 SSH 오류" + "value": "方向が指定されていないか無効です(left|right|up|down)" } } } }, - "sidebar.remote.help.errorWithDetail": { + "socket.surfaceSplitOff.error.invalidWindowId": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "SSH error for %@: %@" + "value": "Missing or invalid window_id" } }, "ja": { "stringUnit": { "state": "translated", - "value": "%@ の SSH エラー: %@" + "value": "window_idが指定されていないか無効です" } - }, - "uk": { + } + } + }, + "socket.surfaceSplitOff.error.invalidWorkspaceId": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Помилка SSH для %@: %@" + "value": "Missing or invalid workspace_id" } }, - "ko": { + "ja": { "stringUnit": { "state": "translated", - "value": "%@에 대한 SSH 오류: %@" + "value": "workspace_idが指定されていないか無効です" } } } }, - "sidebar.remote.help.disconnected": { + "socket.surfaceSplitOff.error.missingSurfaceId": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "SSH disconnected from %@" + "value": "Missing or invalid surface_id" } }, "ja": { "stringUnit": { "state": "translated", - "value": "SSH は %@ から切断済み" + "value": "surface_idが指定されていないか無効です" } - }, - "uk": { + } + } + }, + "socket.surfaceSplitOff.error.moveSurfaceFailed": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "SSH відключено від %@" + "value": "Failed to move surface" } }, - "ko": { + "ja": { "stringUnit": { "state": "translated", - "value": "%@에서 SSH 연결 해제됨" + "value": "サーフェスを移動できませんでした" } } } }, - "sidebar.remote.help.targetFallback": { + "socket.surfaceSplitOff.error.sourcePaneNotFound": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "remote host" + "value": "Source pane not found" } }, "ja": { "stringUnit": { "state": "translated", - "value": "リモートホスト" + "value": "移動元ペインが見つかりません" } - }, - "uk": { + } + } + }, + "socket.surfaceSplitOff.error.splitPaneFailed": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "віддалений хост" + "value": "Failed to split pane" } }, - "ko": { + "ja": { "stringUnit": { "state": "translated", - "value": "원격 호스트" + "value": "ペインを分割できませんでした" } } } }, - "sidebar.activeTabIndicator.leftRail": { + "socket.surfaceSplitOff.error.surfaceNotFound": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Left Rail" + "value": "Surface not found" } }, "ja": { "stringUnit": { "state": "translated", - "value": "左レール" + "value": "サーフェスが見つかりません" } - }, - "uk": { + } + } + }, + "socket.surfaceSplitOff.error.surfaceNotFoundInWindow": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Лівий рейл" + "value": "Surface not found in window" } }, - "ko": { + "ja": { "stringUnit": { "state": "translated", - "value": "왼쪽 레일" + "value": "ウィンドウ内にサーフェスが見つかりません" } } } }, - "sidebar.activeTabIndicator.solidFill": { + "socket.surfaceSplitOff.error.surfaceNotFoundInWorkspace": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Solid Fill" + "value": "Surface not found in workspace" } }, "ja": { "stringUnit": { "state": "translated", - "value": "塗りつぶし" + "value": "ワークスペース内にサーフェスが見つかりません" } - }, - "uk": { + } + } + }, + "socket.surfaceSplitOff.error.wouldEmptySourcePane": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Суцільне заповнення" + "value": "splitting off would leave the source pane empty" } }, - "ko": { + "ja": { "stringUnit": { "state": "translated", - "value": "단색 채우기" + "value": "分割して移動すると移動元ペインが空になります" } } } }, - "sidebar.workspace.moveDownAction": { + "socketControl.cmuxOnly.name": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Move Down" + "value": "cmux processes only" } }, "ja": { "stringUnit": { "state": "translated", - "value": "下に移動" + "value": "cmux プロセスのみ" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "下移" + "value": "仅限 cmux 进程" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "下移" + "value": "僅限 cmux 程序" } }, "ko": { "stringUnit": { "state": "translated", - "value": "아래로 이동" + "value": "cmux 프로세스만" } }, "de": { "stringUnit": { "state": "translated", - "value": "Nach unten bewegen" + "value": "Nur cmux-Prozesse" } }, "es": { "stringUnit": { "state": "translated", - "value": "Mover hacia abajo" + "value": "Solo procesos de cmux" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Déplacer vers le bas" + "value": "Processus cmux uniquement" } }, "it": { "stringUnit": { "state": "translated", - "value": "Sposta in basso" + "value": "Solo processi cmux" } }, "da": { "stringUnit": { "state": "translated", - "value": "Flyt ned" + "value": "Kun cmux-processer" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Przenieś w dół" + "value": "Tylko procesy cmux" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Переместить вниз" + "value": "Только процессы cmux" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Pomjeri dolje" + "value": "Samo cmux procesi" } }, "ar": { "stringUnit": { "state": "translated", - "value": "نقل للأسفل" + "value": "عمليات cmux فقط" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Flytt ned" + "value": "Kun cmux-prosesser" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Mover para Baixo" + "value": "Apenas processos do cmux" } }, "th": { "stringUnit": { "state": "translated", - "value": "เลื่อนลง" + "value": "กระบวนการ cmux เท่านั้น" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Aşağı Taşı" + "value": "Yalnızca cmux işlemleri" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Перемістити вниз" + "value": "Тільки процеси cmux" } } } }, - "sidebar.workspace.moveUpAction": { + "socketControl.error.passwordFilePath": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Move Up" + "value": "Unable to resolve socket password file path." } }, "ja": { "stringUnit": { "state": "translated", - "value": "上に移動" + "value": "ソケットパスワードファイルのパスを解決できません。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "上移" + "value": "无法解析套接字密码文件路径。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "上移" + "value": "無法解析 Socket 密碼檔案路徑。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "위로 이동" + "value": "소켓 비밀번호 파일 경로를 확인할 수 없습니다." } }, "de": { "stringUnit": { "state": "translated", - "value": "Nach oben bewegen" + "value": "Der Pfad zur Socket-Passwortdatei konnte nicht aufgelöst werden." } }, "es": { "stringUnit": { "state": "translated", - "value": "Mover hacia arriba" + "value": "No se pudo resolver la ruta del archivo de contraseña del socket." } }, "fr": { "stringUnit": { "state": "translated", - "value": "Déplacer vers le haut" + "value": "Impossible de résoudre le chemin du fichier de mot de passe du socket." } }, "it": { "stringUnit": { "state": "translated", - "value": "Sposta in alto" + "value": "Impossibile risolvere il percorso del file password del socket." } }, "da": { "stringUnit": { "state": "translated", - "value": "Flyt op" + "value": "Kunne ikke bestemme stien til socket-adgangskodefilen." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Przenieś w górę" + "value": "Nie można rozwiązać ścieżki pliku hasła gniazda." } }, "ru": { "stringUnit": { "state": "translated", - "value": "Переместить вверх" + "value": "Не удалось определить путь к файлу пароля сокета." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Pomjeri gore" + "value": "Nije moguće razriješiti putanju datoteke lozinke utičnice." } }, "ar": { "stringUnit": { "state": "translated", - "value": "نقل للأعلى" + "value": "تعذر تحديد مسار ملف كلمة مرور المقبس." } }, "nb": { "stringUnit": { "state": "translated", - "value": "Flytt opp" + "value": "Kan ikke finne filstien for socket-passord." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Mover para Cima" + "value": "Não foi possível resolver o caminho do arquivo de senha do socket." } }, "th": { "stringUnit": { "state": "translated", - "value": "เลื่อนขึ้น" + "value": "ไม่สามารถระบุเส้นทางไฟล์รหัสผ่านซ็อกเก็ตได้" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Yukarı Taşı" + "value": "Soket parola dosyası yolu çözümlenemedi." } }, "uk": { "stringUnit": { "state": "translated", - "value": "Перемістити вгору" + "value": "Не вдалося визначити шлях до файлу пароля сокета." } } } }, - "socketControl.allowAll.description": { + "socketControl.off.description": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Allow any local process and user to connect with no auth. Unsafe." + "value": "Disable the local control socket." } }, "ja": { "stringUnit": { "state": "translated", - "value": "認証なしで任意のローカルプロセスおよびユーザーの接続を許可します。安全ではありません。" + "value": "ローカルコントロールソケットを無効にします。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "允许任何本地进程和用户无需认证即可连接。不安全。" + "value": "禁用本地控制套接字。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "允許任何本機程序和使用者連線,無需驗證。不安全。" + "value": "停用本機控制 Socket。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "인증 없이 모든 로컬 프로세스 및 사용자의 연결을 허용합니다. 안전하지 않습니다." + "value": "로컬 제어 소켓을 비활성화합니다." } }, "de": { "stringUnit": { "state": "translated", - "value": "Jeden lokalen Prozess und Benutzer ohne Authentifizierung verbinden lassen. Unsicher." + "value": "Den lokalen Steuerungs-Socket deaktivieren." } }, "es": { "stringUnit": { "state": "translated", - "value": "Permitir que cualquier proceso y usuario local se conecte sin autenticación. Inseguro." + "value": "Desactivar el socket de control local." } }, "fr": { "stringUnit": { "state": "translated", - "value": "Autoriser tout processus et utilisateur local à se connecter sans authentification. Non sécurisé." + "value": "Désactiver le socket de contrôle local." } }, "it": { "stringUnit": { "state": "translated", - "value": "Consenti a qualsiasi processo e utente locale di connettersi senza autenticazione. Non sicuro." + "value": "Disabilita il socket di controllo locale." } }, "da": { "stringUnit": { "state": "translated", - "value": "Tillad enhver lokal proces og bruger at forbinde uden autentifikation. Usikkert." + "value": "Deaktiver den lokale kontrolsocket." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Zezwól dowolnemu lokalnemu procesowi i użytkownikowi na połączenie bez uwierzytelniania. Niebezpieczne." + "value": "Wyłącz lokalne gniazdo sterujące." } }, "ru": { "stringUnit": { "state": "translated", - "value": "Разрешить подключение любому локальному процессу и пользователю без авторизации. Небезопасно." + "value": "Отключить локальный управляющий сокет." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Dozvolite bilo kojem lokalnom procesu i korisniku da se poveže bez autentikacije. Nesigurno." + "value": "Onemogući lokalnu kontrolnu utičnicu." } }, "ar": { "stringUnit": { "state": "translated", - "value": "السماح لأي عملية ومستخدم محلي بالاتصال بدون مصادقة. غير آمن." + "value": "تعطيل مقبس التحكم المحلي." } }, "nb": { "stringUnit": { "state": "translated", - "value": "Tillat enhver lokal prosess og bruker å koble til uten autentisering. Usikkert." + "value": "Deaktiver den lokale kontrollsocketen." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Permitir que qualquer processo e usuário local se conecte sem autenticação. Inseguro." + "value": "Desativar o socket de controle local." } }, "th": { "stringUnit": { "state": "translated", - "value": "อนุญาตให้กระบวนการในเครื่องและผู้ใช้ทุกคนเชื่อมต่อโดยไม่ต้องยืนยันตัวตน ไม่ปลอดภัย" + "value": "ปิดใช้งานซ็อกเก็ตควบคุมในเครื่อง" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Herhangi bir yerel işlem ve kullanıcının kimlik doğrulama olmadan bağlanmasına izin ver. Güvensiz." + "value": "Yerel kontrol soketini devre dışı bırak." } }, "uk": { "stringUnit": { "state": "translated", - "value": "Дозволити будь-якому локальному процесу та користувачу підключатися без автентифікації. Небезпечно." + "value": "Вимкнути локальний керуючий сокет." } } } }, - "socketControl.allowAll.name": { + "socketControl.off.name": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Full open access" + "value": "Off" } }, "ja": { "stringUnit": { "state": "translated", - "value": "完全オープンアクセス" + "value": "オフ" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "完全开放访问" + "value": "关闭" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "完全開放存取" + "value": "關閉" } }, "ko": { "stringUnit": { "state": "translated", - "value": "전체 개방 접근" + "value": "끔" } }, "de": { "stringUnit": { "state": "translated", - "value": "Vollständiger offener Zugriff" + "value": "Aus" } }, "es": { "stringUnit": { "state": "translated", - "value": "Acceso abierto completo" + "value": "Desactivado" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Accès ouvert complet" + "value": "Désactivé" } }, "it": { "stringUnit": { "state": "translated", - "value": "Accesso aperto completo" + "value": "Disattivato" } }, "da": { "stringUnit": { "state": "translated", - "value": "Fuld åben adgang" + "value": "Fra" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Pełny otwarty dostęp" + "value": "Wyłączone" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Полный открытый доступ" + "value": "Выключено" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Potpuni otvoreni pristup" + "value": "Isključeno" } }, "ar": { "stringUnit": { "state": "translated", - "value": "وصول مفتوح كامل" + "value": "إيقاف" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Full åpen tilgang" + "value": "Av" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Acesso aberto total" + "value": "Desativado" } }, "th": { "stringUnit": { "state": "translated", - "value": "การเข้าถึงเปิดแบบเต็ม" + "value": "ปิด" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Tam açık erişim" + "value": "Kapalı" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Повний відкритий доступ" + "value": "Вимкнено" } } } }, - "socketControl.automation.description": { + "socketControl.password.description": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Allow external local automation clients from this macOS user (no ancestry check)." + "value": "Require socket authentication with a password stored in a local file." } }, "ja": { "stringUnit": { "state": "translated", - "value": "この macOS ユーザーからの外部ローカル自動化クライアントを許可します(プロセス系譜チェックなし)。" + "value": "ローカルファイルに保存されたパスワードでソケット認証を要求します。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "允许当前 macOS 用户的外部本地自动化客户端连接(不检查进程来源)。" + "value": "使用存储在本地文件中的密码进行套接字认证。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "允許此 macOS 使用者的外部本機自動化用戶端(不檢查來源)。" + "value": "使用儲存在本機檔案中的密碼進行 Socket 驗證。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "이 macOS 사용자의 외부 로컬 자동화 클라이언트를 허용합니다 (출처 확인 없음)." + "value": "로컬 파일에 저장된 비밀번호로 소켓 인증을 요구합니다." } }, "de": { "stringUnit": { "state": "translated", - "value": "Externe lokale Automatisierungs-Clients dieses macOS-Benutzers zulassen (keine Abstammungsprüfung)." + "value": "Socket-Authentifizierung mit einem in einer lokalen Datei gespeicherten Passwort erfordern." } }, "es": { "stringUnit": { "state": "translated", - "value": "Permitir clientes de automatización locales externos de este usuario de macOS (sin verificación de ascendencia)." + "value": "Requerir autenticación del socket con una contraseña almacenada en un archivo local." } }, "fr": { "stringUnit": { "state": "translated", - "value": "Autoriser les clients d'automatisation locaux externes de cet utilisateur macOS (sans vérification de parenté)." + "value": "Exiger l'authentification du socket avec un mot de passe stocké dans un fichier local." } }, "it": { "stringUnit": { "state": "translated", - "value": "Consenti ai client di automazione locale esterni di questo utente macOS (senza controllo di discendenza)." + "value": "Richiedi l'autenticazione del socket con una password memorizzata in un file locale." } }, "da": { "stringUnit": { "state": "translated", - "value": "Tillad eksterne lokale automatiseringsklienter fra denne macOS-bruger (ingen herkomstkontrol)." + "value": "Kræv socket-autentifikation med en adgangskode gemt i en lokal fil." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Zezwól zewnętrznym lokalnym klientom automatyzacji od tego użytkownika macOS (bez sprawdzania pochodzenia)." + "value": "Wymagaj uwierzytelniania gniazda hasłem przechowywanym w pliku lokalnym." } }, "ru": { "stringUnit": { "state": "translated", - "value": "Разрешить внешним клиентам автоматизации от текущего пользователя macOS (без проверки происхождения)." + "value": "Требовать аутентификацию сокета с паролем, хранящимся в локальном файле." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Dozvolite vanjskim lokalnim klijentima automatizacije od ovog macOS korisnika (bez provjere porijekla)." + "value": "Zahtijevaj autentikaciju utičnice lozinkom pohranjenom u lokalnoj datoteci." } }, "ar": { "stringUnit": { "state": "translated", - "value": "السماح لعملاء الأتمتة المحليين الخارجيين من مستخدم macOS هذا (بدون فحص النسب)." + "value": "طلب مصادقة المقبس بكلمة مرور مخزنة في ملف محلي." } }, "nb": { "stringUnit": { "state": "translated", - "value": "Tillat eksterne lokale automatiseringsklienter fra denne macOS-brukeren (ingen opphavskontroll)." + "value": "Krev socket-autentisering med et passord lagret i en lokal fil." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Permitir clientes de automação locais externos deste usuário macOS (sem verificação de ancestralidade)." + "value": "Exigir autenticação do socket com uma senha armazenada em um arquivo local." } }, "th": { "stringUnit": { "state": "translated", - "value": "อนุญาตไคลเอ็นต์ระบบอัตโนมัติภายนอกจากผู้ใช้ macOS นี้ (ไม่ตรวจสอบสายสืบทอด)" + "value": "ต้องมีการยืนยันตัวตนซ็อกเก็ตด้วยรหัสผ่านที่จัดเก็บในไฟล์ในเครื่อง" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Bu macOS kullanıcısından gelen harici yerel otomasyon istemcilerine izin ver (soy denetimi yok)." + "value": "Yerel dosyada saklanan bir parola ile soket kimlik doğrulaması gerektir." } }, "uk": { "stringUnit": { "state": "translated", - "value": "Дозволити зовнішнім локальним клієнтам автоматизації від цього користувача macOS (без перевірки походження)." + "value": "Вимагати автентифікацію сокета з паролем, збереженим у локальному файлі." } } } }, - "socketControl.automation.name": { + "socketControl.password.name": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Automation mode" + "value": "Password mode" } }, "ja": { "stringUnit": { "state": "translated", - "value": "自動化モード" + "value": "パスワードモード" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "自动化模式" + "value": "密码模式" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "自動化模式" + "value": "密碼模式" } }, "ko": { "stringUnit": { "state": "translated", - "value": "자동화 모드" + "value": "비밀번호 모드" } }, "de": { "stringUnit": { "state": "translated", - "value": "Automatisierungsmodus" + "value": "Passwortmodus" } }, "es": { "stringUnit": { "state": "translated", - "value": "Modo de automatización" + "value": "Modo de contraseña" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Mode automatisation" + "value": "Mode mot de passe" } }, "it": { "stringUnit": { "state": "translated", - "value": "Modalità automazione" + "value": "Modalità password" } }, "da": { "stringUnit": { "state": "translated", - "value": "Automatiseringstilstand" + "value": "Adgangskodetilstand" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Tryb automatyzacji" + "value": "Tryb hasła" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Режим автоматизации" + "value": "Режим пароля" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Režim automatizacije" + "value": "Režim lozinke" } }, "ar": { "stringUnit": { "state": "translated", - "value": "وضع الأتمتة" + "value": "وضع كلمة المرور" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Automatiseringsmodus" + "value": "Passordmodus" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Modo de automação" + "value": "Modo de senha" } }, "th": { "stringUnit": { "state": "translated", - "value": "โหมดระบบอัตโนมัติ" + "value": "โหมดรหัสผ่าน" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Otomasyon modu" + "value": "Parola modu" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Режим автоматизації" + "value": "Режим пароля" } } } }, - "socketControl.cmuxOnly.description": { + "statusMenu.clearAll": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Only processes started inside cmux terminals can send commands." + "value": "Clear All" } }, "ja": { "stringUnit": { "state": "translated", - "value": "cmux ターミナル内で起動したプロセスのみがコマンドを送信できます。" + "value": "すべてクリア" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "仅允许在 cmux 终端内启动的进程发送命令。" + "value": "全部清除" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "僅在 cmux 終端機內啟動的程序可以傳送指令。" + "value": "清除全部" } }, "ko": { "stringUnit": { "state": "translated", - "value": "cmux 터미널 내에서 시작된 프로세스만 명령을 보낼 수 있습니다." + "value": "모두 지우기" } }, "de": { "stringUnit": { "state": "translated", - "value": "Nur Prozesse, die in cmux-Terminals gestartet wurden, können Befehle senden." + "value": "Alle löschen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Solo los procesos iniciados dentro de terminales de cmux pueden enviar comandos." + "value": "Borrar todo" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Seuls les processus lancés dans les terminaux cmux peuvent envoyer des commandes." + "value": "Tout effacer" } }, "it": { "stringUnit": { "state": "translated", - "value": "Solo i processi avviati nei terminali cmux possono inviare comandi." + "value": "Cancella tutto" } }, "da": { "stringUnit": { "state": "translated", - "value": "Kun processer startet i cmux-terminaler kan sende kommandoer." + "value": "Ryd alle" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Tylko procesy uruchomione wewnątrz terminali cmux mogą wysyłać polecenia." + "value": "Wyczyść wszystko" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Только процессы, запущенные в терминалах cmux, могут отправлять команды." + "value": "Очистить все" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Samo procesi pokrenuti unutar cmux terminala mogu slati naredbe." + "value": "Obriši sve" } }, "ar": { "stringUnit": { "state": "translated", - "value": "فقط العمليات التي بدأت داخل طرفيات cmux يمكنها إرسال الأوامر." + "value": "مسح الكل" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Bare prosesser startet innenfor cmux-terminaler kan sende kommandoer." + "value": "Fjern alle" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Apenas processos iniciados dentro de terminais do cmux podem enviar comandos." - } - }, - "th": { - "stringUnit": { - "state": "translated", - "value": "เฉพาะกระบวนการที่เริ่มต้นภายในเทอร์มินัล cmux เท่านั้นที่สามารถส่งคำสั่งได้" - } - }, - "tr": { - "stringUnit": { - "state": "translated", - "value": "Yalnızca cmux terminalleri içinden başlatılan işlemler komut gönderebilir." - } - }, - "uk": { - "stringUnit": { - "state": "translated", - "value": "Тільки процеси, запущені в терміналах cmux, можуть надсилати команди." - } - } - } - }, - "socket.surfaceSplitOff.error.appDelegateUnavailable": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "AppDelegate not available" + "value": "Limpar Tudo" } }, - "ja": { + "th": { "stringUnit": { "state": "translated", - "value": "AppDelegateを利用できません" + "value": "ล้างทั้งหมด" } - } - } - }, - "socket.surfaceSplitOff.error.invalidDirection": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "tr": { "stringUnit": { "state": "translated", - "value": "Missing or invalid direction (left|right|up|down)" + "value": "Tümünü Temizle" } }, - "ja": { + "uk": { "stringUnit": { "state": "translated", - "value": "方向が指定されていないか無効です(left|right|up|down)" + "value": "Очистити все" } } } }, - "socket.surfaceSplitOff.error.invalidWindowId": { + "statusMenu.jumpToLatestUnread": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Missing or invalid window_id" + "value": "Jump to Latest Unread" } }, "ja": { "stringUnit": { "state": "translated", - "value": "window_idが指定されていないか無効です" - } - } - } - }, - "socket.surfaceSplitOff.error.invalidWorkspaceId": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Missing or invalid workspace_id" + "value": "最新の未読にジャンプ" } }, - "ja": { + "zh-Hans": { "stringUnit": { "state": "translated", - "value": "workspace_idが指定されていないか無効です" + "value": "跳转到最新未读" } - } - } - }, - "socket.surfaceSplitOff.error.missingSurfaceId": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "zh-Hant": { "stringUnit": { "state": "translated", - "value": "Missing or invalid surface_id" + "value": "跳至最新未讀" } }, - "ja": { + "ko": { "stringUnit": { "state": "translated", - "value": "surface_idが指定されていないか無効です" + "value": "최신 읽지 않은 항목으로 이동" } - } - } - }, - "socket.surfaceSplitOff.error.moveSurfaceFailed": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "de": { "stringUnit": { "state": "translated", - "value": "Failed to move surface" + "value": "Zur letzten ungelesenen springen" } }, - "ja": { + "es": { "stringUnit": { "state": "translated", - "value": "サーフェスを移動できませんでした" + "value": "Ir a la última no leída" } - } - } - }, - "socket.surfaceSplitOff.error.sourcePaneNotFound": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "fr": { "stringUnit": { "state": "translated", - "value": "Source pane not found" + "value": "Aller au dernier message non lu" } }, - "ja": { + "it": { "stringUnit": { "state": "translated", - "value": "移動元ペインが見つかりません" + "value": "Vai all'ultimo non letto" } - } - } - }, - "socket.surfaceSplitOff.error.splitPaneFailed": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "da": { "stringUnit": { "state": "translated", - "value": "Failed to split pane" + "value": "Gå til seneste ulæste" } }, - "ja": { + "pl": { "stringUnit": { "state": "translated", - "value": "ペインを分割できませんでした" + "value": "Przejdź do najnowszego nieprzeczytanego" } - } - } - }, - "socket.surfaceSplitOff.error.surfaceNotFound": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "ru": { "stringUnit": { "state": "translated", - "value": "Surface not found" + "value": "Перейти к последнему непрочитанному" } }, - "ja": { + "bs": { "stringUnit": { "state": "translated", - "value": "サーフェスが見つかりません" + "value": "Skoči na najnovije nepročitano" } - } - } - }, - "socket.surfaceSplitOff.error.surfaceNotFoundInWindow": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "ar": { "stringUnit": { "state": "translated", - "value": "Surface not found in window" + "value": "الانتقال إلى أحدث غير مقروء" } }, - "ja": { + "nb": { "stringUnit": { "state": "translated", - "value": "ウィンドウ内にサーフェスが見つかりません" + "value": "Gå til siste uleste" } - } - } - }, - "socket.surfaceSplitOff.error.surfaceNotFoundInWorkspace": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "pt-BR": { "stringUnit": { "state": "translated", - "value": "Surface not found in workspace" + "value": "Ir para Última Não Lida" } }, - "ja": { + "th": { "stringUnit": { "state": "translated", - "value": "ワークスペース内にサーフェスが見つかりません" + "value": "ข้ามไปยังรายการยังไม่อ่านล่าสุด" } - } - } - }, - "socket.surfaceSplitOff.error.wouldEmptySourcePane": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "tr": { "stringUnit": { "state": "translated", - "value": "splitting off would leave the source pane empty" + "value": "Son Okunmamışa Atla" } }, - "ja": { + "uk": { "stringUnit": { "state": "translated", - "value": "分割して移動すると移動元ペインが空になります" + "value": "Перейти до останнього непрочитаного" } } } }, - "socketControl.cmuxOnly.name": { + "statusMenu.markAllRead": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "cmux processes only" + "value": "Mark All Read" } }, "ja": { "stringUnit": { "state": "translated", - "value": "cmux プロセスのみ" + "value": "すべて既読にする" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "仅限 cmux 进程" + "value": "全部标记为已读" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "僅限 cmux 程序" + "value": "全部標為已讀" } }, "ko": { "stringUnit": { "state": "translated", - "value": "cmux 프로세스만" + "value": "모두 읽음으로 표시" } }, "de": { "stringUnit": { "state": "translated", - "value": "Nur cmux-Prozesse" + "value": "Alle als gelesen markieren" } }, "es": { "stringUnit": { "state": "translated", - "value": "Solo procesos de cmux" + "value": "Marcar todo como leído" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Processus cmux uniquement" + "value": "Tout marquer comme lu" } }, "it": { "stringUnit": { "state": "translated", - "value": "Solo processi cmux" + "value": "Segna tutto come letto" } }, "da": { "stringUnit": { "state": "translated", - "value": "Kun cmux-processer" + "value": "Marker alle som læste" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Tylko procesy cmux" + "value": "Oznacz wszystko jako przeczytane" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Только процессы cmux" + "value": "Отметить все как прочитанные" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Samo cmux procesi" + "value": "Označi sve kao pročitano" } }, "ar": { "stringUnit": { "state": "translated", - "value": "عمليات cmux فقط" + "value": "تعليم الكل كمقروء" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Kun cmux-prosesser" + "value": "Merk alle som lest" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Apenas processos do cmux" + "value": "Marcar Tudo como Lido" } }, "th": { "stringUnit": { "state": "translated", - "value": "กระบวนการ cmux เท่านั้น" + "value": "ทำเครื่องหมายว่าอ่านทั้งหมดแล้ว" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Yalnızca cmux işlemleri" + "value": "Tümünü Okundu İşaretle" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Тільки процеси cmux" + "value": "Позначити все як прочитане" } } } }, - "socketControl.error.passwordFilePath": { + "statusMenu.noUnread": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Unable to resolve socket password file path." + "value": "No unread notifications" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ソケットパスワードファイルのパスを解決できません。" + "value": "未読の通知はありません" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "无法解析套接字密码文件路径。" + "value": "没有未读通知" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "無法解析 Socket 密碼檔案路徑。" + "value": "沒有未讀通知" } }, "ko": { "stringUnit": { "state": "translated", - "value": "소켓 비밀번호 파일 경로를 확인할 수 없습니다." + "value": "읽지 않은 알림 없음" } }, "de": { "stringUnit": { "state": "translated", - "value": "Der Pfad zur Socket-Passwortdatei konnte nicht aufgelöst werden." + "value": "Keine ungelesenen Benachrichtigungen" } }, "es": { "stringUnit": { "state": "translated", - "value": "No se pudo resolver la ruta del archivo de contraseña del socket." + "value": "Sin notificaciones no leídas" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Impossible de résoudre le chemin du fichier de mot de passe du socket." + "value": "Aucune notification non lue" } }, "it": { "stringUnit": { "state": "translated", - "value": "Impossibile risolvere il percorso del file password del socket." + "value": "Nessuna notifica non letta" } }, "da": { "stringUnit": { "state": "translated", - "value": "Kunne ikke bestemme stien til socket-adgangskodefilen." + "value": "Ingen ulæste notifikationer" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Nie można rozwiązać ścieżki pliku hasła gniazda." + "value": "Brak nieprzeczytanych powiadomień" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Не удалось определить путь к файлу пароля сокета." + "value": "Нет непрочитанных уведомлений" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Nije moguće razriješiti putanju datoteke lozinke utičnice." + "value": "Nema nepročitanih obavještenja" } }, "ar": { "stringUnit": { "state": "translated", - "value": "تعذر تحديد مسار ملف كلمة مرور المقبس." + "value": "لا توجد إشعارات غير مقروءة" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Kan ikke finne filstien for socket-passord." + "value": "Ingen uleste varsler" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Não foi possível resolver o caminho do arquivo de senha do socket." + "value": "Nenhuma notificação não lida" } }, "th": { "stringUnit": { "state": "translated", - "value": "ไม่สามารถระบุเส้นทางไฟล์รหัสผ่านซ็อกเก็ตได้" + "value": "ไม่มีการแจ้งเตือนที่ยังไม่อ่าน" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Soket parola dosyası yolu çözümlenemedi." + "value": "Okunmamış bildirim yok" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Не вдалося визначити шлях до файлу пароля сокета." + "value": "Непрочитаних сповіщень немає" } } } }, - "socketControl.off.description": { + "statusMenu.showCmux": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Disable the local control socket." + "value": "Show cmux" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ローカルコントロールソケットを無効にします。" + "value": "cmuxを表示" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "禁用本地控制套接字。" + "value": "显示 cmux" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "停用本機控制 Socket。" + "value": "顯示 cmux" } }, "ko": { "stringUnit": { "state": "translated", - "value": "로컬 제어 소켓을 비활성화합니다." + "value": "cmux 표시" } }, "de": { "stringUnit": { "state": "translated", - "value": "Den lokalen Steuerungs-Socket deaktivieren." + "value": "cmux anzeigen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Desactivar el socket de control local." + "value": "Mostrar cmux" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Désactiver le socket de contrôle local." + "value": "Afficher cmux" } }, "it": { "stringUnit": { "state": "translated", - "value": "Disabilita il socket di controllo locale." + "value": "Mostra cmux" } }, "da": { "stringUnit": { "state": "translated", - "value": "Deaktiver den lokale kontrolsocket." + "value": "Vis cmux" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Wyłącz lokalne gniazdo sterujące." + "value": "Pokaż cmux" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Отключить локальный управляющий сокет." + "value": "Показать cmux" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Onemogući lokalnu kontrolnu utičnicu." + "value": "Prikaži cmux" } }, "ar": { "stringUnit": { "state": "translated", - "value": "تعطيل مقبس التحكم المحلي." + "value": "عرض cmux" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Deaktiver den lokale kontrollsocketen." + "value": "Vis cmux" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Desativar o socket de controle local." + "value": "Mostrar cmux" } }, "th": { "stringUnit": { "state": "translated", - "value": "ปิดใช้งานซ็อกเก็ตควบคุมในเครื่อง" + "value": "แสดง cmux" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Yerel kontrol soketini devre dışı bırak." + "value": "cmux'u Göster" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Вимкнути локальний керуючий сокет." + "value": "Показати cmux" } } } }, - "socketControl.off.name": { + "statusMenu.showNotifications": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Off" + "value": "Show Notifications" } }, "ja": { "stringUnit": { "state": "translated", - "value": "オフ" + "value": "通知を表示" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "关闭" + "value": "显示通知" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "關閉" + "value": "顯示通知" } }, "ko": { "stringUnit": { "state": "translated", - "value": "끔" + "value": "알림 표시" } }, "de": { "stringUnit": { "state": "translated", - "value": "Aus" + "value": "Benachrichtigungen anzeigen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Desactivado" + "value": "Mostrar notificaciones" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Désactivé" + "value": "Afficher les notifications" } }, "it": { "stringUnit": { "state": "translated", - "value": "Disattivato" + "value": "Mostra notifiche" } }, "da": { "stringUnit": { "state": "translated", - "value": "Fra" + "value": "Vis notifikationer" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Wyłączone" + "value": "Pokaż powiadomienia" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Выключено" + "value": "Показать уведомления" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Isključeno" + "value": "Prikaži obavještenja" } }, "ar": { "stringUnit": { "state": "translated", - "value": "إيقاف" + "value": "عرض الإشعارات" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Av" + "value": "Vis varsler" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Desativado" + "value": "Mostrar Notificações" } }, "th": { "stringUnit": { "state": "translated", - "value": "ปิด" + "value": "แสดงการแจ้งเตือน" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Kapalı" + "value": "Bildirimleri Göster" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Вимкнено" + "value": "Показати сповіщення" } } } }, - "socketControl.password.description": { + "statusMenu.tooltip.unread.one": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Require socket authentication with a password stored in a local file." + "value": "1 unread notification" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ローカルファイルに保存されたパスワードでソケット認証を要求します。" + "value": "未読通知 1件" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "使用存储在本地文件中的密码进行套接字认证。" + "value": "1 条未读通知" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "使用儲存在本機檔案中的密碼進行 Socket 驗證。" + "value": "1 則未讀通知" } }, "ko": { "stringUnit": { "state": "translated", - "value": "로컬 파일에 저장된 비밀번호로 소켓 인증을 요구합니다." + "value": "읽지 않은 알림 1개" } }, "de": { "stringUnit": { "state": "translated", - "value": "Socket-Authentifizierung mit einem in einer lokalen Datei gespeicherten Passwort erfordern." + "value": "1 ungelesene Benachrichtigung" } }, "es": { "stringUnit": { "state": "translated", - "value": "Requerir autenticación del socket con una contraseña almacenada en un archivo local." + "value": "1 notificación no leída" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Exiger l'authentification du socket avec un mot de passe stocké dans un fichier local." + "value": "1 notification non lue" } }, "it": { "stringUnit": { "state": "translated", - "value": "Richiedi l'autenticazione del socket con una password memorizzata in un file locale." + "value": "1 notifica non letta" } }, "da": { "stringUnit": { "state": "translated", - "value": "Kræv socket-autentifikation med en adgangskode gemt i en lokal fil." + "value": "1 ulæst notifikation" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Wymagaj uwierzytelniania gniazda hasłem przechowywanym w pliku lokalnym." + "value": "1 nieprzeczytane powiadomienie" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Требовать аутентификацию сокета с паролем, хранящимся в локальном файле." + "value": "1 непрочитанное уведомление" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Zahtijevaj autentikaciju utičnice lozinkom pohranjenom u lokalnoj datoteci." + "value": "1 nepročitano obavještenje" } }, "ar": { "stringUnit": { "state": "translated", - "value": "طلب مصادقة المقبس بكلمة مرور مخزنة في ملف محلي." + "value": "إشعار واحد غير مقروء" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Krev socket-autentisering med et passord lagret i en lokal fil." + "value": "1 ulest varsel" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Exigir autenticação do socket com uma senha armazenada em um arquivo local." + "value": "1 notificação não lida" } }, "th": { "stringUnit": { "state": "translated", - "value": "ต้องมีการยืนยันตัวตนซ็อกเก็ตด้วยรหัสผ่านที่จัดเก็บในไฟล์ในเครื่อง" + "value": "1 การแจ้งเตือนที่ยังไม่อ่าน" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Yerel dosyada saklanan bir parola ile soket kimlik doğrulaması gerektir." + "value": "1 okunmamış bildirim" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Вимагати автентифікацію сокета з паролем, збереженим у локальному файлі." + "value": "1 непрочитане сповіщення" } } } }, - "socketControl.password.name": { + "statusMenu.tooltip.unread.other": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Password mode" + "value": "%lld unread notifications" } }, "ja": { "stringUnit": { "state": "translated", - "value": "パスワードモード" + "value": "未読通知 %lld件" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "密码模式" + "value": "%lld 条未读通知" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "密碼模式" + "value": "%lld 則未讀通知" } }, "ko": { "stringUnit": { "state": "translated", - "value": "비밀번호 모드" + "value": "읽지 않은 알림 %lld개" } }, "de": { "stringUnit": { "state": "translated", - "value": "Passwortmodus" + "value": "%lld ungelesene Benachrichtigungen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Modo de contraseña" + "value": "%lld notificaciones no leídas" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Mode mot de passe" + "value": "%lld notifications non lues" } }, "it": { "stringUnit": { "state": "translated", - "value": "Modalità password" + "value": "%lld notifiche non lette" } }, "da": { "stringUnit": { "state": "translated", - "value": "Adgangskodetilstand" + "value": "%lld ulæste notifikationer" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Tryb hasła" + "value": "%lld nieprzeczytanych powiadomień" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Режим пароля" + "value": "Непрочитанных уведомлений: %lld" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Režim lozinke" + "value": "%lld nepročitanih obavještenja" } }, "ar": { "stringUnit": { "state": "translated", - "value": "وضع كلمة المرور" + "value": "%lld إشعار غير مقروء" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Passordmodus" + "value": "%lld uleste varsler" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Modo de senha" + "value": "%lld notificações não lidas" } }, "th": { "stringUnit": { "state": "translated", - "value": "โหมดรหัสผ่าน" + "value": "%lld การแจ้งเตือนที่ยังไม่อ่าน" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Parola modu" + "value": "%lld okunmamış bildirim" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Режим пароля" + "value": "%lld непрочитаних сповіщень" } } } }, - "statusMenu.clearAll": { + "statusMenu.unreadCount.one": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Clear All" + "value": "1 unread notification" } }, "ja": { "stringUnit": { "state": "translated", - "value": "すべてクリア" + "value": "未読通知 1件" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "全部清除" + "value": "1 条未读通知" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "清除全部" + "value": "1 則未讀通知" } }, "ko": { "stringUnit": { "state": "translated", - "value": "모두 지우기" + "value": "읽지 않은 알림 1개" } }, "de": { "stringUnit": { "state": "translated", - "value": "Alle löschen" + "value": "1 ungelesene Benachrichtigung" } }, "es": { "stringUnit": { "state": "translated", - "value": "Borrar todo" + "value": "1 notificación no leída" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Tout effacer" + "value": "1 notification non lue" } }, "it": { "stringUnit": { "state": "translated", - "value": "Cancella tutto" + "value": "1 notifica non letta" } }, "da": { "stringUnit": { "state": "translated", - "value": "Ryd alle" + "value": "1 ulæst notifikation" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Wyczyść wszystko" + "value": "1 nieprzeczytane powiadomienie" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Очистить все" + "value": "1 непрочитанное уведомление" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Obriši sve" + "value": "1 nepročitano obavještenje" } }, "ar": { "stringUnit": { "state": "translated", - "value": "مسح الكل" + "value": "إشعار واحد غير مقروء" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Fjern alle" + "value": "1 ulest varsel" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Limpar Tudo" + "value": "1 notificação não lida" } }, "th": { "stringUnit": { "state": "translated", - "value": "ล้างทั้งหมด" + "value": "1 การแจ้งเตือนที่ยังไม่อ่าน" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Tümünü Temizle" + "value": "1 okunmamış bildirim" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Очистити все" + "value": "1 непрочитане сповіщення" } } } }, - "statusMenu.jumpToLatestUnread": { + "statusMenu.unreadCount.other": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Jump to Latest Unread" + "value": "%lld unread notifications" } }, "ja": { "stringUnit": { "state": "translated", - "value": "最新の未読にジャンプ" + "value": "未読通知 %lld件" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "跳转到最新未读" + "value": "%lld 条未读通知" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "跳至最新未讀" + "value": "%lld 則未讀通知" } }, "ko": { "stringUnit": { "state": "translated", - "value": "최신 읽지 않은 항목으로 이동" + "value": "읽지 않은 알림 %lld개" } }, "de": { "stringUnit": { "state": "translated", - "value": "Zur letzten ungelesenen springen" + "value": "%lld ungelesene Benachrichtigungen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Ir a la última no leída" + "value": "%lld notificaciones no leídas" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Aller au dernier message non lu" + "value": "%lld notifications non lues" } }, "it": { "stringUnit": { "state": "translated", - "value": "Vai all'ultimo non letto" + "value": "%lld notifiche non lette" } }, "da": { "stringUnit": { "state": "translated", - "value": "Gå til seneste ulæste" + "value": "%lld ulæste notifikationer" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Przejdź do najnowszego nieprzeczytanego" + "value": "%lld nieprzeczytanych powiadomień" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Перейти к последнему непрочитанному" + "value": "Непрочитанных уведомлений: %lld" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Skoči na najnovije nepročitano" + "value": "%lld nepročitanih obavještenja" } }, "ar": { "stringUnit": { "state": "translated", - "value": "الانتقال إلى أحدث غير مقروء" + "value": "%lld إشعار غير مقروء" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Gå til siste uleste" + "value": "%lld uleste varsler" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Ir para Última Não Lida" + "value": "%lld notificações não lidas" } }, "th": { "stringUnit": { "state": "translated", - "value": "ข้ามไปยังรายการยังไม่อ่านล่าสุด" + "value": "%lld การแจ้งเตือนที่ยังไม่อ่าน" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Son Okunmamışa Atla" + "value": "%lld okunmamış bildirim" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Перейти до останнього непрочитаного" + "value": "%lld непрочитаних сповіщень" } } } }, - "statusMenu.markAllRead": { + "tab.untitled": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Mark All Read" + "value": "Untitled Tab" } }, "ja": { "stringUnit": { "state": "translated", - "value": "すべて既読にする" + "value": "名称未設定タブ" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "全部标记为已读" + "value": "未命名标签页" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "全部標為已讀" + "value": "未命名標籤頁" } }, "ko": { "stringUnit": { "state": "translated", - "value": "모두 읽음으로 표시" + "value": "제목 없는 탭" } }, "de": { "stringUnit": { "state": "translated", - "value": "Alle als gelesen markieren" + "value": "Unbenannter Tab" } }, "es": { "stringUnit": { "state": "translated", - "value": "Marcar todo como leído" + "value": "Pestaña sin título" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Tout marquer comme lu" + "value": "Onglet sans titre" } }, "it": { "stringUnit": { "state": "translated", - "value": "Segna tutto come letto" + "value": "Scheda senza titolo" } }, "da": { "stringUnit": { "state": "translated", - "value": "Marker alle som læste" + "value": "Unavngivet fane" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Oznacz wszystko jako przeczytane" + "value": "Karta bez nazwy" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Отметить все как прочитанные" + "value": "Безымянная вкладка" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Označi sve kao pročitano" + "value": "Tab bez naziva" } }, "ar": { "stringUnit": { "state": "translated", - "value": "تعليم الكل كمقروء" + "value": "لسان بلا عنوان" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Merk alle som lest" + "value": "Uten navn-fane" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Marcar Tudo como Lido" + "value": "Aba Sem Título" } }, "th": { "stringUnit": { "state": "translated", - "value": "ทำเครื่องหมายว่าอ่านทั้งหมดแล้ว" + "value": "แท็บไม่มีชื่อ" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Tümünü Okundu İşaretle" + "value": "Adsız Sekme" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Позначити все як прочитане" + "value": "Безіменна вкладка" } } } }, - "statusMenu.noUnread": { + "theme.dark": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "No unread notifications" + "value": "Dark" } }, "ja": { "stringUnit": { "state": "translated", - "value": "未読の通知はありません" + "value": "ダーク" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "没有未读通知" + "value": "深色" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "沒有未讀通知" + "value": "深色" } }, "ko": { "stringUnit": { "state": "translated", - "value": "읽지 않은 알림 없음" + "value": "다크" } }, "de": { "stringUnit": { "state": "translated", - "value": "Keine ungelesenen Benachrichtigungen" + "value": "Dunkel" } }, "es": { "stringUnit": { "state": "translated", - "value": "Sin notificaciones no leídas" + "value": "Oscuro" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Aucune notification non lue" + "value": "Sombre" } }, "it": { "stringUnit": { "state": "translated", - "value": "Nessuna notifica non letta" + "value": "Scuro" } }, "da": { "stringUnit": { "state": "translated", - "value": "Ingen ulæste notifikationer" + "value": "Mørk" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Brak nieprzeczytanych powiadomień" + "value": "Ciemny" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Нет непрочитанных уведомлений" + "value": "Темная" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Nema nepročitanih obavještenja" + "value": "Tamna" } }, "ar": { "stringUnit": { "state": "translated", - "value": "لا توجد إشعارات غير مقروءة" + "value": "داكن" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Ingen uleste varsler" + "value": "Mørk" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Nenhuma notificação não lida" + "value": "Escuro" } }, "th": { "stringUnit": { "state": "translated", - "value": "ไม่มีการแจ้งเตือนที่ยังไม่อ่าน" + "value": "มืด" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Okunmamış bildirim yok" + "value": "Koyu" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Непрочитаних сповіщень немає" + "value": "Темна" } } } }, - "statusMenu.showCmux": { + "theme.light": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Show cmux" + "value": "Light" } }, "ja": { "stringUnit": { "state": "translated", - "value": "cmuxを表示" + "value": "ライト" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "显示 cmux" + "value": "浅色" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "顯示 cmux" + "value": "淺色" } }, "ko": { "stringUnit": { "state": "translated", - "value": "cmux 표시" + "value": "라이트" } }, "de": { "stringUnit": { "state": "translated", - "value": "cmux anzeigen" + "value": "Hell" } }, "es": { "stringUnit": { "state": "translated", - "value": "Mostrar cmux" + "value": "Claro" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Afficher cmux" + "value": "Clair" } }, "it": { "stringUnit": { "state": "translated", - "value": "Mostra cmux" + "value": "Chiaro" } }, "da": { "stringUnit": { "state": "translated", - "value": "Vis cmux" + "value": "Lys" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Pokaż cmux" + "value": "Jasny" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Показать cmux" + "value": "Светлая" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Prikaži cmux" + "value": "Svijetla" } }, "ar": { "stringUnit": { "state": "translated", - "value": "عرض cmux" + "value": "فاتح" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Vis cmux" + "value": "Lys" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Mostrar cmux" + "value": "Claro" } }, "th": { "stringUnit": { "state": "translated", - "value": "แสดง cmux" + "value": "สว่าง" } }, "tr": { "stringUnit": { "state": "translated", - "value": "cmux'u Göster" + "value": "Açık" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Показати cmux" + "value": "Світла" } } } }, - "statusMenu.showNotifications": { + "theme.system": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Show Notifications" + "value": "System" } }, "ja": { "stringUnit": { "state": "translated", - "value": "通知を表示" + "value": "システム" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "显示通知" + "value": "系统" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "顯示通知" + "value": "系統" } }, "ko": { "stringUnit": { "state": "translated", - "value": "알림 표시" + "value": "시스템" } }, "de": { "stringUnit": { "state": "translated", - "value": "Benachrichtigungen anzeigen" + "value": "System" } }, "es": { "stringUnit": { "state": "translated", - "value": "Mostrar notificaciones" + "value": "Sistema" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Afficher les notifications" + "value": "Système" } }, "it": { "stringUnit": { "state": "translated", - "value": "Mostra notifiche" + "value": "Sistema" } }, "da": { "stringUnit": { "state": "translated", - "value": "Vis notifikationer" + "value": "System" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Pokaż powiadomienia" + "value": "Systemowy" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Показать уведомления" + "value": "Системная" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Prikaži obavještenja" + "value": "Sistemski" } }, "ar": { "stringUnit": { "state": "translated", - "value": "عرض الإشعارات" + "value": "النظام" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Vis varsler" + "value": "System" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Mostrar Notificações" + "value": "Sistema" } }, "th": { "stringUnit": { "state": "translated", - "value": "แสดงการแจ้งเตือน" + "value": "ระบบ" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Bildirimleri Göster" + "value": "Sistem" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Показати сповіщення" + "value": "Системна" } } } }, - "statusMenu.tooltip.unread.one": { + "titlebar.newWorkspace.accessibilityLabel": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "1 unread notification" + "value": "New Workspace" } }, "ja": { "stringUnit": { "state": "translated", - "value": "未読通知 1件" + "value": "新規ワークスペース" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "1 条未读通知" + "value": "新建工作区" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "1 則未讀通知" + "value": "新增工作區" } }, "ko": { "stringUnit": { "state": "translated", - "value": "읽지 않은 알림 1개" + "value": "새 작업 공간" } }, "de": { "stringUnit": { "state": "translated", - "value": "1 ungelesene Benachrichtigung" + "value": "Neuer Arbeitsbereich" } }, "es": { "stringUnit": { "state": "translated", - "value": "1 notificación no leída" + "value": "Nuevo espacio de trabajo" } }, "fr": { "stringUnit": { "state": "translated", - "value": "1 notification non lue" + "value": "Nouvel espace de travail" } }, "it": { "stringUnit": { "state": "translated", - "value": "1 notifica non letta" + "value": "Nuova area di lavoro" } }, "da": { "stringUnit": { "state": "translated", - "value": "1 ulæst notifikation" + "value": "Nyt arbejdsområde" } }, "pl": { "stringUnit": { "state": "translated", - "value": "1 nieprzeczytane powiadomienie" + "value": "Nowa przestrzeń robocza" } }, "ru": { "stringUnit": { "state": "translated", - "value": "1 непрочитанное уведомление" + "value": "Новое рабочее пространство" } }, "bs": { "stringUnit": { "state": "translated", - "value": "1 nepročitano obavještenje" + "value": "Novi radni prostor" } }, "ar": { "stringUnit": { "state": "translated", - "value": "إشعار واحد غير مقروء" + "value": "مساحة عمل جديدة" } }, "nb": { "stringUnit": { "state": "translated", - "value": "1 ulest varsel" + "value": "Nytt arbeidsområde" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "1 notificação não lida" + "value": "Nova Área de Trabalho" } }, "th": { "stringUnit": { "state": "translated", - "value": "1 การแจ้งเตือนที่ยังไม่อ่าน" + "value": "เวิร์กสเปซใหม่" } }, "tr": { "stringUnit": { "state": "translated", - "value": "1 okunmamış bildirim" + "value": "Yeni Çalışma Alanı" } }, "uk": { "stringUnit": { "state": "translated", - "value": "1 непрочитане сповіщення" + "value": "Нова робоча область" } } } }, - "statusMenu.tooltip.unread.other": { + "titlebar.newWorkspace.tooltip": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "%lld unread notifications" + "value": "New workspace" } }, "ja": { "stringUnit": { "state": "translated", - "value": "未読通知 %lld件" + "value": "新規ワークスペース" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "%lld 条未读通知" + "value": "新建工作区" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "%lld 則未讀通知" + "value": "新增工作區" } }, "ko": { "stringUnit": { "state": "translated", - "value": "읽지 않은 알림 %lld개" + "value": "새 작업 공간" } }, "de": { "stringUnit": { "state": "translated", - "value": "%lld ungelesene Benachrichtigungen" + "value": "Neuer Arbeitsbereich" } }, "es": { "stringUnit": { "state": "translated", - "value": "%lld notificaciones no leídas" + "value": "Nuevo espacio de trabajo" } }, "fr": { "stringUnit": { "state": "translated", - "value": "%lld notifications non lues" + "value": "Nouvel espace de travail" } }, "it": { "stringUnit": { "state": "translated", - "value": "%lld notifiche non lette" + "value": "Nuova area di lavoro" } }, "da": { "stringUnit": { "state": "translated", - "value": "%lld ulæste notifikationer" + "value": "Nyt arbejdsområde" } }, "pl": { "stringUnit": { "state": "translated", - "value": "%lld nieprzeczytanych powiadomień" + "value": "Nowa przestrzeń robocza" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Непрочитанных уведомлений: %lld" + "value": "Новое рабочее пространство" } }, "bs": { "stringUnit": { "state": "translated", - "value": "%lld nepročitanih obavještenja" + "value": "Novi radni prostor" } }, "ar": { "stringUnit": { "state": "translated", - "value": "%lld إشعار غير مقروء" + "value": "مساحة عمل جديدة" } }, "nb": { "stringUnit": { "state": "translated", - "value": "%lld uleste varsler" + "value": "Nytt arbeidsområde" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "%lld notificações não lidas" + "value": "Nova área de trabalho" } }, "th": { "stringUnit": { "state": "translated", - "value": "%lld การแจ้งเตือนที่ยังไม่อ่าน" + "value": "เวิร์กสเปซใหม่" } }, "tr": { "stringUnit": { "state": "translated", - "value": "%lld okunmamış bildirim" + "value": "Yeni çalışma alanı" } }, "uk": { "stringUnit": { "state": "translated", - "value": "%lld непрочитаних сповіщень" + "value": "Нова робоча область" } } } }, - "statusMenu.unreadCount.one": { + "titlebar.notifications.accessibilityLabel": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "1 unread notification" + "value": "Notifications" } }, "ja": { "stringUnit": { "state": "translated", - "value": "未読通知 1件" + "value": "通知" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "1 条未读通知" + "value": "通知" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "1 則未讀通知" + "value": "通知" } }, "ko": { "stringUnit": { "state": "translated", - "value": "읽지 않은 알림 1개" + "value": "알림" } }, "de": { "stringUnit": { "state": "translated", - "value": "1 ungelesene Benachrichtigung" + "value": "Benachrichtigungen" } }, "es": { "stringUnit": { "state": "translated", - "value": "1 notificación no leída" + "value": "Notificaciones" } }, "fr": { "stringUnit": { "state": "translated", - "value": "1 notification non lue" + "value": "Notifications" } }, "it": { "stringUnit": { "state": "translated", - "value": "1 notifica non letta" + "value": "Notifiche" } }, "da": { "stringUnit": { "state": "translated", - "value": "1 ulæst notifikation" + "value": "Notifikationer" } }, "pl": { "stringUnit": { "state": "translated", - "value": "1 nieprzeczytane powiadomienie" + "value": "Powiadomienia" } }, "ru": { "stringUnit": { "state": "translated", - "value": "1 непрочитанное уведомление" + "value": "Уведомления" } }, "bs": { "stringUnit": { "state": "translated", - "value": "1 nepročitano obavještenje" + "value": "Obavještenja" } }, "ar": { "stringUnit": { "state": "translated", - "value": "إشعار واحد غير مقروء" + "value": "الإشعارات" } }, "nb": { "stringUnit": { "state": "translated", - "value": "1 ulest varsel" + "value": "Varsler" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "1 notificação não lida" + "value": "Notificações" } }, "th": { "stringUnit": { "state": "translated", - "value": "1 การแจ้งเตือนที่ยังไม่อ่าน" + "value": "การแจ้งเตือน" } }, "tr": { "stringUnit": { "state": "translated", - "value": "1 okunmamış bildirim" + "value": "Bildirimler" } }, "uk": { "stringUnit": { "state": "translated", - "value": "1 непрочитане сповіщення" + "value": "Сповіщення" } } } }, - "statusMenu.unreadCount.other": { + "titlebar.notifications.tooltip": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "%lld unread notifications" + "value": "Show notifications" } }, "ja": { "stringUnit": { "state": "translated", - "value": "未読通知 %lld件" + "value": "通知を表示" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "%lld 条未读通知" + "value": "显示通知" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "%lld 則未讀通知" + "value": "顯示通知" } }, "ko": { "stringUnit": { "state": "translated", - "value": "읽지 않은 알림 %lld개" + "value": "알림 표시" } }, "de": { "stringUnit": { "state": "translated", - "value": "%lld ungelesene Benachrichtigungen" + "value": "Benachrichtigungen anzeigen" } }, "es": { "stringUnit": { "state": "translated", - "value": "%lld notificaciones no leídas" + "value": "Mostrar notificaciones" } }, "fr": { "stringUnit": { "state": "translated", - "value": "%lld notifications non lues" + "value": "Afficher les notifications" } }, "it": { "stringUnit": { "state": "translated", - "value": "%lld notifiche non lette" + "value": "Mostra notifiche" } }, "da": { "stringUnit": { "state": "translated", - "value": "%lld ulæste notifikationer" + "value": "Vis notifikationer" } }, "pl": { "stringUnit": { "state": "translated", - "value": "%lld nieprzeczytanych powiadomień" + "value": "Pokaż powiadomienia" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Непрочитанных уведомлений: %lld" + "value": "Показать уведомления" } }, "bs": { "stringUnit": { "state": "translated", - "value": "%lld nepročitanih obavještenja" + "value": "Prikaži obavještenja" } }, "ar": { "stringUnit": { "state": "translated", - "value": "%lld إشعار غير مقروء" + "value": "عرض الإشعارات" } }, "nb": { "stringUnit": { "state": "translated", - "value": "%lld uleste varsler" + "value": "Vis varsler" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "%lld notificações não lidas" + "value": "Mostrar notificações" } }, "th": { "stringUnit": { "state": "translated", - "value": "%lld การแจ้งเตือนที่ยังไม่อ่าน" + "value": "แสดงการแจ้งเตือน" } }, "tr": { "stringUnit": { "state": "translated", - "value": "%lld okunmamış bildirim" + "value": "Bildirimleri göster" } }, "uk": { "stringUnit": { "state": "translated", - "value": "%lld непрочитаних сповіщень" + "value": "Показати сповіщення" } } } }, - "tab.untitled": { + "titlebar.sidebar.accessibilityLabel": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Untitled Tab" + "value": "Toggle Sidebar" } }, "ja": { "stringUnit": { "state": "translated", - "value": "名称未設定タブ" + "value": "サイドバーの切り替え" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "未命名标签页" + "value": "切换侧边栏" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "未命名標籤頁" + "value": "切換側邊欄" } }, "ko": { "stringUnit": { "state": "translated", - "value": "제목 없는 탭" + "value": "사이드바 전환" } }, "de": { "stringUnit": { "state": "translated", - "value": "Unbenannter Tab" + "value": "Seitenleiste ein-/ausblenden" } }, "es": { "stringUnit": { "state": "translated", - "value": "Pestaña sin título" + "value": "Alternar barra lateral" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Onglet sans titre" + "value": "Afficher/masquer la barre latérale" } }, "it": { "stringUnit": { "state": "translated", - "value": "Scheda senza titolo" + "value": "Attiva/Disattiva barra laterale" } }, "da": { "stringUnit": { "state": "translated", - "value": "Unavngivet fane" + "value": "Slå sidebjælke til/fra" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Karta bez nazwy" + "value": "Przełącz pasek boczny" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Безымянная вкладка" + "value": "Боковая панель" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Tab bez naziva" + "value": "Prebaci bočnu traku" } }, "ar": { "stringUnit": { "state": "translated", - "value": "لسان بلا عنوان" + "value": "تبديل الشريط الجانبي" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Uten navn-fane" + "value": "Slå sidepanelet av/på" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Aba Sem Título" + "value": "Alternar Barra Lateral" } }, "th": { "stringUnit": { "state": "translated", - "value": "แท็บไม่มีชื่อ" + "value": "สลับแถบด้านข้าง" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Adsız Sekme" + "value": "Kenar Çubuğunu Aç/Kapat" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Безіменна вкладка" + "value": "Перемкнути бічну панель" } } } }, - "theme.dark": { + "titlebar.sidebar.tooltip": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Dark" + "value": "Show or hide the sidebar" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ダーク" + "value": "サイドバーの表示/非表示" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "深色" + "value": "显示或隐藏侧边栏" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "深色" + "value": "顯示或隱藏側邊欄" } }, "ko": { "stringUnit": { "state": "translated", - "value": "다크" + "value": "사이드바 표시 또는 숨기기" } }, "de": { "stringUnit": { "state": "translated", - "value": "Dunkel" + "value": "Seitenleiste ein- oder ausblenden" } }, "es": { "stringUnit": { "state": "translated", - "value": "Oscuro" + "value": "Mostrar u ocultar la barra lateral" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Sombre" + "value": "Afficher ou masquer la barre latérale" } }, "it": { "stringUnit": { "state": "translated", - "value": "Scuro" + "value": "Mostra o nascondi la barra laterale" } }, "da": { "stringUnit": { "state": "translated", - "value": "Mørk" + "value": "Vis eller skjul sidebjælken" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Ciemny" + "value": "Pokaż lub ukryj pasek boczny" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Темная" + "value": "Показать или скрыть боковую панель" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Tamna" + "value": "Prikaži ili sakrij bočnu traku" } }, "ar": { "stringUnit": { "state": "translated", - "value": "داكن" + "value": "إظهار أو إخفاء الشريط الجانبي" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Mørk" + "value": "Vis eller skjul sidepanelet" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Escuro" + "value": "Mostrar ou ocultar a barra lateral" } }, "th": { "stringUnit": { "state": "translated", - "value": "มืด" + "value": "แสดงหรือซ่อนแถบด้านข้าง" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Koyu" + "value": "Kenar çubuğunu göster veya gizle" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Темна" + "value": "Показати або сховати бічну панель" } } } }, - "theme.light": { + "update.available.short": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Light" + "value": "Update Available" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ライト" + "value": "アップデートがあります" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "浅色" + "value": "有可用更新" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "淺色" + "value": "有可用的更新" } }, "ko": { "stringUnit": { "state": "translated", - "value": "라이트" + "value": "업데이트 사용 가능" } }, "de": { "stringUnit": { "state": "translated", - "value": "Hell" + "value": "Update verfügbar" } }, "es": { "stringUnit": { "state": "translated", - "value": "Claro" + "value": "Actualización disponible" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Clair" + "value": "Mise à jour disponible" } }, "it": { "stringUnit": { "state": "translated", - "value": "Chiaro" + "value": "Aggiornamento disponibile" } }, "da": { "stringUnit": { "state": "translated", - "value": "Lys" + "value": "Opdatering tilgængelig" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Jasny" + "value": "Dostępna aktualizacja" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Светлая" + "value": "Доступно обновление" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Svijetla" + "value": "Ažuriranje dostupno" } }, "ar": { "stringUnit": { "state": "translated", - "value": "فاتح" + "value": "تحديث متوفر" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Lys" + "value": "Oppdatering tilgjengelig" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Claro" + "value": "Atualização Disponível" } }, "th": { "stringUnit": { "state": "translated", - "value": "สว่าง" + "value": "มีอัปเดตใหม่" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Açık" + "value": "Güncelleme Mevcut" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Світла" + "value": "Доступне оновлення" } } } }, - "theme.system": { + "update.available.withVersion": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "System" + "value": "Update Available: %@" } }, "ja": { "stringUnit": { "state": "translated", - "value": "システム" + "value": "アップデートあり: %@" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "系统" + "value": "有可用更新:%@" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "系統" + "value": "有可用的更新:%@" } }, "ko": { "stringUnit": { "state": "translated", - "value": "시스템" + "value": "업데이트 사용 가능: %@" } }, "de": { "stringUnit": { "state": "translated", - "value": "System" + "value": "Update verfügbar: %@" } }, "es": { "stringUnit": { "state": "translated", - "value": "Sistema" + "value": "Actualización disponible: %@" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Système" + "value": "Mise à jour disponible : %@" } }, "it": { "stringUnit": { "state": "translated", - "value": "Sistema" + "value": "Aggiornamento disponibile: %@" } }, "da": { "stringUnit": { "state": "translated", - "value": "System" + "value": "Opdatering tilgængelig: %@" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Systemowy" + "value": "Dostępna aktualizacja: %@" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Системная" + "value": "Доступно обновление: %@" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Sistemski" + "value": "Ažuriranje dostupno: %@" } }, "ar": { "stringUnit": { "state": "translated", - "value": "النظام" + "value": "تحديث متوفر: %@" } }, "nb": { "stringUnit": { "state": "translated", - "value": "System" + "value": "Oppdatering tilgjengelig: %@" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Sistema" + "value": "Atualização Disponível: %@" } }, "th": { "stringUnit": { "state": "translated", - "value": "ระบบ" + "value": "มีอัปเดตใหม่: %@" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Sistem" + "value": "Güncelleme Mevcut: %@" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Системна" + "value": "Доступне оновлення: %@" } } } }, - "titlebar.newWorkspace.accessibilityLabel": { + "update.checking": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "New Workspace" + "value": "Checking for Updates…" } }, "ja": { "stringUnit": { "state": "translated", - "value": "新規ワークスペース" + "value": "アップデートを確認中…" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "新建工作区" + "value": "正在检查更新..." } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "新增工作區" + "value": "正在檢查更新..." } }, "ko": { "stringUnit": { "state": "translated", - "value": "새 작업 공간" + "value": "업데이트 확인 중…" } }, "de": { "stringUnit": { "state": "translated", - "value": "Neuer Arbeitsbereich" + "value": "Suche nach Updates …" } }, "es": { "stringUnit": { "state": "translated", - "value": "Nuevo espacio de trabajo" + "value": "Buscando actualizaciones…" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Nouvel espace de travail" + "value": "Recherche de mises à jour..." } }, "it": { "stringUnit": { "state": "translated", - "value": "Nuova area di lavoro" + "value": "Verifica aggiornamenti in corso…" } }, "da": { "stringUnit": { "state": "translated", - "value": "Nyt arbejdsområde" + "value": "Søger efter opdateringer…" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Nowa przestrzeń robocza" + "value": "Sprawdzanie aktualizacji…" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Новое рабочее пространство" + "value": "Проверка обновлений..." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Novi radni prostor" + "value": "Provjeravanje ažuriranja…" } }, "ar": { "stringUnit": { "state": "translated", - "value": "مساحة عمل جديدة" + "value": "جارٍ التحقق من التحديثات…" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Nytt arbeidsområde" + "value": "Ser etter oppdateringer …" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Nova Área de Trabalho" + "value": "Verificando Atualizações…" } }, "th": { "stringUnit": { "state": "translated", - "value": "เวิร์กสเปซใหม่" + "value": "กำลังตรวจหาอัปเดต..." } }, "tr": { "stringUnit": { "state": "translated", - "value": "Yeni Çalışma Alanı" + "value": "Güncellemeler denetleniyor…" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Нова робоча область" + "value": "Перевірка оновлень…" } } } }, - "titlebar.newWorkspace.tooltip": { + "update.configureAutoUpdates": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "New workspace" + "value": "Configure automatic update preferences" } }, "ja": { "stringUnit": { "state": "translated", - "value": "新規ワークスペース" + "value": "自動アップデートの設定" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "新建工作区" + "value": "配置自动更新偏好设置" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "新增工作區" + "value": "設定自動更新偏好" } }, "ko": { "stringUnit": { "state": "translated", - "value": "새 작업 공간" + "value": "자동 업데이트 환경설정 구성" } }, "de": { "stringUnit": { "state": "translated", - "value": "Neuer Arbeitsbereich" + "value": "Einstellungen für automatische Updates konfigurieren" } }, "es": { "stringUnit": { "state": "translated", - "value": "Nuevo espacio de trabajo" + "value": "Configurar preferencias de actualización automática" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Nouvel espace de travail" + "value": "Configurer les préférences de mise à jour automatique" } }, "it": { "stringUnit": { "state": "translated", - "value": "Nuova area di lavoro" + "value": "Configura le preferenze di aggiornamento automatico" } }, "da": { "stringUnit": { "state": "translated", - "value": "Nyt arbejdsområde" + "value": "Konfigurer præferencer for automatiske opdateringer" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Nowa przestrzeń robocza" + "value": "Skonfiguruj preferencje automatycznych aktualizacji" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Новое рабочее пространство" + "value": "Настроить параметры автоматических обновлений" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Novi radni prostor" + "value": "Konfigurišite postavke automatskog ažuriranja" } }, "ar": { "stringUnit": { "state": "translated", - "value": "مساحة عمل جديدة" + "value": "تكوين تفضيلات التحديث التلقائي" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Nytt arbeidsområde" + "value": "Konfigurer innstillinger for automatiske oppdateringer" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Nova área de trabalho" + "value": "Configurar preferências de atualização automática" } }, "th": { "stringUnit": { "state": "translated", - "value": "เวิร์กสเปซใหม่" + "value": "กำหนดค่าการอัปเดตอัตโนมัติ" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Yeni çalışma alanı" + "value": "Otomatik güncelleme tercihlerini yapılandır" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Нова робоча область" + "value": "Налаштувати параметри автоматичного оновлення" } } } }, - "titlebar.notifications.accessibilityLabel": { + "update.downloadAndInstall": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Notifications" + "value": "Download and install the latest version" } }, "ja": { "stringUnit": { "state": "translated", - "value": "通知" + "value": "最新バージョンをダウンロードしてインストール" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "通知" + "value": "下载并安装最新版本" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "通知" + "value": "下載並安裝最新版本" } }, "ko": { "stringUnit": { "state": "translated", - "value": "알림" + "value": "최신 버전 다운로드 및 설치" } }, "de": { "stringUnit": { "state": "translated", - "value": "Benachrichtigungen" + "value": "Neueste Version herunterladen und installieren" } }, "es": { "stringUnit": { "state": "translated", - "value": "Notificaciones" + "value": "Descargar e instalar la última versión" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Notifications" + "value": "Télécharger et installer la dernière version" } }, "it": { "stringUnit": { "state": "translated", - "value": "Notifiche" + "value": "Scarica e installa l'ultima versione" } }, "da": { "stringUnit": { "state": "translated", - "value": "Notifikationer" + "value": "Download og installer den seneste version" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Powiadomienia" + "value": "Pobierz i zainstaluj najnowszą wersję" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Уведомления" + "value": "Загрузить и установить последнюю версию" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Obavještenja" + "value": "Preuzmite i instalirajte najnoviju verziju" } }, "ar": { "stringUnit": { "state": "translated", - "value": "الإشعارات" + "value": "تنزيل وتثبيت أحدث إصدار" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Varsler" + "value": "Last ned og installer den nyeste versjonen" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Notificações" + "value": "Baixar e instalar a versão mais recente" } }, "th": { "stringUnit": { "state": "translated", - "value": "การแจ้งเตือน" + "value": "ดาวน์โหลดและติดตั้งเวอร์ชันล่าสุด" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Bildirimler" + "value": "En son sürümü indir ve yükle" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Сповіщення" + "value": "Завантажити та встановити найновішу версію" } } } }, - "titlebar.notifications.tooltip": { + "update.downloading.progress": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Show notifications" + "value": "Downloading: %@" } }, "ja": { "stringUnit": { "state": "translated", - "value": "通知を表示" + "value": "ダウンロード中: %@" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "显示通知" + "value": "正在下载:%@" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "顯示通知" + "value": "正在下載:%@" } }, "ko": { "stringUnit": { "state": "translated", - "value": "알림 표시" + "value": "다운로드 중: %@" } }, "de": { "stringUnit": { "state": "translated", - "value": "Benachrichtigungen anzeigen" + "value": "Herunterladen: %@" } }, "es": { "stringUnit": { "state": "translated", - "value": "Mostrar notificaciones" + "value": "Descargando: %@" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Afficher les notifications" + "value": "Téléchargement : %@" } }, "it": { "stringUnit": { "state": "translated", - "value": "Mostra notifiche" + "value": "Download: %@" } }, "da": { "stringUnit": { "state": "translated", - "value": "Vis notifikationer" + "value": "Downloader: %@" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Pokaż powiadomienia" + "value": "Pobieranie: %@" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Показать уведомления" + "value": "Загрузка: %@" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Prikaži obavještenja" + "value": "Preuzimanje: %@" } }, "ar": { "stringUnit": { "state": "translated", - "value": "عرض الإشعارات" + "value": "جارٍ التنزيل: %@" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Vis varsler" + "value": "Laster ned: %@" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Mostrar notificações" + "value": "Baixando: %@" } }, "th": { "stringUnit": { "state": "translated", - "value": "แสดงการแจ้งเตือน" + "value": "กำลังดาวน์โหลด: %@" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Bildirimleri göster" + "value": "İndiriliyor: %@" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Показати сповіщення" + "value": "Завантаження: %@" } } } }, - "titlebar.sidebar.accessibilityLabel": { + "update.downloading.status": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Toggle Sidebar" + "value": "Downloading…" } }, "ja": { "stringUnit": { "state": "translated", - "value": "サイドバーの切り替え" + "value": "ダウンロード中…" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "切换侧边栏" + "value": "正在下载..." } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "切換側邊欄" + "value": "下載中..." } }, "ko": { "stringUnit": { "state": "translated", - "value": "사이드바 전환" + "value": "다운로드 중…" } }, "de": { "stringUnit": { "state": "translated", - "value": "Seitenleiste ein-/ausblenden" + "value": "Wird heruntergeladen …" } }, "es": { "stringUnit": { "state": "translated", - "value": "Alternar barra lateral" + "value": "Descargando…" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Afficher/masquer la barre latérale" + "value": "Téléchargement..." } }, "it": { "stringUnit": { "state": "translated", - "value": "Attiva/Disattiva barra laterale" + "value": "Download in corso…" } }, "da": { "stringUnit": { "state": "translated", - "value": "Slå sidebjælke til/fra" + "value": "Downloader…" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Przełącz pasek boczny" + "value": "Pobieranie…" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Боковая панель" + "value": "Загрузка..." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Prebaci bočnu traku" + "value": "Preuzimanje…" } }, "ar": { "stringUnit": { "state": "translated", - "value": "تبديل الشريط الجانبي" + "value": "جارٍ التنزيل…" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Slå sidepanelet av/på" + "value": "Laster ned …" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Alternar Barra Lateral" + "value": "Baixando…" } }, "th": { "stringUnit": { "state": "translated", - "value": "สลับแถบด้านข้าง" + "value": "กำลังดาวน์โหลด..." } }, "tr": { "stringUnit": { "state": "translated", - "value": "Kenar Çubuğunu Aç/Kapat" + "value": "İndiriliyor…" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Перемкнути бічну панель" + "value": "Завантаження…" } } } }, - "titlebar.sidebar.tooltip": { + "update.downloadingPackage": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Show or hide the sidebar" + "value": "Downloading the update package" } }, "ja": { "stringUnit": { "state": "translated", - "value": "サイドバーの表示/非表示" + "value": "アップデートパッケージをダウンロード中" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "显示或隐藏侧边栏" + "value": "正在下载更新包" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "顯示或隱藏側邊欄" + "value": "正在下載更新套件" } }, "ko": { "stringUnit": { "state": "translated", - "value": "사이드바 표시 또는 숨기기" + "value": "업데이트 패키지 다운로드 중" } }, "de": { "stringUnit": { "state": "translated", - "value": "Seitenleiste ein- oder ausblenden" + "value": "Update-Paket wird heruntergeladen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Mostrar u ocultar la barra lateral" + "value": "Descargando el paquete de actualización" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Afficher ou masquer la barre latérale" + "value": "Téléchargement du paquet de mise à jour" } }, "it": { "stringUnit": { "state": "translated", - "value": "Mostra o nascondi la barra laterale" + "value": "Download del pacchetto di aggiornamento" } }, "da": { "stringUnit": { "state": "translated", - "value": "Vis eller skjul sidebjælken" + "value": "Downloader opdateringspakken" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Pokaż lub ukryj pasek boczny" + "value": "Pobieranie pakietu aktualizacji" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Показать или скрыть боковую панель" + "value": "Загрузка пакета обновления" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Prikaži ili sakrij bočnu traku" + "value": "Preuzimanje paketa ažuriranja" } }, "ar": { "stringUnit": { "state": "translated", - "value": "إظهار أو إخفاء الشريط الجانبي" + "value": "جارٍ تنزيل حزمة التحديث" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Vis eller skjul sidepanelet" + "value": "Laster ned oppdateringspakken" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Mostrar ou ocultar a barra lateral" + "value": "Baixando o pacote de atualização" } }, "th": { "stringUnit": { "state": "translated", - "value": "แสดงหรือซ่อนแถบด้านข้าง" + "value": "กำลังดาวน์โหลดแพ็คเกจอัปเดต" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Kenar çubuğunu göster veya gizle" + "value": "Güncelleme paketi indiriliyor" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Показати або сховати бічну панель" + "value": "Завантаження пакета оновлення" } } } }, - "update.available.short": { + "update.error.appLocation.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Update Available" + "value": "App Location Issue" } }, "ja": { "stringUnit": { "state": "translated", - "value": "アップデートがあります" + "value": "アプリの場所の問題" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "有可用更新" + "value": "应用位置问题" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "有可用的更新" + "value": "App 位置問題" } }, "ko": { "stringUnit": { "state": "translated", - "value": "업데이트 사용 가능" + "value": "앱 위치 문제" } }, "de": { "stringUnit": { "state": "translated", - "value": "Update verfügbar" + "value": "Problem mit dem App-Speicherort" } }, "es": { "stringUnit": { "state": "translated", - "value": "Actualización disponible" + "value": "Problema con la ubicación de la app" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Mise à jour disponible" + "value": "Problème d'emplacement de l'app" } }, "it": { "stringUnit": { "state": "translated", - "value": "Aggiornamento disponibile" + "value": "Problema posizione app" } }, "da": { "stringUnit": { "state": "translated", - "value": "Opdatering tilgængelig" + "value": "Problem med appplacering" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Dostępna aktualizacja" + "value": "Problem z lokalizacją aplikacji" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Доступно обновление" + "value": "Проблема с расположением приложения" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Ažuriranje dostupno" + "value": "Problem s lokacijom aplikacije" } }, "ar": { "stringUnit": { "state": "translated", - "value": "تحديث متوفر" + "value": "مشكلة في موقع التطبيق" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Oppdatering tilgjengelig" + "value": "Problem med appplassering" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Atualização Disponível" + "value": "Problema com Local do App" } }, "th": { "stringUnit": { "state": "translated", - "value": "มีอัปเดตใหม่" + "value": "ปัญหาตำแหน่งแอป" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Güncelleme Mevcut" + "value": "Uygulama Konumu Sorunu" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Доступне оновлення" + "value": "Проблема з розташуванням програми" } } } }, - "update.available.withVersion": { + "update.error.connectionLost.message": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Update Available: %@" + "value": "The network connection was lost while checking for updates. Try again." } }, "ja": { "stringUnit": { "state": "translated", - "value": "アップデートあり: %@" + "value": "アップデートの確認中にネットワーク接続が切れました。もう一度お試しください。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "有可用更新:%@" + "value": "检查更新时网络连接中断。请重试。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "有可用的更新:%@" + "value": "檢查更新時網路連線中斷。請再試一次。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "업데이트 사용 가능: %@" + "value": "업데이트 확인 중 네트워크 연결이 끊어졌습니다. 다시 시도하세요." } }, "de": { "stringUnit": { "state": "translated", - "value": "Update verfügbar: %@" + "value": "Die Netzwerkverbindung wurde beim Suchen nach Updates unterbrochen. Versuchen Sie es erneut." } }, "es": { "stringUnit": { "state": "translated", - "value": "Actualización disponible: %@" + "value": "Se perdió la conexión de red al buscar actualizaciones. Inténtalo de nuevo." } }, "fr": { "stringUnit": { "state": "translated", - "value": "Mise à jour disponible : %@" + "value": "La connexion réseau a été perdue lors de la recherche de mises à jour. Réessayez." } }, "it": { "stringUnit": { "state": "translated", - "value": "Aggiornamento disponibile: %@" + "value": "La connessione di rete è stata persa durante la verifica degli aggiornamenti. Riprova." } }, "da": { "stringUnit": { "state": "translated", - "value": "Opdatering tilgængelig: %@" + "value": "Netværksforbindelsen gik tabt under søgning efter opdateringer. Prøv igen." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Dostępna aktualizacja: %@" + "value": "Połączenie sieciowe zostało utracone podczas sprawdzania aktualizacji. Spróbuj ponownie." } }, "ru": { "stringUnit": { "state": "translated", - "value": "Доступно обновление: %@" + "value": "Сетевое подключение было потеряно во время проверки обновлений. Повторите попытку." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Ažuriranje dostupno: %@" + "value": "Mrežna veza je prekinuta tokom provjere ažuriranja. Pokušajte ponovo." } }, "ar": { "stringUnit": { "state": "translated", - "value": "تحديث متوفر: %@" + "value": "انقطع اتصال الشبكة أثناء التحقق من التحديثات. حاول مجددًا." } }, "nb": { "stringUnit": { "state": "translated", - "value": "Oppdatering tilgjengelig: %@" + "value": "Nettverkstilkoblingen ble mistet under søk etter oppdateringer. Prøv igjen." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Atualização Disponível: %@" + "value": "A conexão de rede foi perdida ao verificar atualizações. Tente novamente." } }, "th": { "stringUnit": { "state": "translated", - "value": "มีอัปเดตใหม่: %@" + "value": "การเชื่อมต่อเครือข่ายขาดหายขณะตรวจหาอัปเดต ลองอีกครั้ง" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Güncelleme Mevcut: %@" + "value": "Güncellemeler denetlenirken ağ bağlantısı kesildi. Tekrar deneyin." } }, "uk": { "stringUnit": { "state": "translated", - "value": "Доступне оновлення: %@" + "value": "З'єднання з мережею було втрачено під час перевірки оновлень. Спробуйте ще раз." } } } }, - "update.checking": { + "update.error.connectionLost.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Checking for Updates…" + "value": "Connection Lost" } }, "ja": { "stringUnit": { "state": "translated", - "value": "アップデートを確認中…" + "value": "接続が切れました" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "正在检查更新..." + "value": "连接中断" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "正在檢查更新..." + "value": "連線中斷" } }, "ko": { "stringUnit": { "state": "translated", - "value": "업데이트 확인 중…" + "value": "연결 끊김" } }, "de": { "stringUnit": { "state": "translated", - "value": "Suche nach Updates …" + "value": "Verbindung unterbrochen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Buscando actualizaciones…" + "value": "Conexión perdida" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Recherche de mises à jour..." + "value": "Connexion perdue" } }, "it": { "stringUnit": { "state": "translated", - "value": "Verifica aggiornamenti in corso…" + "value": "Connessione persa" } }, "da": { "stringUnit": { "state": "translated", - "value": "Søger efter opdateringer…" + "value": "Forbindelse tabt" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Sprawdzanie aktualizacji…" + "value": "Utracono połączenie" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Проверка обновлений..." + "value": "Подключение потеряно" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Provjeravanje ažuriranja…" + "value": "Veza prekinuta" } }, "ar": { "stringUnit": { "state": "translated", - "value": "جارٍ التحقق من التحديثات…" + "value": "انقطع الاتصال" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Ser etter oppdateringer …" + "value": "Tilkobling mistet" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Verificando Atualizações…" + "value": "Conexão Perdida" } }, "th": { "stringUnit": { "state": "translated", - "value": "กำลังตรวจหาอัปเดต..." + "value": "การเชื่อมต่อขาดหาย" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Güncellemeler denetleniyor…" + "value": "Bağlantı Kesildi" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Перевірка оновлень…" + "value": "З'єднання втрачено" } } } }, - "update.configureAutoUpdates": { + "update.error.downloadFailed.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Configure automatic update preferences" + "value": "Couldn't Download Update" } }, "ja": { "stringUnit": { "state": "translated", - "value": "自動アップデートの設定" + "value": "アップデートをダウンロードできませんでした" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "配置自动更新偏好设置" + "value": "无法下载更新" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "設定自動更新偏好" + "value": "無法下載更新" } }, "ko": { "stringUnit": { "state": "translated", - "value": "자동 업데이트 환경설정 구성" + "value": "업데이트를 다운로드할 수 없습니다" } }, "de": { "stringUnit": { "state": "translated", - "value": "Einstellungen für automatische Updates konfigurieren" + "value": "Update konnte nicht heruntergeladen werden" } }, "es": { "stringUnit": { "state": "translated", - "value": "Configurar preferencias de actualización automática" + "value": "No se pudo descargar la actualización" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Configurer les préférences de mise à jour automatique" + "value": "Impossible de télécharger la mise à jour" } }, "it": { "stringUnit": { "state": "translated", - "value": "Configura le preferenze di aggiornamento automatico" + "value": "Impossibile scaricare l'aggiornamento" } }, "da": { "stringUnit": { "state": "translated", - "value": "Konfigurer præferencer for automatiske opdateringer" + "value": "Kunne ikke downloade opdatering" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Skonfiguruj preferencje automatycznych aktualizacji" + "value": "Nie udało się pobrać aktualizacji" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Настроить параметры автоматических обновлений" + "value": "Не удалось загрузить обновление" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Konfigurišite postavke automatskog ažuriranja" + "value": "Nije moguće preuzeti ažuriranje" } }, "ar": { "stringUnit": { "state": "translated", - "value": "تكوين تفضيلات التحديث التلقائي" + "value": "تعذر تنزيل التحديث" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Konfigurer innstillinger for automatiske oppdateringer" + "value": "Kunne ikke laste ned oppdatering" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Configurar preferências de atualização automática" + "value": "Não Foi Possível Baixar a Atualização" } }, "th": { "stringUnit": { "state": "translated", - "value": "กำหนดค่าการอัปเดตอัตโนมัติ" + "value": "ไม่สามารถดาวน์โหลดอัปเดตได้" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Otomatik güncelleme tercihlerini yapılandır" + "value": "Güncelleme İndirilemedi" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Налаштувати параметри автоматичного оновлення" + "value": "Не вдалося завантажити оновлення" } } } }, - "update.downloadAndInstall": { + "update.error.failed.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Download and install the latest version" + "value": "Update Failed" } }, "ja": { "stringUnit": { "state": "translated", - "value": "最新バージョンをダウンロードしてインストール" + "value": "アップデートに失敗しました" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "下载并安装最新版本" + "value": "更新失败" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "下載並安裝最新版本" + "value": "更新失敗" } }, "ko": { "stringUnit": { "state": "translated", - "value": "최신 버전 다운로드 및 설치" + "value": "업데이트 실패" } }, "de": { "stringUnit": { "state": "translated", - "value": "Neueste Version herunterladen und installieren" + "value": "Update fehlgeschlagen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Descargar e instalar la última versión" + "value": "Error de actualización" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Télécharger et installer la dernière version" + "value": "Échec de la mise à jour" } }, "it": { "stringUnit": { "state": "translated", - "value": "Scarica e installa l'ultima versione" + "value": "Aggiornamento non riuscito" } }, "da": { "stringUnit": { "state": "translated", - "value": "Download og installer den seneste version" + "value": "Opdatering mislykkedes" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Pobierz i zainstaluj najnowszą wersję" + "value": "Aktualizacja nie powiodła się" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Загрузить и установить последнюю версию" + "value": "Ошибка обновления" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Preuzmite i instalirajte najnoviju verziju" + "value": "Ažuriranje nije uspjelo" } }, "ar": { "stringUnit": { "state": "translated", - "value": "تنزيل وتثبيت أحدث إصدار" + "value": "فشل التحديث" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Last ned og installer den nyeste versjonen" + "value": "Oppdatering mislyktes" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Baixar e instalar a versão mais recente" + "value": "Falha na Atualização" } }, "th": { "stringUnit": { "state": "translated", - "value": "ดาวน์โหลดและติดตั้งเวอร์ชันล่าสุด" + "value": "การอัปเดตล้มเหลว" } }, "tr": { "stringUnit": { "state": "translated", - "value": "En son sürümü indir ve yükle" + "value": "Güncelleme Başarısız" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Завантажити та встановити найновішу версію" + "value": "Помилка оновлення" } } } }, - "update.downloading.progress": { + "update.error.feedDownload.message": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Downloading: %@" + "value": "cmux couldn't download the update feed. Check your connection and try again." } }, "ja": { "stringUnit": { "state": "translated", - "value": "ダウンロード中: %@" + "value": "cmux はアップデートフィードをダウンロードできませんでした。接続を確認してもう一度お試しください。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "正在下载:%@" + "value": "cmux 无法下载更新源。请检查网络连接后重试。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "正在下載:%@" + "value": "cmux 無法下載更新來源。請檢查您的連線後再試一次。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "다운로드 중: %@" + "value": "cmux에서 업데이트 피드를 다운로드할 수 없습니다. 연결을 확인하고 다시 시도하세요." } }, "de": { "stringUnit": { "state": "translated", - "value": "Herunterladen: %@" + "value": "cmux konnte den Update-Feed nicht herunterladen. Überprüfen Sie Ihre Verbindung und versuchen Sie es erneut." } }, "es": { "stringUnit": { "state": "translated", - "value": "Descargando: %@" + "value": "cmux no pudo descargar la fuente de actualizaciones. Comprueba tu conexión e inténtalo de nuevo." } }, "fr": { "stringUnit": { "state": "translated", - "value": "Téléchargement : %@" + "value": "cmux n'a pas pu télécharger le flux de mises à jour. Vérifiez votre connexion et réessayez." } }, "it": { "stringUnit": { "state": "translated", - "value": "Download: %@" + "value": "cmux non è riuscito a scaricare il feed degli aggiornamenti. Controlla la connessione e riprova." } }, "da": { "stringUnit": { "state": "translated", - "value": "Downloader: %@" + "value": "cmux kunne ikke downloade opdateringsfeedet. Kontroller din forbindelse, og prøv igen." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Pobieranie: %@" + "value": "cmux nie mógł pobrać kanału aktualizacji. Sprawdź połączenie i spróbuj ponownie." } }, "ru": { "stringUnit": { "state": "translated", - "value": "Загрузка: %@" + "value": "cmux не удалось загрузить канал обновлений. Проверьте подключение и повторите попытку." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Preuzimanje: %@" + "value": "cmux nije mogao preuzeti feed ažuriranja. Provjerite vezu i pokušajte ponovo." } }, "ar": { "stringUnit": { "state": "translated", - "value": "جارٍ التنزيل: %@" + "value": "تعذر على cmux تنزيل موجز التحديثات. تحقق من اتصالك وحاول مجددًا." } }, "nb": { "stringUnit": { "state": "translated", - "value": "Laster ned: %@" + "value": "cmux kunne ikke laste ned oppdateringsfeeden. Kontroller tilkoblingen og prøv igjen." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Baixando: %@" + "value": "O cmux não conseguiu baixar o feed de atualização. Verifique sua conexão e tente novamente." } }, "th": { "stringUnit": { "state": "translated", - "value": "กำลังดาวน์โหลด: %@" + "value": "cmux ไม่สามารถดาวน์โหลดฟีดอัปเดตได้ ตรวจสอบการเชื่อมต่อแล้วลองอีกครั้ง" } }, "tr": { "stringUnit": { "state": "translated", - "value": "İndiriliyor: %@" + "value": "cmux güncelleme akışını indiremedi. Bağlantınızı kontrol edip tekrar deneyin." } }, "uk": { "stringUnit": { "state": "translated", - "value": "Завантаження: %@" + "value": "cmux не зміг завантажити стрічку оновлень. Перевірте підключення та спробуйте ще раз." } } } }, - "update.downloading.status": { + "update.error.feedError.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Downloading…" + "value": "Update Feed Error" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ダウンロード中…" + "value": "アップデートフィードエラー" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "正在下载..." + "value": "更新源错误" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "下載中..." + "value": "更新來源錯誤" } }, "ko": { "stringUnit": { "state": "translated", - "value": "다운로드 중…" + "value": "업데이트 피드 오류" } }, "de": { "stringUnit": { "state": "translated", - "value": "Wird heruntergeladen …" + "value": "Fehler im Update-Feed" } }, "es": { "stringUnit": { "state": "translated", - "value": "Descargando…" + "value": "Error en la fuente de actualizaciones" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Téléchargement..." + "value": "Erreur du flux de mises à jour" } }, "it": { "stringUnit": { "state": "translated", - "value": "Download in corso…" + "value": "Errore feed aggiornamento" } }, "da": { "stringUnit": { "state": "translated", - "value": "Downloader…" + "value": "Fejl i opdateringsfeed" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Pobieranie…" + "value": "Błąd kanału aktualizacji" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Загрузка..." + "value": "Ошибка канала обновлений" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Preuzimanje…" + "value": "Greška feeda ažuriranja" } }, "ar": { "stringUnit": { "state": "translated", - "value": "جارٍ التنزيل…" + "value": "خطأ في موجز التحديثات" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Laster ned …" + "value": "Feil i oppdateringsfeed" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Baixando…" + "value": "Erro no Feed de Atualização" } }, "th": { "stringUnit": { "state": "translated", - "value": "กำลังดาวน์โหลด..." + "value": "ข้อผิดพลาดฟีดอัปเดต" } }, "tr": { "stringUnit": { "state": "translated", - "value": "İndiriliyor…" + "value": "Güncelleme Akışı Hatası" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Завантаження…" + "value": "Помилка стрічки оновлень" } } } }, - "update.downloadingPackage": { + "update.error.feedRead.message": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Downloading the update package" + "value": "The update feed could not be read. Please try again later." } }, "ja": { "stringUnit": { "state": "translated", - "value": "アップデートパッケージをダウンロード中" + "value": "アップデートフィードを読み取れませんでした。後でもう一度お試しください。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "正在下载更新包" + "value": "无法读取更新源。请稍后重试。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "正在下載更新套件" + "value": "無法讀取更新來源。請稍後再試。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "업데이트 패키지 다운로드 중" + "value": "업데이트 피드를 읽을 수 없습니다. 나중에 다시 시도하세요." } }, "de": { "stringUnit": { "state": "translated", - "value": "Update-Paket wird heruntergeladen" + "value": "Der Update-Feed konnte nicht gelesen werden. Bitte versuchen Sie es später erneut." } }, "es": { "stringUnit": { "state": "translated", - "value": "Descargando el paquete de actualización" + "value": "No se pudo leer la fuente de actualizaciones. Inténtalo de nuevo más tarde." } }, "fr": { "stringUnit": { "state": "translated", - "value": "Téléchargement du paquet de mise à jour" + "value": "Le flux de mises à jour n'a pas pu être lu. Veuillez réessayer plus tard." } }, "it": { "stringUnit": { "state": "translated", - "value": "Download del pacchetto di aggiornamento" + "value": "Impossibile leggere il feed degli aggiornamenti. Riprova più tardi." } }, "da": { "stringUnit": { "state": "translated", - "value": "Downloader opdateringspakken" + "value": "Opdateringsfeedet kunne ikke læses. Prøv igen senere." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Pobieranie pakietu aktualizacji" + "value": "Nie można odczytać kanału aktualizacji. Spróbuj ponownie później." } }, "ru": { "stringUnit": { "state": "translated", - "value": "Загрузка пакета обновления" + "value": "Не удалось прочитать канал обновлений. Повторите попытку позже." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Preuzimanje paketa ažuriranja" + "value": "Feed ažuriranja nije moguće pročitati. Pokušajte ponovo kasnije." } }, "ar": { "stringUnit": { "state": "translated", - "value": "جارٍ تنزيل حزمة التحديث" + "value": "تعذر قراءة موجز التحديثات. يرجى المحاولة لاحقًا." } }, "nb": { "stringUnit": { "state": "translated", - "value": "Laster ned oppdateringspakken" + "value": "Oppdateringsfeeden kunne ikke leses. Prøv igjen senere." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Baixando o pacote de atualização" + "value": "O feed de atualização não pôde ser lido. Tente novamente mais tarde." } }, "th": { "stringUnit": { "state": "translated", - "value": "กำลังดาวน์โหลดแพ็คเกจอัปเดต" + "value": "ไม่สามารถอ่านฟีดอัปเดตได้ กรุณาลองอีกครั้งในภายหลัง" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Güncelleme paketi indiriliyor" + "value": "Güncelleme akışı okunamadı. Lütfen daha sonra tekrar deneyin." } }, "uk": { "stringUnit": { "state": "translated", - "value": "Завантаження пакета оновлення" + "value": "Не вдалося прочитати стрічку оновлень. Спробуйте пізніше." } } } }, - "update.error.appLocation.title": { + "update.error.insecureFeed.message": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "App Location Issue" + "value": "The update feed is insecure. Please contact support." } }, "ja": { "stringUnit": { "state": "translated", - "value": "アプリの場所の問題" + "value": "アップデートフィードが安全ではありません。サポートにお問い合わせください。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "应用位置问题" + "value": "更新源不安全。请联系支持团队。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "App 位置問題" + "value": "更新來源不安全。請聯絡支援團隊。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "앱 위치 문제" + "value": "업데이트 피드가 안전하지 않습니다. 지원팀에 문의하세요." } }, "de": { "stringUnit": { "state": "translated", - "value": "Problem mit dem App-Speicherort" + "value": "Der Update-Feed ist unsicher. Bitte kontaktieren Sie den Support." } }, "es": { "stringUnit": { "state": "translated", - "value": "Problema con la ubicación de la app" + "value": "La fuente de actualizaciones no es segura. Contacta con soporte." } }, "fr": { "stringUnit": { "state": "translated", - "value": "Problème d'emplacement de l'app" + "value": "Le flux de mises à jour n'est pas sécurisé. Veuillez contacter le support." } }, "it": { "stringUnit": { "state": "translated", - "value": "Problema posizione app" + "value": "Il feed degli aggiornamenti non è sicuro. Contatta il supporto." } }, "da": { "stringUnit": { "state": "translated", - "value": "Problem med appplacering" + "value": "Opdateringsfeedet er usikkert. Kontakt venligst supporten." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Problem z lokalizacją aplikacji" + "value": "Kanał aktualizacji nie jest bezpieczny. Skontaktuj się ze wsparciem." } }, "ru": { "stringUnit": { "state": "translated", - "value": "Проблема с расположением приложения" + "value": "Канал обновлений не защищен. Обратитесь в службу поддержки." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Problem s lokacijom aplikacije" + "value": "Feed ažuriranja nije siguran. Kontaktirajte podršku." } }, "ar": { "stringUnit": { "state": "translated", - "value": "مشكلة في موقع التطبيق" + "value": "موجز التحديثات غير آمن. يرجى الاتصال بالدعم." } }, "nb": { "stringUnit": { "state": "translated", - "value": "Problem med appplassering" + "value": "Oppdateringsfeeden er usikker. Kontakt brukerstøtte." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Problema com Local do App" + "value": "O feed de atualização é inseguro. Entre em contato com o suporte." } }, "th": { "stringUnit": { "state": "translated", - "value": "ปัญหาตำแหน่งแอป" + "value": "ฟีดอัปเดตไม่ปลอดภัย กรุณาติดต่อฝ่ายสนับสนุน" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Uygulama Konumu Sorunu" + "value": "Güncelleme akışı güvensiz. Lütfen destekle iletişime geçin." } }, "uk": { "stringUnit": { "state": "translated", - "value": "Проблема з розташуванням програми" + "value": "Стрічка оновлень незахищена. Зверніться до служби підтримки." } } } }, - "update.error.connectionLost.message": { + "update.error.insecureFeed.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "The network connection was lost while checking for updates. Try again." + "value": "Insecure Update Feed" } }, "ja": { "stringUnit": { "state": "translated", - "value": "アップデートの確認中にネットワーク接続が切れました。もう一度お試しください。" + "value": "安全でないアップデートフィード" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "检查更新时网络连接中断。请重试。" + "value": "不安全的更新源" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "檢查更新時網路連線中斷。請再試一次。" + "value": "不安全的更新來源" } }, "ko": { "stringUnit": { "state": "translated", - "value": "업데이트 확인 중 네트워크 연결이 끊어졌습니다. 다시 시도하세요." + "value": "안전하지 않은 업데이트 피드" } }, "de": { "stringUnit": { "state": "translated", - "value": "Die Netzwerkverbindung wurde beim Suchen nach Updates unterbrochen. Versuchen Sie es erneut." + "value": "Unsicherer Update-Feed" } }, "es": { "stringUnit": { "state": "translated", - "value": "Se perdió la conexión de red al buscar actualizaciones. Inténtalo de nuevo." + "value": "Fuente de actualizaciones insegura" } }, "fr": { "stringUnit": { "state": "translated", - "value": "La connexion réseau a été perdue lors de la recherche de mises à jour. Réessayez." + "value": "Flux de mises à jour non sécurisé" } }, "it": { "stringUnit": { "state": "translated", - "value": "La connessione di rete è stata persa durante la verifica degli aggiornamenti. Riprova." + "value": "Feed aggiornamento non sicuro" } }, "da": { "stringUnit": { "state": "translated", - "value": "Netværksforbindelsen gik tabt under søgning efter opdateringer. Prøv igen." + "value": "Usikkert opdateringsfeed" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Połączenie sieciowe zostało utracone podczas sprawdzania aktualizacji. Spróbuj ponownie." + "value": "Niezabezpieczony kanał aktualizacji" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Сетевое подключение было потеряно во время проверки обновлений. Повторите попытку." + "value": "Незащищенный канал обновлений" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Mrežna veza je prekinuta tokom provjere ažuriranja. Pokušajte ponovo." + "value": "Nesiguran feed ažuriranja" } }, "ar": { "stringUnit": { "state": "translated", - "value": "انقطع اتصال الشبكة أثناء التحقق من التحديثات. حاول مجددًا." + "value": "موجز تحديثات غير آمن" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Nettverkstilkoblingen ble mistet under søk etter oppdateringer. Prøv igjen." + "value": "Usikker oppdateringsfeed" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "A conexão de rede foi perdida ao verificar atualizações. Tente novamente." + "value": "Feed de Atualização Inseguro" } }, "th": { "stringUnit": { "state": "translated", - "value": "การเชื่อมต่อเครือข่ายขาดหายขณะตรวจหาอัปเดต ลองอีกครั้ง" + "value": "ฟีดอัปเดตไม่ปลอดภัย" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Güncellemeler denetlenirken ağ bağlantısı kesildi. Tekrar deneyin." + "value": "Güvensiz Güncelleme Akışı" } }, "uk": { "stringUnit": { "state": "translated", - "value": "З'єднання з мережею було втрачено під час перевірки оновлень. Спробуйте ще раз." + "value": "Незахищена стрічка оновлень" } } } }, - "update.error.connectionLost.title": { + "update.error.invalidFeed.message": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Connection Lost" + "value": "The update feed URL is invalid. Please contact support." } }, "ja": { "stringUnit": { "state": "translated", - "value": "接続が切れました" + "value": "アップデートフィードのURLが無効です。サポートにお問い合わせください。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "连接中断" + "value": "更新源 URL 无效。请联系支持团队。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "連線中斷" + "value": "更新來源 URL 無效。請聯絡支援團隊。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "연결 끊김" + "value": "업데이트 피드 URL이 유효하지 않습니다. 지원팀에 문의하세요." } }, "de": { "stringUnit": { "state": "translated", - "value": "Verbindung unterbrochen" + "value": "Die URL des Update-Feeds ist ungültig. Bitte kontaktieren Sie den Support." } }, "es": { "stringUnit": { "state": "translated", - "value": "Conexión perdida" + "value": "La URL de la fuente de actualizaciones no es válida. Contacta con soporte." } }, "fr": { "stringUnit": { "state": "translated", - "value": "Connexion perdue" + "value": "L'URL du flux de mises à jour n'est pas valide. Veuillez contacter le support." } }, "it": { "stringUnit": { "state": "translated", - "value": "Connessione persa" + "value": "L'URL del feed degli aggiornamenti non è valido. Contatta il supporto." } }, "da": { "stringUnit": { "state": "translated", - "value": "Forbindelse tabt" + "value": "URL'en til opdateringsfeedet er ugyldig. Kontakt venligst supporten." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Utracono połączenie" + "value": "Adres URL kanału aktualizacji jest nieprawidłowy. Skontaktuj się ze wsparciem." } }, "ru": { "stringUnit": { "state": "translated", - "value": "Подключение потеряно" + "value": "URL канала обновлений недействителен. Обратитесь в службу поддержки." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Veza prekinuta" + "value": "URL feeda ažuriranja je nevažeći. Kontaktirajte podršku." } }, "ar": { "stringUnit": { "state": "translated", - "value": "انقطع الاتصال" + "value": "عنوان URL لموجز التحديثات غير صالح. يرجى الاتصال بالدعم." } }, "nb": { "stringUnit": { "state": "translated", - "value": "Tilkobling mistet" + "value": "URL-en for oppdateringsfeeden er ugyldig. Kontakt brukerstøtte." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Conexão Perdida" + "value": "A URL do feed de atualização é inválida. Entre em contato com o suporte." } }, "th": { "stringUnit": { "state": "translated", - "value": "การเชื่อมต่อขาดหาย" + "value": "URL ฟีดอัปเดตไม่ถูกต้อง กรุณาติดต่อฝ่ายสนับสนุน" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Bağlantı Kesildi" + "value": "Güncelleme akışı URL'si geçersiz. Lütfen destekle iletişime geçin." } }, "uk": { "stringUnit": { "state": "translated", - "value": "З'єднання втрачено" + "value": "URL стрічки оновлень недійсний. Зверніться до служби підтримки." } } } }, - "update.error.downloadFailed.title": { + "update.error.invalidFeed.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Couldn't Download Update" + "value": "Invalid Update Feed" } }, "ja": { "stringUnit": { "state": "translated", - "value": "アップデートをダウンロードできませんでした" + "value": "無効なアップデートフィード" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "无法下载更新" + "value": "无效的更新源" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "無法下載更新" + "value": "無效的更新來源" } }, "ko": { "stringUnit": { "state": "translated", - "value": "업데이트를 다운로드할 수 없습니다" + "value": "유효하지 않은 업데이트 피드" } }, "de": { "stringUnit": { "state": "translated", - "value": "Update konnte nicht heruntergeladen werden" + "value": "Ungültiger Update-Feed" } }, "es": { "stringUnit": { "state": "translated", - "value": "No se pudo descargar la actualización" + "value": "Fuente de actualizaciones no válida" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Impossible de télécharger la mise à jour" + "value": "Flux de mises à jour non valide" } }, "it": { "stringUnit": { "state": "translated", - "value": "Impossibile scaricare l'aggiornamento" + "value": "Feed aggiornamento non valido" } }, "da": { "stringUnit": { "state": "translated", - "value": "Kunne ikke downloade opdatering" + "value": "Ugyldigt opdateringsfeed" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Nie udało się pobrać aktualizacji" + "value": "Nieprawidłowy kanał aktualizacji" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Не удалось загрузить обновление" + "value": "Недействительный канал обновлений" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Nije moguće preuzeti ažuriranje" + "value": "Nevažeći feed ažuriranja" } }, "ar": { "stringUnit": { "state": "translated", - "value": "تعذر تنزيل التحديث" + "value": "موجز تحديثات غير صالح" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Kunne ikke laste ned oppdatering" + "value": "Ugyldig oppdateringsfeed" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Não Foi Possível Baixar a Atualização" + "value": "Feed de Atualização Inválido" } }, "th": { "stringUnit": { "state": "translated", - "value": "ไม่สามารถดาวน์โหลดอัปเดตได้" + "value": "ฟีดอัปเดตไม่ถูกต้อง" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Güncelleme İndirilemedi" + "value": "Geçersiz Güncelleme Akışı" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Не вдалося завантажити оновлення" + "value": "Недійсна стрічка оновлень" } } } }, - "update.error.failed.title": { + "update.error.noInternet.message": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Update Failed" + "value": "cmux can't reach the update server. Check your internet connection and try again." } }, "ja": { "stringUnit": { "state": "translated", - "value": "アップデートに失敗しました" + "value": "cmux はアップデートサーバーに接続できません。インターネット接続を確認してもう一度お試しください。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "更新失败" + "value": "cmux 无法连接到更新服务器。请检查互联网连接后重试。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "更新失敗" + "value": "cmux 無法連線至更新伺服器。請檢查您的網際網路連線後再試一次。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "업데이트 실패" + "value": "cmux에서 업데이트 서버에 연결할 수 없습니다. 인터넷 연결을 확인하고 다시 시도하세요." } }, "de": { "stringUnit": { "state": "translated", - "value": "Update fehlgeschlagen" + "value": "cmux kann den Update-Server nicht erreichen. Überprüfen Sie Ihre Internetverbindung und versuchen Sie es erneut." } }, "es": { "stringUnit": { "state": "translated", - "value": "Error de actualización" + "value": "cmux no puede acceder al servidor de actualizaciones. Comprueba tu conexión a internet e inténtalo de nuevo." } }, "fr": { "stringUnit": { "state": "translated", - "value": "Échec de la mise à jour" + "value": "cmux ne peut pas atteindre le serveur de mises à jour. Vérifiez votre connexion Internet et réessayez." } }, "it": { "stringUnit": { "state": "translated", - "value": "Aggiornamento non riuscito" + "value": "cmux non riesce a raggiungere il server degli aggiornamenti. Controlla la connessione a internet e riprova." } }, "da": { "stringUnit": { "state": "translated", - "value": "Opdatering mislykkedes" + "value": "cmux kan ikke nå opdateringsserveren. Kontroller din internetforbindelse, og prøv igen." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Aktualizacja nie powiodła się" + "value": "cmux nie może połączyć się z serwerem aktualizacji. Sprawdź połączenie z internetem i spróbuj ponownie." } }, "ru": { "stringUnit": { "state": "translated", - "value": "Ошибка обновления" + "value": "cmux не может связаться с сервером обновлений. Проверьте подключение к интернету и повторите попытку." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Ažuriranje nije uspjelo" + "value": "cmux ne može dosegnuti server za ažuriranje. Provjerite internetsku vezu i pokušajte ponovo." } }, "ar": { "stringUnit": { "state": "translated", - "value": "فشل التحديث" + "value": "لا يمكن لـ cmux الوصول إلى خادم التحديثات. تحقق من اتصال الإنترنت وحاول مجددًا." } }, "nb": { "stringUnit": { "state": "translated", - "value": "Oppdatering mislyktes" + "value": "cmux kan ikke nå oppdateringsserveren. Kontroller internettforbindelsen og prøv igjen." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Falha na Atualização" + "value": "O cmux não consegue acessar o servidor de atualização. Verifique sua conexão com a internet e tente novamente." } }, "th": { "stringUnit": { "state": "translated", - "value": "การอัปเดตล้มเหลว" + "value": "cmux ไม่สามารถเข้าถึงเซิร์ฟเวอร์อัปเดตได้ ตรวจสอบการเชื่อมต่ออินเทอร์เน็ตแล้วลองอีกครั้ง" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Güncelleme Başarısız" + "value": "cmux güncelleme sunucusuna ulaşamıyor. İnternet bağlantınızı kontrol edip tekrar deneyin." } }, "uk": { "stringUnit": { "state": "translated", - "value": "Помилка оновлення" + "value": "cmux не може зв'язатися з сервером оновлень. Перевірте підключення до інтернету та спробуйте ще раз." } } } }, - "update.error.feedDownload.message": { + "update.error.noInternet.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "cmux couldn't download the update feed. Check your connection and try again." + "value": "No Internet Connection" } }, "ja": { "stringUnit": { "state": "translated", - "value": "cmux はアップデートフィードをダウンロードできませんでした。接続を確認してもう一度お試しください。" + "value": "インターネット接続がありません" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "cmux 无法下载更新源。请检查网络连接后重试。" + "value": "无互联网连接" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "cmux 無法下載更新來源。請檢查您的連線後再試一次。" + "value": "沒有網際網路連線" } }, "ko": { "stringUnit": { "state": "translated", - "value": "cmux에서 업데이트 피드를 다운로드할 수 없습니다. 연결을 확인하고 다시 시도하세요." + "value": "인터넷 연결 없음" } }, "de": { "stringUnit": { "state": "translated", - "value": "cmux konnte den Update-Feed nicht herunterladen. Überprüfen Sie Ihre Verbindung und versuchen Sie es erneut." + "value": "Keine Internetverbindung" } }, "es": { "stringUnit": { "state": "translated", - "value": "cmux no pudo descargar la fuente de actualizaciones. Comprueba tu conexión e inténtalo de nuevo." + "value": "Sin conexión a internet" } }, "fr": { "stringUnit": { "state": "translated", - "value": "cmux n'a pas pu télécharger le flux de mises à jour. Vérifiez votre connexion et réessayez." + "value": "Aucune connexion Internet" } }, "it": { "stringUnit": { "state": "translated", - "value": "cmux non è riuscito a scaricare il feed degli aggiornamenti. Controlla la connessione e riprova." + "value": "Nessuna connessione a internet" } }, "da": { "stringUnit": { "state": "translated", - "value": "cmux kunne ikke downloade opdateringsfeedet. Kontroller din forbindelse, og prøv igen." + "value": "Ingen internetforbindelse" } }, "pl": { "stringUnit": { "state": "translated", - "value": "cmux nie mógł pobrać kanału aktualizacji. Sprawdź połączenie i spróbuj ponownie." + "value": "Brak połączenia z internetem" } }, "ru": { "stringUnit": { "state": "translated", - "value": "cmux не удалось загрузить канал обновлений. Проверьте подключение и повторите попытку." + "value": "Нет подключения к интернету" } }, "bs": { "stringUnit": { "state": "translated", - "value": "cmux nije mogao preuzeti feed ažuriranja. Provjerite vezu i pokušajte ponovo." + "value": "Nema internetske veze" } }, "ar": { "stringUnit": { "state": "translated", - "value": "تعذر على cmux تنزيل موجز التحديثات. تحقق من اتصالك وحاول مجددًا." + "value": "لا يوجد اتصال بالإنترنت" } }, "nb": { "stringUnit": { "state": "translated", - "value": "cmux kunne ikke laste ned oppdateringsfeeden. Kontroller tilkoblingen og prøv igjen." + "value": "Ingen internettforbindelse" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "O cmux não conseguiu baixar o feed de atualização. Verifique sua conexão e tente novamente." + "value": "Sem Conexão com a Internet" } }, "th": { "stringUnit": { "state": "translated", - "value": "cmux ไม่สามารถดาวน์โหลดฟีดอัปเดตได้ ตรวจสอบการเชื่อมต่อแล้วลองอีกครั้ง" + "value": "ไม่มีการเชื่อมต่ออินเทอร์เน็ต" } }, "tr": { "stringUnit": { "state": "translated", - "value": "cmux güncelleme akışını indiremedi. Bağlantınızı kontrol edip tekrar deneyin." + "value": "İnternet Bağlantısı Yok" } }, "uk": { "stringUnit": { "state": "translated", - "value": "cmux не зміг завантажити стрічку оновлень. Перевірте підключення та спробуйте ще раз." + "value": "Немає підключення до інтернету" } } } }, - "update.error.feedError.title": { + "update.error.permissionError.message": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Update Feed Error" + "value": "Move cmux into Applications and relaunch to enable updates." } }, "ja": { "stringUnit": { "state": "translated", - "value": "アップデートフィードエラー" + "value": "アップデートを有効にするには、cmux を「アプリケーション」に移動して再起動してください。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "更新源错误" + "value": "请将 cmux 移到「应用程序」文件夹中,然后重新启动以启用更新。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "更新來源錯誤" + "value": "請將 cmux 移至「應用程式」資料夾並重新啟動,以啟用更新。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "업데이트 피드 오류" + "value": "cmux를 응용 프로그램 폴더로 이동하고 재실행하여 업데이트를 활성화하세요." } }, "de": { "stringUnit": { "state": "translated", - "value": "Fehler im Update-Feed" + "value": "Verschieben Sie cmux in den Ordner 'Programme' und starten Sie die App neu, um Updates zu aktivieren." } }, "es": { "stringUnit": { "state": "translated", - "value": "Error en la fuente de actualizaciones" + "value": "Mueve cmux a Aplicaciones y vuelve a iniciarlo para activar las actualizaciones." } }, "fr": { "stringUnit": { "state": "translated", - "value": "Erreur du flux de mises à jour" + "value": "Déplacez cmux dans Applications et relancez pour activer les mises à jour." } }, "it": { "stringUnit": { "state": "translated", - "value": "Errore feed aggiornamento" + "value": "Sposta cmux nella cartella Applicazioni e riavvia per abilitare gli aggiornamenti." } }, "da": { "stringUnit": { "state": "translated", - "value": "Fejl i opdateringsfeed" + "value": "Flyt cmux til Programmer, og genstart for at aktivere opdateringer." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Błąd kanału aktualizacji" + "value": "Przenieś cmux do folderu Aplikacje i uruchom ponownie, aby włączyć aktualizacje." } }, "ru": { "stringUnit": { "state": "translated", - "value": "Ошибка канала обновлений" + "value": "Переместите cmux в папку «Программы» и перезапустите для включения обновлений." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Greška feeda ažuriranja" + "value": "Premjestite cmux u Applications i ponovo pokrenite da biste omogućili ažuriranja." } }, "ar": { "stringUnit": { "state": "translated", - "value": "خطأ في موجز التحديثات" + "value": "انقل cmux إلى مجلد التطبيقات وأعد التشغيل لتفعيل التحديثات." } }, "nb": { "stringUnit": { "state": "translated", - "value": "Feil i oppdateringsfeed" + "value": "Flytt cmux til Programmer og start på nytt for å aktivere oppdateringer." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Erro no Feed de Atualização" + "value": "Mova o cmux para Aplicativos e reinicie para ativar as atualizações." } }, "th": { "stringUnit": { "state": "translated", - "value": "ข้อผิดพลาดฟีดอัปเดต" + "value": "ย้าย cmux ไปที่โฟลเดอร์ Applications แล้วเปิดใหม่เพื่อเปิดใช้งานการอัปเดต" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Güncelleme Akışı Hatası" + "value": "Güncellemeleri etkinleştirmek için cmux'u Uygulamalar klasörüne taşıyıp yeniden başlatın." } }, "uk": { "stringUnit": { "state": "translated", - "value": "Помилка стрічки оновлень" + "value": "Перемістіть cmux до теки Програми та перезапустіть для увімкнення оновлень." } } } }, - "update.error.feedRead.message": { + "update.error.permissionError.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "The update feed could not be read. Please try again later." + "value": "Updater Permission Error" } }, "ja": { "stringUnit": { "state": "translated", - "value": "アップデートフィードを読み取れませんでした。後でもう一度お試しください。" + "value": "アップデーター権限エラー" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "无法读取更新源。请稍后重试。" + "value": "更新程序权限错误" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "無法讀取更新來源。請稍後再試。" + "value": "更新程式權限錯誤" } }, "ko": { "stringUnit": { "state": "translated", - "value": "업데이트 피드를 읽을 수 없습니다. 나중에 다시 시도하세요." + "value": "업데이터 권한 오류" } }, "de": { "stringUnit": { "state": "translated", - "value": "Der Update-Feed konnte nicht gelesen werden. Bitte versuchen Sie es später erneut." + "value": "Berechtigungsfehler des Updaters" } }, "es": { "stringUnit": { "state": "translated", - "value": "No se pudo leer la fuente de actualizaciones. Inténtalo de nuevo más tarde." + "value": "Error de permisos del actualizador" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Le flux de mises à jour n'a pas pu être lu. Veuillez réessayer plus tard." + "value": "Erreur de permissions du programme de mise à jour" } }, "it": { "stringUnit": { "state": "translated", - "value": "Impossibile leggere il feed degli aggiornamenti. Riprova più tardi." + "value": "Errore di autorizzazione dell'aggiornamento" } }, "da": { "stringUnit": { "state": "translated", - "value": "Opdateringsfeedet kunne ikke læses. Prøv igen senere." + "value": "Fejl i opdateringstilladelse" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Nie można odczytać kanału aktualizacji. Spróbuj ponownie później." + "value": "Błąd uprawnień aktualizatora" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Не удалось прочитать канал обновлений. Повторите попытку позже." + "value": "Ошибка прав доступа программы обновления" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Feed ažuriranja nije moguće pročitati. Pokušajte ponovo kasnije." + "value": "Greška dozvole za ažuriranje" } }, "ar": { "stringUnit": { "state": "translated", - "value": "تعذر قراءة موجز التحديثات. يرجى المحاولة لاحقًا." + "value": "خطأ في صلاحيات المحدّث" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Oppdateringsfeeden kunne ikke leses. Prøv igjen senere." + "value": "Tillatelsessfeil for oppdatering" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "O feed de atualização não pôde ser lido. Tente novamente mais tarde." + "value": "Erro de Permissão do Atualizador" } }, "th": { "stringUnit": { "state": "translated", - "value": "ไม่สามารถอ่านฟีดอัปเดตได้ กรุณาลองอีกครั้งในภายหลัง" + "value": "ข้อผิดพลาดสิทธิ์ตัวอัปเดต" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Güncelleme akışı okunamadı. Lütfen daha sonra tekrar deneyin." + "value": "Güncelleyici İzin Hatası" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Не вдалося прочитати стрічку оновлень. Спробуйте пізніше." + "value": "Помилка прав доступу оновлювача" } } } }, - "update.error.insecureFeed.message": { + "update.error.secureConnectionFailed.message": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "The update feed is insecure. Please contact support." + "value": "A secure connection to the update server couldn't be established. Try again later." } }, "ja": { "stringUnit": { "state": "translated", - "value": "アップデートフィードが安全ではありません。サポートにお問い合わせください。" + "value": "アップデートサーバーへのセキュア接続を確立できませんでした。後でもう一度お試しください。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "更新源不安全。请联系支持团队。" + "value": "无法与更新服务器建立安全连接。请稍后重试。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "更新來源不安全。請聯絡支援團隊。" + "value": "無法建立與更新伺服器的安全連線。請稍後再試。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "업데이트 피드가 안전하지 않습니다. 지원팀에 문의하세요." + "value": "업데이트 서버에 대한 보안 연결을 설정할 수 없습니다. 나중에 다시 시도하세요." } }, "de": { "stringUnit": { "state": "translated", - "value": "Der Update-Feed ist unsicher. Bitte kontaktieren Sie den Support." + "value": "Es konnte keine sichere Verbindung zum Update-Server hergestellt werden. Versuchen Sie es später erneut." } }, "es": { "stringUnit": { "state": "translated", - "value": "La fuente de actualizaciones no es segura. Contacta con soporte." + "value": "No se pudo establecer una conexión segura con el servidor de actualizaciones. Inténtalo de nuevo más tarde." } }, "fr": { "stringUnit": { "state": "translated", - "value": "Le flux de mises à jour n'est pas sécurisé. Veuillez contacter le support." + "value": "Impossible d'établir une connexion sécurisée avec le serveur de mises à jour. Réessayez plus tard." } }, "it": { "stringUnit": { "state": "translated", - "value": "Il feed degli aggiornamenti non è sicuro. Contatta il supporto." + "value": "Impossibile stabilire una connessione sicura al server degli aggiornamenti. Riprova più tardi." } }, "da": { "stringUnit": { "state": "translated", - "value": "Opdateringsfeedet er usikkert. Kontakt venligst supporten." + "value": "En sikker forbindelse til opdateringsserveren kunne ikke oprettes. Prøv igen senere." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Kanał aktualizacji nie jest bezpieczny. Skontaktuj się ze wsparciem." + "value": "Nie udało się nawiązać bezpiecznego połączenia z serwerem aktualizacji. Spróbuj ponownie później." } }, "ru": { "stringUnit": { "state": "translated", - "value": "Канал обновлений не защищен. Обратитесь в службу поддержки." + "value": "Не удалось установить защищенное подключение к серверу обновлений. Повторите попытку позже." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Feed ažuriranja nije siguran. Kontaktirajte podršku." + "value": "Nije moguće uspostaviti sigurnu vezu sa serverom za ažuriranje. Pokušajte ponovo kasnije." } }, "ar": { "stringUnit": { "state": "translated", - "value": "موجز التحديثات غير آمن. يرجى الاتصال بالدعم." + "value": "تعذر إنشاء اتصال آمن بخادم التحديثات. حاول لاحقًا." } }, "nb": { "stringUnit": { "state": "translated", - "value": "Oppdateringsfeeden er usikker. Kontakt brukerstøtte." + "value": "En sikker tilkobling til oppdateringsserveren kunne ikke opprettes. Prøv igjen senere." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "O feed de atualização é inseguro. Entre em contato com o suporte." + "value": "Não foi possível estabelecer uma conexão segura com o servidor de atualização. Tente novamente mais tarde." } }, "th": { "stringUnit": { "state": "translated", - "value": "ฟีดอัปเดตไม่ปลอดภัย กรุณาติดต่อฝ่ายสนับสนุน" + "value": "ไม่สามารถสร้างการเชื่อมต่อที่ปลอดภัยกับเซิร์ฟเวอร์อัปเดตได้ ลองอีกครั้งในภายหลัง" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Güncelleme akışı güvensiz. Lütfen destekle iletişime geçin." + "value": "Güncelleme sunucusuyla güvenli bir bağlantı kurulamadı. Daha sonra tekrar deneyin." } }, "uk": { "stringUnit": { "state": "translated", - "value": "Стрічка оновлень незахищена. Зверніться до служби підтримки." + "value": "Не вдалося встановити захищене з'єднання з сервером оновлень. Спробуйте пізніше." } } } }, - "update.error.insecureFeed.title": { + "update.error.secureConnectionFailed.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Insecure Update Feed" + "value": "Secure Connection Failed" } }, "ja": { "stringUnit": { "state": "translated", - "value": "安全でないアップデートフィード" + "value": "セキュア接続に失敗しました" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "不安全的更新源" + "value": "安全连接失败" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "不安全的更新來源" + "value": "安全連線失敗" } }, "ko": { "stringUnit": { "state": "translated", - "value": "안전하지 않은 업데이트 피드" + "value": "보안 연결 실패" } }, "de": { "stringUnit": { "state": "translated", - "value": "Unsicherer Update-Feed" + "value": "Sichere Verbindung fehlgeschlagen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Fuente de actualizaciones insegura" + "value": "Error de conexión segura" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Flux de mises à jour non sécurisé" + "value": "Échec de la connexion sécurisée" } }, "it": { "stringUnit": { "state": "translated", - "value": "Feed aggiornamento non sicuro" + "value": "Connessione sicura non riuscita" } }, "da": { "stringUnit": { "state": "translated", - "value": "Usikkert opdateringsfeed" + "value": "Sikker forbindelse mislykkedes" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Niezabezpieczony kanał aktualizacji" + "value": "Bezpieczne połączenie nie powiodło się" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Незащищенный канал обновлений" + "value": "Ошибка защищенного подключения" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Nesiguran feed ažuriranja" + "value": "Sigurna veza nije uspjela" } }, "ar": { "stringUnit": { "state": "translated", - "value": "موجز تحديثات غير آمن" + "value": "فشل الاتصال الآمن" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Usikker oppdateringsfeed" + "value": "Sikker tilkobling mislyktes" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Feed de Atualização Inseguro" + "value": "Falha na Conexão Segura" } }, "th": { "stringUnit": { "state": "translated", - "value": "ฟีดอัปเดตไม่ปลอดภัย" + "value": "การเชื่อมต่อที่ปลอดภัยล้มเหลว" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Güvensiz Güncelleme Akışı" + "value": "Güvenli Bağlantı Başarısız" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Незахищена стрічка оновлень" + "value": "Помилка захищеного з'єднання" } } } }, - "update.error.invalidFeed.message": { + "update.error.serverNotFound.message": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "The update feed URL is invalid. Please contact support." + "value": "The update server can't be found. Check your connection or try again later." } }, "ja": { "stringUnit": { "state": "translated", - "value": "アップデートフィードのURLが無効です。サポートにお問い合わせください。" + "value": "アップデートサーバーが見つかりません。接続を確認するか、後でもう一度お試しください。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "更新源 URL 无效。请联系支持团队。" + "value": "找不到更新服务器。请检查网络连接或稍后重试。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "更新來源 URL 無效。請聯絡支援團隊。" + "value": "找不到更新伺服器。請檢查您的連線或稍後再試。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "업데이트 피드 URL이 유효하지 않습니다. 지원팀에 문의하세요." + "value": "업데이트 서버를 찾을 수 없습니다. 연결을 확인하거나 나중에 다시 시도하세요." } }, "de": { "stringUnit": { "state": "translated", - "value": "Die URL des Update-Feeds ist ungültig. Bitte kontaktieren Sie den Support." + "value": "Der Update-Server kann nicht gefunden werden. Überprüfen Sie Ihre Verbindung oder versuchen Sie es später erneut." } }, "es": { "stringUnit": { "state": "translated", - "value": "La URL de la fuente de actualizaciones no es válida. Contacta con soporte." + "value": "No se encuentra el servidor de actualizaciones. Comprueba tu conexión o inténtalo de nuevo más tarde." } }, "fr": { "stringUnit": { "state": "translated", - "value": "L'URL du flux de mises à jour n'est pas valide. Veuillez contacter le support." + "value": "Le serveur de mises à jour est introuvable. Vérifiez votre connexion ou réessayez plus tard." } }, "it": { "stringUnit": { "state": "translated", - "value": "L'URL del feed degli aggiornamenti non è valido. Contatta il supporto." + "value": "Impossibile trovare il server degli aggiornamenti. Controlla la connessione o riprova più tardi." } }, "da": { "stringUnit": { "state": "translated", - "value": "URL'en til opdateringsfeedet er ugyldig. Kontakt venligst supporten." + "value": "Opdateringsserveren kan ikke findes. Kontroller din forbindelse, eller prøv igen senere." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Adres URL kanału aktualizacji jest nieprawidłowy. Skontaktuj się ze wsparciem." + "value": "Nie można znaleźć serwera aktualizacji. Sprawdź połączenie lub spróbuj ponownie później." } }, "ru": { "stringUnit": { "state": "translated", - "value": "URL канала обновлений недействителен. Обратитесь в службу поддержки." + "value": "Сервер обновлений не найден. Проверьте подключение или повторите попытку позже." } }, "bs": { "stringUnit": { "state": "translated", - "value": "URL feeda ažuriranja je nevažeći. Kontaktirajte podršku." + "value": "Server za ažuriranje nije pronađen. Provjerite vezu ili pokušajte ponovo kasnije." } }, "ar": { "stringUnit": { "state": "translated", - "value": "عنوان URL لموجز التحديثات غير صالح. يرجى الاتصال بالدعم." + "value": "تعذر العثور على خادم التحديثات. تحقق من اتصالك أو حاول لاحقًا." } }, "nb": { "stringUnit": { "state": "translated", - "value": "URL-en for oppdateringsfeeden er ugyldig. Kontakt brukerstøtte." + "value": "Oppdateringsserveren ble ikke funnet. Kontroller tilkoblingen eller prøv igjen senere." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "A URL do feed de atualização é inválida. Entre em contato com o suporte." + "value": "O servidor de atualização não foi encontrado. Verifique sua conexão ou tente novamente mais tarde." } }, "th": { "stringUnit": { "state": "translated", - "value": "URL ฟีดอัปเดตไม่ถูกต้อง กรุณาติดต่อฝ่ายสนับสนุน" + "value": "ไม่พบเซิร์ฟเวอร์อัปเดต ตรวจสอบการเชื่อมต่อหรือลองอีกครั้งในภายหลัง" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Güncelleme akışı URL'si geçersiz. Lütfen destekle iletişime geçin." + "value": "Güncelleme sunucusu bulunamıyor. Bağlantınızı kontrol edin veya daha sonra tekrar deneyin." } }, "uk": { "stringUnit": { "state": "translated", - "value": "URL стрічки оновлень недійсний. Зверніться до служби підтримки." + "value": "Сервер оновлень не знайдено. Перевірте підключення або спробуйте пізніше." } } } }, - "update.error.invalidFeed.title": { + "update.error.serverNotFound.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Invalid Update Feed" + "value": "Server Not Found" } }, "ja": { "stringUnit": { "state": "translated", - "value": "無効なアップデートフィード" + "value": "サーバーが見つかりません" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "无效的更新源" + "value": "找不到服务器" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "無效的更新來源" + "value": "找不到伺服器" } }, "ko": { "stringUnit": { "state": "translated", - "value": "유효하지 않은 업데이트 피드" + "value": "서버를 찾을 수 없음" } }, "de": { "stringUnit": { "state": "translated", - "value": "Ungültiger Update-Feed" + "value": "Server nicht gefunden" } }, "es": { "stringUnit": { "state": "translated", - "value": "Fuente de actualizaciones no válida" + "value": "Servidor no encontrado" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Flux de mises à jour non valide" + "value": "Serveur introuvable" } }, "it": { "stringUnit": { "state": "translated", - "value": "Feed aggiornamento non valido" + "value": "Server non trovato" } }, "da": { "stringUnit": { "state": "translated", - "value": "Ugyldigt opdateringsfeed" + "value": "Server ikke fundet" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Nieprawidłowy kanał aktualizacji" + "value": "Nie znaleziono serwera" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Недействительный канал обновлений" + "value": "Сервер не найден" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Nevažeći feed ažuriranja" + "value": "Server nije pronađen" } }, "ar": { "stringUnit": { "state": "translated", - "value": "موجز تحديثات غير صالح" + "value": "لم يتم العثور على الخادم" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Ugyldig oppdateringsfeed" + "value": "Server ikke funnet" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Feed de Atualização Inválido" + "value": "Servidor Não Encontrado" } }, "th": { "stringUnit": { "state": "translated", - "value": "ฟีดอัปเดตไม่ถูกต้อง" + "value": "ไม่พบเซิร์ฟเวอร์" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Geçersiz Güncelleme Akışı" + "value": "Sunucu Bulunamadı" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Недійсна стрічка оновлень" + "value": "Сервер не знайдено" } } } }, - "update.error.noInternet.message": { + "update.error.serverUnreachable.message": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "cmux can't reach the update server. Check your internet connection and try again." + "value": "cmux couldn't connect to the update server. Check your connection or try again later." } }, "ja": { "stringUnit": { "state": "translated", - "value": "cmux はアップデートサーバーに接続できません。インターネット接続を確認してもう一度お試しください。" + "value": "cmux はアップデートサーバーに接続できませんでした。接続を確認するか、後でもう一度お試しください。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "cmux 无法连接到更新服务器。请检查互联网连接后重试。" + "value": "cmux 无法连接到更新服务器。请检查网络连接或稍后重试。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "cmux 無法連線至更新伺服器。請檢查您的網際網路連線後再試一次。" + "value": "cmux 無法連線至更新伺服器。請檢查您的連線或稍後再試。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "cmux에서 업데이트 서버에 연결할 수 없습니다. 인터넷 연결을 확인하고 다시 시도하세요." + "value": "cmux에서 업데이트 서버에 연결할 수 없습니다. 연결을 확인하거나 나중에 다시 시도하세요." } }, "de": { "stringUnit": { "state": "translated", - "value": "cmux kann den Update-Server nicht erreichen. Überprüfen Sie Ihre Internetverbindung und versuchen Sie es erneut." + "value": "cmux konnte keine Verbindung zum Update-Server herstellen. Überprüfen Sie Ihre Verbindung oder versuchen Sie es später erneut." } }, "es": { "stringUnit": { "state": "translated", - "value": "cmux no puede acceder al servidor de actualizaciones. Comprueba tu conexión a internet e inténtalo de nuevo." + "value": "cmux no pudo conectar con el servidor de actualizaciones. Comprueba tu conexión o inténtalo de nuevo más tarde." } }, "fr": { "stringUnit": { "state": "translated", - "value": "cmux ne peut pas atteindre le serveur de mises à jour. Vérifiez votre connexion Internet et réessayez." + "value": "cmux n'a pas pu se connecter au serveur de mises à jour. Vérifiez votre connexion ou réessayez plus tard." } }, "it": { "stringUnit": { "state": "translated", - "value": "cmux non riesce a raggiungere il server degli aggiornamenti. Controlla la connessione a internet e riprova." + "value": "cmux non è riuscito a connettersi al server degli aggiornamenti. Controlla la connessione o riprova più tardi." } }, "da": { "stringUnit": { "state": "translated", - "value": "cmux kan ikke nå opdateringsserveren. Kontroller din internetforbindelse, og prøv igen." + "value": "cmux kunne ikke oprette forbindelse til opdateringsserveren. Kontroller din forbindelse, eller prøv igen senere." } }, "pl": { "stringUnit": { "state": "translated", - "value": "cmux nie może połączyć się z serwerem aktualizacji. Sprawdź połączenie z internetem i spróbuj ponownie." + "value": "cmux nie mógł połączyć się z serwerem aktualizacji. Sprawdź połączenie lub spróbuj ponownie później." } }, "ru": { "stringUnit": { "state": "translated", - "value": "cmux не может связаться с сервером обновлений. Проверьте подключение к интернету и повторите попытку." + "value": "cmux не удалось подключиться к серверу обновлений. Проверьте подключение или повторите попытку позже." } }, "bs": { "stringUnit": { "state": "translated", - "value": "cmux ne može dosegnuti server za ažuriranje. Provjerite internetsku vezu i pokušajte ponovo." + "value": "cmux se nije mogao povezati na server za ažuriranje. Provjerite vezu ili pokušajte ponovo kasnije." } }, "ar": { "stringUnit": { "state": "translated", - "value": "لا يمكن لـ cmux الوصول إلى خادم التحديثات. تحقق من اتصال الإنترنت وحاول مجددًا." + "value": "تعذر على cmux الاتصال بخادم التحديثات. تحقق من اتصالك أو حاول لاحقًا." } }, "nb": { "stringUnit": { "state": "translated", - "value": "cmux kan ikke nå oppdateringsserveren. Kontroller internettforbindelsen og prøv igjen." + "value": "cmux kunne ikke koble til oppdateringsserveren. Kontroller tilkoblingen eller prøv igjen senere." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "O cmux não consegue acessar o servidor de atualização. Verifique sua conexão com a internet e tente novamente." + "value": "O cmux não conseguiu se conectar ao servidor de atualização. Verifique sua conexão ou tente novamente mais tarde." } }, "th": { "stringUnit": { "state": "translated", - "value": "cmux ไม่สามารถเข้าถึงเซิร์ฟเวอร์อัปเดตได้ ตรวจสอบการเชื่อมต่ออินเทอร์เน็ตแล้วลองอีกครั้ง" + "value": "cmux ไม่สามารถเชื่อมต่อกับเซิร์ฟเวอร์อัปเดตได้ ตรวจสอบการเชื่อมต่อหรือลองอีกครั้งในภายหลัง" } }, "tr": { "stringUnit": { "state": "translated", - "value": "cmux güncelleme sunucusuna ulaşamıyor. İnternet bağlantınızı kontrol edip tekrar deneyin." + "value": "cmux güncelleme sunucusuna bağlanamadı. Bağlantınızı kontrol edin veya daha sonra tekrar deneyin." } }, "uk": { "stringUnit": { "state": "translated", - "value": "cmux не може зв'язатися з сервером оновлень. Перевірте підключення до інтернету та спробуйте ще раз." + "value": "cmux не зміг підключитися до сервера оновлень. Перевірте підключення або спробуйте пізніше." } } } }, - "update.error.noInternet.title": { + "update.error.serverUnreachable.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "No Internet Connection" + "value": "Server Unreachable" } }, "ja": { "stringUnit": { "state": "translated", - "value": "インターネット接続がありません" + "value": "サーバーに接続できません" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "无互联网连接" + "value": "服务器不可达" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "沒有網際網路連線" + "value": "伺服器無法連線" } }, "ko": { "stringUnit": { "state": "translated", - "value": "인터넷 연결 없음" + "value": "서버에 연결할 수 없음" } }, "de": { "stringUnit": { "state": "translated", - "value": "Keine Internetverbindung" + "value": "Server nicht erreichbar" } }, "es": { "stringUnit": { "state": "translated", - "value": "Sin conexión a internet" + "value": "Servidor inaccesible" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Aucune connexion Internet" + "value": "Serveur inaccessible" } }, "it": { "stringUnit": { "state": "translated", - "value": "Nessuna connessione a internet" + "value": "Server non raggiungibile" } }, "da": { "stringUnit": { "state": "translated", - "value": "Ingen internetforbindelse" + "value": "Server utilgængelig" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Brak połączenia z internetem" + "value": "Serwer nieosiągalny" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Нет подключения к интернету" + "value": "Сервер недоступен" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Nema internetske veze" + "value": "Server nedostupan" } }, "ar": { "stringUnit": { "state": "translated", - "value": "لا يوجد اتصال بالإنترنت" + "value": "الخادم غير قابل للوصول" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Ingen internettforbindelse" + "value": "Server utilgjengelig" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Sem Conexão com a Internet" + "value": "Servidor Inacessível" } }, "th": { "stringUnit": { "state": "translated", - "value": "ไม่มีการเชื่อมต่ออินเทอร์เน็ต" + "value": "เซิร์ฟเวอร์เข้าถึงไม่ได้" } }, "tr": { "stringUnit": { "state": "translated", - "value": "İnternet Bağlantısı Yok" + "value": "Sunucuya Erişilemiyor" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Немає підключення до інтернету" + "value": "Сервер недоступний" } } } }, - "update.error.permissionError.message": { + "update.error.signatureError.message": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Move cmux into Applications and relaunch to enable updates." + "value": "The update's signature could not be verified. Please try again later." } }, "ja": { "stringUnit": { "state": "translated", - "value": "アップデートを有効にするには、cmux を「アプリケーション」に移動して再起動してください。" + "value": "アップデートの署名を検証できませんでした。後でもう一度お試しください。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "请将 cmux 移到「应用程序」文件夹中,然后重新启动以启用更新。" + "value": "无法验证更新的签名。请稍后重试。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "請將 cmux 移至「應用程式」資料夾並重新啟動,以啟用更新。" + "value": "無法驗證更新的簽章。請稍後再試。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "cmux를 응용 프로그램 폴더로 이동하고 재실행하여 업데이트를 활성화하세요." + "value": "업데이트 서명을 확인할 수 없습니다. 나중에 다시 시도하세요." } }, "de": { "stringUnit": { "state": "translated", - "value": "Verschieben Sie cmux in den Ordner 'Programme' und starten Sie die App neu, um Updates zu aktivieren." + "value": "Die Signatur des Updates konnte nicht überprüft werden. Bitte versuchen Sie es später erneut." } }, "es": { "stringUnit": { "state": "translated", - "value": "Mueve cmux a Aplicaciones y vuelve a iniciarlo para activar las actualizaciones." + "value": "No se pudo verificar la firma de la actualización. Inténtalo de nuevo más tarde." } }, "fr": { "stringUnit": { "state": "translated", - "value": "Déplacez cmux dans Applications et relancez pour activer les mises à jour." + "value": "La signature de la mise à jour n'a pas pu être vérifiée. Veuillez réessayer plus tard." } }, "it": { "stringUnit": { "state": "translated", - "value": "Sposta cmux nella cartella Applicazioni e riavvia per abilitare gli aggiornamenti." + "value": "Impossibile verificare la firma dell'aggiornamento. Riprova più tardi." } }, "da": { "stringUnit": { "state": "translated", - "value": "Flyt cmux til Programmer, og genstart for at aktivere opdateringer." + "value": "Opdateringens signatur kunne ikke verificeres. Prøv igen senere." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Przenieś cmux do folderu Aplikacje i uruchom ponownie, aby włączyć aktualizacje." + "value": "Nie udało się zweryfikować podpisu aktualizacji. Spróbuj ponownie później." } }, "ru": { "stringUnit": { "state": "translated", - "value": "Переместите cmux в папку «Программы» и перезапустите для включения обновлений." + "value": "Не удалось проверить подпись обновления. Повторите попытку позже." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Premjestite cmux u Applications i ponovo pokrenite da biste omogućili ažuriranja." + "value": "Potpis ažuriranja nije mogao biti verificiran. Pokušajte ponovo kasnije." } }, "ar": { "stringUnit": { "state": "translated", - "value": "انقل cmux إلى مجلد التطبيقات وأعد التشغيل لتفعيل التحديثات." + "value": "تعذر التحقق من توقيع التحديث. يرجى المحاولة لاحقًا." } }, "nb": { "stringUnit": { "state": "translated", - "value": "Flytt cmux til Programmer og start på nytt for å aktivere oppdateringer." + "value": "Oppdateringens signatur kunne ikke verifiseres. Prøv igjen senere." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Mova o cmux para Aplicativos e reinicie para ativar as atualizações." + "value": "A assinatura da atualização não pôde ser verificada. Tente novamente mais tarde." } }, "th": { "stringUnit": { "state": "translated", - "value": "ย้าย cmux ไปที่โฟลเดอร์ Applications แล้วเปิดใหม่เพื่อเปิดใช้งานการอัปเดต" + "value": "ไม่สามารถยืนยันลายเซ็นของอัปเดตได้ กรุณาลองอีกครั้งในภายหลัง" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Güncellemeleri etkinleştirmek için cmux'u Uygulamalar klasörüne taşıyıp yeniden başlatın." + "value": "Güncellemenin imzası doğrulanamadı. Lütfen daha sonra tekrar deneyin." } }, "uk": { "stringUnit": { "state": "translated", - "value": "Перемістіть cmux до теки Програми та перезапустіть для увімкнення оновлень." + "value": "Не вдалося перевірити підпис оновлення. Спробуйте пізніше." } } } }, - "update.error.permissionError.title": { + "update.error.signatureError.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Updater Permission Error" + "value": "Update Signature Error" } }, "ja": { "stringUnit": { "state": "translated", - "value": "アップデーター権限エラー" + "value": "アップデート署名エラー" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "更新程序权限错误" + "value": "更新签名错误" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "更新程式權限錯誤" + "value": "更新簽章錯誤" } }, "ko": { "stringUnit": { "state": "translated", - "value": "업데이터 권한 오류" + "value": "업데이트 서명 오류" } }, "de": { "stringUnit": { "state": "translated", - "value": "Berechtigungsfehler des Updaters" + "value": "Fehler bei der Update-Signatur" } }, "es": { "stringUnit": { "state": "translated", - "value": "Error de permisos del actualizador" + "value": "Error de firma de actualización" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Erreur de permissions du programme de mise à jour" + "value": "Erreur de signature de la mise à jour" } }, "it": { "stringUnit": { "state": "translated", - "value": "Errore di autorizzazione dell'aggiornamento" + "value": "Errore firma aggiornamento" } }, "da": { "stringUnit": { "state": "translated", - "value": "Fejl i opdateringstilladelse" + "value": "Fejl i opdateringssignatur" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Błąd uprawnień aktualizatora" + "value": "Błąd podpisu aktualizacji" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Ошибка прав доступа программы обновления" + "value": "Ошибка подписи обновления" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Greška dozvole za ažuriranje" + "value": "Greška potpisa ažuriranja" } }, "ar": { "stringUnit": { "state": "translated", - "value": "خطأ في صلاحيات المحدّث" + "value": "خطأ في توقيع التحديث" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Tillatelsessfeil for oppdatering" + "value": "Feil i oppdateringssignatur" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Erro de Permissão do Atualizador" + "value": "Erro de Assinatura da Atualização" } }, "th": { "stringUnit": { "state": "translated", - "value": "ข้อผิดพลาดสิทธิ์ตัวอัปเดต" + "value": "ข้อผิดพลาดลายเซ็นอัปเดต" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Güncelleyici İzin Hatası" + "value": "Güncelleme İmza Hatası" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Помилка прав доступу оновлювача" + "value": "Помилка підпису оновлення" } } } }, - "update.error.secureConnectionFailed.message": { + "update.error.timedOut.message": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "A secure connection to the update server couldn't be established. Try again later." + "value": "The update server took too long to respond. Try again in a moment." } }, "ja": { "stringUnit": { "state": "translated", - "value": "アップデートサーバーへのセキュア接続を確立できませんでした。後でもう一度お試しください。" + "value": "アップデートサーバーの応答に時間がかかりすぎました。しばらくしてからもう一度お試しください。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "无法与更新服务器建立安全连接。请稍后重试。" + "value": "更新服务器响应超时。请稍后重试。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "無法建立與更新伺服器的安全連線。請稍後再試。" + "value": "更新伺服器回應時間過長。請稍後再試。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "업데이트 서버에 대한 보안 연결을 설정할 수 없습니다. 나중에 다시 시도하세요." + "value": "업데이트 서버가 응답하는 데 너무 오래 걸렸습니다. 잠시 후 다시 시도하세요." } }, "de": { "stringUnit": { "state": "translated", - "value": "Es konnte keine sichere Verbindung zum Update-Server hergestellt werden. Versuchen Sie es später erneut." + "value": "Der Update-Server hat zu lange gebraucht, um zu antworten. Versuchen Sie es in einem Moment erneut." } }, "es": { "stringUnit": { "state": "translated", - "value": "No se pudo establecer una conexión segura con el servidor de actualizaciones. Inténtalo de nuevo más tarde." + "value": "El servidor de actualizaciones tardó demasiado en responder. Inténtalo de nuevo en un momento." } }, "fr": { "stringUnit": { "state": "translated", - "value": "Impossible d'établir une connexion sécurisée avec le serveur de mises à jour. Réessayez plus tard." + "value": "Le serveur de mises à jour a mis trop de temps à répondre. Réessayez dans un instant." } }, "it": { "stringUnit": { "state": "translated", - "value": "Impossibile stabilire una connessione sicura al server degli aggiornamenti. Riprova più tardi." + "value": "Il server degli aggiornamenti ha impiegato troppo tempo a rispondere. Riprova tra un momento." } }, "da": { "stringUnit": { "state": "translated", - "value": "En sikker forbindelse til opdateringsserveren kunne ikke oprettes. Prøv igen senere." + "value": "Opdateringsserveren var for lang tid om at svare. Prøv igen om et øjeblik." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Nie udało się nawiązać bezpiecznego połączenia z serwerem aktualizacji. Spróbuj ponownie później." + "value": "Serwer aktualizacji zbyt długo nie odpowiadał. Spróbuj ponownie za chwilę." } }, "ru": { "stringUnit": { "state": "translated", - "value": "Не удалось установить защищенное подключение к серверу обновлений. Повторите попытку позже." + "value": "Сервер обновлений не ответил вовремя. Повторите попытку через некоторое время." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Nije moguće uspostaviti sigurnu vezu sa serverom za ažuriranje. Pokušajte ponovo kasnije." + "value": "Server za ažuriranje je predugo čekao da odgovori. Pokušajte ponovo za trenutak." } }, "ar": { "stringUnit": { "state": "translated", - "value": "تعذر إنشاء اتصال آمن بخادم التحديثات. حاول لاحقًا." + "value": "استغرق خادم التحديثات وقتًا طويلاً للاستجابة. حاول مجددًا بعد لحظة." } }, "nb": { "stringUnit": { "state": "translated", - "value": "En sikker tilkobling til oppdateringsserveren kunne ikke opprettes. Prøv igjen senere." + "value": "Oppdateringsserveren brukte for lang tid på å svare. Prøv igjen om et øyeblikk." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Não foi possível estabelecer uma conexão segura com o servidor de atualização. Tente novamente mais tarde." + "value": "O servidor de atualização demorou muito para responder. Tente novamente em instantes." } }, "th": { "stringUnit": { "state": "translated", - "value": "ไม่สามารถสร้างการเชื่อมต่อที่ปลอดภัยกับเซิร์ฟเวอร์อัปเดตได้ ลองอีกครั้งในภายหลัง" + "value": "เซิร์ฟเวอร์อัปเดตใช้เวลานานเกินไปในการตอบกลับ ลองอีกครั้งในอีกสักครู่" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Güncelleme sunucusuyla güvenli bir bağlantı kurulamadı. Daha sonra tekrar deneyin." + "value": "Güncelleme sunucusu yanıt vermekte çok uzun sürdü. Birazdan tekrar deneyin." } }, "uk": { "stringUnit": { "state": "translated", - "value": "Не вдалося встановити захищене з'єднання з сервером оновлень. Спробуйте пізніше." + "value": "Сервер оновлень не відповів вчасно. Спробуйте через деякий час." } } } }, - "update.error.secureConnectionFailed.title": { + "update.error.timedOut.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Secure Connection Failed" + "value": "Update Timed Out" } }, "ja": { "stringUnit": { "state": "translated", - "value": "セキュア接続に失敗しました" + "value": "アップデートがタイムアウトしました" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "安全连接失败" + "value": "更新超时" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "安全連線失敗" + "value": "更新逾時" } }, "ko": { "stringUnit": { "state": "translated", - "value": "보안 연결 실패" + "value": "업데이트 시간 초과" } }, "de": { "stringUnit": { "state": "translated", - "value": "Sichere Verbindung fehlgeschlagen" + "value": "Update-Zeitüberschreitung" } }, "es": { "stringUnit": { "state": "translated", - "value": "Error de conexión segura" + "value": "Tiempo de espera agotado" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Échec de la connexion sécurisée" + "value": "Délai de mise à jour dépassé" } }, "it": { "stringUnit": { "state": "translated", - "value": "Connessione sicura non riuscita" + "value": "Aggiornamento scaduto" } }, "da": { "stringUnit": { "state": "translated", - "value": "Sikker forbindelse mislykkedes" + "value": "Opdatering fik timeout" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Bezpieczne połączenie nie powiodło się" + "value": "Przekroczono limit czasu aktualizacji" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Ошибка защищенного подключения" + "value": "Время ожидания обновления истекло" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Sigurna veza nije uspjela" + "value": "Isteklo vrijeme ažuriranja" } }, "ar": { "stringUnit": { "state": "translated", - "value": "فشل الاتصال الآمن" + "value": "انتهت مهلة التحديث" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Sikker tilkobling mislyktes" + "value": "Oppdatering tidsavbrutt" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Falha na Conexão Segura" + "value": "Tempo de Atualização Esgotado" } }, "th": { "stringUnit": { "state": "translated", - "value": "การเชื่อมต่อที่ปลอดภัยล้มเหลว" + "value": "การอัปเดตหมดเวลา" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Güvenli Bağlantı Başarısız" + "value": "Güncelleme Zaman Aşımına Uğradı" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Помилка захищеного з'єднання" + "value": "Час очікування оновлення вичерпано" } } } }, - "update.error.serverNotFound.message": { + "update.extracting.progress": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "The update server can't be found. Check your connection or try again later." + "value": "Preparing: %@" } }, "ja": { "stringUnit": { "state": "translated", - "value": "アップデートサーバーが見つかりません。接続を確認するか、後でもう一度お試しください。" + "value": "準備中: %@" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "找不到更新服务器。请检查网络连接或稍后重试。" + "value": "正在准备:%@" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "找不到更新伺服器。請檢查您的連線或稍後再試。" + "value": "正在準備:%@" } }, "ko": { "stringUnit": { "state": "translated", - "value": "업데이트 서버를 찾을 수 없습니다. 연결을 확인하거나 나중에 다시 시도하세요." + "value": "준비 중: %@" } }, "de": { "stringUnit": { "state": "translated", - "value": "Der Update-Server kann nicht gefunden werden. Überprüfen Sie Ihre Verbindung oder versuchen Sie es später erneut." + "value": "Vorbereitung: %@" } }, "es": { "stringUnit": { "state": "translated", - "value": "No se encuentra el servidor de actualizaciones. Comprueba tu conexión o inténtalo de nuevo más tarde." + "value": "Preparando: %@" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Le serveur de mises à jour est introuvable. Vérifiez votre connexion ou réessayez plus tard." + "value": "Préparation : %@" } }, "it": { "stringUnit": { "state": "translated", - "value": "Impossibile trovare il server degli aggiornamenti. Controlla la connessione o riprova più tardi." + "value": "Preparazione: %@" } }, "da": { "stringUnit": { "state": "translated", - "value": "Opdateringsserveren kan ikke findes. Kontroller din forbindelse, eller prøv igen senere." + "value": "Forbereder: %@" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Nie można znaleźć serwera aktualizacji. Sprawdź połączenie lub spróbuj ponownie później." + "value": "Przygotowywanie: %@" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Сервер обновлений не найден. Проверьте подключение или повторите попытку позже." + "value": "Подготовка: %@" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Server za ažuriranje nije pronađen. Provjerite vezu ili pokušajte ponovo kasnije." + "value": "Priprema: %@" } }, "ar": { "stringUnit": { "state": "translated", - "value": "تعذر العثور على خادم التحديثات. تحقق من اتصالك أو حاول لاحقًا." + "value": "جارٍ التحضير: %@" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Oppdateringsserveren ble ikke funnet. Kontroller tilkoblingen eller prøv igjen senere." + "value": "Forbereder: %@" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "O servidor de atualização não foi encontrado. Verifique sua conexão ou tente novamente mais tarde." + "value": "Preparando: %@" } }, "th": { "stringUnit": { "state": "translated", - "value": "ไม่พบเซิร์ฟเวอร์อัปเดต ตรวจสอบการเชื่อมต่อหรือลองอีกครั้งในภายหลัง" + "value": "กำลังเตรียม: %@" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Güncelleme sunucusu bulunamıyor. Bağlantınızı kontrol edin veya daha sonra tekrar deneyin." + "value": "Hazırlanıyor: %@" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Сервер оновлень не знайдено. Перевірте підключення або спробуйте пізніше." + "value": "Підготовка: %@" } } } }, - "update.error.serverNotFound.title": { + "update.installAndRelaunch": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Server Not Found" + "value": "Install Update and Relaunch" } }, "ja": { "stringUnit": { "state": "translated", - "value": "サーバーが見つかりません" + "value": "アップデートをインストールして再起動" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "找不到服务器" + "value": "安装更新并重新启动" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "找不到伺服器" + "value": "安裝更新並重新啟動" } }, "ko": { "stringUnit": { "state": "translated", - "value": "서버를 찾을 수 없음" + "value": "업데이트 설치 후 재실행" } }, "de": { "stringUnit": { "state": "translated", - "value": "Server nicht gefunden" + "value": "Update installieren und neu starten" } }, "es": { "stringUnit": { "state": "translated", - "value": "Servidor no encontrado" + "value": "Instalar actualización y reiniciar" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Serveur introuvable" + "value": "Installer la mise à jour et relancer" } }, "it": { "stringUnit": { "state": "translated", - "value": "Server non trovato" + "value": "Installa aggiornamento e riavvia" } }, "da": { "stringUnit": { "state": "translated", - "value": "Server ikke fundet" + "value": "Installer opdatering og genstart" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Nie znaleziono serwera" + "value": "Zainstaluj aktualizację i uruchom ponownie" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Сервер не найден" + "value": "Установить обновление и перезапустить" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Server nije pronađen" + "value": "Instaliraj ažuriranje i ponovo pokreni" } }, "ar": { "stringUnit": { "state": "translated", - "value": "لم يتم العثور على الخادم" + "value": "تثبيت التحديث وإعادة التشغيل" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Server ikke funnet" + "value": "Installer oppdatering og start på nytt" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Servidor Não Encontrado" + "value": "Instalar Atualização e Reiniciar" } }, "th": { "stringUnit": { "state": "translated", - "value": "ไม่พบเซิร์ฟเวอร์" + "value": "ติดตั้งอัปเดตและเปิดใหม่" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Sunucu Bulunamadı" + "value": "Güncellemeyi Yükle ve Yeniden Başlat" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Сервер не знайдено" + "value": "Встановити оновлення та перезапустити" } } } }, - "update.error.serverUnreachable.message": { + "update.installing.status": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "cmux couldn't connect to the update server. Check your connection or try again later." + "value": "Installing…" } }, "ja": { "stringUnit": { "state": "translated", - "value": "cmux はアップデートサーバーに接続できませんでした。接続を確認するか、後でもう一度お試しください。" + "value": "インストール中…" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "cmux 无法连接到更新服务器。请检查网络连接或稍后重试。" + "value": "正在安装..." } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "cmux 無法連線至更新伺服器。請檢查您的連線或稍後再試。" + "value": "安裝中..." } }, "ko": { "stringUnit": { "state": "translated", - "value": "cmux에서 업데이트 서버에 연결할 수 없습니다. 연결을 확인하거나 나중에 다시 시도하세요." + "value": "설치 중…" } }, "de": { "stringUnit": { "state": "translated", - "value": "cmux konnte keine Verbindung zum Update-Server herstellen. Überprüfen Sie Ihre Verbindung oder versuchen Sie es später erneut." + "value": "Wird installiert …" } }, "es": { "stringUnit": { "state": "translated", - "value": "cmux no pudo conectar con el servidor de actualizaciones. Comprueba tu conexión o inténtalo de nuevo más tarde." + "value": "Instalando…" } }, "fr": { "stringUnit": { "state": "translated", - "value": "cmux n'a pas pu se connecter au serveur de mises à jour. Vérifiez votre connexion ou réessayez plus tard." + "value": "Installation..." } }, "it": { "stringUnit": { "state": "translated", - "value": "cmux non è riuscito a connettersi al server degli aggiornamenti. Controlla la connessione o riprova più tardi." + "value": "Installazione in corso…" } }, "da": { "stringUnit": { "state": "translated", - "value": "cmux kunne ikke oprette forbindelse til opdateringsserveren. Kontroller din forbindelse, eller prøv igen senere." + "value": "Installerer…" } }, "pl": { "stringUnit": { "state": "translated", - "value": "cmux nie mógł połączyć się z serwerem aktualizacji. Sprawdź połączenie lub spróbuj ponownie później." + "value": "Instalowanie…" } }, "ru": { "stringUnit": { "state": "translated", - "value": "cmux не удалось подключиться к серверу обновлений. Проверьте подключение или повторите попытку позже." + "value": "Установка..." } }, "bs": { "stringUnit": { "state": "translated", - "value": "cmux se nije mogao povezati na server za ažuriranje. Provjerite vezu ili pokušajte ponovo kasnije." + "value": "Instaliranje…" } }, "ar": { "stringUnit": { "state": "translated", - "value": "تعذر على cmux الاتصال بخادم التحديثات. تحقق من اتصالك أو حاول لاحقًا." + "value": "جارٍ التثبيت…" } }, "nb": { "stringUnit": { "state": "translated", - "value": "cmux kunne ikke koble til oppdateringsserveren. Kontroller tilkoblingen eller prøv igjen senere." + "value": "Installerer …" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "O cmux não conseguiu se conectar ao servidor de atualização. Verifique sua conexão ou tente novamente mais tarde." + "value": "Instalando…" } }, "th": { "stringUnit": { "state": "translated", - "value": "cmux ไม่สามารถเชื่อมต่อกับเซิร์ฟเวอร์อัปเดตได้ ตรวจสอบการเชื่อมต่อหรือลองอีกครั้งในภายหลัง" + "value": "กำลังติดตั้ง..." } }, "tr": { "stringUnit": { "state": "translated", - "value": "cmux güncelleme sunucusuna bağlanamadı. Bağlantınızı kontrol edin veya daha sonra tekrar deneyin." + "value": "Yükleniyor…" } }, "uk": { "stringUnit": { "state": "translated", - "value": "cmux не зміг підключитися до сервера оновлень. Перевірте підключення або спробуйте пізніше." + "value": "Встановлення…" } } } }, - "update.error.serverUnreachable.title": { + "update.installingAndRestarting": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Server Unreachable" + "value": "Installing update and preparing to restart" } }, "ja": { "stringUnit": { "state": "translated", - "value": "サーバーに接続できません" + "value": "アップデートをインストールして再起動を準備中" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "服务器不可达" + "value": "正在安装更新并准备重启" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "伺服器無法連線" + "value": "正在安裝更新並準備重新啟動" } }, "ko": { "stringUnit": { "state": "translated", - "value": "서버에 연결할 수 없음" + "value": "업데이트 설치 및 재시작 준비 중" } }, "de": { "stringUnit": { "state": "translated", - "value": "Server nicht erreichbar" + "value": "Update wird installiert und Neustart wird vorbereitet" } }, "es": { "stringUnit": { "state": "translated", - "value": "Servidor inaccesible" + "value": "Instalando la actualización y preparando el reinicio" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Serveur inaccessible" + "value": "Installation de la mise à jour et préparation du redémarrage" } }, "it": { "stringUnit": { "state": "translated", - "value": "Server non raggiungibile" + "value": "Installazione dell'aggiornamento e preparazione al riavvio" } }, "da": { "stringUnit": { "state": "translated", - "value": "Server utilgængelig" + "value": "Installerer opdatering og forbereder genstart" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Serwer nieosiągalny" + "value": "Instalowanie aktualizacji i przygotowywanie do ponownego uruchomienia" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Сервер недоступен" + "value": "Установка обновления и подготовка к перезапуску" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Server nedostupan" + "value": "Instaliranje ažuriranja i priprema za ponovni start" } }, "ar": { "stringUnit": { "state": "translated", - "value": "الخادم غير قابل للوصول" + "value": "جارٍ تثبيت التحديث والتحضير لإعادة التشغيل" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Server utilgjengelig" + "value": "Installerer oppdatering og forbereder omstart" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Servidor Inacessível" + "value": "Instalando a atualização e preparando para reiniciar" } }, "th": { "stringUnit": { "state": "translated", - "value": "เซิร์ฟเวอร์เข้าถึงไม่ได้" + "value": "กำลังติดตั้งอัปเดตและเตรียมรีสตาร์ต" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Sunucuya Erişilemiyor" + "value": "Güncelleme yükleniyor ve yeniden başlatmaya hazırlanıyor" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Сервер недоступний" + "value": "Встановлення оновлення та підготовка до перезапуску" } } } }, - "update.error.signatureError.message": { + "update.noUpdates.message": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "The update's signature could not be verified. Please try again later." + "value": "You are running the latest version" } }, "ja": { "stringUnit": { "state": "translated", - "value": "アップデートの署名を検証できませんでした。後でもう一度お試しください。" + "value": "最新バージョンを使用しています" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "无法验证更新的签名。请稍后重试。" + "value": "您正在运行最新版本" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "無法驗證更新的簽章。請稍後再試。" + "value": "您正在執行最新版本" } }, "ko": { "stringUnit": { "state": "translated", - "value": "업데이트 서명을 확인할 수 없습니다. 나중에 다시 시도하세요." + "value": "최신 버전을 사용 중입니다" } }, "de": { "stringUnit": { "state": "translated", - "value": "Die Signatur des Updates konnte nicht überprüft werden. Bitte versuchen Sie es später erneut." + "value": "Sie verwenden die neueste Version" } }, "es": { "stringUnit": { "state": "translated", - "value": "No se pudo verificar la firma de la actualización. Inténtalo de nuevo más tarde." + "value": "Estás ejecutando la última versión" } }, "fr": { "stringUnit": { "state": "translated", - "value": "La signature de la mise à jour n'a pas pu être vérifiée. Veuillez réessayer plus tard." + "value": "Vous utilisez la dernière version" } }, "it": { "stringUnit": { "state": "translated", - "value": "Impossibile verificare la firma dell'aggiornamento. Riprova più tardi." + "value": "Stai utilizzando l'ultima versione" } }, "da": { "stringUnit": { "state": "translated", - "value": "Opdateringens signatur kunne ikke verificeres. Prøv igen senere." + "value": "Du kører den seneste version" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Nie udało się zweryfikować podpisu aktualizacji. Spróbuj ponownie później." + "value": "Używasz najnowszej wersji" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Не удалось проверить подпись обновления. Повторите попытку позже." + "value": "У вас установлена последняя версия" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Potpis ažuriranja nije mogao biti verificiran. Pokušajte ponovo kasnije." + "value": "Koristite najnoviju verziju" } }, "ar": { "stringUnit": { "state": "translated", - "value": "تعذر التحقق من توقيع التحديث. يرجى المحاولة لاحقًا." + "value": "أنت تستخدم أحدث إصدار" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Oppdateringens signatur kunne ikke verifiseres. Prøv igjen senere." + "value": "Du kjører den nyeste versjonen" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "A assinatura da atualização não pôde ser verificada. Tente novamente mais tarde." + "value": "Você está usando a versão mais recente" } }, "th": { "stringUnit": { "state": "translated", - "value": "ไม่สามารถยืนยันลายเซ็นของอัปเดตได้ กรุณาลองอีกครั้งในภายหลัง" + "value": "คุณใช้เวอร์ชันล่าสุดแล้ว" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Güncellemenin imzası doğrulanamadı. Lütfen daha sonra tekrar deneyin." + "value": "En son sürümü kullanıyorsunuz" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Не вдалося перевірити підпис оновлення. Спробуйте пізніше." + "value": "Ви використовуєте найновішу версію" } } } }, - "update.error.signatureError.title": { + "update.noUpdates.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Update Signature Error" + "value": "No Updates Available" } }, "ja": { "stringUnit": { "state": "translated", - "value": "アップデート署名エラー" + "value": "アップデートはありません" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "更新签名错误" + "value": "没有可用更新" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "更新簽章錯誤" + "value": "沒有可用的更新" } }, "ko": { "stringUnit": { "state": "translated", - "value": "업데이트 서명 오류" + "value": "사용 가능한 업데이트 없음" } }, "de": { "stringUnit": { "state": "translated", - "value": "Fehler bei der Update-Signatur" + "value": "Keine Updates verfügbar" } }, "es": { "stringUnit": { "state": "translated", - "value": "Error de firma de actualización" + "value": "No hay actualizaciones disponibles" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Erreur de signature de la mise à jour" + "value": "Aucune mise à jour disponible" } }, "it": { "stringUnit": { "state": "translated", - "value": "Errore firma aggiornamento" + "value": "Nessun aggiornamento disponibile" } }, "da": { "stringUnit": { "state": "translated", - "value": "Fejl i opdateringssignatur" + "value": "Ingen tilgængelige opdateringer" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Błąd podpisu aktualizacji" + "value": "Brak dostępnych aktualizacji" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Ошибка подписи обновления" + "value": "Обновлений нет" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Greška potpisa ažuriranja" + "value": "Nema dostupnih ažuriranja" } }, "ar": { "stringUnit": { "state": "translated", - "value": "خطأ في توقيع التحديث" + "value": "لا توجد تحديثات متوفرة" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Feil i oppdateringssignatur" + "value": "Ingen oppdateringer tilgjengelig" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Erro de Assinatura da Atualização" + "value": "Nenhuma Atualização Disponível" } }, "th": { "stringUnit": { "state": "translated", - "value": "ข้อผิดพลาดลายเซ็นอัปเดต" + "value": "ไม่มีอัปเดตใหม่" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Güncelleme İmza Hatası" + "value": "Güncelleme Yok" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Помилка підпису оновлення" + "value": "Оновлень немає" } } } }, - "update.error.timedOut.message": { + "update.permissionRequest.text": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "The update server took too long to respond. Try again in a moment." + "value": "Enable Automatic Updates?" } }, "ja": { "stringUnit": { "state": "translated", - "value": "アップデートサーバーの応答に時間がかかりすぎました。しばらくしてからもう一度お試しください。" + "value": "自動アップデートを有効にしますか?" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "更新服务器响应超时。请稍后重试。" + "value": "启用自动更新?" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "更新伺服器回應時間過長。請稍後再試。" + "value": "要啟用自動更新嗎?" } }, "ko": { "stringUnit": { "state": "translated", - "value": "업데이트 서버가 응답하는 데 너무 오래 걸렸습니다. 잠시 후 다시 시도하세요." + "value": "자동 업데이트를 활성화하시겠습니까?" } }, "de": { "stringUnit": { "state": "translated", - "value": "Der Update-Server hat zu lange gebraucht, um zu antworten. Versuchen Sie es in einem Moment erneut." + "value": "Automatische Updates aktivieren?" } }, "es": { "stringUnit": { "state": "translated", - "value": "El servidor de actualizaciones tardó demasiado en responder. Inténtalo de nuevo en un momento." + "value": "¿Activar actualizaciones automáticas?" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Le serveur de mises à jour a mis trop de temps à répondre. Réessayez dans un instant." + "value": "Activer les mises à jour automatiques ?" } }, "it": { "stringUnit": { "state": "translated", - "value": "Il server degli aggiornamenti ha impiegato troppo tempo a rispondere. Riprova tra un momento." + "value": "Abilitare gli aggiornamenti automatici?" } }, "da": { "stringUnit": { "state": "translated", - "value": "Opdateringsserveren var for lang tid om at svare. Prøv igen om et øjeblik." + "value": "Aktiver automatiske opdateringer?" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Serwer aktualizacji zbyt długo nie odpowiadał. Spróbuj ponownie za chwilę." + "value": "Włączyć automatyczne aktualizacje?" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Сервер обновлений не ответил вовремя. Повторите попытку через некоторое время." + "value": "Включить автоматические обновления?" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Server za ažuriranje je predugo čekao da odgovori. Pokušajte ponovo za trenutak." + "value": "Omogućiti automatska ažuriranja?" } }, "ar": { "stringUnit": { "state": "translated", - "value": "استغرق خادم التحديثات وقتًا طويلاً للاستجابة. حاول مجددًا بعد لحظة." + "value": "تفعيل التحديثات التلقائية؟" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Oppdateringsserveren brukte for lang tid på å svare. Prøv igjen om et øyeblikk." + "value": "Aktivere automatiske oppdateringer?" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "O servidor de atualização demorou muito para responder. Tente novamente em instantes." + "value": "Ativar Atualizações Automáticas?" } }, "th": { "stringUnit": { "state": "translated", - "value": "เซิร์ฟเวอร์อัปเดตใช้เวลานานเกินไปในการตอบกลับ ลองอีกครั้งในอีกสักครู่" + "value": "เปิดใช้งานการอัปเดตอัตโนมัติหรือไม่?" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Güncelleme sunucusu yanıt vermekte çok uzun sürdü. Birazdan tekrar deneyin." + "value": "Otomatik Güncellemeler Etkinleştirilsin mi?" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Сервер оновлень не відповів вчасно. Спробуйте через деякий час." + "value": "Увімкнути автоматичне оновлення?" } } } }, - "update.error.timedOut.title": { + "update.pleaseWait": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Update Timed Out" + "value": "Please wait while we check for available updates" } }, "ja": { "stringUnit": { "state": "translated", - "value": "アップデートがタイムアウトしました" + "value": "アップデートを確認しています。しばらくお待ちください" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "更新超时" + "value": "正在检查可用更新,请稍候" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "更新逾時" + "value": "請稍候,正在檢查可用的更新" } }, "ko": { "stringUnit": { "state": "translated", - "value": "업데이트 시간 초과" + "value": "사용 가능한 업데이트를 확인하는 동안 잠시 기다려주세요" } }, "de": { "stringUnit": { "state": "translated", - "value": "Update-Zeitüberschreitung" + "value": "Bitte warten Sie, während nach verfügbaren Updates gesucht wird" } }, "es": { "stringUnit": { "state": "translated", - "value": "Tiempo de espera agotado" + "value": "Espera mientras buscamos actualizaciones disponibles" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Délai de mise à jour dépassé" + "value": "Veuillez patienter pendant la recherche de mises à jour disponibles" } }, "it": { "stringUnit": { "state": "translated", - "value": "Aggiornamento scaduto" + "value": "Attendi mentre verifichiamo gli aggiornamenti disponibili" } }, "da": { "stringUnit": { "state": "translated", - "value": "Opdatering fik timeout" + "value": "Vent venligst, mens vi søger efter tilgængelige opdateringer" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Przekroczono limit czasu aktualizacji" + "value": "Proszę czekać, sprawdzamy dostępne aktualizacje" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Время ожидания обновления истекло" + "value": "Подождите, пока мы проверяем наличие обновлений" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Isteklo vrijeme ažuriranja" + "value": "Pričekajte dok provjeravamo dostupna ažuriranja" } }, "ar": { "stringUnit": { "state": "translated", - "value": "انتهت مهلة التحديث" + "value": "يرجى الانتظار أثناء التحقق من التحديثات المتوفرة" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Oppdatering tidsavbrutt" + "value": "Vennligst vent mens vi ser etter tilgjengelige oppdateringer" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Tempo de Atualização Esgotado" + "value": "Aguarde enquanto verificamos as atualizações disponíveis" } }, "th": { "stringUnit": { "state": "translated", - "value": "การอัปเดตหมดเวลา" + "value": "กรุณารอขณะตรวจหาอัปเดตที่มีอยู่" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Güncelleme Zaman Aşımına Uğradı" + "value": "Mevcut güncellemeler denetlenirken lütfen bekleyin" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Час очікування оновлення вичерпано" + "value": "Зачекайте, поки ми перевіряємо наявність оновлень" } } } }, - "update.extracting.progress": { + "update.popover.autoUpdatesDescription": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Preparing: %@" + "value": "cmux can automatically check for updates in the background." } }, "ja": { "stringUnit": { "state": "translated", - "value": "準備中: %@" + "value": "cmux はバックグラウンドで自動的にアップデートを確認できます。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "正在准备:%@" + "value": "cmux 可以在后台自动检查更新。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "正在準備:%@" + "value": "cmux 可以在背景自動檢查更新。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "준비 중: %@" + "value": "cmux가 백그라운드에서 자동으로 업데이트를 확인할 수 있습니다." } }, "de": { "stringUnit": { "state": "translated", - "value": "Vorbereitung: %@" + "value": "cmux kann automatisch im Hintergrund nach Updates suchen." } }, "es": { "stringUnit": { "state": "translated", - "value": "Preparando: %@" + "value": "cmux puede buscar actualizaciones automáticamente en segundo plano." } }, "fr": { "stringUnit": { "state": "translated", - "value": "Préparation : %@" + "value": "cmux peut rechercher automatiquement les mises à jour en arrière-plan." } }, "it": { "stringUnit": { "state": "translated", - "value": "Preparazione: %@" + "value": "cmux può verificare automaticamente la disponibilità di aggiornamenti in background." } }, "da": { "stringUnit": { "state": "translated", - "value": "Forbereder: %@" + "value": "cmux kan automatisk søge efter opdateringer i baggrunden." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Przygotowywanie: %@" + "value": "cmux może automatycznie sprawdzać aktualizacje w tle." } }, "ru": { "stringUnit": { "state": "translated", - "value": "Подготовка: %@" + "value": "cmux может автоматически проверять наличие обновлений в фоновом режиме." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Priprema: %@" + "value": "cmux može automatski provjeravati ažuriranja u pozadini." } }, "ar": { "stringUnit": { "state": "translated", - "value": "جارٍ التحضير: %@" + "value": "يمكن لـ cmux التحقق تلقائيًا من التحديثات في الخلفية." } }, "nb": { "stringUnit": { "state": "translated", - "value": "Forbereder: %@" + "value": "cmux kan automatisk se etter oppdateringer i bakgrunnen." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Preparando: %@" + "value": "O cmux pode verificar automaticamente se há atualizações em segundo plano." } }, "th": { "stringUnit": { "state": "translated", - "value": "กำลังเตรียม: %@" + "value": "cmux สามารถตรวจหาอัปเดตอัตโนมัติในเบื้องหลังได้" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Hazırlanıyor: %@" + "value": "cmux arka planda otomatik olarak güncellemeleri denetleyebilir." } }, "uk": { "stringUnit": { "state": "translated", - "value": "Підготовка: %@" + "value": "cmux може автоматично перевіряти оновлення у фоновому режимі." } } } }, - "update.installAndRelaunch": { + "update.popover.checking": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Install Update and Relaunch" + "value": "Checking for updates…" } }, "ja": { "stringUnit": { "state": "translated", - "value": "アップデートをインストールして再起動" + "value": "アップデートを確認中…" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "安装更新并重新启动" + "value": "正在检查更新..." } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "安裝更新並重新啟動" + "value": "正在檢查更新..." } }, "ko": { "stringUnit": { "state": "translated", - "value": "업데이트 설치 후 재실행" + "value": "업데이트 확인 중…" } }, "de": { "stringUnit": { "state": "translated", - "value": "Update installieren und neu starten" + "value": "Suche nach Updates …" } }, "es": { "stringUnit": { "state": "translated", - "value": "Instalar actualización y reiniciar" + "value": "Buscando actualizaciones…" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Installer la mise à jour et relancer" + "value": "Recherche de mises à jour..." } }, "it": { "stringUnit": { "state": "translated", - "value": "Installa aggiornamento e riavvia" + "value": "Verifica aggiornamenti in corso…" } }, "da": { "stringUnit": { "state": "translated", - "value": "Installer opdatering og genstart" + "value": "Søger efter opdateringer…" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Zainstaluj aktualizację i uruchom ponownie" + "value": "Sprawdzanie aktualizacji…" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Установить обновление и перезапустить" + "value": "Проверка обновлений..." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Instaliraj ažuriranje i ponovo pokreni" + "value": "Provjeravanje ažuriranja…" } }, "ar": { "stringUnit": { "state": "translated", - "value": "تثبيت التحديث وإعادة التشغيل" + "value": "جارٍ التحقق من التحديثات…" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Installer oppdatering og start på nytt" + "value": "Ser etter oppdateringer …" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Instalar Atualização e Reiniciar" + "value": "Verificando atualizações…" } }, "th": { "stringUnit": { "state": "translated", - "value": "ติดตั้งอัปเดตและเปิดใหม่" + "value": "กำลังตรวจหาอัปเดต..." } }, "tr": { "stringUnit": { "state": "translated", - "value": "Güncellemeyi Yükle ve Yeniden Başlat" + "value": "Güncellemeler denetleniyor…" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Встановити оновлення та перезапустити" + "value": "Перевірка оновлень…" } } } }, - "update.installing.status": { + "update.popover.details": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Installing…" + "value": "Details" } }, "ja": { "stringUnit": { "state": "translated", - "value": "インストール中…" + "value": "詳細" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "正在安装..." + "value": "详细信息" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "安裝中..." + "value": "詳細資訊" } }, "ko": { "stringUnit": { "state": "translated", - "value": "설치 중…" + "value": "세부 정보" } }, "de": { "stringUnit": { "state": "translated", - "value": "Wird installiert …" + "value": "Details" } }, "es": { "stringUnit": { "state": "translated", - "value": "Instalando…" + "value": "Detalles" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Installation..." + "value": "Détails" } }, "it": { "stringUnit": { "state": "translated", - "value": "Installazione in corso…" + "value": "Dettagli" } }, "da": { "stringUnit": { "state": "translated", - "value": "Installerer…" + "value": "Detaljer" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Instalowanie…" + "value": "Szczegóły" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Установка..." + "value": "Подробности" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Instaliranje…" + "value": "Detalji" } }, "ar": { "stringUnit": { "state": "translated", - "value": "جارٍ التثبيت…" + "value": "التفاصيل" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Installerer …" + "value": "Detaljer" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Instalando…" + "value": "Detalhes" } }, "th": { "stringUnit": { "state": "translated", - "value": "กำลังติดตั้ง..." + "value": "รายละเอียด" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Yükleniyor…" + "value": "Ayrıntılar" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Встановлення…" + "value": "Деталі" } } } }, - "update.installingAndRestarting": { + "update.popover.downloadingUpdate": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Installing update and preparing to restart" + "value": "Downloading Update" } }, "ja": { "stringUnit": { "state": "translated", - "value": "アップデートをインストールして再起動を準備中" + "value": "アップデートをダウンロード中" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "正在安装更新并准备重启" + "value": "正在下载更新" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "正在安裝更新並準備重新啟動" + "value": "正在下載更新" } }, "ko": { "stringUnit": { "state": "translated", - "value": "업데이트 설치 및 재시작 준비 중" + "value": "업데이트 다운로드 중" } }, "de": { "stringUnit": { "state": "translated", - "value": "Update wird installiert und Neustart wird vorbereitet" + "value": "Update wird heruntergeladen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Instalando la actualización y preparando el reinicio" + "value": "Descargando actualización" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Installation de la mise à jour et préparation du redémarrage" + "value": "Téléchargement de la mise à jour" } }, "it": { "stringUnit": { "state": "translated", - "value": "Installazione dell'aggiornamento e preparazione al riavvio" + "value": "Download aggiornamento" } }, "da": { "stringUnit": { "state": "translated", - "value": "Installerer opdatering og forbereder genstart" + "value": "Downloader opdatering" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Instalowanie aktualizacji i przygotowywanie do ponownego uruchomienia" + "value": "Pobieranie aktualizacji" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Установка обновления и подготовка к перезапуску" + "value": "Загрузка обновления" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Instaliranje ažuriranja i priprema za ponovni start" + "value": "Preuzimanje ažuriranja" } }, "ar": { "stringUnit": { "state": "translated", - "value": "جارٍ تثبيت التحديث والتحضير لإعادة التشغيل" + "value": "جارٍ تنزيل التحديث" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Installerer oppdatering og forbereder omstart" + "value": "Laster ned oppdatering" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Instalando a atualização e preparando para reiniciar" + "value": "Baixando Atualização" } }, "th": { "stringUnit": { "state": "translated", - "value": "กำลังติดตั้งอัปเดตและเตรียมรีสตาร์ต" + "value": "กำลังดาวน์โหลดอัปเดต" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Güncelleme yükleniyor ve yeniden başlatmaya hazırlanıyor" + "value": "Güncelleme İndiriliyor" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Встановлення оновлення та підготовка до перезапуску" + "value": "Завантаження оновлення" } } } }, - "update.noUpdates.message": { + "update.popover.enableAutoUpdates": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "You are running the latest version" + "value": "Enable automatic updates?" } }, "ja": { "stringUnit": { "state": "translated", - "value": "最新バージョンを使用しています" + "value": "自動アップデートを有効にしますか?" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "您正在运行最新版本" + "value": "启用自动更新?" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "您正在執行最新版本" + "value": "要啟用自動更新嗎?" } }, "ko": { "stringUnit": { "state": "translated", - "value": "최신 버전을 사용 중입니다" + "value": "자동 업데이트를 활성화하시겠습니까?" } }, "de": { "stringUnit": { "state": "translated", - "value": "Sie verwenden die neueste Version" + "value": "Automatische Updates aktivieren?" } }, "es": { "stringUnit": { "state": "translated", - "value": "Estás ejecutando la última versión" + "value": "¿Activar actualizaciones automáticas?" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Vous utilisez la dernière version" + "value": "Activer les mises à jour automatiques ?" } }, "it": { "stringUnit": { "state": "translated", - "value": "Stai utilizzando l'ultima versione" + "value": "Abilitare gli aggiornamenti automatici?" } }, "da": { "stringUnit": { "state": "translated", - "value": "Du kører den seneste version" + "value": "Aktiver automatiske opdateringer?" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Używasz najnowszej wersji" + "value": "Włączyć automatyczne aktualizacje?" } }, "ru": { "stringUnit": { "state": "translated", - "value": "У вас установлена последняя версия" + "value": "Включить автоматические обновления?" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Koristite najnoviju verziju" + "value": "Omogućiti automatska ažuriranja?" } }, "ar": { "stringUnit": { "state": "translated", - "value": "أنت تستخدم أحدث إصدار" + "value": "تفعيل التحديثات التلقائية؟" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Du kjører den nyeste versjonen" + "value": "Aktivere automatiske oppdateringer?" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Você está usando a versão mais recente" + "value": "Ativar atualizações automáticas?" } }, "th": { "stringUnit": { "state": "translated", - "value": "คุณใช้เวอร์ชันล่าสุดแล้ว" + "value": "เปิดใช้งานการอัปเดตอัตโนมัติหรือไม่?" } }, "tr": { "stringUnit": { "state": "translated", - "value": "En son sürümü kullanıyorsunuz" + "value": "Otomatik güncellemeler etkinleştirilsin mi?" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Ви використовуєте найновішу версію" + "value": "Увімкнути автоматичне оновлення?" } } } }, - "update.noUpdates.title": { + "update.popover.noUpdatesFound": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "No Updates Available" + "value": "No Updates Found" } }, "ja": { "stringUnit": { "state": "translated", - "value": "アップデートはありません" + "value": "アップデートは見つかりませんでした" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "没有可用更新" + "value": "未发现更新" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "沒有可用的更新" + "value": "沒有找到更新" } }, "ko": { "stringUnit": { "state": "translated", - "value": "사용 가능한 업데이트 없음" + "value": "업데이트 없음" } }, "de": { "stringUnit": { "state": "translated", - "value": "Keine Updates verfügbar" + "value": "Keine Updates gefunden" } }, "es": { "stringUnit": { "state": "translated", - "value": "No hay actualizaciones disponibles" + "value": "No se encontraron actualizaciones" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Aucune mise à jour disponible" + "value": "Aucune mise à jour trouvée" } }, "it": { "stringUnit": { "state": "translated", - "value": "Nessun aggiornamento disponibile" + "value": "Nessun aggiornamento trovato" } }, "da": { "stringUnit": { "state": "translated", - "value": "Ingen tilgængelige opdateringer" + "value": "Ingen opdateringer fundet" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Brak dostępnych aktualizacji" + "value": "Nie znaleziono aktualizacji" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Обновлений нет" + "value": "Обновлений не найдено" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Nema dostupnih ažuriranja" + "value": "Ažuriranja nisu pronađena" } }, "ar": { "stringUnit": { "state": "translated", - "value": "لا توجد تحديثات متوفرة" + "value": "لم يتم العثور على تحديثات" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Ingen oppdateringer tilgjengelig" + "value": "Ingen oppdateringer funnet" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Nenhuma Atualização Disponível" + "value": "Nenhuma Atualização Encontrada" } }, "th": { "stringUnit": { "state": "translated", - "value": "ไม่มีอัปเดตใหม่" + "value": "ไม่พบอัปเดต" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Güncelleme Yok" + "value": "Güncelleme Bulunamadı" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Оновлень немає" + "value": "Оновлень не знайдено" } } } }, - "update.permissionRequest.text": { + "update.popover.noUpdatesFound.message": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Enable Automatic Updates?" + "value": "You're already running the latest version." } }, "ja": { "stringUnit": { "state": "translated", - "value": "自動アップデートを有効にしますか?" + "value": "すでに最新バージョンを使用しています。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "启用自动更新?" + "value": "您已经在运行最新版本。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "要啟用自動更新嗎?" + "value": "您已經在使用最新版本。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "자동 업데이트를 활성화하시겠습니까?" + "value": "이미 최신 버전을 사용 중입니다." } }, "de": { "stringUnit": { "state": "translated", - "value": "Automatische Updates aktivieren?" + "value": "Sie verwenden bereits die neueste Version." } }, "es": { "stringUnit": { "state": "translated", - "value": "¿Activar actualizaciones automáticas?" + "value": "Ya estás ejecutando la última versión." } }, "fr": { "stringUnit": { "state": "translated", - "value": "Activer les mises à jour automatiques ?" + "value": "Vous utilisez déjà la dernière version." } }, "it": { "stringUnit": { "state": "translated", - "value": "Abilitare gli aggiornamenti automatici?" + "value": "Stai già utilizzando l'ultima versione." } }, "da": { "stringUnit": { "state": "translated", - "value": "Aktiver automatiske opdateringer?" + "value": "Du kører allerede den seneste version." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Włączyć automatyczne aktualizacje?" + "value": "Używasz już najnowszej wersji." } }, "ru": { "stringUnit": { "state": "translated", - "value": "Включить автоматические обновления?" + "value": "У вас уже установлена последняя версия." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Omogućiti automatska ažuriranja?" + "value": "Već koristite najnoviju verziju." } }, "ar": { "stringUnit": { "state": "translated", - "value": "تفعيل التحديثات التلقائية؟" + "value": "أنت تستخدم أحدث إصدار بالفعل." } }, "nb": { "stringUnit": { "state": "translated", - "value": "Aktivere automatiske oppdateringer?" + "value": "Du kjører allerede den nyeste versjonen." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Ativar Atualizações Automáticas?" + "value": "Você já está usando a versão mais recente." } }, "th": { "stringUnit": { "state": "translated", - "value": "เปิดใช้งานการอัปเดตอัตโนมัติหรือไม่?" + "value": "คุณใช้เวอร์ชันล่าสุดอยู่แล้ว" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Otomatik Güncellemeler Etkinleştirilsin mi?" + "value": "Zaten en son sürümü kullanıyorsunuz." } }, "uk": { "stringUnit": { "state": "translated", - "value": "Увімкнути автоматичне оновлення?" + "value": "Ви вже використовуєте найновішу версію." } } } }, - "update.pleaseWait": { + "update.popover.preparingUpdate": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Please wait while we check for available updates" + "value": "Preparing Update" } }, "ja": { "stringUnit": { "state": "translated", - "value": "アップデートを確認しています。しばらくお待ちください" + "value": "アップデートを準備中" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "正在检查可用更新,请稍候" + "value": "正在准备更新" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "請稍候,正在檢查可用的更新" + "value": "正在準備更新" } }, "ko": { "stringUnit": { "state": "translated", - "value": "사용 가능한 업데이트를 확인하는 동안 잠시 기다려주세요" + "value": "업데이트 준비 중" } }, "de": { "stringUnit": { "state": "translated", - "value": "Bitte warten Sie, während nach verfügbaren Updates gesucht wird" + "value": "Update wird vorbereitet" } }, "es": { "stringUnit": { "state": "translated", - "value": "Espera mientras buscamos actualizaciones disponibles" + "value": "Preparando actualización" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Veuillez patienter pendant la recherche de mises à jour disponibles" + "value": "Préparation de la mise à jour" } }, "it": { "stringUnit": { "state": "translated", - "value": "Attendi mentre verifichiamo gli aggiornamenti disponibili" + "value": "Preparazione aggiornamento" } }, "da": { "stringUnit": { "state": "translated", - "value": "Vent venligst, mens vi søger efter tilgængelige opdateringer" + "value": "Forbereder opdatering" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Proszę czekać, sprawdzamy dostępne aktualizacje" + "value": "Przygotowywanie aktualizacji" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Подождите, пока мы проверяем наличие обновлений" + "value": "Подготовка обновления" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Pričekajte dok provjeravamo dostupna ažuriranja" + "value": "Priprema ažuriranja" } }, "ar": { "stringUnit": { "state": "translated", - "value": "يرجى الانتظار أثناء التحقق من التحديثات المتوفرة" + "value": "جارٍ تحضير التحديث" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Vennligst vent mens vi ser etter tilgjengelige oppdateringer" + "value": "Forbereder oppdatering" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Aguarde enquanto verificamos as atualizações disponíveis" + "value": "Preparando Atualização" } }, "th": { "stringUnit": { "state": "translated", - "value": "กรุณารอขณะตรวจหาอัปเดตที่มีอยู่" + "value": "กำลังเตรียมอัปเดต" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Mevcut güncellemeler denetlenirken lütfen bekleyin" + "value": "Güncelleme Hazırlanıyor" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Зачекайте, поки ми перевіряємо наявність оновлень" + "value": "Підготовка оновлення" } } } }, - "update.popover.autoUpdatesDescription": { + "update.popover.released": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "cmux can automatically check for updates in the background." + "value": "Released:" } }, "ja": { "stringUnit": { "state": "translated", - "value": "cmux はバックグラウンドで自動的にアップデートを確認できます。" + "value": "リリース日:" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "cmux 可以在后台自动检查更新。" + "value": "发布日期:" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "cmux 可以在背景自動檢查更新。" + "value": "發佈日期:" } }, "ko": { "stringUnit": { "state": "translated", - "value": "cmux가 백그라운드에서 자동으로 업데이트를 확인할 수 있습니다." + "value": "출시일:" } }, "de": { "stringUnit": { "state": "translated", - "value": "cmux kann automatisch im Hintergrund nach Updates suchen." + "value": "Veröffentlicht:" } }, "es": { "stringUnit": { "state": "translated", - "value": "cmux puede buscar actualizaciones automáticamente en segundo plano." + "value": "Publicado:" } }, "fr": { "stringUnit": { "state": "translated", - "value": "cmux peut rechercher automatiquement les mises à jour en arrière-plan." + "value": "Publiée le :" } }, "it": { "stringUnit": { "state": "translated", - "value": "cmux può verificare automaticamente la disponibilità di aggiornamenti in background." + "value": "Rilasciato:" } }, "da": { "stringUnit": { "state": "translated", - "value": "cmux kan automatisk søge efter opdateringer i baggrunden." + "value": "Udgivet:" } }, "pl": { "stringUnit": { "state": "translated", - "value": "cmux może automatycznie sprawdzać aktualizacje w tle." + "value": "Wydano:" } }, "ru": { "stringUnit": { "state": "translated", - "value": "cmux может автоматически проверять наличие обновлений в фоновом режиме." + "value": "Выпущено:" } }, "bs": { "stringUnit": { "state": "translated", - "value": "cmux može automatski provjeravati ažuriranja u pozadini." + "value": "Objavljeno:" } }, "ar": { "stringUnit": { "state": "translated", - "value": "يمكن لـ cmux التحقق تلقائيًا من التحديثات في الخلفية." + "value": "تاريخ الإصدار:" } }, "nb": { "stringUnit": { "state": "translated", - "value": "cmux kan automatisk se etter oppdateringer i bakgrunnen." + "value": "Utgitt:" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "O cmux pode verificar automaticamente se há atualizações em segundo plano." + "value": "Lançado:" } }, "th": { "stringUnit": { "state": "translated", - "value": "cmux สามารถตรวจหาอัปเดตอัตโนมัติในเบื้องหลังได้" + "value": "เผยแพร่:" } }, "tr": { "stringUnit": { "state": "translated", - "value": "cmux arka planda otomatik olarak güncellemeleri denetleyebilir." + "value": "Yayınlanma:" } }, "uk": { "stringUnit": { "state": "translated", - "value": "cmux може автоматично перевіряти оновлення у фоновому режимі." + "value": "Випущено:" } } } }, - "update.popover.checking": { + "update.popover.restartRequired": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Checking for updates…" + "value": "Restart Required" } }, "ja": { "stringUnit": { "state": "translated", - "value": "アップデートを確認中…" + "value": "再起動が必要です" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "正在检查更新..." + "value": "需要重启" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "正在檢查更新..." + "value": "需要重新啟動" } }, "ko": { "stringUnit": { "state": "translated", - "value": "업데이트 확인 중…" + "value": "재시작 필요" } }, "de": { "stringUnit": { "state": "translated", - "value": "Suche nach Updates …" + "value": "Neustart erforderlich" } }, "es": { "stringUnit": { "state": "translated", - "value": "Buscando actualizaciones…" + "value": "Reinicio requerido" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Recherche de mises à jour..." + "value": "Redémarrage requis" } }, "it": { "stringUnit": { "state": "translated", - "value": "Verifica aggiornamenti in corso…" + "value": "Riavvio necessario" } }, "da": { "stringUnit": { "state": "translated", - "value": "Søger efter opdateringer…" + "value": "Genstart påkrævet" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Sprawdzanie aktualizacji…" + "value": "Wymagane ponowne uruchomienie" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Проверка обновлений..." + "value": "Требуется перезапуск" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Provjeravanje ažuriranja…" + "value": "Potreban ponovni start" } }, "ar": { "stringUnit": { "state": "translated", - "value": "جارٍ التحقق من التحديثات…" + "value": "إعادة التشغيل مطلوبة" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Ser etter oppdateringer …" + "value": "Omstart nødvendig" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Verificando atualizações…" + "value": "Reinicialização Necessária" } }, "th": { "stringUnit": { "state": "translated", - "value": "กำลังตรวจหาอัปเดต..." + "value": "ต้องรีสตาร์ต" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Güncellemeler denetleniyor…" + "value": "Yeniden Başlatma Gerekli" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Перевірка оновлень…" + "value": "Потрібен перезапуск" } } } }, - "update.popover.details": { + "update.popover.restartRequired.message": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Details" + "value": "The update is ready. Please restart the application to complete the installation." } }, "ja": { "stringUnit": { "state": "translated", - "value": "詳細" + "value": "アップデートの準備ができました。インストールを完了するにはアプリケーションを再起動してください。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "详细信息" + "value": "更新已就绪。请重启应用程序以完成安装。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "詳細資訊" + "value": "更新已就緒。請重新啟動應用程式以完成安裝。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "세부 정보" + "value": "업데이트가 준비되었습니다. 설치를 완료하려면 앱을 재시작하세요." } }, "de": { "stringUnit": { "state": "translated", - "value": "Details" + "value": "Das Update ist bereit. Bitte starten Sie die Anwendung neu, um die Installation abzuschließen." } }, "es": { "stringUnit": { "state": "translated", - "value": "Detalles" + "value": "La actualización está lista. Reinicia la aplicación para completar la instalación." } }, "fr": { "stringUnit": { "state": "translated", - "value": "Détails" + "value": "La mise à jour est prête. Veuillez redémarrer l'application pour terminer l'installation." } }, "it": { "stringUnit": { "state": "translated", - "value": "Dettagli" + "value": "L'aggiornamento è pronto. Riavvia l'applicazione per completare l'installazione." } }, "da": { "stringUnit": { "state": "translated", - "value": "Detaljer" + "value": "Opdateringen er klar. Genstart programmet for at fuldføre installationen." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Szczegóły" + "value": "Aktualizacja jest gotowa. Uruchom ponownie aplikację, aby zakończyć instalację." } }, "ru": { "stringUnit": { "state": "translated", - "value": "Подробности" + "value": "Обновление готово. Перезапустите приложение для завершения установки." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Detalji" + "value": "Ažuriranje je spremno. Ponovo pokrenite aplikaciju da završite instalaciju." } }, "ar": { "stringUnit": { "state": "translated", - "value": "التفاصيل" + "value": "التحديث جاهز. يرجى إعادة تشغيل التطبيق لإكمال التثبيت." } }, "nb": { "stringUnit": { "state": "translated", - "value": "Detaljer" + "value": "Oppdateringen er klar. Start programmet på nytt for å fullføre installasjonen." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Detalhes" + "value": "A atualização está pronta. Reinicie o aplicativo para concluir a instalação." } }, "th": { "stringUnit": { "state": "translated", - "value": "รายละเอียด" + "value": "อัปเดตพร้อมแล้ว กรุณารีสตาร์ตแอปพลิเคชันเพื่อเสร็จสิ้นการติดตั้ง" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Ayrıntılar" + "value": "Güncelleme hazır. Yüklemeyi tamamlamak için lütfen uygulamayı yeniden başlatın." } }, "uk": { "stringUnit": { "state": "translated", - "value": "Деталі" + "value": "Оновлення готове. Перезапустіть програму для завершення встановлення." } } } }, - "update.popover.downloadingUpdate": { + "update.popover.size": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Downloading Update" + "value": "Size:" } }, "ja": { "stringUnit": { "state": "translated", - "value": "アップデートをダウンロード中" + "value": "サイズ:" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "正在下载更新" + "value": "大小:" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "正在下載更新" + "value": "大小:" } }, "ko": { "stringUnit": { "state": "translated", - "value": "업데이트 다운로드 중" + "value": "크기:" } }, "de": { "stringUnit": { "state": "translated", - "value": "Update wird heruntergeladen" + "value": "Größe:" } }, "es": { "stringUnit": { "state": "translated", - "value": "Descargando actualización" + "value": "Tamaño:" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Téléchargement de la mise à jour" + "value": "Taille :" } }, "it": { "stringUnit": { "state": "translated", - "value": "Download aggiornamento" + "value": "Dimensione:" } }, "da": { "stringUnit": { "state": "translated", - "value": "Downloader opdatering" + "value": "Størrelse:" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Pobieranie aktualizacji" + "value": "Rozmiar:" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Загрузка обновления" + "value": "Размер:" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Preuzimanje ažuriranja" + "value": "Veličina:" } }, "ar": { "stringUnit": { "state": "translated", - "value": "جارٍ تنزيل التحديث" + "value": "الحجم:" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Laster ned oppdatering" + "value": "Størrelse:" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Baixando Atualização" + "value": "Tamanho:" } }, "th": { "stringUnit": { "state": "translated", - "value": "กำลังดาวน์โหลดอัปเดต" + "value": "ขนาด:" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Güncelleme İndiriliyor" + "value": "Boyut:" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Завантаження оновлення" + "value": "Розмір:" } } } }, - "update.popover.enableAutoUpdates": { + "update.popover.updateAvailable": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Enable automatic updates?" + "value": "Update Available" } }, "ja": { "stringUnit": { "state": "translated", - "value": "自動アップデートを有効にしますか?" + "value": "アップデートがあります" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "启用自动更新?" + "value": "有可用更新" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "要啟用自動更新嗎?" + "value": "有可用的更新" } }, "ko": { "stringUnit": { "state": "translated", - "value": "자동 업데이트를 활성화하시겠습니까?" + "value": "업데이트 사용 가능" } }, "de": { "stringUnit": { "state": "translated", - "value": "Automatische Updates aktivieren?" + "value": "Update verfügbar" } }, "es": { "stringUnit": { "state": "translated", - "value": "¿Activar actualizaciones automáticas?" + "value": "Actualización disponible" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Activer les mises à jour automatiques ?" + "value": "Mise à jour disponible" } }, "it": { "stringUnit": { "state": "translated", - "value": "Abilitare gli aggiornamenti automatici?" + "value": "Aggiornamento disponibile" } }, "da": { "stringUnit": { "state": "translated", - "value": "Aktiver automatiske opdateringer?" + "value": "Opdatering tilgængelig" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Włączyć automatyczne aktualizacje?" + "value": "Dostępna aktualizacja" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Включить автоматические обновления?" + "value": "Доступно обновление" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Omogućiti automatska ažuriranja?" + "value": "Ažuriranje dostupno" } }, "ar": { "stringUnit": { "state": "translated", - "value": "تفعيل التحديثات التلقائية؟" + "value": "تحديث متوفر" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Aktivere automatiske oppdateringer?" + "value": "Oppdatering tilgjengelig" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Ativar atualizações automáticas?" + "value": "Atualização Disponível" } }, "th": { "stringUnit": { "state": "translated", - "value": "เปิดใช้งานการอัปเดตอัตโนมัติหรือไม่?" + "value": "มีอัปเดตใหม่" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Otomatik güncellemeler etkinleştirilsin mi?" + "value": "Güncelleme Mevcut" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Увімкнути автоматичне оновлення?" + "value": "Доступне оновлення" } } } }, - "update.popover.noUpdatesFound": { + "update.popover.version": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "No Updates Found" + "value": "Version:" } }, "ja": { "stringUnit": { "state": "translated", - "value": "アップデートは見つかりませんでした" + "value": "バージョン:" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "未发现更新" + "value": "版本:" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "沒有找到更新" + "value": "版本:" } }, "ko": { "stringUnit": { "state": "translated", - "value": "업데이트 없음" + "value": "버전:" } }, "de": { "stringUnit": { "state": "translated", - "value": "Keine Updates gefunden" + "value": "Version:" } }, "es": { "stringUnit": { "state": "translated", - "value": "No se encontraron actualizaciones" + "value": "Versión:" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Aucune mise à jour trouvée" + "value": "Version :" } }, "it": { "stringUnit": { "state": "translated", - "value": "Nessun aggiornamento trovato" + "value": "Versione:" } }, "da": { "stringUnit": { "state": "translated", - "value": "Ingen opdateringer fundet" + "value": "Version:" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Nie znaleziono aktualizacji" + "value": "Wersja:" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Обновлений не найдено" + "value": "Версия:" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Ažuriranja nisu pronađena" + "value": "Verzija:" } }, "ar": { "stringUnit": { "state": "translated", - "value": "لم يتم العثور على تحديثات" + "value": "الإصدار:" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Ingen oppdateringer funnet" + "value": "Versjon:" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Nenhuma Atualização Encontrada" + "value": "Versão:" } }, "th": { "stringUnit": { "state": "translated", - "value": "ไม่พบอัปเดต" + "value": "เวอร์ชัน:" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Güncelleme Bulunamadı" + "value": "Sürüm:" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Оновлень не знайдено" + "value": "Версія:" } } } }, - "update.popover.noUpdatesFound.message": { + "update.preparingUpdate": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "You're already running the latest version." + "value": "Extracting and preparing the update" } }, "ja": { "stringUnit": { "state": "translated", - "value": "すでに最新バージョンを使用しています。" + "value": "アップデートを展開して準備中" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "您已经在运行最新版本。" + "value": "正在解压和准备更新" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "您已經在使用最新版本。" + "value": "正在解壓並準備更新" } }, "ko": { "stringUnit": { "state": "translated", - "value": "이미 최신 버전을 사용 중입니다." + "value": "업데이트 추출 및 준비 중" } }, "de": { "stringUnit": { "state": "translated", - "value": "Sie verwenden bereits die neueste Version." + "value": "Update wird entpackt und vorbereitet" } }, "es": { "stringUnit": { "state": "translated", - "value": "Ya estás ejecutando la última versión." + "value": "Extrayendo y preparando la actualización" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Vous utilisez déjà la dernière version." + "value": "Extraction et préparation de la mise à jour" } }, "it": { "stringUnit": { "state": "translated", - "value": "Stai già utilizzando l'ultima versione." + "value": "Estrazione e preparazione dell'aggiornamento" } }, "da": { "stringUnit": { "state": "translated", - "value": "Du kører allerede den seneste version." + "value": "Udpakker og forbereder opdateringen" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Używasz już najnowszej wersji." + "value": "Rozpakowywanie i przygotowywanie aktualizacji" } }, "ru": { "stringUnit": { "state": "translated", - "value": "У вас уже установлена последняя версия." + "value": "Извлечение и подготовка обновления" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Već koristite najnoviju verziju." + "value": "Izdvajanje i priprema ažuriranja" } }, "ar": { "stringUnit": { "state": "translated", - "value": "أنت تستخدم أحدث إصدار بالفعل." + "value": "جارٍ استخراج التحديث وتحضيره" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Du kjører allerede den nyeste versjonen." + "value": "Pakker ut og forbereder oppdateringen" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Você já está usando a versão mais recente." + "value": "Extraindo e preparando a atualização" } }, "th": { "stringUnit": { "state": "translated", - "value": "คุณใช้เวอร์ชันล่าสุดอยู่แล้ว" + "value": "กำลังแตกไฟล์และเตรียมอัปเดต" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Zaten en son sürümü kullanıyorsunuz." + "value": "Güncelleme çıkarılıyor ve hazırlanıyor" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Ви вже використовуєте найновішу версію." + "value": "Розпакування та підготовка оновлення" } } } }, - "update.popover.preparingUpdate": { + "update.restartToComplete": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Preparing Update" + "value": "Restart to Complete Update" } }, "ja": { "stringUnit": { "state": "translated", - "value": "アップデートを準備中" + "value": "アップデートを完了するには再起動してください" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "正在准备更新" + "value": "重启以完成更新" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "正在準備更新" + "value": "重新啟動以完成更新" } }, "ko": { "stringUnit": { "state": "translated", - "value": "업데이트 준비 중" + "value": "업데이트를 완료하려면 재시작" } }, "de": { "stringUnit": { "state": "translated", - "value": "Update wird vorbereitet" + "value": "Neustart zum Abschließen des Updates" } }, "es": { "stringUnit": { "state": "translated", - "value": "Preparando actualización" + "value": "Reiniciar para completar la actualización" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Préparation de la mise à jour" + "value": "Redémarrer pour terminer la mise à jour" } }, "it": { "stringUnit": { "state": "translated", - "value": "Preparazione aggiornamento" + "value": "Riavvia per completare l'aggiornamento" } }, "da": { "stringUnit": { "state": "translated", - "value": "Forbereder opdatering" + "value": "Genstart for at fuldføre opdatering" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Przygotowywanie aktualizacji" + "value": "Uruchom ponownie, aby zakończyć aktualizację" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Подготовка обновления" + "value": "Перезапустите для завершения обновления" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Priprema ažuriranja" + "value": "Ponovo pokrenite da završite ažuriranje" } }, "ar": { "stringUnit": { "state": "translated", - "value": "جارٍ تحضير التحديث" + "value": "أعد التشغيل لإكمال التحديث" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Forbereder oppdatering" + "value": "Start på nytt for å fullføre oppdateringen" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Preparando Atualização" + "value": "Reiniciar para Concluir a Atualização" } }, "th": { "stringUnit": { "state": "translated", - "value": "กำลังเตรียมอัปเดต" + "value": "รีสตาร์ตเพื่อเสร็จสิ้นการอัปเดต" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Güncelleme Hazırlanıyor" + "value": "Güncellemeyi Tamamlamak İçin Yeniden Başlat" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Підготовка оновлення" + "value": "Перезапустіть для завершення оновлення" } } } }, - "update.popover.released": { + "update.viewGitHubCommit": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Released:" + "value": "View GitHub Commit" } }, "ja": { "stringUnit": { "state": "translated", - "value": "リリース日:" + "value": "GitHub コミットを表示" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "发布日期:" + "value": "查看 GitHub 提交" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "發佈日期:" + "value": "檢視 GitHub 提交" } }, "ko": { "stringUnit": { "state": "translated", - "value": "출시일:" + "value": "GitHub 커밋 보기" } }, "de": { "stringUnit": { "state": "translated", - "value": "Veröffentlicht:" + "value": "GitHub-Commit anzeigen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Publicado:" + "value": "Ver commit en GitHub" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Publiée le :" + "value": "Voir le commit GitHub" } }, "it": { "stringUnit": { "state": "translated", - "value": "Rilasciato:" + "value": "Visualizza commit su GitHub" } }, "da": { "stringUnit": { "state": "translated", - "value": "Udgivet:" + "value": "Vis GitHub Commit" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Wydano:" + "value": "Pokaż commit na GitHub" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Выпущено:" + "value": "Просмотреть коммит на GitHub" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Objavljeno:" + "value": "Pogledaj GitHub commit" } }, "ar": { "stringUnit": { "state": "translated", - "value": "تاريخ الإصدار:" + "value": "عرض إيداع GitHub" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Utgitt:" + "value": "Vis GitHub-commit" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Lançado:" + "value": "Ver Commit no GitHub" } }, "th": { "stringUnit": { "state": "translated", - "value": "เผยแพร่:" + "value": "ดูคอมมิต GitHub" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Yayınlanma:" + "value": "GitHub Commit'ini Görüntüle" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Випущено:" + "value": "Переглянути коміт на GitHub" } } } }, - "update.popover.restartRequired": { + "update.viewReleaseNotes": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Restart Required" + "value": "View Release Notes" } }, "ja": { "stringUnit": { "state": "translated", - "value": "再起動が必要です" + "value": "リリースノートを表示" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "需要重启" + "value": "查看发行说明" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "需要重新啟動" + "value": "檢視版本說明" } }, "ko": { "stringUnit": { "state": "translated", - "value": "재시작 필요" + "value": "릴리스 노트 보기" } }, "de": { "stringUnit": { "state": "translated", - "value": "Neustart erforderlich" + "value": "Versionshinweise anzeigen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Reinicio requerido" + "value": "Ver notas de la versión" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Redémarrage requis" + "value": "Voir les notes de version" } }, "it": { "stringUnit": { "state": "translated", - "value": "Riavvio necessario" + "value": "Visualizza note di rilascio" } }, "da": { "stringUnit": { "state": "translated", - "value": "Genstart påkrævet" + "value": "Vis udgivelsesnoter" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Wymagane ponowne uruchomienie" + "value": "Pokaż informacje o wydaniu" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Требуется перезапуск" + "value": "Просмотреть заметки о выпуске" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Potreban ponovni start" + "value": "Pogledaj bilješke o izdanju" } }, "ar": { "stringUnit": { "state": "translated", - "value": "إعادة التشغيل مطلوبة" + "value": "عرض ملاحظات الإصدار" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Omstart nødvendig" + "value": "Vis versjonsnotater" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Reinicialização Necessária" + "value": "Ver Notas de Lançamento" } }, "th": { "stringUnit": { "state": "translated", - "value": "ต้องรีสตาร์ต" + "value": "ดูบันทึกการเผยแพร่" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Yeniden Başlatma Gerekli" + "value": "Sürüm Notlarını Görüntüle" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Потрібен перезапуск" + "value": "Переглянути примітки до випуску" } } } }, - "update.popover.restartRequired.message": { + "workspace.displayName.fallback": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "The update is ready. Please restart the application to complete the installation." + "value": "Workspace" } }, "ja": { "stringUnit": { "state": "translated", - "value": "アップデートの準備ができました。インストールを完了するにはアプリケーションを再起動してください。" + "value": "ワークスペース" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "更新已就绪。请重启应用程序以完成安装。" + "value": "工作区" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "更新已就緒。請重新啟動應用程式以完成安裝。" + "value": "工作區" } }, "ko": { "stringUnit": { "state": "translated", - "value": "업데이트가 준비되었습니다. 설치를 완료하려면 앱을 재시작하세요." + "value": "작업 공간" } }, "de": { "stringUnit": { "state": "translated", - "value": "Das Update ist bereit. Bitte starten Sie die Anwendung neu, um die Installation abzuschließen." + "value": "Arbeitsbereich" } }, "es": { "stringUnit": { "state": "translated", - "value": "La actualización está lista. Reinicia la aplicación para completar la instalación." + "value": "Espacio de trabajo" } }, "fr": { "stringUnit": { "state": "translated", - "value": "La mise à jour est prête. Veuillez redémarrer l'application pour terminer l'installation." + "value": "Espace de travail" } }, "it": { "stringUnit": { "state": "translated", - "value": "L'aggiornamento è pronto. Riavvia l'applicazione per completare l'installazione." + "value": "Area di lavoro" } }, "da": { "stringUnit": { "state": "translated", - "value": "Opdateringen er klar. Genstart programmet for at fuldføre installationen." + "value": "Arbejdsområde" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Aktualizacja jest gotowa. Uruchom ponownie aplikację, aby zakończyć instalację." + "value": "Przestrzeń robocza" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Обновление готово. Перезапустите приложение для завершения установки." + "value": "Рабочее пространство" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Ažuriranje je spremno. Ponovo pokrenite aplikaciju da završite instalaciju." + "value": "Radni prostor" } }, "ar": { "stringUnit": { "state": "translated", - "value": "التحديث جاهز. يرجى إعادة تشغيل التطبيق لإكمال التثبيت." + "value": "مساحة العمل" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Oppdateringen er klar. Start programmet på nytt for å fullføre installasjonen." + "value": "Arbeidsområde" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "A atualização está pronta. Reinicie o aplicativo para concluir a instalação." + "value": "Área de Trabalho" } }, "th": { "stringUnit": { "state": "translated", - "value": "อัปเดตพร้อมแล้ว กรุณารีสตาร์ตแอปพลิเคชันเพื่อเสร็จสิ้นการติดตั้ง" + "value": "เวิร์กสเปซ" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Güncelleme hazır. Yüklemeyi tamamlamak için lütfen uygulamayı yeniden başlatın." + "value": "Çalışma Alanı" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Оновлення готове. Перезапустіть програму для завершення встановлення." + "value": "Робоча область" } } } }, - "update.popover.size": { + "workspace.closeProtected.message": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Size:" + "value": "Pinned workspaces can't be closed while pinned. Unpin the workspace first." } }, "ja": { "stringUnit": { "state": "translated", - "value": "サイズ:" + "value": "ピン留めされたワークスペースは閉じられません。先にピンを外してください。" + } + }, + "uk": { + "stringUnit": { + "state": "translated", + "value": "Закріплені робочі області не можна закрити, поки вони закріплені. Спочатку відкріпіть робочу область." + } + }, + "ko": { + "stringUnit": { + "state": "translated", + "value": "고정된 워크스페이스는 고정된 상태에서 닫을 수 없습니다. 먼저 워크스페이스의 고정을 해제하세요." + } + } + } + }, + "workspace.placement.afterCurrent": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "After current" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "現在の後" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "大小:" + "value": "当前之后" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "大小:" + "value": "目前之後" } }, "ko": { "stringUnit": { "state": "translated", - "value": "크기:" + "value": "현재 다음" } }, "de": { "stringUnit": { "state": "translated", - "value": "Größe:" + "value": "Nach aktuellem" } }, "es": { "stringUnit": { "state": "translated", - "value": "Tamaño:" + "value": "Después del actual" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Taille :" + "value": "Après l'actuel" } }, "it": { "stringUnit": { "state": "translated", - "value": "Dimensione:" + "value": "Dopo la corrente" } }, "da": { "stringUnit": { "state": "translated", - "value": "Størrelse:" + "value": "Efter nuværende" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Rozmiar:" + "value": "Po bieżącej" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Размер:" + "value": "После текущего" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Veličina:" + "value": "Poslije trenutnog" } }, "ar": { "stringUnit": { "state": "translated", - "value": "الحجم:" + "value": "بعد الحالي" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Størrelse:" + "value": "Etter gjeldende" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Tamanho:" + "value": "Após a atual" } }, "th": { "stringUnit": { "state": "translated", - "value": "ขนาด:" + "value": "หลังรายการปัจจุบัน" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Boyut:" + "value": "Geçerli sonrasına" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Розмір:" + "value": "Після поточної" } } } }, - "update.popover.updateAvailable": { + "workspace.placement.afterCurrent.description": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Update Available" + "value": "Insert new workspaces directly after the active workspace." } }, "ja": { "stringUnit": { "state": "translated", - "value": "アップデートがあります" + "value": "アクティブなワークスペースの直後に新しいワークスペースを挿入します。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "有可用更新" + "value": "在活动工作区之后插入新工作区。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "有可用的更新" + "value": "將新工作區插入目前使用中工作區的後方。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "업데이트 사용 가능" + "value": "활성 작업 공간 바로 다음에 새 작업 공간을 삽입합니다." } }, "de": { "stringUnit": { "state": "translated", - "value": "Update verfügbar" + "value": "Neue Arbeitsbereiche direkt nach dem aktiven Arbeitsbereich einfügen." } }, "es": { "stringUnit": { "state": "translated", - "value": "Actualización disponible" + "value": "Insertar nuevos espacios de trabajo justo después del espacio de trabajo activo." } }, "fr": { "stringUnit": { "state": "translated", - "value": "Mise à jour disponible" + "value": "Insérer les nouveaux espaces de travail juste après l'espace de travail actif." } }, "it": { "stringUnit": { "state": "translated", - "value": "Aggiornamento disponibile" + "value": "Inserisci le nuove aree di lavoro subito dopo quella attiva." } }, "da": { "stringUnit": { "state": "translated", - "value": "Opdatering tilgængelig" + "value": "Indsæt nye arbejdsområder direkte efter det aktive arbejdsområde." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Dostępna aktualizacja" + "value": "Wstaw nowe przestrzenie robocze bezpośrednio po aktywnej." } }, "ru": { "stringUnit": { "state": "translated", - "value": "Доступно обновление" + "value": "Вставлять новые рабочие пространства сразу после активного." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Ažuriranje dostupno" + "value": "Umetnite nove radne prostore odmah nakon aktivnog radnog prostora." } }, "ar": { "stringUnit": { "state": "translated", - "value": "تحديث متوفر" + "value": "إدراج مساحات العمل الجديدة مباشرة بعد مساحة العمل النشطة." } }, "nb": { "stringUnit": { "state": "translated", - "value": "Oppdatering tilgjengelig" + "value": "Sett inn nye arbeidsområder rett etter det aktive arbeidsområdet." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Atualização Disponível" + "value": "Inserir novas áreas de trabalho diretamente após a área de trabalho ativa." } }, "th": { "stringUnit": { "state": "translated", - "value": "มีอัปเดตใหม่" + "value": "แทรกเวิร์กสเปซใหม่หลังเวิร์กสเปซที่ใช้งานอยู่โดยตรง" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Güncelleme Mevcut" + "value": "Yeni çalışma alanlarını etkin çalışma alanının hemen sonrasına ekle." } }, "uk": { "stringUnit": { "state": "translated", - "value": "Доступне оновлення" + "value": "Вставляти нові робочі області одразу після активної." } } } }, - "update.popover.version": { + "workspace.placement.end": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Version:" + "value": "End" } }, "ja": { "stringUnit": { "state": "translated", - "value": "バージョン:" + "value": "末尾" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "版本:" + "value": "末尾" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "版本:" + "value": "底部" } }, "ko": { "stringUnit": { "state": "translated", - "value": "버전:" + "value": "끝" } }, "de": { "stringUnit": { "state": "translated", - "value": "Version:" + "value": "Ende" } }, "es": { "stringUnit": { "state": "translated", - "value": "Versión:" + "value": "Final" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Version :" + "value": "Fin" } }, "it": { "stringUnit": { "state": "translated", - "value": "Versione:" + "value": "Fine" } }, "da": { "stringUnit": { "state": "translated", - "value": "Version:" + "value": "Sidst" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Wersja:" + "value": "Na końcu" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Версия:" + "value": "В конец" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Verzija:" + "value": "Kraj" } }, "ar": { "stringUnit": { "state": "translated", - "value": "الإصدار:" + "value": "النهاية" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Versjon:" + "value": "Slutt" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Versão:" + "value": "Final" } }, "th": { "stringUnit": { "state": "translated", - "value": "เวอร์ชัน:" + "value": "ท้ายสุด" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Sürüm:" + "value": "Sona" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Версія:" + "value": "В кінці" } } } }, - "update.preparingUpdate": { + "workspace.placement.end.description": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Extracting and preparing the update" + "value": "Append new workspaces to the bottom of the list." } }, "ja": { "stringUnit": { "state": "translated", - "value": "アップデートを展開して準備中" + "value": "新しいワークスペースをリストの末尾に追加します。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "正在解压和准备更新" + "value": "将新工作区添加到列表底部。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "正在解壓並準備更新" + "value": "將新工作區附加到列表底部。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "업데이트 추출 및 준비 중" + "value": "목록 하단에 새 작업 공간을 추가합니다." } }, "de": { "stringUnit": { "state": "translated", - "value": "Update wird entpackt und vorbereitet" + "value": "Neue Arbeitsbereiche am Ende der Liste anfügen." } }, "es": { "stringUnit": { "state": "translated", - "value": "Extrayendo y preparando la actualización" + "value": "Agregar nuevos espacios de trabajo al final de la lista." } }, "fr": { "stringUnit": { "state": "translated", - "value": "Extraction et préparation de la mise à jour" + "value": "Ajouter les nouveaux espaces de travail en bas de la liste." } }, "it": { "stringUnit": { "state": "translated", - "value": "Estrazione e preparazione dell'aggiornamento" + "value": "Aggiungi le nuove aree di lavoro in fondo alla lista." } }, "da": { "stringUnit": { "state": "translated", - "value": "Udpakker og forbereder opdateringen" + "value": "Tilføj nye arbejdsområder nederst på listen." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Rozpakowywanie i przygotowywanie aktualizacji" + "value": "Dodaj nowe przestrzenie robocze na dole listy." } }, "ru": { "stringUnit": { "state": "translated", - "value": "Извлечение и подготовка обновления" + "value": "Добавлять новые рабочие пространства в конец списка." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Izdvajanje i priprema ažuriranja" + "value": "Dodajte nove radne prostore na kraj liste." } }, "ar": { "stringUnit": { "state": "translated", - "value": "جارٍ استخراج التحديث وتحضيره" + "value": "إلحاق مساحات العمل الجديدة في أسفل القائمة." } }, "nb": { "stringUnit": { "state": "translated", - "value": "Pakker ut og forbereder oppdateringen" + "value": "Legg til nye arbeidsområder nederst i listen." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Extraindo e preparando a atualização" + "value": "Adicionar novas áreas de trabalho ao final da lista." } }, "th": { "stringUnit": { "state": "translated", - "value": "กำลังแตกไฟล์และเตรียมอัปเดต" + "value": "เพิ่มเวิร์กสเปซใหม่ที่ด้านล่างของรายการ" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Güncelleme çıkarılıyor ve hazırlanıyor" + "value": "Yeni çalışma alanlarını listenin sonuna ekle." } }, "uk": { "stringUnit": { "state": "translated", - "value": "Розпакування та підготовка оновлення" + "value": "Додавати нові робочі області в кінець списку." } } } }, - "update.restartToComplete": { + "workspace.placement.top": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Restart to Complete Update" + "value": "Top" } }, "ja": { "stringUnit": { "state": "translated", - "value": "アップデートを完了するには再起動してください" + "value": "先頭" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "重启以完成更新" + "value": "顶部" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "重新啟動以完成更新" + "value": "最上方" } }, "ko": { "stringUnit": { "state": "translated", - "value": "업데이트를 완료하려면 재시작" + "value": "맨 위" } }, "de": { "stringUnit": { "state": "translated", - "value": "Neustart zum Abschließen des Updates" + "value": "Oben" } }, "es": { "stringUnit": { "state": "translated", - "value": "Reiniciar para completar la actualización" + "value": "Inicio" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Redémarrer pour terminer la mise à jour" + "value": "Début" } }, "it": { "stringUnit": { "state": "translated", - "value": "Riavvia per completare l'aggiornamento" + "value": "Inizio" } }, "da": { "stringUnit": { "state": "translated", - "value": "Genstart for at fuldføre opdatering" + "value": "Øverst" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Uruchom ponownie, aby zakończyć aktualizację" + "value": "Na górze" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Перезапустите для завершения обновления" + "value": "В начало" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Ponovo pokrenite da završite ažuriranje" + "value": "Vrh" } }, "ar": { "stringUnit": { "state": "translated", - "value": "أعد التشغيل لإكمال التحديث" + "value": "الأعلى" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Start på nytt for å fullføre oppdateringen" + "value": "Topp" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Reiniciar para Concluir a Atualização" + "value": "Topo" } }, "th": { "stringUnit": { "state": "translated", - "value": "รีสตาร์ตเพื่อเสร็จสิ้นการอัปเดต" + "value": "ด้านบน" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Güncellemeyi Tamamlamak İçin Yeniden Başlat" + "value": "En Üste" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Перезапустіть для завершення оновлення" + "value": "На початку" } } } }, - "update.viewGitHubCommit": { + "workspace.placement.top.description": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "View GitHub Commit" + "value": "Insert new workspaces at the top of the list." } }, "ja": { "stringUnit": { "state": "translated", - "value": "GitHub コミットを表示" + "value": "新しいワークスペースをリストの先頭に挿入します。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "查看 GitHub 提交" + "value": "在列表顶部插入新工作区。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "檢視 GitHub 提交" + "value": "將新工作區插入列表最上方。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "GitHub 커밋 보기" + "value": "목록 맨 위에 새 작업 공간을 삽입합니다." } }, "de": { "stringUnit": { "state": "translated", - "value": "GitHub-Commit anzeigen" + "value": "Neue Arbeitsbereiche oben in der Liste einfügen." } }, "es": { "stringUnit": { "state": "translated", - "value": "Ver commit en GitHub" + "value": "Insertar nuevos espacios de trabajo al inicio de la lista." } }, "fr": { "stringUnit": { "state": "translated", - "value": "Voir le commit GitHub" + "value": "Insérer les nouveaux espaces de travail en haut de la liste." } }, "it": { "stringUnit": { "state": "translated", - "value": "Visualizza commit su GitHub" + "value": "Inserisci le nuove aree di lavoro in cima alla lista." } }, "da": { "stringUnit": { "state": "translated", - "value": "Vis GitHub Commit" + "value": "Indsæt nye arbejdsområder øverst på listen." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Pokaż commit na GitHub" + "value": "Wstaw nowe przestrzenie robocze na górze listy." } }, "ru": { "stringUnit": { "state": "translated", - "value": "Просмотреть коммит на GitHub" + "value": "Вставлять новые рабочие пространства в начало списка." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Pogledaj GitHub commit" + "value": "Umetnite nove radne prostore na vrh liste." } }, "ar": { "stringUnit": { "state": "translated", - "value": "عرض إيداع GitHub" + "value": "إدراج مساحات العمل الجديدة في أعلى القائمة." } }, "nb": { "stringUnit": { "state": "translated", - "value": "Vis GitHub-commit" + "value": "Sett inn nye arbeidsområder øverst i listen." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Ver Commit no GitHub" + "value": "Inserir novas áreas de trabalho no topo da lista." } }, "th": { "stringUnit": { "state": "translated", - "value": "ดูคอมมิต GitHub" + "value": "แทรกเวิร์กสเปซใหม่ที่ด้านบนของรายการ" } }, "tr": { "stringUnit": { "state": "translated", - "value": "GitHub Commit'ini Görüntüle" + "value": "Yeni çalışma alanlarını listenin en üstüne ekle." } }, "uk": { "stringUnit": { "state": "translated", - "value": "Переглянути коміт на GitHub" + "value": "Вставляти нові робочі області на початок списку." } } } }, - "update.viewReleaseNotes": { + "workspace.tooltip.newBrowser": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "View Release Notes" + "value": "New Browser" } }, "ja": { "stringUnit": { "state": "translated", - "value": "リリースノートを表示" + "value": "新規ブラウザ" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "查看发行说明" + "value": "新建浏览器" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "檢視版本說明" + "value": "新增瀏覽器" } }, "ko": { "stringUnit": { "state": "translated", - "value": "릴리스 노트 보기" + "value": "새 브라우저" } }, "de": { "stringUnit": { "state": "translated", - "value": "Versionshinweise anzeigen" + "value": "Neuer Browser" } }, "es": { "stringUnit": { "state": "translated", - "value": "Ver notas de la versión" + "value": "Nuevo navegador" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Voir les notes de version" + "value": "Nouveau navigateur" } }, "it": { "stringUnit": { "state": "translated", - "value": "Visualizza note di rilascio" + "value": "Nuovo browser" } }, "da": { "stringUnit": { "state": "translated", - "value": "Vis udgivelsesnoter" + "value": "Ny browser" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Pokaż informacje o wydaniu" + "value": "Nowa przeglądarka" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Просмотреть заметки о выпуске" + "value": "Новый браузер" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Pogledaj bilješke o izdanju" + "value": "Novi preglednik" } }, "ar": { "stringUnit": { "state": "translated", - "value": "عرض ملاحظات الإصدار" + "value": "متصفح جديد" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Vis versjonsnotater" + "value": "Ny nettleser" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Ver Notas de Lançamento" + "value": "Novo Navegador" } }, "th": { "stringUnit": { "state": "translated", - "value": "ดูบันทึกการเผยแพร่" + "value": "เบราว์เซอร์ใหม่" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Sürüm Notlarını Görüntüle" + "value": "Yeni Tarayıcı" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Переглянути примітки до випуску" + "value": "Новий браузер" } } } }, - "workspace.displayName.fallback": { + "workspace.tooltip.newTerminal": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Workspace" + "value": "New Terminal" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ワークスペース" + "value": "新規ターミナル" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "工作区" + "value": "新建终端" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "工作區" + "value": "新增終端機" } }, "ko": { "stringUnit": { "state": "translated", - "value": "작업 공간" + "value": "새 터미널" } }, "de": { "stringUnit": { "state": "translated", - "value": "Arbeitsbereich" + "value": "Neues Terminal" } }, "es": { "stringUnit": { "state": "translated", - "value": "Espacio de trabajo" + "value": "Nuevo terminal" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Espace de travail" + "value": "Nouveau terminal" } }, "it": { "stringUnit": { "state": "translated", - "value": "Area di lavoro" + "value": "Nuovo terminale" } }, "da": { "stringUnit": { "state": "translated", - "value": "Arbejdsområde" + "value": "Ny terminal" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Przestrzeń robocza" + "value": "Nowy terminal" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Рабочее пространство" + "value": "Новый терминал" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Radni prostor" + "value": "Novi terminal" } }, "ar": { "stringUnit": { "state": "translated", - "value": "مساحة العمل" + "value": "طرفية جديدة" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Arbeidsområde" + "value": "Ny terminal" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Área de Trabalho" + "value": "Novo Terminal" } }, "th": { "stringUnit": { "state": "translated", - "value": "เวิร์กสเปซ" + "value": "เทอร์มินัลใหม่" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Çalışma Alanı" - } - }, - "uk": { - "stringUnit": { - "state": "translated", - "value": "Робоча область" - } - } - } - }, - "workspace.closeProtected.message": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Pinned workspaces can't be closed while pinned. Unpin the workspace first." - } - }, - "ja": { - "stringUnit": { - "state": "translated", - "value": "ピン留めされたワークスペースは閉じられません。先にピンを外してください。" + "value": "Yeni Terminal" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Закріплені робочі області не можна закрити, поки вони закріплені. Спочатку відкріпіть робочу область." - } - }, - "ko": { - "stringUnit": { - "state": "translated", - "value": "고정된 워크스페이스는 고정된 상태에서 닫을 수 없습니다. 먼저 워크스페이스의 고정을 해제하세요." + "value": "Новий термінал" } } } }, - "workspace.placement.afterCurrent": { + "workspace.tooltip.splitDown": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "After current" + "value": "Split Down" } }, "ja": { "stringUnit": { "state": "translated", - "value": "現在の後" + "value": "下に分割" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "当前之后" + "value": "向下拆分" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "目前之後" + "value": "向下分割" } }, "ko": { "stringUnit": { "state": "translated", - "value": "현재 다음" + "value": "아래로 분할" } }, "de": { "stringUnit": { "state": "translated", - "value": "Nach aktuellem" + "value": "Nach unten teilen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Después del actual" + "value": "Dividir hacia abajo" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Après l'actuel" + "value": "Diviser vers le bas" } }, "it": { "stringUnit": { "state": "translated", - "value": "Dopo la corrente" + "value": "Dividi in basso" } }, "da": { "stringUnit": { "state": "translated", - "value": "Efter nuværende" + "value": "Opdel nedad" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Po bieżącej" + "value": "Podziel w dół" } }, "ru": { "stringUnit": { "state": "translated", - "value": "После текущего" + "value": "Разделить вниз" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Poslije trenutnog" + "value": "Podijeli dolje" } }, "ar": { "stringUnit": { "state": "translated", - "value": "بعد الحالي" + "value": "تقسيم للأسفل" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Etter gjeldende" + "value": "Del ned" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Após a atual" + "value": "Dividir para Baixo" } }, "th": { "stringUnit": { "state": "translated", - "value": "หลังรายการปัจจุบัน" + "value": "แยกลงล่าง" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Geçerli sonrasına" + "value": "Aşağı Böl" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Після поточної" + "value": "Розділити вниз" } } } }, - "workspace.placement.afterCurrent.description": { + "workspace.tooltip.splitRight": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Insert new workspaces directly after the active workspace." + "value": "Split Right" } }, "ja": { "stringUnit": { "state": "translated", - "value": "アクティブなワークスペースの直後に新しいワークスペースを挿入します。" + "value": "右に分割" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "在活动工作区之后插入新工作区。" + "value": "向右拆分" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "將新工作區插入目前使用中工作區的後方。" + "value": "向右分割" } }, "ko": { "stringUnit": { "state": "translated", - "value": "활성 작업 공간 바로 다음에 새 작업 공간을 삽입합니다." + "value": "오른쪽으로 분할" } }, "de": { "stringUnit": { "state": "translated", - "value": "Neue Arbeitsbereiche direkt nach dem aktiven Arbeitsbereich einfügen." + "value": "Nach rechts teilen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Insertar nuevos espacios de trabajo justo después del espacio de trabajo activo." + "value": "Dividir a la derecha" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Insérer les nouveaux espaces de travail juste après l'espace de travail actif." + "value": "Diviser à droite" } }, "it": { "stringUnit": { "state": "translated", - "value": "Inserisci le nuove aree di lavoro subito dopo quella attiva." + "value": "Dividi a destra" } }, "da": { "stringUnit": { "state": "translated", - "value": "Indsæt nye arbejdsområder direkte efter det aktive arbejdsområde." + "value": "Opdel til højre" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Wstaw nowe przestrzenie robocze bezpośrednio po aktywnej." + "value": "Podziel w prawo" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Вставлять новые рабочие пространства сразу после активного." + "value": "Разделить вправо" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Umetnite nove radne prostore odmah nakon aktivnog radnog prostora." + "value": "Podijeli desno" } }, "ar": { "stringUnit": { "state": "translated", - "value": "إدراج مساحات العمل الجديدة مباشرة بعد مساحة العمل النشطة." + "value": "تقسيم لليمين" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Sett inn nye arbeidsområder rett etter det aktive arbeidsområdet." + "value": "Del til høyre" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Inserir novas áreas de trabalho diretamente após a área de trabalho ativa." + "value": "Dividir à Direita" } }, "th": { "stringUnit": { "state": "translated", - "value": "แทรกเวิร์กสเปซใหม่หลังเวิร์กสเปซที่ใช้งานอยู่โดยตรง" + "value": "แยกไปทางขวา" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Yeni çalışma alanlarını etkin çalışma alanının hemen sonrasına ekle." + "value": "Sağa Böl" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Вставляти нові робочі області одразу після активної." + "value": "Розділити праворуч" } } } }, - "workspace.placement.end": { + "filePreview.openExternally": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "End" + "value": "Open Externally" } }, "ja": { "stringUnit": { "state": "translated", - "value": "末尾" - } - }, - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "末尾" + "value": "外部アプリで開く" } - }, - "zh-Hant": { + } + } + }, + "filePreview.openInApplication": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "底部" + "value": "Open in %@" } }, - "ko": { + "ja": { "stringUnit": { "state": "translated", - "value": "끝" + "value": "%@で開く" } - }, - "de": { + } + } + }, + "filePreview.openWith.menu": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Ende" + "value": "Open With" } }, - "es": { + "ja": { "stringUnit": { "state": "translated", - "value": "Final" + "value": "このアプリケーションで開く" } - }, - "fr": { + } + } + }, + "markdown.copyConfirm.html": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Fin" + "value": "Copied as HTML" } }, - "it": { + "ja": { "stringUnit": { "state": "translated", - "value": "Fine" + "value": "HTMLとしてコピーしました" } - }, - "da": { + } + } + }, + "markdown.copyConfirm.markdown": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Sidst" + "value": "Copied as Markdown" } }, - "pl": { + "ja": { "stringUnit": { "state": "translated", - "value": "Na końcu" + "value": "Markdownとしてコピーしました" } - }, - "ru": { + } + } + }, + "markdown.fileUnavailable.message": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "В конец" + "value": "The file may have been moved or deleted." } }, - "bs": { + "ja": { "stringUnit": { "state": "translated", - "value": "Kraj" + "value": "ファイルが移動または削除された可能性があります。" } }, - "ar": { + "uk": { "stringUnit": { "state": "translated", - "value": "النهاية" + "value": "Можливо, файл було переміщено або видалено." } }, - "nb": { + "ko": { "stringUnit": { "state": "translated", - "value": "Slutt" + "value": "파일이 이동되었거나 삭제되었을 수 있습니다." } - }, - "pt-BR": { + } + } + }, + "markdown.fileUnavailable.title": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Final" + "value": "File unavailable" } }, - "th": { + "ja": { "stringUnit": { "state": "translated", - "value": "ท้ายสุด" + "value": "ファイルを利用できません" } }, - "tr": { + "uk": { "stringUnit": { "state": "translated", - "value": "Sona" + "value": "Файл недоступний" } }, - "uk": { + "ko": { "stringUnit": { "state": "translated", - "value": "В кінці" + "value": "파일을 사용할 수 없음" } } } }, - "workspace.placement.end.description": { + "markdown.mode.preview": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Append new workspaces to the bottom of the list." + "value": "Preview" } }, "ja": { "stringUnit": { "state": "translated", - "value": "新しいワークスペースをリストの末尾に追加します。" - } - }, - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "将新工作区添加到列表底部。" + "value": "プレビュー" } - }, - "zh-Hant": { + } + } + }, + "markdown.mode.showPreview": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "將新工作區附加到列表底部。" + "value": "Show Preview" } }, - "ko": { + "ja": { "stringUnit": { "state": "translated", - "value": "목록 하단에 새 작업 공간을 추가합니다." + "value": "プレビューを表示" } - }, - "de": { + } + } + }, + "markdown.mode.showTextEdit": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Neue Arbeitsbereiche am Ende der Liste anfügen." + "value": "Show TextEdit" } }, - "es": { + "ja": { "stringUnit": { "state": "translated", - "value": "Agregar nuevos espacios de trabajo al final de la lista." + "value": "テキスト編集を表示" } - }, - "fr": { + } + } + }, + "markdown.mode.text": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Ajouter les nouveaux espaces de travail en bas de la liste." + "value": "TextEdit" } }, - "it": { + "ja": { "stringUnit": { "state": "translated", - "value": "Aggiungi le nuove aree di lavoro in fondo alla lista." + "value": "テキスト編集" } - }, - "da": { + } + } + }, + "markdown.mode.toggle": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Tilføj nye arbejdsområder nederst på listen." + "value": "Toggle Markdown Mode" } }, - "pl": { + "ja": { "stringUnit": { "state": "translated", - "value": "Dodaj nowe przestrzenie robocze na dole listy." + "value": "Markdownモードを切り替え" } - }, - "ru": { + } + } + }, + "markdown.toolbar.copyHTML": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Добавлять новые рабочие пространства в конец списка." + "value": "Copy as HTML" } }, - "bs": { + "ja": { "stringUnit": { "state": "translated", - "value": "Dodajte nove radne prostore na kraj liste." + "value": "HTMLとしてコピー" } - }, - "ar": { + } + } + }, + "markdown.toolbar.copyMarkdown": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "إلحاق مساحات العمل الجديدة في أسفل القائمة." + "value": "Copy as Markdown" } }, - "nb": { + "ja": { "stringUnit": { "state": "translated", - "value": "Legg til nye arbeidsområder nederst i listen." + "value": "Markdownとしてコピー" } - }, - "pt-BR": { + } + } + }, + "markdown.toolbar.revert": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Adicionar novas áreas de trabalho ao final da lista." + "value": "Revert" } }, - "th": { + "ja": { "stringUnit": { "state": "translated", - "value": "เพิ่มเวิร์กสเปซใหม่ที่ด้านล่างของรายการ" + "value": "元に戻す" } - }, - "tr": { + } + } + }, + "markdown.toolbar.save": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Yeni çalışma alanlarını listenin sonuna ekle." + "value": "Save" } }, - "uk": { + "ja": { "stringUnit": { "state": "translated", - "value": "Додавати нові робочі області в кінець списку." + "value": "保存" } } } }, - "workspace.placement.top": { + "markdown.web.remoteImageBlocked": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Top" + "value": "Remote image blocked" } }, "ja": { "stringUnit": { "state": "translated", - "value": "先頭" + "value": "リモート画像をブロックしました" } - }, - "zh-Hans": { + } + } + }, + "markdown.web.remoteImageConsentMessage": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "顶部" + "value": "cmux will not contact this image URL until you load this image." } }, - "zh-Hant": { + "ja": { "stringUnit": { "state": "translated", - "value": "最上方" + "value": "この画像を読み込むまで、cmux はこの画像 URL に接続しません。" } - }, - "ko": { + } + } + }, + "markdown.web.remoteImageLoadImage": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "맨 위" + "value": "Load this image" } }, - "de": { + "ja": { "stringUnit": { "state": "translated", - "value": "Oben" + "value": "この画像を読み込む" } - }, - "es": { + } + } + }, + "markdown.web.remoteImageLoading": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Inicio" + "value": "Loading" } }, - "fr": { + "ja": { "stringUnit": { "state": "translated", - "value": "Début" + "value": "読み込み中" } - }, - "it": { + } + } + }, + "markdown.web.remoteImageHTTPSOnly": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Inizio" + "value": "Only HTTPS remote images can be loaded in the viewer." } }, - "da": { + "ja": { + "stringUnit": { + "state": "translated", + "value": "ビューアー内で読み込めるのは HTTPS のリモート画像のみです。" + } + } + } + }, + "markdown.web.remoteImageCopyURL": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Øverst" + "value": "Copy image URL" } }, - "pl": { + "ja": { "stringUnit": { "state": "translated", - "value": "Na górze" + "value": "画像 URL をコピー" } - }, - "ru": { + } + } + }, + "markdown.web.remoteImageCopied": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "В начало" + "value": "Copied" } }, - "bs": { + "ja": { "stringUnit": { "state": "translated", - "value": "Vrh" + "value": "コピーしました" } - }, - "ar": { + } + } + }, + "markdown.web.remoteImageOpenURL": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "الأعلى" + "value": "Open image URL" } }, - "nb": { + "ja": { "stringUnit": { "state": "translated", - "value": "Topp" + "value": "画像 URL を開く" } - }, - "pt-BR": { + } + } + }, + "markdown.web.remoteImageNotAllowed": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Topo" + "value": "This remote image URL cannot be loaded in the viewer." } }, - "th": { + "ja": { "stringUnit": { "state": "translated", - "value": "ด้านบน" + "value": "このリモート画像 URL はビューアー内で読み込めません。" } - }, - "tr": { + } + } + }, + "markdown.web.remoteImageURL": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "En Üste" + "value": "Image URL: {url}" } }, - "uk": { + "ja": { "stringUnit": { "state": "translated", - "value": "На початку" + "value": "画像 URL: {url}" } } } }, - "workspace.placement.top.description": { + "settings.section.sidebarAppearance": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Insert new workspaces at the top of the list." + "value": "Sidebar" } }, "ja": { "stringUnit": { "state": "translated", - "value": "新しいワークスペースをリストの先頭に挿入します。" + "value": "サイドバー" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "在列表顶部插入新工作区。" + "value": "侧边栏" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "將新工作區插入列表最上方。" + "value": "側邊欄" } }, "ko": { "stringUnit": { "state": "translated", - "value": "목록 맨 위에 새 작업 공간을 삽입합니다." + "value": "사이드바" } }, "de": { "stringUnit": { "state": "translated", - "value": "Neue Arbeitsbereiche oben in der Liste einfügen." + "value": "Seitenleiste" } }, "es": { "stringUnit": { "state": "translated", - "value": "Insertar nuevos espacios de trabajo al inicio de la lista." + "value": "Barra lateral" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Insérer les nouveaux espaces de travail en haut de la liste." + "value": "Barre latérale" } }, "it": { "stringUnit": { "state": "translated", - "value": "Inserisci le nuove aree di lavoro in cima alla lista." + "value": "Barra laterale" } }, "da": { "stringUnit": { "state": "translated", - "value": "Indsæt nye arbejdsområder øverst på listen." + "value": "Sidebjælke" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Wstaw nowe przestrzenie robocze na górze listy." + "value": "Pasek boczny" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Вставлять новые рабочие пространства в начало списка." + "value": "Боковая панель" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Umetnite nove radne prostore na vrh liste." + "value": "Bočna traka" } }, "ar": { "stringUnit": { "state": "translated", - "value": "إدراج مساحات العمل الجديدة في أعلى القائمة." + "value": "الشريط الجانبي" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Sett inn nye arbeidsområder øverst i listen." + "value": "Sidefelt" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Inserir novas áreas de trabalho no topo da lista." + "value": "Barra lateral" } }, "th": { "stringUnit": { "state": "translated", - "value": "แทรกเวิร์กสเปซใหม่ที่ด้านบนของรายการ" + "value": "แถบด้านข้าง" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Yeni çalışma alanlarını listenin en üstüne ekle." + "value": "Kenar Çubuğu" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Вставляти нові робочі області на початок списку." + "value": "Бічна панель" } } } }, - "workspace.tooltip.newBrowser": { + "settings.sidebarAppearance.matchTerminalBackground": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "New Browser" + "value": "Match Terminal Background" } }, "ja": { "stringUnit": { "state": "translated", - "value": "新規ブラウザ" + "value": "ターミナルの背景に合わせる" } }, - "zh-Hans": { + "ar": { "stringUnit": { - "state": "translated", - "value": "新建浏览器" + "state": "needs_review", + "value": "Match Terminal Background" } }, - "zh-Hant": { + "bs": { "stringUnit": { - "state": "translated", - "value": "新增瀏覽器" + "state": "needs_review", + "value": "Match Terminal Background" } }, - "ko": { + "da": { "stringUnit": { - "state": "translated", - "value": "새 브라우저" + "state": "needs_review", + "value": "Match Terminal Background" } }, "de": { "stringUnit": { - "state": "translated", - "value": "Neuer Browser" + "state": "needs_review", + "value": "Match Terminal Background" } }, "es": { "stringUnit": { - "state": "translated", - "value": "Nuevo navegador" + "state": "needs_review", + "value": "Match Terminal Background" } }, "fr": { "stringUnit": { - "state": "translated", - "value": "Nouveau navigateur" + "state": "needs_review", + "value": "Match Terminal Background" } }, "it": { "stringUnit": { - "state": "translated", - "value": "Nuovo browser" + "state": "needs_review", + "value": "Match Terminal Background" } }, - "da": { + "ko": { "stringUnit": { - "state": "translated", - "value": "Ny browser" + "state": "needs_review", + "value": "Match Terminal Background" } }, - "pl": { + "nb": { "stringUnit": { - "state": "translated", - "value": "Nowa przeglądarka" + "state": "needs_review", + "value": "Match Terminal Background" } }, - "ru": { + "pl": { "stringUnit": { - "state": "translated", - "value": "Новый браузер" + "state": "needs_review", + "value": "Match Terminal Background" } }, - "bs": { + "pt-BR": { "stringUnit": { - "state": "translated", - "value": "Novi preglednik" + "state": "needs_review", + "value": "Match Terminal Background" } }, - "ar": { + "ru": { "stringUnit": { - "state": "translated", - "value": "متصفح جديد" + "state": "needs_review", + "value": "Match Terminal Background" } }, - "nb": { + "th": { "stringUnit": { - "state": "translated", - "value": "Ny nettleser" + "state": "needs_review", + "value": "Match Terminal Background" } }, - "pt-BR": { + "tr": { "stringUnit": { - "state": "translated", - "value": "Novo Navegador" + "state": "needs_review", + "value": "Match Terminal Background" } }, - "th": { + "uk": { "stringUnit": { - "state": "translated", - "value": "เบราว์เซอร์ใหม่" + "state": "needs_review", + "value": "Match Terminal Background" } }, - "tr": { + "zh-Hans": { "stringUnit": { - "state": "translated", - "value": "Yeni Tarayıcı" + "state": "needs_review", + "value": "Match Terminal Background" } }, - "uk": { + "zh-Hant": { "stringUnit": { - "state": "translated", - "value": "Новий браузер" + "state": "needs_review", + "value": "Match Terminal Background" } } } }, - "workspace.tooltip.newTerminal": { + "settings.sidebarAppearance.matchTerminalBackground.subtitle": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "New Terminal" + "value": "Use the same background color and transparency as the terminal." } }, "ja": { "stringUnit": { "state": "translated", - "value": "新規ターミナル" + "value": "ターミナルと同じ背景色と透明度を使用します。" } }, - "zh-Hans": { + "ar": { "stringUnit": { - "state": "translated", - "value": "新建终端" + "state": "needs_review", + "value": "Use the same background color and transparency as the terminal." } }, - "zh-Hant": { + "bs": { "stringUnit": { - "state": "translated", - "value": "新增終端機" + "state": "needs_review", + "value": "Use the same background color and transparency as the terminal." } }, - "ko": { + "da": { "stringUnit": { - "state": "translated", - "value": "새 터미널" + "state": "needs_review", + "value": "Use the same background color and transparency as the terminal." } }, "de": { "stringUnit": { - "state": "translated", - "value": "Neues Terminal" + "state": "needs_review", + "value": "Use the same background color and transparency as the terminal." } }, "es": { "stringUnit": { - "state": "translated", - "value": "Nuevo terminal" + "state": "needs_review", + "value": "Use the same background color and transparency as the terminal." } }, "fr": { "stringUnit": { - "state": "translated", - "value": "Nouveau terminal" + "state": "needs_review", + "value": "Use the same background color and transparency as the terminal." } }, "it": { "stringUnit": { - "state": "translated", - "value": "Nuovo terminale" + "state": "needs_review", + "value": "Use the same background color and transparency as the terminal." } }, - "da": { + "ko": { "stringUnit": { - "state": "translated", - "value": "Ny terminal" + "state": "needs_review", + "value": "Use the same background color and transparency as the terminal." } }, - "pl": { + "nb": { "stringUnit": { - "state": "translated", - "value": "Nowy terminal" + "state": "needs_review", + "value": "Use the same background color and transparency as the terminal." } }, - "ru": { + "pl": { "stringUnit": { - "state": "translated", - "value": "Новый терминал" + "state": "needs_review", + "value": "Use the same background color and transparency as the terminal." } }, - "bs": { + "pt-BR": { "stringUnit": { - "state": "translated", - "value": "Novi terminal" + "state": "needs_review", + "value": "Use the same background color and transparency as the terminal." } }, - "ar": { + "ru": { "stringUnit": { - "state": "translated", - "value": "طرفية جديدة" + "state": "needs_review", + "value": "Use the same background color and transparency as the terminal." } }, - "nb": { + "th": { "stringUnit": { - "state": "translated", - "value": "Ny terminal" + "state": "needs_review", + "value": "Use the same background color and transparency as the terminal." } }, - "pt-BR": { + "tr": { "stringUnit": { - "state": "translated", - "value": "Novo Terminal" + "state": "needs_review", + "value": "Use the same background color and transparency as the terminal." } }, - "th": { + "uk": { "stringUnit": { - "state": "translated", - "value": "เทอร์มินัลใหม่" + "state": "needs_review", + "value": "Use the same background color and transparency as the terminal." } }, - "tr": { + "zh-Hans": { "stringUnit": { - "state": "translated", - "value": "Yeni Terminal" + "state": "needs_review", + "value": "Use the same background color and transparency as the terminal." } }, - "uk": { + "zh-Hant": { "stringUnit": { - "state": "translated", - "value": "Новий термінал" + "state": "needs_review", + "value": "Use the same background color and transparency as the terminal." } } } }, - "workspace.tooltip.splitDown": { + "settings.sidebarAppearance.tintColorLight": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Split Down" + "value": "Light Mode Tint" } }, "ja": { "stringUnit": { "state": "translated", - "value": "下に分割" + "value": "ライトモードのティント" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "向下拆分" + "value": "浅色模式色调" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "向下分割" + "value": "淺色模式色調" } }, "ko": { "stringUnit": { "state": "translated", - "value": "아래로 분할" + "value": "라이트 모드 색조" } }, "de": { "stringUnit": { "state": "translated", - "value": "Nach unten teilen" + "value": "Farbton im hellen Modus" } }, "es": { "stringUnit": { "state": "translated", - "value": "Dividir hacia abajo" + "value": "Tinte del modo claro" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Diviser vers le bas" + "value": "Teinte du mode clair" } }, "it": { "stringUnit": { "state": "translated", - "value": "Dividi in basso" + "value": "Tinta modalità chiara" } }, "da": { "stringUnit": { "state": "translated", - "value": "Opdel nedad" + "value": "Lys tilstand farvetone" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Podziel w dół" + "value": "Odcień trybu jasnego" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Разделить вниз" + "value": "Оттенок светлого режима" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Podijeli dolje" + "value": "Nijansa svijetlog načina" } }, "ar": { "stringUnit": { "state": "translated", - "value": "تقسيم للأسفل" + "value": "لون الوضع الفاتح" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Del ned" + "value": "Fargetone for lys modus" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Dividir para Baixo" + "value": "Tonalidade do Modo Claro" } }, "th": { "stringUnit": { "state": "translated", - "value": "แยกลงล่าง" + "value": "โทนสีโหมดสว่าง" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Aşağı Böl" + "value": "Açık Mod Renk Tonu" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Розділити вниз" + "value": "Відтінок для світлого режиму" } } } }, - "workspace.tooltip.splitRight": { + "settings.sidebarAppearance.tintColorLight.subtitle": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Split Right" + "value": "Sidebar tint color when using light appearance." } }, "ja": { "stringUnit": { "state": "translated", - "value": "右に分割" + "value": "ライト表示時のサイドバーのティントカラー。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "向右拆分" + "value": "使用浅色外观时侧边栏的色调颜色。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "向右分割" + "value": "使用淺色外觀時側邊欄的色調顏色。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "오른쪽으로 분할" + "value": "라이트 모양 사용 시 사이드바 색조 색상." } }, "de": { "stringUnit": { "state": "translated", - "value": "Nach rechts teilen" + "value": "Seitenleisten-Farbton bei hellem Erscheinungsbild." } }, "es": { "stringUnit": { "state": "translated", - "value": "Dividir a la derecha" + "value": "Color de tinte de la barra lateral en apariencia clara." } }, "fr": { "stringUnit": { "state": "translated", - "value": "Diviser à droite" + "value": "Couleur de teinte de la barre latérale en apparence claire." } }, "it": { "stringUnit": { "state": "translated", - "value": "Dividi a destra" + "value": "Colore tinta della barra laterale in modalità chiara." } }, "da": { "stringUnit": { "state": "translated", - "value": "Opdel til højre" + "value": "Sidebjælkens farvetone ved lyst udseende." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Podziel w prawo" + "value": "Kolor odcienia paska bocznego w jasnym wyglądzie." } }, "ru": { "stringUnit": { "state": "translated", - "value": "Разделить вправо" + "value": "Цвет оттенка боковой панели в светлом режиме." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Podijeli desno" + "value": "Boja nijanse bočne trake pri svijetlom izgledu." } }, "ar": { "stringUnit": { "state": "translated", - "value": "تقسيم لليمين" + "value": "لون تلوين الشريط الجانبي عند استخدام المظهر الفاتح." } }, "nb": { "stringUnit": { "state": "translated", - "value": "Del til høyre" + "value": "Fargetone for sidefeltet med lyst utseende." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Dividir à Direita" + "value": "Cor de tonalidade da barra lateral na aparência clara." } }, "th": { "stringUnit": { "state": "translated", - "value": "แยกไปทางขวา" + "value": "สีโทนของแถบด้านข้างเมื่อใช้รูปลักษณ์สว่าง" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Sağa Böl" + "value": "Açık görünüm kullanılırken kenar çubuğu renk tonu." } }, "uk": { "stringUnit": { "state": "translated", - "value": "Розділити праворуч" + "value": "Колір відтінку бічної панелі при світлому зовнішньому вигляді." } } } }, - "filePreview.openExternally": { + "settings.sidebarAppearance.tintColorLight.picker": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Open Externally" + "value": "Light tint" } }, "ja": { "stringUnit": { "state": "translated", - "value": "外部アプリで開く" - } - } - } - }, - "filePreview.openInApplication": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Open in %@" + "value": "ライトティント" } }, - "ja": { + "zh-Hans": { "stringUnit": { "state": "translated", - "value": "%@で開く" + "value": "浅色色调" } - } - } - }, - "filePreview.openWith.menu": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "zh-Hant": { "stringUnit": { "state": "translated", - "value": "Open With" + "value": "淺色色調" } }, - "ja": { + "ko": { "stringUnit": { "state": "translated", - "value": "このアプリケーションで開く" + "value": "라이트 색조" } - } - } - }, - "markdown.copyConfirm.html": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "de": { "stringUnit": { "state": "translated", - "value": "Copied as HTML" + "value": "Heller Farbton" } }, - "ja": { + "es": { "stringUnit": { "state": "translated", - "value": "HTMLとしてコピーしました" + "value": "Tinte claro" } - } - } - }, - "markdown.copyConfirm.markdown": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "fr": { "stringUnit": { "state": "translated", - "value": "Copied as Markdown" + "value": "Teinte claire" } }, - "ja": { + "it": { "stringUnit": { "state": "translated", - "value": "Markdownとしてコピーしました" + "value": "Tinta chiara" } - } - } - }, - "markdown.fileUnavailable.message": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "da": { "stringUnit": { "state": "translated", - "value": "The file may have been moved or deleted." + "value": "Lys farvetone" } }, - "ja": { + "pl": { "stringUnit": { "state": "translated", - "value": "ファイルが移動または削除された可能性があります。" + "value": "Jasny odcień" } }, - "uk": { + "ru": { "stringUnit": { "state": "translated", - "value": "Можливо, файл було переміщено або видалено." + "value": "Светлый оттенок" } }, - "ko": { + "bs": { "stringUnit": { "state": "translated", - "value": "파일이 이동되었거나 삭제되었을 수 있습니다." + "value": "Svijetla nijansa" } - } - } - }, - "markdown.fileUnavailable.title": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "ar": { "stringUnit": { "state": "translated", - "value": "File unavailable" + "value": "لون فاتح" } }, - "ja": { + "nb": { "stringUnit": { "state": "translated", - "value": "ファイルを利用できません" + "value": "Lys fargetone" } }, - "uk": { + "pt-BR": { "stringUnit": { "state": "translated", - "value": "Файл недоступний" + "value": "Tonalidade clara" } }, - "ko": { + "th": { "stringUnit": { "state": "translated", - "value": "파일을 사용할 수 없음" - } - } - } - }, - "markdown.mode.preview": { - "extractionState": "manual", - "localizations": { - "en": { + "value": "โทนสว่าง" + } + }, + "tr": { "stringUnit": { "state": "translated", - "value": "Preview" + "value": "Açık ton" } }, - "ja": { + "uk": { "stringUnit": { "state": "translated", - "value": "プレビュー" + "value": "Світлий відтінок" } } } }, - "markdown.mode.showPreview": { + "settings.sidebarAppearance.tintColorDark": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Show Preview" + "value": "Dark Mode Tint" } }, "ja": { "stringUnit": { "state": "translated", - "value": "プレビューを表示" + "value": "ダークモードのティント" } - } - } - }, - "markdown.mode.showTextEdit": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "zh-Hans": { "stringUnit": { "state": "translated", - "value": "Show TextEdit" + "value": "深色模式色调" } }, - "ja": { + "zh-Hant": { "stringUnit": { "state": "translated", - "value": "テキスト編集を表示" + "value": "深色模式色調" } - } - } - }, - "markdown.mode.text": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "ko": { "stringUnit": { "state": "translated", - "value": "TextEdit" + "value": "다크 모드 색조" } }, - "ja": { + "de": { "stringUnit": { "state": "translated", - "value": "テキスト編集" + "value": "Farbton im dunklen Modus" } - } - } - }, - "markdown.mode.toggle": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "es": { "stringUnit": { "state": "translated", - "value": "Toggle Markdown Mode" + "value": "Tinte del modo oscuro" } }, - "ja": { + "fr": { "stringUnit": { "state": "translated", - "value": "Markdownモードを切り替え" + "value": "Teinte du mode sombre" } - } - } - }, - "markdown.toolbar.copyHTML": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "it": { "stringUnit": { "state": "translated", - "value": "Copy as HTML" + "value": "Tinta modalità scura" } }, - "ja": { + "da": { "stringUnit": { "state": "translated", - "value": "HTMLとしてコピー" + "value": "Mørk tilstand farvetone" } - } - } - }, - "markdown.toolbar.copyMarkdown": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "pl": { "stringUnit": { "state": "translated", - "value": "Copy as Markdown" + "value": "Odcień trybu ciemnego" } }, - "ja": { + "ru": { "stringUnit": { "state": "translated", - "value": "Markdownとしてコピー" + "value": "Оттенок тёмного режима" } - } - } - }, - "markdown.toolbar.revert": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "bs": { "stringUnit": { "state": "translated", - "value": "Revert" + "value": "Nijansa tamnog načina" } }, - "ja": { + "ar": { "stringUnit": { "state": "translated", - "value": "元に戻す" + "value": "لون الوضع الداكن" } - } - } - }, - "markdown.toolbar.save": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "nb": { "stringUnit": { "state": "translated", - "value": "Save" + "value": "Fargetone for mørk modus" } }, - "ja": { + "pt-BR": { "stringUnit": { "state": "translated", - "value": "保存" + "value": "Tonalidade do Modo Escuro" } - } - } - }, - "markdown.web.remoteImageBlocked": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "th": { "stringUnit": { "state": "translated", - "value": "Remote image blocked" + "value": "โทนสีโหมดมืด" } }, - "ja": { + "tr": { "stringUnit": { "state": "translated", - "value": "リモート画像をブロックしました" + "value": "Koyu Mod Renk Tonu" + } + }, + "uk": { + "stringUnit": { + "state": "translated", + "value": "Відтінок для темного режиму" } } } }, - "markdown.web.remoteImageConsentMessage": { + "settings.sidebarAppearance.tintColorDark.subtitle": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "cmux will not contact this image URL until you load this image." + "value": "Sidebar tint color when using dark appearance." } }, "ja": { "stringUnit": { "state": "translated", - "value": "この画像を読み込むまで、cmux はこの画像 URL に接続しません。" + "value": "ダーク表示時のサイドバーのティントカラー。" } - } - } - }, - "markdown.web.remoteImageLoadImage": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "zh-Hans": { "stringUnit": { "state": "translated", - "value": "Load this image" + "value": "使用深色外观时侧边栏的色调颜色。" } }, - "ja": { + "zh-Hant": { "stringUnit": { "state": "translated", - "value": "この画像を読み込む" + "value": "使用深色外觀時側邊欄的色調顏色。" } - } - } - }, - "markdown.web.remoteImageLoading": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "ko": { "stringUnit": { "state": "translated", - "value": "Loading" + "value": "다크 모양 사용 시 사이드바 색조 색상." } }, - "ja": { + "de": { "stringUnit": { "state": "translated", - "value": "読み込み中" + "value": "Seitenleisten-Farbton bei dunklem Erscheinungsbild." } - } - } - }, - "markdown.web.remoteImageHTTPSOnly": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "es": { "stringUnit": { "state": "translated", - "value": "Only HTTPS remote images can be loaded in the viewer." + "value": "Color de tinte de la barra lateral en apariencia oscura." } }, - "ja": { + "fr": { "stringUnit": { "state": "translated", - "value": "ビューアー内で読み込めるのは HTTPS のリモート画像のみです。" + "value": "Couleur de teinte de la barre latérale en apparence sombre." } - } - } - }, - "markdown.web.remoteImageCopyURL": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "it": { "stringUnit": { "state": "translated", - "value": "Copy image URL" + "value": "Colore tinta della barra laterale in modalità scura." } }, - "ja": { + "da": { "stringUnit": { "state": "translated", - "value": "画像 URL をコピー" + "value": "Sidebjælkens farvetone ved mørkt udseende." } - } - } - }, - "markdown.web.remoteImageCopied": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "pl": { "stringUnit": { "state": "translated", - "value": "Copied" + "value": "Kolor odcienia paska bocznego w ciemnym wyglądzie." } }, - "ja": { + "ru": { "stringUnit": { "state": "translated", - "value": "コピーしました" + "value": "Цвет оттенка боковой панели в тёмном режиме." } - } - } - }, - "markdown.web.remoteImageOpenURL": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "bs": { "stringUnit": { "state": "translated", - "value": "Open image URL" + "value": "Boja nijanse bočne trake pri tamnom izgledu." } }, - "ja": { + "ar": { "stringUnit": { "state": "translated", - "value": "画像 URL を開く" + "value": "لون تلوين الشريط الجانبي عند استخدام المظهر الداكن." } - } - } - }, - "markdown.web.remoteImageNotAllowed": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "nb": { "stringUnit": { "state": "translated", - "value": "This remote image URL cannot be loaded in the viewer." + "value": "Fargetone for sidefeltet med mørkt utseende." } }, - "ja": { + "pt-BR": { "stringUnit": { "state": "translated", - "value": "このリモート画像 URL はビューアー内で読み込めません。" + "value": "Cor de tonalidade da barra lateral na aparência escura." } - } - } - }, - "markdown.web.remoteImageURL": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "th": { "stringUnit": { "state": "translated", - "value": "Image URL: {url}" + "value": "สีโทนของแถบด้านข้างเมื่อใช้รูปลักษณ์มืด" } }, - "ja": { + "tr": { "stringUnit": { "state": "translated", - "value": "画像 URL: {url}" + "value": "Koyu görünüm kullanılırken kenar çubuğu renk tonu." + } + }, + "uk": { + "stringUnit": { + "state": "translated", + "value": "Колір відтінку бічної панелі при темному зовнішньому вигляді." } } } }, - "settings.section.sidebarAppearance": { + "settings.sidebarAppearance.tintColorDark.picker": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Sidebar" + "value": "Dark tint" } }, "ja": { "stringUnit": { "state": "translated", - "value": "サイドバー" + "value": "ダークティント" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "侧边栏" + "value": "深色色调" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "側邊欄" + "value": "深色色調" } }, "ko": { "stringUnit": { "state": "translated", - "value": "사이드바" + "value": "다크 색조" } }, "de": { "stringUnit": { "state": "translated", - "value": "Seitenleiste" + "value": "Dunkler Farbton" } }, "es": { "stringUnit": { "state": "translated", - "value": "Barra lateral" + "value": "Tinte oscuro" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Barre latérale" + "value": "Teinte sombre" } }, "it": { "stringUnit": { "state": "translated", - "value": "Barra laterale" + "value": "Tinta scura" } }, "da": { "stringUnit": { "state": "translated", - "value": "Sidebjælke" + "value": "Mørk farvetone" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Pasek boczny" + "value": "Ciemny odcień" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Боковая панель" + "value": "Тёмный оттенок" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Bočna traka" + "value": "Tamna nijansa" } }, "ar": { "stringUnit": { "state": "translated", - "value": "الشريط الجانبي" + "value": "لون داكن" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Sidefelt" + "value": "Mørk fargetone" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Barra lateral" + "value": "Tonalidade escura" } }, "th": { "stringUnit": { "state": "translated", - "value": "แถบด้านข้าง" + "value": "โทนมืด" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Kenar Çubuğu" + "value": "Koyu ton" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Бічна панель" + "value": "Темний відтінок" } } } }, - "settings.sidebarAppearance.matchTerminalBackground": { + "settings.sidebarAppearance.tintOpacity": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Match Terminal Background" + "value": "Tint Opacity" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ターミナルの背景に合わせる" + "value": "ティントの不透明度" } }, - "ar": { + "zh-Hans": { "stringUnit": { - "state": "needs_review", - "value": "Match Terminal Background" + "state": "translated", + "value": "色调不透明度" } }, - "bs": { + "zh-Hant": { "stringUnit": { - "state": "needs_review", - "value": "Match Terminal Background" + "state": "translated", + "value": "色調不透明度" } }, - "da": { + "ko": { "stringUnit": { - "state": "needs_review", - "value": "Match Terminal Background" + "state": "translated", + "value": "색조 불투명도" } }, "de": { "stringUnit": { - "state": "needs_review", - "value": "Match Terminal Background" + "state": "translated", + "value": "Farbton-Deckkraft" } }, "es": { "stringUnit": { - "state": "needs_review", - "value": "Match Terminal Background" + "state": "translated", + "value": "Opacidad del tinte" } }, "fr": { "stringUnit": { - "state": "needs_review", - "value": "Match Terminal Background" + "state": "translated", + "value": "Opacité de la teinte" } }, "it": { "stringUnit": { - "state": "needs_review", - "value": "Match Terminal Background" + "state": "translated", + "value": "Opacità tinta" } }, - "ko": { + "da": { "stringUnit": { - "state": "needs_review", - "value": "Match Terminal Background" + "state": "translated", + "value": "Farvetone gennemsigtighed" } }, - "nb": { + "pl": { "stringUnit": { - "state": "needs_review", - "value": "Match Terminal Background" + "state": "translated", + "value": "Krycie odcienia" } }, - "pl": { + "ru": { "stringUnit": { - "state": "needs_review", - "value": "Match Terminal Background" + "state": "translated", + "value": "Непрозрачность оттенка" } }, - "pt-BR": { + "bs": { "stringUnit": { - "state": "needs_review", - "value": "Match Terminal Background" + "state": "translated", + "value": "Prozirnost nijanse" } }, - "ru": { + "ar": { "stringUnit": { - "state": "needs_review", - "value": "Match Terminal Background" + "state": "translated", + "value": "شفافية اللون" } }, - "th": { + "nb": { "stringUnit": { - "state": "needs_review", - "value": "Match Terminal Background" + "state": "translated", + "value": "Fargetone-opasitet" } }, - "tr": { + "pt-BR": { "stringUnit": { - "state": "needs_review", - "value": "Match Terminal Background" + "state": "translated", + "value": "Opacidade da Tonalidade" } }, - "uk": { + "th": { "stringUnit": { - "state": "needs_review", - "value": "Match Terminal Background" + "state": "translated", + "value": "ความทึบของโทนสี" } }, - "zh-Hans": { + "tr": { "stringUnit": { - "state": "needs_review", - "value": "Match Terminal Background" + "state": "translated", + "value": "Renk Tonu Opaklığı" } }, - "zh-Hant": { + "uk": { "stringUnit": { - "state": "needs_review", - "value": "Match Terminal Background" + "state": "translated", + "value": "Непрозорість відтінку" } } } }, - "settings.sidebarAppearance.matchTerminalBackground.subtitle": { + "settings.sidebarAppearance.tintOpacity.subtitle": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Use the same background color and transparency as the terminal." + "value": "How strongly the tint color shows over the sidebar material." } }, "ja": { "stringUnit": { "state": "translated", - "value": "ターミナルと同じ背景色と透明度を使用します。" + "value": "サイドバーの素材上にティントカラーがどの程度表示されるか。" } }, - "ar": { + "zh-Hans": { "stringUnit": { - "state": "needs_review", - "value": "Use the same background color and transparency as the terminal." + "state": "translated", + "value": "色调颜色在侧边栏材质上的显示强度。" } }, - "bs": { + "zh-Hant": { "stringUnit": { - "state": "needs_review", - "value": "Use the same background color and transparency as the terminal." + "state": "translated", + "value": "色調顏色在側邊欄材質上的顯示強度。" } }, - "da": { + "ko": { "stringUnit": { - "state": "needs_review", - "value": "Use the same background color and transparency as the terminal." + "state": "translated", + "value": "사이드바 재질 위에 색조 색상이 표시되는 강도." } }, "de": { "stringUnit": { - "state": "needs_review", - "value": "Use the same background color and transparency as the terminal." + "state": "translated", + "value": "Wie stark der Farbton über dem Seitenleisten-Material sichtbar ist." } }, "es": { "stringUnit": { - "state": "needs_review", - "value": "Use the same background color and transparency as the terminal." + "state": "translated", + "value": "Intensidad del color de tinte sobre el material de la barra lateral." } }, "fr": { "stringUnit": { - "state": "needs_review", - "value": "Use the same background color and transparency as the terminal." + "state": "translated", + "value": "Intensité de la teinte sur le matériau de la barre latérale." } }, "it": { "stringUnit": { - "state": "needs_review", - "value": "Use the same background color and transparency as the terminal." + "state": "translated", + "value": "Intensità della tinta sul materiale della barra laterale." } }, - "ko": { + "da": { "stringUnit": { - "state": "needs_review", - "value": "Use the same background color and transparency as the terminal." + "state": "translated", + "value": "Hvor stærkt farvetonen vises over sidebjælkens materiale." } }, - "nb": { + "pl": { "stringUnit": { - "state": "needs_review", - "value": "Use the same background color and transparency as the terminal." + "state": "translated", + "value": "Jak silnie kolor odcienia jest widoczny na materiale paska bocznego." } }, - "pl": { + "ru": { "stringUnit": { - "state": "needs_review", - "value": "Use the same background color and transparency as the terminal." + "state": "translated", + "value": "Насколько сильно оттенок виден на материале боковой панели." } }, - "pt-BR": { + "bs": { "stringUnit": { - "state": "needs_review", - "value": "Use the same background color and transparency as the terminal." + "state": "translated", + "value": "Koliko jako se boja nijanse prikazuje preko materijala bočne trake." } }, - "ru": { + "ar": { "stringUnit": { - "state": "needs_review", - "value": "Use the same background color and transparency as the terminal." + "state": "translated", + "value": "مدى قوة ظهور لون التلوين فوق مادة الشريط الجانبي." } }, - "th": { + "nb": { "stringUnit": { - "state": "needs_review", - "value": "Use the same background color and transparency as the terminal." + "state": "translated", + "value": "Hvor sterkt fargetonen vises over sidefelts materiale." } }, - "tr": { + "pt-BR": { "stringUnit": { - "state": "needs_review", - "value": "Use the same background color and transparency as the terminal." + "state": "translated", + "value": "Intensidade da cor de tonalidade sobre o material da barra lateral." } }, - "uk": { + "th": { "stringUnit": { - "state": "needs_review", - "value": "Use the same background color and transparency as the terminal." + "state": "translated", + "value": "ความเข้มของสีโทนที่แสดงบนวัสดุแถบด้านข้าง" } }, - "zh-Hans": { + "tr": { "stringUnit": { - "state": "needs_review", - "value": "Use the same background color and transparency as the terminal." + "state": "translated", + "value": "Renk tonunun kenar çubuğu materyali üzerinde ne kadar güçlü göründüğü." } }, - "zh-Hant": { + "uk": { "stringUnit": { - "state": "needs_review", - "value": "Use the same background color and transparency as the terminal." + "state": "translated", + "value": "Наскільки сильно колір відтінку проявляється поверх матеріалу бічної панелі." } } } }, - "settings.sidebarAppearance.tintColorLight": { + "settings.sidebarAppearance.reset": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Light Mode Tint" + "value": "Reset Sidebar Tint" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ライトモードのティント" + "value": "サイドバーのティントをリセット" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "浅色模式色调" + "value": "重置侧边栏色调" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "淺色模式色調" + "value": "重置側邊欄色調" } }, "ko": { "stringUnit": { "state": "translated", - "value": "라이트 모드 색조" + "value": "사이드바 색조 초기화" } }, "de": { "stringUnit": { "state": "translated", - "value": "Farbton im hellen Modus" + "value": "Seitenleisten-Farbton zurücksetzen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Tinte del modo claro" + "value": "Restablecer tinte de la barra lateral" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Teinte du mode clair" + "value": "Réinitialiser la teinte de la barre latérale" } }, "it": { "stringUnit": { "state": "translated", - "value": "Tinta modalità chiara" + "value": "Ripristina tinta barra laterale" } }, "da": { "stringUnit": { "state": "translated", - "value": "Lys tilstand farvetone" + "value": "Nulstil sidebjælkens farvetone" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Odcień trybu jasnego" + "value": "Resetuj odcień paska bocznego" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Оттенок светлого режима" + "value": "Сбросить оттенок боковой панели" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Nijansa svijetlog načina" + "value": "Resetuj nijansu bočne trake" } }, "ar": { "stringUnit": { "state": "translated", - "value": "لون الوضع الفاتح" + "value": "إعادة تعيين لون الشريط الجانبي" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Fargetone for lys modus" + "value": "Tilbakestill sidefelts fargetone" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Tonalidade do Modo Claro" + "value": "Redefinir Tonalidade da Barra Lateral" } }, "th": { "stringUnit": { "state": "translated", - "value": "โทนสีโหมดสว่าง" + "value": "รีเซ็ตโทนสีแถบด้านข้าง" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Açık Mod Renk Tonu" + "value": "Kenar Çubuğu Renk Tonunu Sıfırla" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Відтінок для світлого режиму" + "value": "Скинути відтінок бічної панелі" } } } }, - "settings.sidebarAppearance.tintColorLight.subtitle": { + "settings.sidebarAppearance.reset.subtitle": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Sidebar tint color when using light appearance." + "value": "Restore default sidebar appearance." } }, "ja": { "stringUnit": { "state": "translated", - "value": "ライト表示時のサイドバーのティントカラー。" + "value": "サイドバーの外観をデフォルトに戻す。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "使用浅色外观时侧边栏的色调颜色。" + "value": "恢复默认侧边栏外观。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "使用淺色外觀時側邊欄的色調顏色。" + "value": "恢復預設側邊欄外觀。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "라이트 모양 사용 시 사이드바 색조 색상." + "value": "사이드바 모양을 기본값으로 복원합니다." } }, "de": { "stringUnit": { "state": "translated", - "value": "Seitenleisten-Farbton bei hellem Erscheinungsbild." + "value": "Standard-Seitenleisten-Erscheinungsbild wiederherstellen." } }, "es": { "stringUnit": { "state": "translated", - "value": "Color de tinte de la barra lateral en apariencia clara." + "value": "Restaurar la apariencia predeterminada de la barra lateral." } }, "fr": { "stringUnit": { "state": "translated", - "value": "Couleur de teinte de la barre latérale en apparence claire." + "value": "Restaurer l'apparence par défaut de la barre latérale." } }, "it": { "stringUnit": { "state": "translated", - "value": "Colore tinta della barra laterale in modalità chiara." + "value": "Ripristina l'aspetto predefinito della barra laterale." } }, "da": { "stringUnit": { "state": "translated", - "value": "Sidebjælkens farvetone ved lyst udseende." + "value": "Gendan standardudseendet for sidebjælken." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Kolor odcienia paska bocznego w jasnym wyglądzie." + "value": "Przywróć domyślny wygląd paska bocznego." } }, "ru": { "stringUnit": { "state": "translated", - "value": "Цвет оттенка боковой панели в светлом режиме." + "value": "Восстановить внешний вид боковой панели по умолчанию." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Boja nijanse bočne trake pri svijetlom izgledu." + "value": "Vrati zadani izgled bočne trake." } }, "ar": { "stringUnit": { "state": "translated", - "value": "لون تلوين الشريط الجانبي عند استخدام المظهر الفاتح." + "value": "استعادة مظهر الشريط الجانبي الافتراضي." } }, "nb": { "stringUnit": { "state": "translated", - "value": "Fargetone for sidefeltet med lyst utseende." + "value": "Gjenopprett standard sidefelts utseende." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Cor de tonalidade da barra lateral na aparência clara." + "value": "Restaurar aparência padrão da barra lateral." } }, "th": { "stringUnit": { "state": "translated", - "value": "สีโทนของแถบด้านข้างเมื่อใช้รูปลักษณ์สว่าง" + "value": "คืนค่ารูปลักษณ์แถบด้านข้างเป็นค่าเริ่มต้น" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Açık görünüm kullanılırken kenar çubuğu renk tonu." + "value": "Varsayılan kenar çubuğu görünümünü geri yükle." } }, "uk": { "stringUnit": { "state": "translated", - "value": "Колір відтінку бічної панелі при світлому зовнішньому вигляді." + "value": "Відновити стандартний зовнішній вигляд бічної панелі." } } } }, - "settings.sidebarAppearance.tintColorLight.picker": { + "settings.sidebarAppearance.reset.button": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Light tint" + "value": "Reset" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ライトティント" + "value": "リセット" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "浅色色调" + "value": "重置" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "淺色色調" + "value": "重置" } }, "ko": { "stringUnit": { "state": "translated", - "value": "라이트 색조" + "value": "초기화" } }, "de": { "stringUnit": { "state": "translated", - "value": "Heller Farbton" + "value": "Zurücksetzen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Tinte claro" + "value": "Restablecer" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Teinte claire" + "value": "Réinitialiser" } }, "it": { "stringUnit": { "state": "translated", - "value": "Tinta chiara" + "value": "Ripristina" } }, "da": { "stringUnit": { "state": "translated", - "value": "Lys farvetone" + "value": "Nulstil" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Jasny odcień" + "value": "Resetuj" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Светлый оттенок" + "value": "Сбросить" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Svijetla nijansa" + "value": "Resetuj" } }, "ar": { "stringUnit": { "state": "translated", - "value": "لون فاتح" + "value": "إعادة تعيين" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Lys fargetone" + "value": "Tilbakestill" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Tonalidade clara" + "value": "Redefinir" } }, "th": { "stringUnit": { "state": "translated", - "value": "โทนสว่าง" + "value": "รีเซ็ต" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Açık ton" + "value": "Sıfırla" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Світлий відтінок" + "value": "Скинути" } } } }, - "settings.sidebarAppearance.tintColorDark": { + "settings.sidebarAppearance.defaultLabel": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Dark Mode Tint" + "value": "Default" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ダークモードのティント" + "value": "デフォルト" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "深色模式色调" + "value": "默认" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "深色模式色調" + "value": "預設" } }, "ko": { "stringUnit": { "state": "translated", - "value": "다크 모드 색조" + "value": "기본값" } }, "de": { "stringUnit": { "state": "translated", - "value": "Farbton im dunklen Modus" + "value": "Standard" } }, "es": { "stringUnit": { "state": "translated", - "value": "Tinte del modo oscuro" + "value": "Predeterminado" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Teinte du mode sombre" + "value": "Par défaut" } }, "it": { "stringUnit": { "state": "translated", - "value": "Tinta modalità scura" + "value": "Predefinito" } }, "da": { "stringUnit": { "state": "translated", - "value": "Mørk tilstand farvetone" + "value": "Standard" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Odcień trybu ciemnego" + "value": "Domyślny" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Оттенок тёмного режима" + "value": "По умолчанию" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Nijansa tamnog načina" + "value": "Zadano" } }, "ar": { "stringUnit": { "state": "translated", - "value": "لون الوضع الداكن" + "value": "افتراضي" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Fargetone for mørk modus" + "value": "Standard" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Tonalidade do Modo Escuro" + "value": "Padrão" } }, "th": { "stringUnit": { "state": "translated", - "value": "โทนสีโหมดมืด" + "value": "ค่าเริ่มต้น" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Koyu Mod Renk Tonu" + "value": "Varsayılan" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Відтінок для темного режиму" + "value": "Стандартний" } } } }, - "settings.sidebarAppearance.tintColorDark.subtitle": { + "menu.openInIntelliJ": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Sidebar tint color when using dark appearance." + "value": "Open Current Directory in IntelliJ IDEA" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ダーク表示時のサイドバーのティントカラー。" + "value": "現在のディレクトリを IntelliJ IDEA で開く" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "使用深色外观时侧边栏的色调颜色。" + "value": "在 IntelliJ IDEA 中打开当前目录" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "使用深色外觀時側邊欄的色調顏色。" + "value": "在 IntelliJ IDEA 中開啟目前目錄" } }, "ko": { "stringUnit": { "state": "translated", - "value": "다크 모양 사용 시 사이드바 색조 색상." + "value": "현재 디렉토리를 IntelliJ IDEA에서 열기" } }, "de": { "stringUnit": { "state": "translated", - "value": "Seitenleisten-Farbton bei dunklem Erscheinungsbild." + "value": "Aktuelles Verzeichnis in IntelliJ IDEA öffnen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Color de tinte de la barra lateral en apariencia oscura." + "value": "Abrir directorio actual en IntelliJ IDEA" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Couleur de teinte de la barre latérale en apparence sombre." + "value": "Ouvrir le répertoire courant dans IntelliJ IDEA" } }, "it": { "stringUnit": { "state": "translated", - "value": "Colore tinta della barra laterale in modalità scura." + "value": "Apri la directory corrente in IntelliJ IDEA" } }, "da": { "stringUnit": { "state": "translated", - "value": "Sidebjælkens farvetone ved mørkt udseende." + "value": "Åbn nuværende mappe i IntelliJ IDEA" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Kolor odcienia paska bocznego w ciemnym wyglądzie." + "value": "Otwórz bieżący katalog w IntelliJ IDEA" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Цвет оттенка боковой панели в тёмном режиме." + "value": "Открыть текущий каталог в IntelliJ IDEA" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Boja nijanse bočne trake pri tamnom izgledu." + "value": "Otvori trenutni direktorij u IntelliJ IDEA" } }, "ar": { "stringUnit": { "state": "translated", - "value": "لون تلوين الشريط الجانبي عند استخدام المظهر الداكن." + "value": "فتح الدليل الحالي في IntelliJ IDEA" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Fargetone for sidefeltet med mørkt utseende." + "value": "Åpne gjeldende katalog i IntelliJ IDEA" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Cor de tonalidade da barra lateral na aparência escura." + "value": "Abrir Diretório Atual no IntelliJ IDEA" } }, "th": { "stringUnit": { "state": "translated", - "value": "สีโทนของแถบด้านข้างเมื่อใช้รูปลักษณ์มืด" + "value": "เปิดไดเรกทอรีปัจจุบันใน IntelliJ IDEA" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Koyu görünüm kullanılırken kenar çubuğu renk tonu." + "value": "Geçerli Dizini IntelliJ IDEA'da Aç" } }, "uk": { "stringUnit": { "state": "translated", - "value": "Колір відтінку бічної панелі при темному зовнішньому вигляді." + "value": "Відкрити поточну теку в IntelliJ IDEA" } } } }, - "settings.sidebarAppearance.tintColorDark.picker": { + "error.remoteDrop.invalidFileURL": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Dark tint" + "value": "Dropped item is not a file URL." } }, "ja": { "stringUnit": { "state": "translated", - "value": "ダークティント" - } - }, - "zh-Hans": { - "stringUnit": { - "state": "translated", - "value": "深色色调" + "value": "ドロップされた項目はファイル URL ではありません。" } }, - "zh-Hant": { + "uk": { "stringUnit": { "state": "translated", - "value": "深色色調" + "value": "Перетягнутий елемент не є файловою URL-адресою." } }, "ko": { "stringUnit": { "state": "translated", - "value": "다크 색조" + "value": "드롭한 항목이 파일 URL이 아닙니다." } - }, - "de": { + } + } + }, + "error.remoteDrop.unavailable": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Dunkler Farbton" + "value": "Remote drop is unavailable." } }, - "es": { + "ja": { "stringUnit": { "state": "translated", - "value": "Tinte oscuro" + "value": "リモートへのドロップは利用できません。" } }, - "fr": { + "uk": { "stringUnit": { "state": "translated", - "value": "Teinte sombre" + "value": "Віддалене перетягування недоступне." } }, - "it": { + "ko": { "stringUnit": { "state": "translated", - "value": "Tinta scura" + "value": "원격 드롭을 사용할 수 없습니다." } - }, - "da": { + } + } + }, + "error.remoteDrop.uploadFailed": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Mørk farvetone" + "value": "Failed to upload dropped file: %@" } }, - "pl": { + "ja": { "stringUnit": { "state": "translated", - "value": "Ciemny odcień" + "value": "ドロップされたファイルのアップロードに失敗しました: %@" } }, - "ru": { + "uk": { "stringUnit": { "state": "translated", - "value": "Тёмный оттенок" + "value": "Не вдалося завантажити перетягнутий файл: %@" } }, - "bs": { + "ko": { "stringUnit": { "state": "translated", - "value": "Tamna nijansa" + "value": "드롭한 파일을 업로드하지 못했습니다: %@" } - }, - "ar": { + } + } + }, + "terminalContextMenu.copy": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "لون داكن" + "value": "Copy" } }, - "nb": { + "ja": { "stringUnit": { "state": "translated", - "value": "Mørk fargetone" + "value": "コピー" } }, - "pt-BR": { + "ko": { "stringUnit": { "state": "translated", - "value": "Tonalidade escura" + "value": "복사" } - }, - "th": { + } + } + }, + "terminalContextMenu.copyIdentifiers": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "โทนมืด" + "value": "Copy IDs" } }, - "tr": { + "ja": { "stringUnit": { "state": "translated", - "value": "Koyu ton" + "value": "IDをコピー" } }, - "uk": { + "ko": { "stringUnit": { "state": "translated", - "value": "Темний відтінок" + "value": "ID 복사" } } } }, - "settings.sidebarAppearance.tintOpacity": { + "terminalContextMenu.moveTab": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Tint Opacity" + "value": "Move Tab" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ティントの不透明度" + "value": "タブを移動" } }, - "zh-Hans": { + "ko": { "stringUnit": { "state": "translated", - "value": "色调不透明度" + "value": "탭 이동" + } + } + } + }, + "terminalContextMenu.moveTabToNewWorkspace": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Move Tab to New Workspace" } }, - "zh-Hant": { + "ja": { "stringUnit": { "state": "translated", - "value": "色調不透明度" + "value": "タブを新規ワークスペースに移動" } }, "ko": { "stringUnit": { "state": "translated", - "value": "색조 불투명도" + "value": "탭을 새 작업 공간으로 이동" } - }, - "de": { + } + } + }, + "terminalContextMenu.paste": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Farbton-Deckkraft" + "value": "Paste" } }, - "es": { + "ja": { "stringUnit": { "state": "translated", - "value": "Opacidad del tinte" + "value": "ペースト" } }, - "fr": { + "ko": { "stringUnit": { "state": "translated", - "value": "Opacité de la teinte" + "value": "붙여넣기" } - }, - "it": { + } + } + }, + "terminalContextMenu.resetTerminal": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Opacità tinta" + "value": "Reset Terminal" } }, - "da": { + "ja": { "stringUnit": { "state": "translated", - "value": "Farvetone gennemsigtighed" + "value": "ターミナルをリセット" } }, - "pl": { + "ko": { "stringUnit": { "state": "translated", - "value": "Krycie odcienia" + "value": "터미널 초기화" } - }, - "ru": { + } + } + }, + "terminalContextMenu.splitHorizontally": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Непрозрачность оттенка" + "value": "Split Horizontally" } }, - "bs": { + "ja": { "stringUnit": { "state": "translated", - "value": "Prozirnost nijanse" + "value": "水平に分割" } }, - "ar": { + "ko": { "stringUnit": { "state": "translated", - "value": "شفافية اللون" + "value": "가로 분할" } - }, - "nb": { + } + } + }, + "terminalContextMenu.splitVertically": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Fargetone-opasitet" + "value": "Split Vertically" } }, - "pt-BR": { + "ja": { "stringUnit": { "state": "translated", - "value": "Opacidade da Tonalidade" + "value": "垂直に分割" } }, - "th": { + "ko": { "stringUnit": { "state": "translated", - "value": "ความทึบของโทนสี" + "value": "세로 분할" + } + } + } + }, + "terminalContextMenu.triggerFlash": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Trigger Flash" } }, - "tr": { + "ja": { "stringUnit": { "state": "translated", - "value": "Renk Tonu Opaklığı" + "value": "フラッシュを発火" } }, - "uk": { + "ko": { "stringUnit": { "state": "translated", - "value": "Непрозорість відтінку" + "value": "플래시 실행" } } } }, - "settings.sidebarAppearance.tintOpacity.subtitle": { + "alert.cancel": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "How strongly the tint color shows over the sidebar material." + "value": "Cancel" } }, "ja": { "stringUnit": { "state": "translated", - "value": "サイドバーの素材上にティントカラーがどの程度表示されるか。" + "value": "キャンセル" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "色调颜色在侧边栏材质上的显示强度。" + "value": "取消" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "色調顏色在側邊欄材質上的顯示強度。" + "value": "取消" } }, "ko": { "stringUnit": { "state": "translated", - "value": "사이드바 재질 위에 색조 색상이 표시되는 강도." + "value": "취소" } }, "de": { "stringUnit": { "state": "translated", - "value": "Wie stark der Farbton über dem Seitenleisten-Material sichtbar ist." + "value": "Abbrechen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Intensidad del color de tinte sobre el material de la barra lateral." + "value": "Cancelar" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Intensité de la teinte sur le matériau de la barre latérale." + "value": "Annuler" } }, "it": { "stringUnit": { "state": "translated", - "value": "Intensità della tinta sul materiale della barra laterale." + "value": "Annulla" } }, "da": { "stringUnit": { "state": "translated", - "value": "Hvor stærkt farvetonen vises over sidebjælkens materiale." + "value": "Annuller" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Jak silnie kolor odcienia jest widoczny na materiale paska bocznego." + "value": "Anuluj" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Насколько сильно оттенок виден на материале боковой панели." + "value": "Отмена" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Koliko jako se boja nijanse prikazuje preko materijala bočne trake." + "value": "Otkaži" } }, "ar": { "stringUnit": { "state": "translated", - "value": "مدى قوة ظهور لون التلوين فوق مادة الشريط الجانبي." + "value": "إلغاء" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Hvor sterkt fargetonen vises over sidefelts materiale." + "value": "Avbryt" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Intensidade da cor de tonalidade sobre o material da barra lateral." + "value": "Cancelar" } }, "th": { "stringUnit": { "state": "translated", - "value": "ความเข้มของสีโทนที่แสดงบนวัสดุแถบด้านข้าง" + "value": "ยกเลิก" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Renk tonunun kenar çubuğu materyali üzerinde ne kadar güçlü göründüğü." - } - }, - "uk": { - "stringUnit": { - "state": "translated", - "value": "Наскільки сильно колір відтінку проявляється поверх матеріалу бічної панелі." + "value": "İptal" } } } }, - "settings.sidebarAppearance.reset": { + "alert.moveTab.failed.message": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Reset Sidebar Tint" + "value": "cmux could not move this tab to the selected destination." } }, "ja": { "stringUnit": { "state": "translated", - "value": "サイドバーのティントをリセット" + "value": "cmuxはこのタブを選択した移動先に移動できませんでした。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "重置侧边栏色调" + "value": "cmux 无法将此标签页移动到所选位置。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "重置側邊欄色調" + "value": "cmux 無法將此標籤頁移動到所選位置。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "사이드바 색조 초기화" + "value": "cmux가 이 탭을 선택한 대상으로 이동할 수 없습니다." } }, "de": { "stringUnit": { "state": "translated", - "value": "Seitenleisten-Farbton zurücksetzen" + "value": "cmux konnte diesen Tab nicht zum ausgewählten Ziel verschieben." } }, "es": { "stringUnit": { "state": "translated", - "value": "Restablecer tinte de la barra lateral" + "value": "cmux no pudo mover esta pestaña al destino seleccionado." } }, "fr": { "stringUnit": { "state": "translated", - "value": "Réinitialiser la teinte de la barre latérale" + "value": "cmux n'a pas pu déplacer cet onglet vers la destination sélectionnée." } }, "it": { "stringUnit": { "state": "translated", - "value": "Ripristina tinta barra laterale" + "value": "cmux non è riuscito a spostare questa scheda nella destinazione selezionata." } }, "da": { "stringUnit": { "state": "translated", - "value": "Nulstil sidebjælkens farvetone" + "value": "cmux kunne ikke flytte dette faneblad til den valgte destination." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Resetuj odcień paska bocznego" + "value": "cmux nie mógł przenieść tej karty do wybranego miejsca docelowego." } }, "ru": { "stringUnit": { "state": "translated", - "value": "Сбросить оттенок боковой панели" + "value": "cmux не смог переместить эту вкладку в выбранное место назначения." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Resetuj nijansu bočne trake" + "value": "cmux nije mogao premjestiti ovu karticu na odabrano odredište." } }, "ar": { "stringUnit": { "state": "translated", - "value": "إعادة تعيين لون الشريط الجانبي" + "value": "لم يتمكن cmux من نقل علامة التبويب هذه إلى الوجهة المحددة." } }, "nb": { "stringUnit": { "state": "translated", - "value": "Tilbakestill sidefelts fargetone" + "value": "cmux kunne ikke flytte denne fanen til det valgte målet." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Redefinir Tonalidade da Barra Lateral" + "value": "O cmux não conseguiu mover esta aba para o destino selecionado." } }, "th": { "stringUnit": { "state": "translated", - "value": "รีเซ็ตโทนสีแถบด้านข้าง" + "value": "cmux ไม่สามารถย้ายแท็บนี้ไปยังปลายทางที่เลือกได้" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Kenar Çubuğu Renk Tonunu Sıfırla" - } - }, - "uk": { - "stringUnit": { - "state": "translated", - "value": "Скинути відтінок бічної панелі" + "value": "cmux bu sekmeyi seçilen hedefe taşıyamadı." } } } }, - "settings.sidebarAppearance.reset.subtitle": { + "alert.moveTab.failed.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Restore default sidebar appearance." + "value": "Move Failed" } }, "ja": { "stringUnit": { "state": "translated", - "value": "サイドバーの外観をデフォルトに戻す。" + "value": "移動に失敗" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "恢复默认侧边栏外观。" + "value": "移动失败" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "恢復預設側邊欄外觀。" + "value": "移動失敗" } }, "ko": { "stringUnit": { "state": "translated", - "value": "사이드바 모양을 기본값으로 복원합니다." + "value": "이동 실패" } }, "de": { "stringUnit": { "state": "translated", - "value": "Standard-Seitenleisten-Erscheinungsbild wiederherstellen." + "value": "Verschieben fehlgeschlagen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Restaurar la apariencia predeterminada de la barra lateral." + "value": "Error al mover" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Restaurer l'apparence par défaut de la barre latérale." + "value": "Échec du déplacement" } }, "it": { "stringUnit": { "state": "translated", - "value": "Ripristina l'aspetto predefinito della barra laterale." + "value": "Spostamento non riuscito" } }, "da": { "stringUnit": { "state": "translated", - "value": "Gendan standardudseendet for sidebjælken." + "value": "Flytning mislykkedes" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Przywróć domyślny wygląd paska bocznego." + "value": "Przenoszenie nie powiodło się" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Восстановить внешний вид боковой панели по умолчанию." + "value": "Не удалось переместить" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Vrati zadani izgled bočne trake." + "value": "Premještanje nije uspjelo" } }, "ar": { "stringUnit": { "state": "translated", - "value": "استعادة مظهر الشريط الجانبي الافتراضي." + "value": "فشل النقل" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Gjenopprett standard sidefelts utseende." + "value": "Flytting mislyktes" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Restaurar aparência padrão da barra lateral." + "value": "Falha ao Mover" } }, "th": { "stringUnit": { "state": "translated", - "value": "คืนค่ารูปลักษณ์แถบด้านข้างเป็นค่าเริ่มต้น" + "value": "ย้ายไม่สำเร็จ" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Varsayılan kenar çubuğu görünümünü geri yükle." - } - }, - "uk": { - "stringUnit": { - "state": "translated", - "value": "Відновити стандартний зовнішній вигляд бічної панелі." + "value": "Taşıma Başarısız" } } } }, - "settings.sidebarAppearance.reset.button": { + "alert.moveTab.message": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Reset" + "value": "Choose a destination for this tab." } }, "ja": { "stringUnit": { "state": "translated", - "value": "リセット" + "value": "このタブの移動先を選択してください。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "重置" + "value": "选择此标签页的目标位置。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "重置" + "value": "選擇此標籤頁的目標位置。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "초기화" + "value": "이 탭의 대상을 선택하세요." } }, "de": { "stringUnit": { "state": "translated", - "value": "Zurücksetzen" + "value": "Wählen Sie ein Ziel für diesen Tab." } }, "es": { "stringUnit": { "state": "translated", - "value": "Restablecer" + "value": "Elige un destino para esta pestaña." } }, "fr": { "stringUnit": { "state": "translated", - "value": "Réinitialiser" + "value": "Choisissez une destination pour cet onglet." } }, "it": { "stringUnit": { "state": "translated", - "value": "Ripristina" + "value": "Scegli una destinazione per questa scheda." } }, "da": { "stringUnit": { "state": "translated", - "value": "Nulstil" + "value": "Vælg en destination for dette faneblad." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Resetuj" + "value": "Wybierz miejsce docelowe dla tej karty." } }, "ru": { "stringUnit": { "state": "translated", - "value": "Сбросить" + "value": "Выберите назначение для этой вкладки." } }, "bs": { "stringUnit": { "state": "translated", - "value": "Resetuj" + "value": "Odaberite odredište za ovu karticu." } }, "ar": { "stringUnit": { "state": "translated", - "value": "إعادة تعيين" + "value": "اختر وجهة لعلامة التبويب هذه." } }, "nb": { "stringUnit": { "state": "translated", - "value": "Tilbakestill" + "value": "Velg et mål for denne fanen." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Redefinir" + "value": "Escolha um destino para esta aba." } }, "th": { "stringUnit": { "state": "translated", - "value": "รีเซ็ต" + "value": "เลือกปลายทางสำหรับแท็บนี้" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Sıfırla" - } - }, - "uk": { - "stringUnit": { - "state": "translated", - "value": "Скинути" + "value": "Bu sekme için bir hedef seçin." } } } }, - "settings.sidebarAppearance.defaultLabel": { + "alert.moveTab.move": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Default" + "value": "Move" } }, "ja": { "stringUnit": { "state": "translated", - "value": "デフォルト" + "value": "移動" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "默认" + "value": "移动" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "預設" + "value": "移動" } }, "ko": { "stringUnit": { "state": "translated", - "value": "기본값" + "value": "이동" } }, "de": { "stringUnit": { "state": "translated", - "value": "Standard" + "value": "Verschieben" } }, "es": { "stringUnit": { "state": "translated", - "value": "Predeterminado" + "value": "Mover" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Par défaut" + "value": "Déplacer" } }, "it": { "stringUnit": { "state": "translated", - "value": "Predefinito" + "value": "Sposta" } }, "da": { "stringUnit": { "state": "translated", - "value": "Standard" + "value": "Flyt" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Domyślny" + "value": "Przenieś" } }, "ru": { "stringUnit": { "state": "translated", - "value": "По умолчанию" + "value": "Переместить" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Zadano" + "value": "Premjesti" } }, "ar": { "stringUnit": { "state": "translated", - "value": "افتراضي" + "value": "نقل" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Standard" + "value": "Flytt" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Padrão" + "value": "Mover" } }, "th": { "stringUnit": { "state": "translated", - "value": "ค่าเริ่มต้น" + "value": "ย้าย" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Varsayılan" - } - }, - "uk": { - "stringUnit": { - "state": "translated", - "value": "Стандартний" + "value": "Taşı" } } } }, - "menu.openInIntelliJ": { + "alert.moveTab.newWorkspaceInCurrentWindow": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Open Current Directory in IntelliJ IDEA" + "value": "New Workspace in Current Window" } }, "ja": { "stringUnit": { "state": "translated", - "value": "現在のディレクトリを IntelliJ IDEA で開く" + "value": "現在のウィンドウに新しいワークスペース" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "在 IntelliJ IDEA 中打开当前目录" + "value": "在当前窗口新建工作区" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "在 IntelliJ IDEA 中開啟目前目錄" + "value": "在目前視窗新建工作區" } }, "ko": { "stringUnit": { "state": "translated", - "value": "현재 디렉토리를 IntelliJ IDEA에서 열기" + "value": "현재 창에 새 작업 공간" } }, "de": { "stringUnit": { "state": "translated", - "value": "Aktuelles Verzeichnis in IntelliJ IDEA öffnen" + "value": "Neuer Arbeitsbereich im aktuellen Fenster" } }, "es": { "stringUnit": { "state": "translated", - "value": "Abrir directorio actual en IntelliJ IDEA" + "value": "Nuevo espacio de trabajo en ventana actual" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Ouvrir le répertoire courant dans IntelliJ IDEA" + "value": "Nouvel espace de travail dans la fenêtre actuelle" } }, "it": { "stringUnit": { "state": "translated", - "value": "Apri la directory corrente in IntelliJ IDEA" + "value": "Nuova area di lavoro nella finestra corrente" } }, "da": { "stringUnit": { "state": "translated", - "value": "Åbn nuværende mappe i IntelliJ IDEA" + "value": "Nyt arbejdsområde i aktuelt vindue" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Otwórz bieżący katalog w IntelliJ IDEA" + "value": "Nowa przestrzeń robocza w bieżącym oknie" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Открыть текущий каталог в IntelliJ IDEA" + "value": "Новое рабочее пространство в текущем окне" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Otvori trenutni direktorij u IntelliJ IDEA" + "value": "Novi radni prostor u trenutnom prozoru" } }, "ar": { "stringUnit": { "state": "translated", - "value": "فتح الدليل الحالي في IntelliJ IDEA" + "value": "مساحة عمل جديدة في النافذة الحالية" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Åpne gjeldende katalog i IntelliJ IDEA" + "value": "Nytt arbeidsområde i nåværende vindu" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Abrir Diretório Atual no IntelliJ IDEA" + "value": "Nova Área de Trabalho na Janela Atual" } }, "th": { "stringUnit": { "state": "translated", - "value": "เปิดไดเรกทอรีปัจจุบันใน IntelliJ IDEA" + "value": "เวิร์กสเปซใหม่ในหน้าต่างปัจจุบัน" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Geçerli Dizini IntelliJ IDEA'da Aç" - } - }, - "uk": { - "stringUnit": { - "state": "translated", - "value": "Відкрити поточну теку в IntelliJ IDEA" + "value": "Mevcut Pencerede Yeni Çalışma Alanı" } } } }, - "error.remoteDrop.invalidFileURL": { + "alert.moveTab.selectedWorkspaceInNewWindow": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Dropped item is not a file URL." + "value": "Selected Workspace in New Window" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ドロップされた項目はファイル URL ではありません。" + "value": "選択したワークスペースを新しいウィンドウに" } }, - "uk": { + "zh-Hans": { "stringUnit": { "state": "translated", - "value": "Перетягнутий елемент не є файловою URL-адресою." + "value": "在新窗口中打开选中的工作区" } }, - "ko": { + "zh-Hant": { "stringUnit": { "state": "translated", - "value": "드롭한 항목이 파일 URL이 아닙니다." + "value": "在新視窗中開啟選取的工作區" } - } - } - }, - "error.remoteDrop.unavailable": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "ko": { "stringUnit": { "state": "translated", - "value": "Remote drop is unavailable." + "value": "새 창에서 선택한 작업 공간" } }, - "ja": { + "de": { "stringUnit": { "state": "translated", - "value": "リモートへのドロップは利用できません。" + "value": "Ausgewählter Arbeitsbereich in neuem Fenster" } }, - "uk": { + "es": { "stringUnit": { "state": "translated", - "value": "Віддалене перетягування недоступне." + "value": "Espacio de trabajo seleccionado en nueva ventana" } }, - "ko": { + "fr": { "stringUnit": { "state": "translated", - "value": "원격 드롭을 사용할 수 없습니다." + "value": "Espace de travail sélectionné dans une nouvelle fenêtre" } - } - } - }, - "error.remoteDrop.uploadFailed": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "it": { "stringUnit": { "state": "translated", - "value": "Failed to upload dropped file: %@" + "value": "Area di lavoro selezionata in nuova finestra" } }, - "ja": { + "da": { "stringUnit": { "state": "translated", - "value": "ドロップされたファイルのアップロードに失敗しました: %@" + "value": "Valgt arbejdsområde i nyt vindue" } }, - "uk": { + "pl": { "stringUnit": { "state": "translated", - "value": "Не вдалося завантажити перетягнутий файл: %@" + "value": "Wybrana przestrzeń robocza w nowym oknie" } }, - "ko": { + "ru": { "stringUnit": { "state": "translated", - "value": "드롭한 파일을 업로드하지 못했습니다: %@" + "value": "Выбранное рабочее пространство в новом окне" } - } - } - }, - "terminalContextMenu.copy": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "bs": { "stringUnit": { "state": "translated", - "value": "Copy" + "value": "Odabrani radni prostor u novom prozoru" } }, - "ja": { + "ar": { "stringUnit": { "state": "translated", - "value": "コピー" + "value": "مساحة العمل المحددة في نافذة جديدة" } }, - "ko": { + "nb": { "stringUnit": { "state": "translated", - "value": "복사" + "value": "Valgt arbeidsområde i nytt vindu" } - } - } - }, - "terminalContextMenu.copyIdentifiers": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "pt-BR": { "stringUnit": { "state": "translated", - "value": "Copy IDs" + "value": "Área de Trabalho Selecionada em Nova Janela" } }, - "ja": { + "th": { "stringUnit": { "state": "translated", - "value": "IDをコピー" + "value": "เวิร์กสเปซที่เลือกในหน้าต่างใหม่" } }, - "ko": { + "tr": { "stringUnit": { "state": "translated", - "value": "ID 복사" + "value": "Seçili Çalışma Alanı Yeni Pencerede" } } } }, - "terminalContextMenu.moveTab": { + "alert.moveTab.title": { "extractionState": "manual", "localizations": { "en": { @@ -106579,2075 +105994,2075 @@ "value": "タブを移動" } }, - "ko": { - "stringUnit": { - "state": "translated", - "value": "탭 이동" - } - } - } - }, - "terminalContextMenu.moveTabToNewWorkspace": { - "extractionState": "manual", - "localizations": { - "en": { + "zh-Hans": { "stringUnit": { "state": "translated", - "value": "Move Tab to New Workspace" + "value": "移动标签页" } }, - "ja": { + "zh-Hant": { "stringUnit": { "state": "translated", - "value": "タブを新規ワークスペースに移動" + "value": "移動標籤頁" } }, "ko": { "stringUnit": { "state": "translated", - "value": "탭을 새 작업 공간으로 이동" - } - } - } - }, - "terminalContextMenu.paste": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Paste" + "value": "탭 이동" } }, - "ja": { + "de": { "stringUnit": { "state": "translated", - "value": "ペースト" + "value": "Tab verschieben" } }, - "ko": { - "stringUnit": { - "state": "translated", - "value": "붙여넣기" - } - } - } - }, - "terminalContextMenu.resetTerminal": { - "extractionState": "manual", - "localizations": { - "en": { + "es": { "stringUnit": { "state": "translated", - "value": "Reset Terminal" + "value": "Mover pestaña" } }, - "ja": { + "fr": { "stringUnit": { "state": "translated", - "value": "ターミナルをリセット" + "value": "Déplacer l'onglet" } }, - "ko": { + "it": { "stringUnit": { "state": "translated", - "value": "터미널 초기화" + "value": "Sposta scheda" } - } - } - }, - "terminalContextMenu.splitHorizontally": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "da": { "stringUnit": { "state": "translated", - "value": "Split Horizontally" + "value": "Flyt faneblad" } }, - "ja": { + "pl": { "stringUnit": { "state": "translated", - "value": "水平に分割" + "value": "Przenieś kartę" } }, - "ko": { + "ru": { "stringUnit": { "state": "translated", - "value": "가로 분할" + "value": "Переместить вкладку" } - } - } - }, - "terminalContextMenu.splitVertically": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "bs": { "stringUnit": { "state": "translated", - "value": "Split Vertically" + "value": "Premjesti karticu" } }, - "ja": { + "ar": { "stringUnit": { "state": "translated", - "value": "垂直に分割" + "value": "نقل علامة التبويب" } }, - "ko": { + "nb": { "stringUnit": { "state": "translated", - "value": "세로 분할" + "value": "Flytt fane" } - } - } - }, - "terminalContextMenu.triggerFlash": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "pt-BR": { "stringUnit": { "state": "translated", - "value": "Trigger Flash" + "value": "Mover Aba" } }, - "ja": { + "th": { "stringUnit": { "state": "translated", - "value": "フラッシュを発火" + "value": "ย้ายแท็บ" } }, - "ko": { + "tr": { "stringUnit": { "state": "translated", - "value": "플래시 실행" + "value": "Sekmeyi Taşı" } } } }, - "alert.cancel": { + "alert.ok": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Cancel" + "value": "OK" } }, "ja": { "stringUnit": { "state": "translated", - "value": "キャンセル" + "value": "OK" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "取消" + "value": "确定" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "取消" + "value": "確定" } }, "ko": { "stringUnit": { "state": "translated", - "value": "취소" + "value": "확인" } }, "de": { "stringUnit": { "state": "translated", - "value": "Abbrechen" + "value": "OK" } }, "es": { "stringUnit": { "state": "translated", - "value": "Cancelar" + "value": "Aceptar" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Annuler" + "value": "OK" } }, "it": { "stringUnit": { "state": "translated", - "value": "Annulla" + "value": "OK" } }, "da": { "stringUnit": { "state": "translated", - "value": "Annuller" + "value": "OK" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Anuluj" + "value": "OK" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Отмена" + "value": "ОК" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Otkaži" + "value": "OK" } }, "ar": { "stringUnit": { "state": "translated", - "value": "إلغاء" + "value": "موافق" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Avbryt" + "value": "OK" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Cancelar" + "value": "OK" } }, "th": { "stringUnit": { "state": "translated", - "value": "ยกเลิก" + "value": "ตกลง" } }, "tr": { "stringUnit": { "state": "translated", - "value": "İptal" + "value": "Tamam" } } } }, - "alert.moveTab.failed.message": { + "alert.renameTab.message": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "cmux could not move this tab to the selected destination." + "value": "Enter a custom name for this tab." } }, "ja": { "stringUnit": { "state": "translated", - "value": "cmuxはこのタブを選択した移動先に移動できませんでした。" + "value": "このタブのカスタム名を入力してください。" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "cmux 无法将此标签页移动到所选位置。" + "value": "输入此标签页的自定义名称。" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "cmux 無法將此標籤頁移動到所選位置。" + "value": "輸入此標籤頁的自訂名稱。" } }, "ko": { "stringUnit": { "state": "translated", - "value": "cmux가 이 탭을 선택한 대상으로 이동할 수 없습니다." + "value": "이 탭의 사용자 지정 이름을 입력하세요." } }, "de": { "stringUnit": { "state": "translated", - "value": "cmux konnte diesen Tab nicht zum ausgewählten Ziel verschieben." + "value": "Geben Sie einen benutzerdefinierten Namen für diesen Tab ein." } }, "es": { "stringUnit": { "state": "translated", - "value": "cmux no pudo mover esta pestaña al destino seleccionado." + "value": "Introduce un nombre personalizado para esta pestaña." } }, "fr": { "stringUnit": { "state": "translated", - "value": "cmux n'a pas pu déplacer cet onglet vers la destination sélectionnée." + "value": "Entrez un nom personnalisé pour cet onglet." } }, "it": { "stringUnit": { "state": "translated", - "value": "cmux non è riuscito a spostare questa scheda nella destinazione selezionata." + "value": "Inserisci un nome personalizzato per questa scheda." } }, "da": { "stringUnit": { "state": "translated", - "value": "cmux kunne ikke flytte dette faneblad til den valgte destination." + "value": "Indtast et brugerdefineret navn for dette faneblad." } }, "pl": { "stringUnit": { "state": "translated", - "value": "cmux nie mógł przenieść tej karty do wybranego miejsca docelowego." + "value": "Wprowadź niestandardową nazwę dla tej karty." } }, "ru": { "stringUnit": { "state": "translated", - "value": "cmux не смог переместить эту вкладку в выбранное место назначения." + "value": "Введите пользовательское имя для этой вкладки." } }, "bs": { "stringUnit": { "state": "translated", - "value": "cmux nije mogao premjestiti ovu karticu na odabrano odredište." + "value": "Unesite prilagođeno ime za ovu karticu." } }, "ar": { "stringUnit": { "state": "translated", - "value": "لم يتمكن cmux من نقل علامة التبويب هذه إلى الوجهة المحددة." + "value": "أدخل اسمًا مخصصًا لعلامة التبويب هذه." } }, "nb": { "stringUnit": { "state": "translated", - "value": "cmux kunne ikke flytte denne fanen til det valgte målet." + "value": "Skriv inn et egendefinert navn for denne fanen." } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "O cmux não conseguiu mover esta aba para o destino selecionado." + "value": "Insira um nome personalizado para esta aba." } }, "th": { "stringUnit": { "state": "translated", - "value": "cmux ไม่สามารถย้ายแท็บนี้ไปยังปลายทางที่เลือกได้" + "value": "ป้อนชื่อที่กำหนดเองสำหรับแท็บนี้" } }, "tr": { "stringUnit": { "state": "translated", - "value": "cmux bu sekmeyi seçilen hedefe taşıyamadı." + "value": "Bu sekme için özel bir ad girin." } } } }, - "alert.moveTab.failed.title": { + "alert.renameTab.placeholder": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Move Failed" + "value": "Tab name" } }, "ja": { "stringUnit": { "state": "translated", - "value": "移動に失敗" + "value": "タブ名" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "移动失败" + "value": "标签页名称" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "移動失敗" + "value": "標籤頁名稱" } }, "ko": { "stringUnit": { "state": "translated", - "value": "이동 실패" + "value": "탭 이름" } }, "de": { "stringUnit": { "state": "translated", - "value": "Verschieben fehlgeschlagen" + "value": "Tab-Name" } }, "es": { "stringUnit": { "state": "translated", - "value": "Error al mover" + "value": "Nombre de pestaña" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Échec du déplacement" + "value": "Nom de l'onglet" } }, "it": { "stringUnit": { "state": "translated", - "value": "Spostamento non riuscito" + "value": "Nome scheda" } }, "da": { "stringUnit": { "state": "translated", - "value": "Flytning mislykkedes" + "value": "Fanebladnavn" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Przenoszenie nie powiodło się" + "value": "Nazwa karty" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Не удалось переместить" + "value": "Имя вкладки" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Premještanje nije uspjelo" + "value": "Naziv kartice" } }, "ar": { "stringUnit": { "state": "translated", - "value": "فشل النقل" + "value": "اسم علامة التبويب" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Flytting mislyktes" + "value": "Fanenavn" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Falha ao Mover" + "value": "Nome da aba" } }, "th": { "stringUnit": { "state": "translated", - "value": "ย้ายไม่สำเร็จ" + "value": "ชื่อแท็บ" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Taşıma Başarısız" + "value": "Sekme adı" } } } }, - "alert.moveTab.message": { + "alert.renameTab.rename": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Choose a destination for this tab." + "value": "Rename" } }, "ja": { "stringUnit": { "state": "translated", - "value": "このタブの移動先を選択してください。" + "value": "変更" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "选择此标签页的目标位置。" + "value": "重命名" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "選擇此標籤頁的目標位置。" + "value": "重新命名" } }, "ko": { "stringUnit": { "state": "translated", - "value": "이 탭의 대상을 선택하세요." + "value": "이름 변경" } }, "de": { "stringUnit": { "state": "translated", - "value": "Wählen Sie ein Ziel für diesen Tab." + "value": "Umbenennen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Elige un destino para esta pestaña." + "value": "Renombrar" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Choisissez une destination pour cet onglet." + "value": "Renommer" } }, "it": { "stringUnit": { "state": "translated", - "value": "Scegli una destinazione per questa scheda." + "value": "Rinomina" } }, "da": { "stringUnit": { "state": "translated", - "value": "Vælg en destination for dette faneblad." + "value": "Omdøb" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Wybierz miejsce docelowe dla tej karty." + "value": "Zmień nazwę" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Выберите назначение для этой вкладки." + "value": "Переименовать" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Odaberite odredište za ovu karticu." + "value": "Preimenuj" } }, "ar": { "stringUnit": { "state": "translated", - "value": "اختر وجهة لعلامة التبويب هذه." + "value": "إعادة التسمية" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Velg et mål for denne fanen." + "value": "Gi nytt navn" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Escolha um destino para esta aba." + "value": "Renomear" } }, "th": { "stringUnit": { "state": "translated", - "value": "เลือกปลายทางสำหรับแท็บนี้" + "value": "เปลี่ยนชื่อ" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Bu sekme için bir hedef seçin." + "value": "Yeniden Adlandır" } } } }, - "alert.moveTab.move": { + "alert.renameTab.title": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Move" + "value": "Rename Tab" } }, "ja": { "stringUnit": { "state": "translated", - "value": "移動" + "value": "タブ名を変更" } }, "zh-Hans": { "stringUnit": { "state": "translated", - "value": "移动" + "value": "重命名标签页" } }, "zh-Hant": { "stringUnit": { "state": "translated", - "value": "移動" + "value": "重新命名標籤頁" } }, "ko": { "stringUnit": { "state": "translated", - "value": "이동" + "value": "탭 이름 변경" } }, "de": { "stringUnit": { "state": "translated", - "value": "Verschieben" + "value": "Tab umbenennen" } }, "es": { "stringUnit": { "state": "translated", - "value": "Mover" + "value": "Renombrar pestaña" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Déplacer" + "value": "Renommer l'onglet" } }, "it": { "stringUnit": { "state": "translated", - "value": "Sposta" + "value": "Rinomina scheda" } }, "da": { "stringUnit": { "state": "translated", - "value": "Flyt" + "value": "Omdøb faneblad" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Przenieś" + "value": "Zmień nazwę karty" } }, "ru": { "stringUnit": { "state": "translated", - "value": "Переместить" + "value": "Переименовать вкладку" } }, "bs": { "stringUnit": { "state": "translated", - "value": "Premjesti" + "value": "Preimenuj karticu" } }, "ar": { "stringUnit": { "state": "translated", - "value": "نقل" + "value": "إعادة تسمية علامة التبويب" } }, "nb": { "stringUnit": { "state": "translated", - "value": "Flytt" + "value": "Gi fanen nytt navn" } }, "pt-BR": { "stringUnit": { "state": "translated", - "value": "Mover" + "value": "Renomear Aba" } }, "th": { "stringUnit": { "state": "translated", - "value": "ย้าย" + "value": "เปลี่ยนชื่อแท็บ" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Taşı" + "value": "Sekmeyi Yeniden Adlandır" } } } }, - "alert.moveTab.newWorkspaceInCurrentWindow": { + "shortcut.editWorkspaceDescription.label": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "New Workspace in Current Window" + "value": "Edit Workspace Description" } }, "ja": { "stringUnit": { "state": "translated", - "value": "現在のウィンドウに新しいワークスペース" + "value": "ワークスペースの説明を編集" } }, - "zh-Hans": { + "ko": { "stringUnit": { "state": "translated", - "value": "在当前窗口新建工作区" + "value": "워크스페이스 설명 편집" + } + } + } + }, + "shortcut.focusRightSidebar.label": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Toggle Right Sidebar Focus" } }, - "zh-Hant": { + "ja": { "stringUnit": { "state": "translated", - "value": "在目前視窗新建工作區" + "value": "右サイドバーのフォーカスを切替" } }, "ko": { "stringUnit": { "state": "translated", - "value": "현재 창에 새 작업 공간" + "value": "오른쪽 사이드바 포커스 전환" } - }, - "de": { + } + } + }, + "shortcut.switchRightSidebarToFiles.label": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Neuer Arbeitsbereich im aktuellen Fenster" + "value": "Show Sidebar Files" } }, - "es": { + "ja": { "stringUnit": { "state": "translated", - "value": "Nuevo espacio de trabajo en ventana actual" + "value": "サイドバーのファイルを表示" } }, - "fr": { + "ko": { "stringUnit": { "state": "translated", - "value": "Nouvel espace de travail dans la fenêtre actuelle" + "value": "사이드바 파일 표시" } - }, - "it": { + } + } + }, + "shortcut.switchRightSidebarToFind.label": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Nuova area di lavoro nella finestra corrente" + "value": "Show Sidebar Find" } }, - "da": { + "ja": { "stringUnit": { "state": "translated", - "value": "Nyt arbejdsområde i aktuelt vindue" + "value": "サイドバーの検索を表示" } - }, - "pl": { + } + } + }, + "shortcut.switchRightSidebarToSessions.label": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Nowa przestrzeń robocza w bieżącym oknie" + "value": "Show Sidebar Vault" } }, - "ru": { + "ja": { "stringUnit": { "state": "translated", - "value": "Новое рабочее пространство в текущем окне" + "value": "サイドバーのボールトを表示" } }, - "bs": { + "ko": { "stringUnit": { "state": "translated", - "value": "Novi radni prostor u trenutnom prozoru" + "value": "사이드바 볼트 표시" } - }, - "ar": { + } + } + }, + "shortcut.switchRightSidebarToFeed.label": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "مساحة عمل جديدة في النافذة الحالية" + "value": "Show Sidebar Feed" } }, - "nb": { + "ja": { "stringUnit": { "state": "translated", - "value": "Nytt arbeidsområde i nåværende vindu" + "value": "サイドバーのフィードを表示" } }, - "pt-BR": { + "ko": { "stringUnit": { "state": "translated", - "value": "Nova Área de Trabalho na Janela Atual" + "value": "사이드바 피드 표시" + } + } + } + }, + "shortcut.switchRightSidebarToDock.label": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Show Sidebar Dock" } }, - "th": { + "ja": { "stringUnit": { "state": "translated", - "value": "เวิร์กสเปซใหม่ในหน้าต่างปัจจุบัน" + "value": "サイドバーのDockを表示" } }, - "tr": { + "ko": { "stringUnit": { "state": "translated", - "value": "Mevcut Pencerede Yeni Çalışma Alanı" + "value": "사이드바 Dock 표시" } } } }, - "alert.moveTab.selectedWorkspaceInNewWindow": { + "menu.view.focusRightSidebar": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Selected Workspace in New Window" + "value": "Toggle Right Sidebar Focus" } }, "ja": { "stringUnit": { "state": "translated", - "value": "選択したワークスペースを新しいウィンドウに" + "value": "右サイドバーのフォーカスを切替" } }, - "zh-Hans": { + "ko": { "stringUnit": { "state": "translated", - "value": "在新窗口中打开选中的工作区" + "value": "오른쪽 사이드바 포커스 전환" } - }, - "zh-Hant": { + } + } + }, + "menu.view.editWorkspaceDescription": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "在新視窗中開啟選取的工作區" + "value": "Edit Workspace Description…" } }, - "ko": { + "ja": { "stringUnit": { "state": "translated", - "value": "새 창에서 선택한 작업 공간" + "value": "ワークスペースの説明を編集…" } }, - "de": { + "ko": { "stringUnit": { "state": "translated", - "value": "Ausgewählter Arbeitsbereich in neuem Fenster" + "value": "워크스페이스 설명 편집…" } - }, - "es": { + } + } + }, + "command.editWorkspaceDescription.title": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Espacio de trabajo seleccionado en nueva ventana" + "value": "Edit Workspace Description…" } }, - "fr": { + "ja": { "stringUnit": { "state": "translated", - "value": "Espace de travail sélectionné dans une nouvelle fenêtre" + "value": "ワークスペースの説明を編集…" } }, - "it": { + "ko": { "stringUnit": { "state": "translated", - "value": "Area di lavoro selezionata in nuova finestra" + "value": "워크스페이스 설명 편집…" } - }, - "da": { + } + } + }, + "command.clearWorkspaceDescription.title": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Valgt arbejdsområde i nyt vindue" + "value": "Clear Workspace Description" } }, - "pl": { + "ja": { "stringUnit": { "state": "translated", - "value": "Wybrana przestrzeń robocza w nowym oknie" + "value": "ワークスペースの説明を消去" } }, - "ru": { + "ko": { "stringUnit": { "state": "translated", - "value": "Выбранное рабочее пространство в новом окне" + "value": "워크스페이스 설명 지우기" } - }, - "bs": { + } + } + }, + "commandPalette.description.workspacePlaceholder": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Odabrani radni prostor u novom prozoru" + "value": "Workspace description" } }, - "ar": { + "ja": { "stringUnit": { "state": "translated", - "value": "مساحة العمل المحددة في نافذة جديدة" + "value": "ワークスペースの説明" } }, - "nb": { + "ko": { "stringUnit": { "state": "translated", - "value": "Valgt arbeidsområde i nytt vindu" + "value": "워크스페이스 설명" } - }, - "pt-BR": { + } + } + }, + "commandPalette.description.workspaceInputHint": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Área de Trabalho Selecionada em Nova Janela" + "value": "Press Enter to save. Press Shift-Enter for a new line, or Escape to cancel." } }, - "th": { + "ja": { "stringUnit": { "state": "translated", - "value": "เวิร์กสเปซที่เลือกในหน้าต่างใหม่" + "value": "Enter で保存します。Shift-Enter で改行、Escape でキャンセルします。" } }, - "tr": { + "ko": { "stringUnit": { "state": "translated", - "value": "Seçili Çalışma Alanı Yeni Pencerede" + "value": "Enter를 눌러 저장하세요. Shift-Enter로 줄바꿈, Escape로 취소합니다." } } } }, - "alert.moveTab.title": { + "contextMenu.editWorkspaceDescription": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "Move Tab" + "value": "Edit Workspace Description…" } }, "ja": { "stringUnit": { "state": "translated", - "value": "タブを移動" + "value": "ワークスペースの説明を編集…" } }, - "zh-Hans": { + "ko": { "stringUnit": { "state": "translated", - "value": "移动标签页" + "value": "워크스페이스 설명 편집…" } - }, - "zh-Hant": { + } + } + }, + "contextMenu.clearWorkspaceDescription": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "移動標籤頁" + "value": "Clear Workspace Description" } }, - "ko": { + "ja": { "stringUnit": { "state": "translated", - "value": "탭 이동" + "value": "ワークスペースの説明を消去" } }, - "de": { + "ko": { "stringUnit": { "state": "translated", - "value": "Tab verschieben" + "value": "워크스페이스 설명 지우기" } - }, - "es": { + } + } + }, + "contextMenu.showWorkspaceInFinder": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Mover pestaña" + "value": "Show in Finder" } }, - "fr": { + "ja": { "stringUnit": { "state": "translated", - "value": "Déplacer l'onglet" + "value": "Finderで表示" } - }, - "it": { + } + } + }, + "contextMenu.workspaceSettings": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Sposta scheda" + "value": "Workspace Settings" } }, - "da": { + "ja": { "stringUnit": { "state": "translated", - "value": "Flyt faneblad" + "value": "ワークスペース設定" } - }, - "pl": { + } + } + }, + "contextMenu.workspaceSettings.hideTerminalScrollBar": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Przenieś kartę" + "value": "Hide Terminal Scroll Bar" } }, - "ru": { + "ja": { "stringUnit": { "state": "translated", - "value": "Переместить вкладку" + "value": "ターミナルのスクロールバーを隠す" } - }, - "bs": { + } + } + }, + "settings.section.terminal": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Premjesti karticu" + "value": "Terminal" } }, - "ar": { + "ja": { "stringUnit": { "state": "translated", - "value": "نقل علامة التبويب" + "value": "ターミナル" } - }, - "nb": { + } + } + }, + "settings.terminal.scrollBar": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "Flytt fane" + "value": "Show Terminal Scroll Bar" } }, - "pt-BR": { + "ja": { "stringUnit": { "state": "translated", - "value": "Mover Aba" + "value": "ターミナルのスクロールバーを表示" } - }, - "th": { + } + } + }, + "settings.terminal.scrollBar.subtitleOff": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", - "value": "ย้ายแท็บ" + "value": "Hides the right-edge terminal scroll bar everywhere. Changes apply immediately and persist across relaunches." } }, - "tr": { + "ja": { "stringUnit": { "state": "translated", - "value": "Sekmeyi Taşı" + "value": "右端のターミナルスクロールバーを全体で非表示にします。変更はすぐに反映され、再起動後も保持されます。" } } } }, - "alert.ok": { + "settings.terminal.scrollBar.subtitleOn": { "extractionState": "manual", "localizations": { "en": { "stringUnit": { "state": "translated", - "value": "OK" + "value": "Shows the right-edge terminal scroll bar in shell scrollback. cmux hides it automatically for alternate-screen style TUI surfaces and you can also disable it per workspace." } }, "ja": { "stringUnit": { "state": "translated", - "value": "OK" + "value": "シェルのスクロールバックでは右端のターミナルスクロールバーを表示します。cmux は代替画面系の TUI では自動的に隠し、ワークスペースごとにも無効化できます。" } - }, - "zh-Hans": { + } + } + }, + "settings.terminal.timestamps": { + "extractionState": "manual", + "localizations": { + "ar": { "stringUnit": { "state": "translated", - "value": "确定" + "value": "إظهار الطوابع الزمنية للطرفية" } }, - "zh-Hant": { + "bs": { "stringUnit": { "state": "translated", - "value": "確定" + "value": "Prikaži vremenske oznake terminala" } }, - "ko": { + "da": { "stringUnit": { "state": "translated", - "value": "확인" + "value": "Vis terminaltidsstempler" } }, "de": { "stringUnit": { "state": "translated", - "value": "OK" + "value": "Terminal-Zeitstempel anzeigen" + } + }, + "en": { + "stringUnit": { + "state": "translated", + "value": "Show Terminal Timestamps" } }, "es": { "stringUnit": { "state": "translated", - "value": "Aceptar" + "value": "Mostrar marcas de tiempo del terminal" } }, "fr": { "stringUnit": { "state": "translated", - "value": "OK" + "value": "Afficher les horodatages du terminal" } }, "it": { "stringUnit": { "state": "translated", - "value": "OK" + "value": "Mostra timestamp del terminale" } }, - "da": { + "ja": { "stringUnit": { "state": "translated", - "value": "OK" + "value": "ターミナルのタイムスタンプを表示" + } + }, + "ko": { + "stringUnit": { + "state": "translated", + "value": "터미널 타임스탬프 표시" + } + }, + "nb": { + "stringUnit": { + "state": "translated", + "value": "Vis terminaltidsstempler" } }, "pl": { "stringUnit": { "state": "translated", - "value": "OK" + "value": "Pokaż znaczniki czasu terminala" } }, - "ru": { + "pt-BR": { "stringUnit": { "state": "translated", - "value": "ОК" + "value": "Mostrar carimbos de data/hora do terminal" } }, - "bs": { + "ru": { "stringUnit": { "state": "translated", - "value": "OK" + "value": "Показывать временные метки терминала" } }, - "ar": { + "th": { "stringUnit": { "state": "translated", - "value": "موافق" + "value": "แสดงเวลาประทับของเทอร์มินัล" } }, - "nb": { + "tr": { "stringUnit": { "state": "translated", - "value": "OK" + "value": "Terminal Zaman Damgalarını Göster" } }, - "pt-BR": { + "uk": { "stringUnit": { "state": "translated", - "value": "OK" + "value": "Показувати часові мітки термінала" } }, - "th": { + "zh-Hans": { "stringUnit": { "state": "translated", - "value": "ตกลง" + "value": "显示终端时间戳" } }, - "tr": { + "zh-Hant": { "stringUnit": { "state": "translated", - "value": "Tamam" + "value": "顯示終端時間戳" } } } }, - "alert.renameTab.message": { + "settings.terminal.timestamps.subtitleOff": { "extractionState": "manual", "localizations": { - "en": { + "ar": { "stringUnit": { "state": "translated", - "value": "Enter a custom name for this tab." + "value": "يخفي هامش الطوابع الزمنية للطرفية. يمكن أيضًا تبديل الطوابع الزمنية من قائمة العرض أو لوحة الأوامر." } }, - "ja": { + "bs": { "stringUnit": { "state": "translated", - "value": "このタブのカスタム名を入力してください。" + "value": "Sakriva marginu vremenskih oznaka terminala. Vremenske oznake se mogu prebaciti i iz menija Prikaz ili komandne palete." } }, - "zh-Hans": { + "da": { "stringUnit": { "state": "translated", - "value": "输入此标签页的自定义名称。" + "value": "Skjuler terminalens tidsstempelrende. Tidsstempler kan også slås til/fra fra menuen Vis eller kommandopaletten." } }, - "zh-Hant": { + "de": { "stringUnit": { "state": "translated", - "value": "輸入此標籤頁的自訂名稱。" + "value": "Blendet die Zeitstempelleiste des Terminals aus. Zeitstempel können auch über das Menü Ansicht oder die Befehlspalette umgeschaltet werden." } }, - "ko": { + "en": { "stringUnit": { "state": "translated", - "value": "이 탭의 사용자 지정 이름을 입력하세요." + "value": "Hides the terminal timestamp gutter. Timestamps can also be toggled from the View menu or command palette." } }, - "de": { + "es": { "stringUnit": { "state": "translated", - "value": "Geben Sie einen benutzerdefinierten Namen für diesen Tab ein." + "value": "Oculta el margen de marcas de tiempo del terminal. Las marcas de tiempo también se pueden alternar desde el menú Ver o la paleta de comandos." } }, - "es": { + "fr": { "stringUnit": { "state": "translated", - "value": "Introduce un nombre personalizado para esta pestaña." + "value": "Masque la gouttière d'horodatage du terminal. Les horodatages peuvent aussi être activés ou désactivés depuis le menu Présentation ou la palette de commandes." } }, - "fr": { + "it": { "stringUnit": { "state": "translated", - "value": "Entrez un nom personnalisé pour cet onglet." + "value": "Nasconde il margine dei timestamp del terminale. I timestamp possono anche essere attivati o disattivati dal menu Vista o dalla tavolozza comandi." } }, - "it": { + "ja": { "stringUnit": { "state": "translated", - "value": "Inserisci un nome personalizzato per questa scheda." + "value": "ターミナルのタイムスタンプ欄を隠します。タイムスタンプは表示メニューやコマンドパレットからも切り替えられます。" + } + }, + "ko": { + "stringUnit": { + "state": "translated", + "value": "터미널 타임스탬프 여백을 숨깁니다. 보기 메뉴 또는 명령 팔레트에서도 타임스탬프를 전환할 수 있습니다." } }, - "da": { + "nb": { "stringUnit": { "state": "translated", - "value": "Indtast et brugerdefineret navn for dette faneblad." + "value": "Skjuler tidsstempelmargen i terminalen. Tidsstempler kan også slås av og på fra Vis-menyen eller kommandopaletten." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Wprowadź niestandardową nazwę dla tej karty." + "value": "Ukrywa margines znaczników czasu terminala. Znaczniki czasu można też przełączać z menu Widok lub palety poleceń." } }, - "ru": { + "pt-BR": { "stringUnit": { "state": "translated", - "value": "Введите пользовательское имя для этой вкладки." + "value": "Oculta a margem de carimbos de data/hora do terminal. Os carimbos também podem ser alternados pelo menu Visualizar ou pela paleta de comandos." } }, - "bs": { + "ru": { "stringUnit": { "state": "translated", - "value": "Unesite prilagođeno ime za ovu karticu." + "value": "Скрывает область временных меток терминала. Временные метки также можно переключать в меню Вид или палитре команд." } }, - "ar": { + "th": { "stringUnit": { "state": "translated", - "value": "أدخل اسمًا مخصصًا لعلامة التبويب هذه." + "value": "ซ่อนแถบเวลาประทับของเทอร์มินัล คุณยังเปิด/ปิดเวลาประทับได้จากเมนูมุมมองหรือพาเล็ตคำสั่ง" } }, - "nb": { + "tr": { "stringUnit": { "state": "translated", - "value": "Skriv inn et egendefinert navn for denne fanen." + "value": "Terminal zaman damgası sütununu gizler. Zaman damgaları Görünüm menüsünden veya komut paletinden de açılıp kapatılabilir." } }, - "pt-BR": { + "uk": { "stringUnit": { "state": "translated", - "value": "Insira um nome personalizado para esta aba." + "value": "Приховує поле часових міток термінала. Часові мітки також можна перемикати з меню Перегляд або палітри команд." } }, - "th": { + "zh-Hans": { "stringUnit": { "state": "translated", - "value": "ป้อนชื่อที่กำหนดเองสำหรับแท็บนี้" + "value": "隐藏终端时间戳边栏。也可以从“显示”菜单或命令面板切换时间戳。" } }, - "tr": { + "zh-Hant": { "stringUnit": { "state": "translated", - "value": "Bu sekme için özel bir ad girin." + "value": "隱藏終端時間戳邊欄。也可以從「顯示」選單或命令面板切換時間戳。" } } } }, - "alert.renameTab.placeholder": { + "settings.terminal.timestamps.subtitleOn": { "extractionState": "manual", "localizations": { - "en": { + "ar": { "stringUnit": { "state": "translated", - "value": "Tab name" + "value": "يعرض هامشًا زمنيًا على اليسار بمحاذاة صفوف خرج الطرفية." } }, - "ja": { + "bs": { "stringUnit": { "state": "translated", - "value": "タブ名" + "value": "Prikazuje lijevu vremensku marginu poravnatu s redovima izlaza terminala." } }, - "zh-Hans": { + "da": { "stringUnit": { "state": "translated", - "value": "标签页名称" + "value": "Viser en venstresidet tidsrende, der flugter med terminalens outputrækker." } }, - "zh-Hant": { + "de": { "stringUnit": { "state": "translated", - "value": "標籤頁名稱" + "value": "Zeigt links eine Zeitleiste an, die an den Ausgabezeilen des Terminals ausgerichtet ist." } }, - "ko": { + "en": { "stringUnit": { "state": "translated", - "value": "탭 이름" + "value": "Shows a left-side time gutter aligned with terminal output rows." } }, - "de": { + "es": { "stringUnit": { "state": "translated", - "value": "Tab-Name" + "value": "Muestra una columna de hora a la izquierda alineada con las filas de salida del terminal." } }, - "es": { + "fr": { "stringUnit": { "state": "translated", - "value": "Nombre de pestaña" + "value": "Affiche une gouttière horaire à gauche alignée avec les lignes de sortie du terminal." } }, - "fr": { + "it": { "stringUnit": { "state": "translated", - "value": "Nom de l'onglet" + "value": "Mostra un margine temporale a sinistra allineato alle righe di output del terminale." } }, - "it": { + "ja": { "stringUnit": { "state": "translated", - "value": "Nome scheda" + "value": "ターミナル出力行にそろえた左側の時刻欄を表示します。" } }, - "da": { + "ko": { "stringUnit": { "state": "translated", - "value": "Fanebladnavn" + "value": "터미널 출력 행에 맞춘 왼쪽 시간 여백을 표시합니다." + } + }, + "nb": { + "stringUnit": { + "state": "translated", + "value": "Viser en venstrestilt tidsmarg som er justert med terminalens utdatarader." } }, "pl": { "stringUnit": { "state": "translated", - "value": "Nazwa karty" + "value": "Pokazuje lewy margines czasu wyrównany z wierszami wyjścia terminala." } }, - "ru": { + "pt-BR": { "stringUnit": { "state": "translated", - "value": "Имя вкладки" + "value": "Mostra uma margem de horário à esquerda alinhada às linhas de saída do terminal." } }, - "bs": { + "ru": { "stringUnit": { "state": "translated", - "value": "Naziv kartice" + "value": "Показывает слева область времени, выровненную по строкам вывода терминала." } }, - "ar": { + "th": { "stringUnit": { "state": "translated", - "value": "اسم علامة التبويب" + "value": "แสดงแถบเวลาด้านซ้ายที่จัดแนวกับแถวเอาต์พุตของเทอร์มินัล" } }, - "nb": { + "tr": { "stringUnit": { "state": "translated", - "value": "Fanenavn" + "value": "Terminal çıktı satırlarıyla hizalı sol tarafta bir zaman sütunu gösterir." } }, - "pt-BR": { + "uk": { "stringUnit": { "state": "translated", - "value": "Nome da aba" + "value": "Показує ліворуч поле часу, вирівняне за рядками виводу термінала." } }, - "th": { + "zh-Hans": { "stringUnit": { "state": "translated", - "value": "ชื่อแท็บ" + "value": "显示与终端输出行对齐的左侧时间栏。" } }, - "tr": { + "zh-Hant": { "stringUnit": { "state": "translated", - "value": "Sekme adı" + "value": "顯示與終端輸出列對齊的左側時間欄。" } } } }, - "alert.renameTab.rename": { + "shortcut.toggleTerminalTimestamps.label": { "extractionState": "manual", "localizations": { - "en": { + "ar": { "stringUnit": { "state": "translated", - "value": "Rename" + "value": "تبديل الطوابع الزمنية للطرفية" } }, - "ja": { + "bs": { "stringUnit": { "state": "translated", - "value": "変更" + "value": "Prebaci vremenske oznake terminala" } }, - "zh-Hans": { + "da": { "stringUnit": { "state": "translated", - "value": "重命名" + "value": "Slå terminaltidsstempler til/fra" } }, - "zh-Hant": { + "de": { "stringUnit": { "state": "translated", - "value": "重新命名" + "value": "Terminal-Zeitstempel ein-/ausblenden" } }, - "ko": { + "en": { "stringUnit": { "state": "translated", - "value": "이름 변경" + "value": "Toggle Terminal Timestamps" } }, - "de": { + "es": { "stringUnit": { "state": "translated", - "value": "Umbenennen" + "value": "Alternar marcas de tiempo del terminal" } }, - "es": { + "fr": { "stringUnit": { "state": "translated", - "value": "Renombrar" + "value": "Activer/désactiver les horodatages du terminal" } }, - "fr": { + "it": { "stringUnit": { "state": "translated", - "value": "Renommer" + "value": "Attiva/Disattiva timestamp del terminale" } }, - "it": { + "ja": { "stringUnit": { "state": "translated", - "value": "Rinomina" + "value": "ターミナルタイムスタンプを切り替え" } }, - "da": { + "ko": { "stringUnit": { "state": "translated", - "value": "Omdøb" + "value": "터미널 타임스탬프 전환" + } + }, + "nb": { + "stringUnit": { + "state": "translated", + "value": "Slå terminaltidsstempler av/på" } }, "pl": { "stringUnit": { "state": "translated", - "value": "Zmień nazwę" + "value": "Przełącz znaczniki czasu terminala" } }, - "ru": { + "pt-BR": { "stringUnit": { "state": "translated", - "value": "Переименовать" + "value": "Alternar carimbos de data/hora do terminal" } }, - "bs": { + "ru": { "stringUnit": { "state": "translated", - "value": "Preimenuj" + "value": "Переключить временные метки терминала" } }, - "ar": { + "th": { "stringUnit": { "state": "translated", - "value": "إعادة التسمية" + "value": "สลับเวลาประทับของเทอร์มินัล" } }, - "nb": { + "tr": { "stringUnit": { "state": "translated", - "value": "Gi nytt navn" + "value": "Terminal Zaman Damgalarını Aç/Kapat" } }, - "pt-BR": { + "uk": { "stringUnit": { "state": "translated", - "value": "Renomear" + "value": "Перемкнути часові мітки термінала" } }, - "th": { + "zh-Hans": { "stringUnit": { "state": "translated", - "value": "เปลี่ยนชื่อ" + "value": "切换终端时间戳" } }, - "tr": { + "zh-Hant": { "stringUnit": { "state": "translated", - "value": "Yeniden Adlandır" + "value": "切換終端時間戳" } } } }, - "alert.renameTab.title": { + "menu.view.toggleTerminalTimestamps": { "extractionState": "manual", "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Rename Tab" - } - }, - "ja": { + "ar": { "stringUnit": { "state": "translated", - "value": "タブ名を変更" + "value": "تبديل الطوابع الزمنية للطرفية" } }, - "zh-Hans": { + "bs": { "stringUnit": { "state": "translated", - "value": "重命名标签页" + "value": "Prebaci vremenske oznake terminala" } }, - "zh-Hant": { + "da": { "stringUnit": { "state": "translated", - "value": "重新命名標籤頁" + "value": "Slå terminaltidsstempler til/fra" } }, - "ko": { + "de": { "stringUnit": { "state": "translated", - "value": "탭 이름 변경" + "value": "Terminal-Zeitstempel ein-/ausblenden" } }, - "de": { + "en": { "stringUnit": { "state": "translated", - "value": "Tab umbenennen" + "value": "Toggle Terminal Timestamps" } }, "es": { "stringUnit": { "state": "translated", - "value": "Renombrar pestaña" + "value": "Alternar marcas de tiempo del terminal" } }, "fr": { "stringUnit": { "state": "translated", - "value": "Renommer l'onglet" + "value": "Activer/désactiver les horodatages du terminal" } }, "it": { "stringUnit": { "state": "translated", - "value": "Rinomina scheda" - } - }, - "da": { - "stringUnit": { - "state": "translated", - "value": "Omdøb faneblad" + "value": "Attiva/Disattiva timestamp del terminale" } }, - "pl": { + "ja": { "stringUnit": { "state": "translated", - "value": "Zmień nazwę karty" + "value": "ターミナルタイムスタンプを切り替え" } }, - "ru": { + "ko": { "stringUnit": { "state": "translated", - "value": "Переименовать вкладку" + "value": "터미널 타임스탬프 전환" } }, - "bs": { + "nb": { "stringUnit": { "state": "translated", - "value": "Preimenuj karticu" + "value": "Slå terminaltidsstempler av/på" } }, - "ar": { + "pl": { "stringUnit": { "state": "translated", - "value": "إعادة تسمية علامة التبويب" + "value": "Przełącz znaczniki czasu terminala" } }, - "nb": { + "pt-BR": { "stringUnit": { "state": "translated", - "value": "Gi fanen nytt navn" + "value": "Alternar carimbos de data/hora do terminal" } }, - "pt-BR": { + "ru": { "stringUnit": { "state": "translated", - "value": "Renomear Aba" + "value": "Переключить временные метки терминала" } }, "th": { "stringUnit": { "state": "translated", - "value": "เปลี่ยนชื่อแท็บ" + "value": "สลับเวลาประทับของเทอร์มินัล" } }, "tr": { "stringUnit": { "state": "translated", - "value": "Sekmeyi Yeniden Adlandır" + "value": "Terminal Zaman Damgalarını Aç/Kapat" } - } - } - }, - "shortcut.editWorkspaceDescription.label": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "uk": { "stringUnit": { "state": "translated", - "value": "Edit Workspace Description" + "value": "Перемкнути часові мітки термінала" } }, - "ja": { + "zh-Hans": { "stringUnit": { "state": "translated", - "value": "ワークスペースの説明を編集" + "value": "切换终端时间戳" } }, - "ko": { + "zh-Hant": { "stringUnit": { "state": "translated", - "value": "워크스페이스 설명 편집" + "value": "切換終端時間戳" } } } }, - "shortcut.focusRightSidebar.label": { + "command.terminalToggleTimestamps.title": { "extractionState": "manual", "localizations": { - "en": { + "ar": { "stringUnit": { "state": "translated", - "value": "Toggle Right Sidebar Focus" + "value": "تبديل الطوابع الزمنية للطرفية" } }, - "ja": { + "bs": { "stringUnit": { "state": "translated", - "value": "右サイドバーのフォーカスを切替" + "value": "Prebaci vremenske oznake terminala" } }, - "ko": { - "stringUnit": { - "state": "translated", - "value": "오른쪽 사이드바 포커스 전환" - } - } - } - }, - "shortcut.switchRightSidebarToFiles.label": { - "extractionState": "manual", - "localizations": { - "en": { + "da": { "stringUnit": { "state": "translated", - "value": "Show Sidebar Files" + "value": "Slå terminaltidsstempler til/fra" } }, - "ja": { + "de": { "stringUnit": { "state": "translated", - "value": "サイドバーのファイルを表示" + "value": "Terminal-Zeitstempel ein-/ausblenden" } }, - "ko": { + "en": { "stringUnit": { "state": "translated", - "value": "사이드바 파일 표시" + "value": "Toggle Terminal Timestamps" } - } - } - }, - "shortcut.switchRightSidebarToFind.label": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "es": { "stringUnit": { "state": "translated", - "value": "Show Sidebar Find" + "value": "Alternar marcas de tiempo del terminal" } }, - "ja": { + "fr": { "stringUnit": { "state": "translated", - "value": "サイドバーの検索を表示" + "value": "Activer/désactiver les horodatages du terminal" } - } - } - }, - "shortcut.switchRightSidebarToSessions.label": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "it": { "stringUnit": { "state": "translated", - "value": "Show Sidebar Vault" + "value": "Attiva/Disattiva timestamp del terminale" } }, "ja": { "stringUnit": { "state": "translated", - "value": "サイドバーのボールトを表示" + "value": "ターミナルタイムスタンプを切り替え" } }, "ko": { "stringUnit": { "state": "translated", - "value": "사이드바 볼트 표시" + "value": "터미널 타임스탬프 전환" } - } - } - }, - "shortcut.switchRightSidebarToFeed.label": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "nb": { "stringUnit": { "state": "translated", - "value": "Show Sidebar Feed" + "value": "Slå terminaltidsstempler av/på" } }, - "ja": { + "pl": { "stringUnit": { "state": "translated", - "value": "サイドバーのフィードを表示" + "value": "Przełącz znaczniki czasu terminala" } }, - "ko": { + "pt-BR": { "stringUnit": { "state": "translated", - "value": "사이드바 피드 표시" + "value": "Alternar carimbos de data/hora do terminal" } - } - } - }, - "shortcut.switchRightSidebarToDock.label": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "ru": { "stringUnit": { "state": "translated", - "value": "Show Sidebar Dock" + "value": "Переключить временные метки терминала" } }, - "ja": { + "th": { "stringUnit": { "state": "translated", - "value": "サイドバーのDockを表示" + "value": "สลับเวลาประทับของเทอร์มินัล" } }, - "ko": { + "tr": { "stringUnit": { "state": "translated", - "value": "사이드바 Dock 표시" + "value": "Terminal Zaman Damgalarını Aç/Kapat" } - } - } - }, - "menu.view.focusRightSidebar": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "uk": { "stringUnit": { "state": "translated", - "value": "Toggle Right Sidebar Focus" + "value": "Перемкнути часові мітки термінала" } }, - "ja": { + "zh-Hans": { "stringUnit": { "state": "translated", - "value": "右サイドバーのフォーカスを切替" + "value": "切换终端时间戳" } }, - "ko": { + "zh-Hant": { "stringUnit": { "state": "translated", - "value": "오른쪽 사이드바 포커스 전환" + "value": "切換終端時間戳" } } } }, - "menu.view.editWorkspaceDescription": { + "terminal.timestamps.gutter.accessibility": { "extractionState": "manual", "localizations": { - "en": { + "ar": { "stringUnit": { "state": "translated", - "value": "Edit Workspace Description…" + "value": "الطوابع الزمنية للطرفية" } }, - "ja": { + "bs": { "stringUnit": { "state": "translated", - "value": "ワークスペースの説明を編集…" + "value": "Vremenske oznake terminala" } }, - "ko": { + "da": { "stringUnit": { "state": "translated", - "value": "워크스페이스 설명 편집…" + "value": "Terminaltidsstempler" } - } - } - }, - "command.editWorkspaceDescription.title": { - "extractionState": "manual", - "localizations": { + }, + "de": { + "stringUnit": { + "state": "translated", + "value": "Terminal-Zeitstempel" + } + }, "en": { "stringUnit": { "state": "translated", - "value": "Edit Workspace Description…" + "value": "Terminal timestamps" } }, - "ja": { + "es": { "stringUnit": { "state": "translated", - "value": "ワークスペースの説明を編集…" + "value": "Marcas de tiempo del terminal" } }, - "ko": { + "fr": { "stringUnit": { "state": "translated", - "value": "워크스페이스 설명 편집…" + "value": "Horodatages du terminal" } - } - } - }, - "command.clearWorkspaceDescription.title": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "it": { "stringUnit": { "state": "translated", - "value": "Clear Workspace Description" + "value": "Timestamp del terminale" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ワークスペースの説明を消去" + "value": "ターミナルタイムスタンプ" } }, "ko": { "stringUnit": { "state": "translated", - "value": "워크스페이스 설명 지우기" + "value": "터미널 타임스탬프" } - } - } - }, - "commandPalette.description.workspacePlaceholder": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "nb": { "stringUnit": { "state": "translated", - "value": "Workspace description" + "value": "Terminaltidsstempler" } }, - "ja": { + "pl": { "stringUnit": { "state": "translated", - "value": "ワークスペースの説明" + "value": "Znaczniki czasu terminala" } }, - "ko": { + "pt-BR": { "stringUnit": { "state": "translated", - "value": "워크스페이스 설명" + "value": "Carimbos de data/hora do terminal" } - } - } - }, - "commandPalette.description.workspaceInputHint": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "ru": { "stringUnit": { "state": "translated", - "value": "Press Enter to save. Press Shift-Enter for a new line, or Escape to cancel." + "value": "Временные метки терминала" } }, - "ja": { + "th": { "stringUnit": { "state": "translated", - "value": "Enter で保存します。Shift-Enter で改行、Escape でキャンセルします。" + "value": "เวลาประทับของเทอร์มินัล" } }, - "ko": { + "tr": { "stringUnit": { "state": "translated", - "value": "Enter를 눌러 저장하세요. Shift-Enter로 줄바꿈, Escape로 취소합니다." + "value": "Terminal zaman damgaları" } - } - } - }, - "contextMenu.editWorkspaceDescription": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "uk": { "stringUnit": { "state": "translated", - "value": "Edit Workspace Description…" + "value": "Часові мітки термінала" } }, - "ja": { + "zh-Hans": { "stringUnit": { "state": "translated", - "value": "ワークスペースの説明を編集…" + "value": "终端时间戳" } }, - "ko": { + "zh-Hant": { "stringUnit": { "state": "translated", - "value": "워크스페이스 설명 편집…" + "value": "終端時間戳" } } } }, - "contextMenu.clearWorkspaceDescription": { + "settings.search.alias.setting.terminal.timestamps": { "extractionState": "manual", "localizations": { - "en": { + "ar": { "stringUnit": { "state": "translated", - "value": "Clear Workspace Description" + "value": "terminal.showTimestamps timestamps time gutter output lines long running agent hang debug طرفية طوابع زمنية وقت هامش خرج أسطر طويل التشغيل وكيل توقف تصحيح" } }, - "ja": { + "bs": { "stringUnit": { "state": "translated", - "value": "ワークスペースの説明を消去" + "value": "terminal.showTimestamps timestamps time gutter output lines long running agent hang debug terminal vremenske oznake vrijeme margina izlaz redovi dugo pokretanje agent zastoj debug" } }, - "ko": { + "da": { "stringUnit": { "state": "translated", - "value": "워크스페이스 설명 지우기" + "value": "terminal.showTimestamps timestamps time gutter output lines long running agent hang debug terminal tidsstempler tid rende output linjer lang kørsel agent hænger fejlfinding" } - } - } - }, - "contextMenu.showWorkspaceInFinder": { - "extractionState": "manual", - "localizations": { + }, + "de": { + "stringUnit": { + "state": "translated", + "value": "terminal.showTimestamps timestamps time gutter output lines long running agent hang debug terminal zeitstempel zeit leiste ausgabe zeilen lange laufzeit agent hängt debug" + } + }, "en": { "stringUnit": { "state": "translated", - "value": "Show in Finder" + "value": "terminal.showTimestamps timestamps time gutter output lines long running agent hang debug" } }, - "ja": { + "es": { "stringUnit": { "state": "translated", - "value": "Finderで表示" + "value": "terminal.showTimestamps timestamps time gutter output lines long running agent hang debug terminal marcas tiempo hora margen salida líneas ejecución larga agente bloqueo depuración" } - } - } - }, - "contextMenu.workspaceSettings": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "fr": { "stringUnit": { "state": "translated", - "value": "Workspace Settings" + "value": "terminal.showTimestamps timestamps time gutter output lines long running agent hang debug terminal horodatages heure gouttière sortie lignes longue exécution agent blocage débogage" + } + }, + "it": { + "stringUnit": { + "state": "translated", + "value": "terminal.showTimestamps timestamps time gutter output lines long running agent hang debug terminal timestamp ora margine output righe lunga esecuzione agente blocco debug" } }, "ja": { "stringUnit": { "state": "translated", - "value": "ワークスペース設定" + "value": "terminal.showTimestamps タイムスタンプ 時刻 出力 行 長時間 エージェント 停止 デバッグ" } - } - } - }, - "contextMenu.workspaceSettings.hideTerminalScrollBar": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "ko": { "stringUnit": { "state": "translated", - "value": "Hide Terminal Scroll Bar" + "value": "terminal.showTimestamps timestamps time gutter output lines long running agent hang debug 터미널 타임스탬프 시간 여백 출력 행 장시간 실행 에이전트 멈춤 디버그" } }, - "ja": { + "nb": { "stringUnit": { "state": "translated", - "value": "ターミナルのスクロールバーを隠す" + "value": "terminal.showTimestamps timestamps time gutter output lines long running agent hang debug terminal tidsstempler tid marg utdata linjer lang kjøring agent henger feilsøking" } - } - } - }, - "settings.section.terminal": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "pl": { "stringUnit": { "state": "translated", - "value": "Terminal" + "value": "terminal.showTimestamps timestamps time gutter output lines long running agent hang debug terminal znaczniki czasu czas margines wyjście wiersze długie działanie agent zawieszenie debugowanie" } }, - "ja": { + "pt-BR": { "stringUnit": { "state": "translated", - "value": "ターミナル" + "value": "terminal.showTimestamps timestamps time gutter output lines long running agent hang debug terminal carimbos data hora tempo margem saída linhas longa execução agente travamento depuração" } - } - } - }, - "settings.terminal.scrollBar": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "ru": { "stringUnit": { "state": "translated", - "value": "Show Terminal Scroll Bar" + "value": "terminal.showTimestamps timestamps time gutter output lines long running agent hang debug терминал временные метки время область вывод строки долгий запуск агент зависание отладка" } }, - "ja": { + "th": { "stringUnit": { "state": "translated", - "value": "ターミナルのスクロールバーを表示" + "value": "terminal.showTimestamps timestamps time gutter output lines long running agent hang debug เทอร์มินัล เวลาประทับ เวลา แถบ เอาต์พุต บรรทัด ทำงานนาน เอเจนต์ ค้าง ดีบัก" } - } - } - }, - "settings.terminal.scrollBar.subtitleOff": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "tr": { "stringUnit": { "state": "translated", - "value": "Hides the right-edge terminal scroll bar everywhere. Changes apply immediately and persist across relaunches." + "value": "terminal.showTimestamps timestamps time gutter output lines long running agent hang debug terminal zaman damgaları saat sütun çıktı satırlar uzun çalışan ajan takılma hata ayıklama" } }, - "ja": { + "uk": { "stringUnit": { "state": "translated", - "value": "右端のターミナルスクロールバーを全体で非表示にします。変更はすぐに反映され、再起動後も保持されます。" + "value": "terminal.showTimestamps timestamps time gutter output lines long running agent hang debug термінал часові мітки час поле вивід рядки тривалий запуск агент зависання налагодження" } - } - } - }, - "settings.terminal.scrollBar.subtitleOn": { - "extractionState": "manual", - "localizations": { - "en": { + }, + "zh-Hans": { "stringUnit": { "state": "translated", - "value": "Shows the right-edge terminal scroll bar in shell scrollback. cmux hides it automatically for alternate-screen style TUI surfaces and you can also disable it per workspace." + "value": "terminal.showTimestamps timestamps time gutter output lines long running agent hang debug 终端 时间戳 时间 边栏 输出 行 长时间运行 代理 卡住 调试" } }, - "ja": { + "zh-Hant": { "stringUnit": { "state": "translated", - "value": "シェルのスクロールバックでは右端のターミナルスクロールバーを表示します。cmux は代替画面系の TUI では自動的に隠し、ワークスペースごとにも無効化できます。" + "value": "terminal.showTimestamps timestamps time gutter output lines long running agent hang debug 終端 時間戳 時間 邊欄 輸出 列 長時間執行 代理 卡住 除錯" } } } @@ -114745,35 +114160,6 @@ "ja": { "stringUnit": { "state": "translated", "value": "更新" } } } }, - "taskManager.refresh.error": {"extractionState": "manual","localizations": {"ar": {"stringUnit": {"state": "translated","value": "تعذر تحديث بيانات مدير المهام."}},"bs": {"stringUnit": {"state": "translated","value": "Nije moguće osvježiti podatke upravitelja zadataka."}},"da": {"stringUnit": {"state": "translated","value": "Kunne ikke opdatere data i Jobliste."}},"de": {"stringUnit": {"state": "translated","value": "Task-Manager-Daten konnten nicht aktualisiert werden."}},"en": {"stringUnit": {"state": "translated","value": "Unable to refresh Task Manager data."}},"es": {"stringUnit": {"state": "translated","value": "No se pudieron actualizar los datos del Administrador de tareas."}},"fr": {"stringUnit": {"state": "translated","value": "Impossible d’actualiser les données du gestionnaire des tâches."}},"it": {"stringUnit": {"state": "translated","value": "Impossibile aggiornare i dati di Gestione attività."}},"ja": {"stringUnit": {"state": "translated","value": "タスクマネージャのデータを更新できません。"}},"ko": {"stringUnit": {"state": "translated","value": "작업 관리자 데이터를 새로 고칠 수 없습니다."}},"nb": {"stringUnit": {"state": "translated","value": "Kunne ikke oppdatere data i Oppgavebehandling."}},"pl": {"stringUnit": {"state": "translated","value": "Nie można odświeżyć danych Menedżera zadań."}},"pt-BR": {"stringUnit": {"state": "translated","value": "Não foi possível atualizar os dados do Gerenciador de Tarefas."}},"ru": {"stringUnit": {"state": "translated","value": "Не удалось обновить данные диспетчера задач."}},"th": {"stringUnit": {"state": "translated","value": "ไม่สามารถรีเฟรชข้อมูลตัวจัดการงานได้"}},"tr": {"stringUnit": {"state": "translated","value": "Görev Yöneticisi verileri yenilenemedi."}},"uk": {"stringUnit": {"state": "translated","value": "Не вдалося оновити дані Диспетчера завдань."}},"zh-Hans": {"stringUnit": {"state": "translated","value": "无法刷新任务管理器数据。"}},"zh-Hant": {"stringUnit": {"state": "translated","value": "無法重新整理工作管理員資料。"}}}}, - "cli.top.error.processDiagnosticsUnsupported": {"extractionState": "manual","localizations": {"ar": {"stringUnit": {"state": "translated","value": "يتطلب cmux top إصدار cmux قيد التشغيل يدعم تشخيص العمليات"}},"bs": {"stringUnit": {"state": "translated","value": "cmux top zahtijeva pokrenutu cmux verziju koja podržava dijagnostiku procesa"}},"da": {"stringUnit": {"state": "translated","value": "cmux top kræver en kørende cmux-build med procesdiagnostik"}},"de": {"stringUnit": {"state": "translated","value": "cmux top erfordert einen laufenden cmux-Build mit Prozessdiagnose"}},"en": {"stringUnit": {"state": "translated","value": "cmux top requires a running cmux build that supports process diagnostics"}},"es": {"stringUnit": {"state": "translated","value": "cmux top requiere una compilación de cmux en ejecución que admita diagnósticos de procesos"}},"fr": {"stringUnit": {"state": "translated","value": "cmux top nécessite une version cmux en cours d’exécution prenant en charge le diagnostic des processus"}},"it": {"stringUnit": {"state": "translated","value": "cmux top richiede una build cmux in esecuzione che supporti la diagnostica dei processi"}},"ja": {"stringUnit": {"state": "translated","value": "cmux top にはプロセス診断に対応した実行中の cmux ビルドが必要です"}},"ko": {"stringUnit": {"state": "translated","value": "cmux top에는 프로세스 진단을 지원하는 실행 중인 cmux 빌드가 필요합니다"}},"nb": {"stringUnit": {"state": "translated","value": "cmux top krever en kjørende cmux-build som støtter prosessdiagnostikk"}},"pl": {"stringUnit": {"state": "translated","value": "cmux top wymaga uruchomionej kompilacji cmux z obsługą diagnostyki procesów"}},"pt-BR": {"stringUnit": {"state": "translated","value": "cmux top requer uma build cmux em execução com suporte a diagnósticos de processos"}},"ru": {"stringUnit": {"state": "translated","value": "cmux top требует запущенную сборку cmux с поддержкой диагностики процессов"}},"th": {"stringUnit": {"state": "translated","value": "cmux top ต้องใช้บิลด์ cmux ที่กำลังทำงานและรองรับการวินิจฉัยโปรเซส"}},"tr": {"stringUnit": {"state": "translated","value": "cmux top, süreç tanılamasını destekleyen çalışan bir cmux derlemesi gerektirir"}},"uk": {"stringUnit": {"state": "translated","value": "cmux top потребує запущеної збірки cmux із підтримкою діагностики процесів"}},"zh-Hans": {"stringUnit": {"state": "translated","value": "cmux top 需要正在运行且支持进程诊断的 cmux 构建"}},"zh-Hant": {"stringUnit": {"state": "translated","value": "cmux top 需要正在執行且支援行程診斷的 cmux 建置"}}}}, - "cli.top.error.invalidWorkspace": {"extractionState": "manual","localizations": {"ar": {"stringUnit": {"state": "translated","value": "top: معرّف مساحة العمل '%@' غير صالح"}},"bs": {"stringUnit": {"state": "translated","value": "top: neispravan identifikator radnog prostora '%@'"}},"da": {"stringUnit": {"state": "translated","value": "top: ugyldigt arbejdsområdehåndtag '%@'"}},"de": {"stringUnit": {"state": "translated","value": "top: ungültiger Workspace-Bezeichner '%@'"}},"en": {"stringUnit": {"state": "translated","value": "top: invalid workspace handle '%@'"}},"es": {"stringUnit": {"state": "translated","value": "top: identificador de espacio de trabajo no válido '%@'"}},"fr": {"stringUnit": {"state": "translated","value": "top : identifiant d’espace de travail non valide '%@'"}},"it": {"stringUnit": {"state": "translated","value": "top: handle area di lavoro non valido '%@'"}},"ja": {"stringUnit": {"state": "translated","value": "top: ワークスペース指定 '%@' は無効です"}},"ko": {"stringUnit": {"state": "translated","value": "top: 잘못된 워크스페이스 핸들 '%@'"}},"nb": {"stringUnit": {"state": "translated","value": "top: ugyldig arbeidsområdehåndtak '%@'"}},"pl": {"stringUnit": {"state": "translated","value": "top: nieprawidłowy uchwyt obszaru roboczego '%@'"}},"pt-BR": {"stringUnit": {"state": "translated","value": "top: identificador de workspace inválido '%@'"}},"ru": {"stringUnit": {"state": "translated","value": "top: недопустимый дескриптор рабочей области '%@'"}},"th": {"stringUnit": {"state": "translated","value": "top: แฮนเดิลเวิร์กสเปซไม่ถูกต้อง '%@'"}},"tr": {"stringUnit": {"state": "translated","value": "top: geçersiz çalışma alanı tanıtıcısı '%@'"}},"uk": {"stringUnit": {"state": "translated","value": "top: неприпустимий дескриптор робочої області '%@'"}},"zh-Hans": {"stringUnit": {"state": "translated","value": "top:无效的工作区句柄 '%@'"}},"zh-Hant": {"stringUnit": {"state": "translated","value": "top:無效的工作區控制代碼 '%@'"}}}}, - "cli.memory.error.diagnosticsUnsupported": {"extractionState": "manual","localizations": {"ar": {"stringUnit": {"state": "translated","value": "يتطلب cmux memory إصدار cmux قيد التشغيل يدعم تشخيص الذاكرة"}},"bs": {"stringUnit": {"state": "translated","value": "cmux memory zahtijeva pokrenutu cmux verziju koja podržava dijagnostiku memorije"}},"da": {"stringUnit": {"state": "translated","value": "cmux memory kræver en kørende cmux-build med hukommelsesdiagnostik"}},"de": {"stringUnit": {"state": "translated","value": "cmux memory erfordert einen laufenden cmux-Build mit Speicherdiagnose"}},"en": {"stringUnit": {"state": "translated","value": "cmux memory requires a running cmux build that supports memory diagnostics"}},"es": {"stringUnit": {"state": "translated","value": "cmux memory requiere una compilación de cmux en ejecución que admita diagnósticos de memoria"}},"fr": {"stringUnit": {"state": "translated","value": "cmux memory nécessite une version cmux en cours d’exécution prenant en charge le diagnostic mémoire"}},"it": {"stringUnit": {"state": "translated","value": "cmux memory richiede una build cmux in esecuzione che supporti la diagnostica della memoria"}},"ja": {"stringUnit": {"state": "translated","value": "cmux memory にはメモリ診断に対応した実行中の cmux ビルドが必要です"}},"ko": {"stringUnit": {"state": "translated","value": "cmux memory에는 메모리 진단을 지원하는 실행 중인 cmux 빌드가 필요합니다"}},"nb": {"stringUnit": {"state": "translated","value": "cmux memory krever en kjørende cmux-build som støtter minnediagnostikk"}},"pl": {"stringUnit": {"state": "translated","value": "cmux memory wymaga uruchomionej kompilacji cmux z obsługą diagnostyki pamięci"}},"pt-BR": {"stringUnit": {"state": "translated","value": "cmux memory requer uma build cmux em execução com suporte a diagnósticos de memória"}},"ru": {"stringUnit": {"state": "translated","value": "cmux memory требует запущенную сборку cmux с поддержкой диагностики памяти"}},"th": {"stringUnit": {"state": "translated","value": "cmux memory ต้องใช้บิลด์ cmux ที่กำลังทำงานและรองรับการวินิจฉัยหน่วยความจำ"}},"tr": {"stringUnit": {"state": "translated","value": "cmux memory, bellek tanılamasını destekleyen çalışan bir cmux derlemesi gerektirir"}},"uk": {"stringUnit": {"state": "translated","value": "cmux memory потребує запущеної збірки cmux із підтримкою діагностики пам’яті"}},"zh-Hans": {"stringUnit": {"state": "translated","value": "cmux memory 需要正在运行且支持内存诊断的 cmux 构建"}},"zh-Hant": {"stringUnit": {"state": "translated","value": "cmux memory 需要正在執行且支援記憶體診斷的 cmux 建置"}}}}, - "cli.help.memory": {"extractionState": "manual","localizations": {"ar": {"stringUnit": {"state": "translated","value": "الاستخدام: cmux memory [flags]\n\nيشخص ذاكرة تطبيق cmux بشكل منفصل عن RSS العودية لعمليات التيرمنال الفرعية.\n\nالخيارات:\n --all تضمين كل النوافذ (الافتراضي: النافذة الحالية فقط)\n --workspace تقييد سياق مساحة العمل لتسميات الإسناد\n --groups عدد مجموعات أوامر العمليات الفرعية المراد عرضها (الافتراضي: 12)\n --json إخراج JSON منظم\n\nالإخراج:\n بصمة التطبيق هي البصمة الفيزيائية المباشرة لعملية cmux من محاسبة عمليات macOS.\n Child RSS هو الذاكرة المقيمة العودية لذرية عملية تطبيق cmux،\n مجموعة حسب اسم الأمر ومسنَدة إلى مساحة العمل والجزء والسطح عند معرفة ذلك.\n\nمثال:\n cmux memory\n cmux memory --groups 20\n cmux --json memory --all"}},"bs": {"stringUnit": {"state": "translated","value": "Upotreba: cmux memory [flags]\n\nDijagnosticira memoriju cmux aplikacije odvojeno od rekurzivnog RSS-a terminalskih podprocesa.\n\nOpcije:\n --all Uključi sve prozore (zadano: samo trenutni prozor)\n --workspace Ograniči kontekst radnog prostora za oznake pripisivanja\n --groups Broj grupa naredbi podprocesa za prikaz (zadano: 12)\n --json Strukturirani JSON izlaz\n\nIzlaz:\n Otisak aplikacije je direktni fizički otisak cmux procesa iz macOS računanja procesa.\n Child RSS je rekurzivna rezidentna memorija potomaka cmux procesa,\n grupisana po nazivu naredbe i pripisana radnom prostoru, panelu i površini kada je poznato.\n\nPrimjer:\n cmux memory\n cmux memory --groups 20\n cmux --json memory --all"}},"da": {"stringUnit": {"state": "translated","value": "Brug: cmux memory [flags]\n\nDiagnosticerer cmux-appens hukommelse separat fra rekursiv RSS for terminalens underprocesser.\n\nFlag:\n --all Medtag alle vinduer (standard: kun aktuelt vindue)\n --workspace Begræns workspace-kontekst for tilskrivningsetiketter\n --groups Antal underproces-kommandogrupper der vises (standard: 12)\n --json Struktureret JSON-output\n\nOutput:\n Appens fodaftryk er cmux-processens direkte fysiske fodaftryk fra macOS procesregnskab.\n Child RSS er rekursiv resident hukommelse for efterkommere af cmux-app-processen,\n grupperet efter kommandonavn og tilskrevet workspace, rude og flade når det kendes.\n\nEksempel:\n cmux memory\n cmux memory --groups 20\n cmux --json memory --all"}},"de": {"stringUnit": {"state": "translated","value": "Verwendung: cmux memory [flags]\n\nDiagnostiziert den Speicher der cmux-App getrennt vom rekursiven RSS der Terminal-Kindprozesse.\n\nOptionen:\n --all Alle Fenster einbeziehen (Standard: nur aktuelles Fenster)\n --workspace Workspace-Kontext für Zuordnungslabels begrenzen\n --groups Anzahl der anzuzeigenden Kindprozess-Befehlsgruppen (Standard: 12)\n --json Strukturierte JSON-Ausgabe\n\nAusgabe:\n Der App-Footprint ist der direkte physische Footprint des cmux-Prozesses aus der macOS-Prozessabrechnung.\n Child RSS ist der rekursive residente Speicher der Nachkommen des cmux-App-Prozesses,\n gruppiert nach Befehlsname und bei bekannter Zuordnung Workspace, Bereich und Oberfläche zugewiesen.\n\nBeispiel:\n cmux memory\n cmux memory --groups 20\n cmux --json memory --all"}},"en": {"stringUnit": {"state": "translated","value": "Usage: cmux memory [flags]\n\nDiagnose cmux app memory separately from recursive terminal child-process RSS.\n\nFlags:\n --all Include all windows (default: current window only)\n --workspace Limit workspace context for attribution labels\n --groups Number of child command groups to show (default: 12)\n --json Structured JSON output\n\nOutput:\n App footprint is the direct cmux process physical footprint from macOS process accounting.\n Child RSS is recursive resident memory for descendants of the cmux app process,\n grouped by command name and attributed back to workspace, pane, and surface when known.\n\nExample:\n cmux memory\n cmux memory --groups 20\n cmux --json memory --all"}},"es": {"stringUnit": {"state": "translated","value": "Uso: cmux memory [flags]\n\nDiagnostica la memoria de la app cmux por separado del RSS recursivo de procesos secundarios de terminal.\n\nOpciones:\n --all Incluir todas las ventanas (predeterminado: solo la ventana actual)\n --workspace Limitar el contexto del espacio de trabajo para las etiquetas de atribución\n --groups Número de grupos de comandos secundarios que se mostrarán (predeterminado: 12)\n --json Salida JSON estructurada\n\nSalida:\n La huella de la app es la huella física directa del proceso cmux según la contabilidad de procesos de macOS.\n Child RSS es la memoria residente recursiva de los descendientes del proceso de la app cmux,\n agrupada por nombre de comando y atribuida al espacio de trabajo, panel y superficie cuando se conocen.\n\nEjemplo:\n cmux memory\n cmux memory --groups 20\n cmux --json memory --all"}},"fr": {"stringUnit": {"state": "translated","value": "Utilisation : cmux memory [flags]\n\nDiagnostique la mémoire de l’app cmux séparément du RSS récursif des processus enfants du terminal.\n\nOptions:\n --all Inclure toutes les fenêtres (par défaut : fenêtre active uniquement)\n --workspace Limiter le contexte d’espace de travail pour les libellés d’attribution\n --groups Nombre de groupes de commandes enfants à afficher (par défaut : 12)\n --json Sortie JSON structurée\n\nSortie:\n L’empreinte de l’app est l’empreinte physique directe du processus cmux selon la comptabilité des processus macOS.\n Child RSS est la mémoire résidente récursive des descendants du processus de l’app cmux,\n regroupée par nom de commande et attribuée à l’espace de travail, au panneau et à la surface lorsque connus.\n\nExemple:\n cmux memory\n cmux memory --groups 20\n cmux --json memory --all"}},"it": {"stringUnit": {"state": "translated","value": "Uso: cmux memory [flags]\n\nDiagnostica la memoria dell’app cmux separatamente dall’RSS ricorsivo dei processi figli del terminale.\n\nOpzioni:\n --all Includi tutte le finestre (predefinito: solo finestra corrente)\n --workspace Limita il contesto dell’area di lavoro per le etichette di attribuzione\n --groups Numero di gruppi di comandi figli da mostrare (predefinito: 12)\n --json Output JSON strutturato\n\nOutput:\n L’impronta dell’app è l’impronta fisica diretta del processo cmux dalla contabilità dei processi di macOS.\n Child RSS è la memoria residente ricorsiva dei discendenti del processo dell’app cmux,\n raggruppata per nome comando e attribuita ad area di lavoro, pannello e superficie quando noti.\n\nEsempio:\n cmux memory\n cmux memory --groups 20\n cmux --json memory --all"}},"ja": {"stringUnit": {"state": "translated","value": "Usage: cmux memory [flags]\n\ncmux アプリ本体のメモリと、ターミナル配下の再帰的な子プロセス RSS を分けて診断します。\n\nFlags:\n --all すべてのウィンドウを含める(既定: 現在のウィンドウのみ)\n --workspace 帰属ラベルのワークスペース文脈を限定\n --groups 表示する子コマンドグループ数(既定: 12)\n --json 構造化 JSON を出力\n\nOutput:\n App footprint は macOS のプロセス会計による cmux プロセス本体の物理フットプリントです。\n Child RSS は cmux アプリプロセスの子孫プロセスの再帰的な常駐メモリで、\n コマンド名でグループ化し、分かる場合はワークスペース、ペイン、サーフェスへ帰属します。\n\nExample:\n cmux memory\n cmux memory --groups 20\n cmux --json memory --all"}},"ko": {"stringUnit": {"state": "translated","value": "사용법: cmux memory [flags]\n\ncmux 앱 메모리를 터미널 하위 프로세스의 재귀 RSS와 분리해 진단합니다.\n\n플래그:\n --all 모든 창 포함(기본값: 현재 창만)\n --workspace 귀속 레이블의 워크스페이스 컨텍스트 제한\n --groups 표시할 하위 명령 그룹 수(기본값: 12)\n --json 구조화된 JSON 출력\n\n출력:\n 앱 footprint는 macOS 프로세스 회계의 cmux 프로세스 직접 물리 footprint입니다.\n Child RSS는 cmux 앱 프로세스 자손의 재귀 상주 메모리이며,\n 명령 이름으로 그룹화되고 확인 가능한 경우 워크스페이스, 패널, 서피스에 귀속됩니다.\n\n예:\n cmux memory\n cmux memory --groups 20\n cmux --json memory --all"}},"nb": {"stringUnit": {"state": "translated","value": "Bruk: cmux memory [flags]\n\nDiagnostiserer cmux-appens minne separat fra rekursiv RSS for terminalens underprosesser.\n\nFlagg:\n --all Ta med alle vinduer (standard: bare gjeldende vindu)\n --workspace Begrens arbeidsområdekontekst for tilordningsetiketter\n --groups Antall underprosess-kommandogrupper som vises (standard: 12)\n --json Strukturert JSON-utdata\n\nUtdata:\n Appavtrykket er det direkte fysiske avtrykket til cmux-prosessen fra macOS prosessregnskap.\n Child RSS er rekursivt resident minne for etterkommere av cmux-app-prosessen,\n gruppert etter kommandonavn og tilordnet arbeidsområde, rute og flate når kjent.\n\nEksempel:\n cmux memory\n cmux memory --groups 20\n cmux --json memory --all"}},"pl": {"stringUnit": {"state": "translated","value": "Użycie: cmux memory [flags]\n\nDiagnozuje pamięć aplikacji cmux oddzielnie od rekurencyjnego RSS procesów potomnych terminala.\n\nOpcje:\n --all Uwzględnij wszystkie okna (domyślnie: tylko bieżące okno)\n --workspace Ogranicz kontekst obszaru roboczego dla etykiet przypisania\n --groups Liczba grup poleceń procesów potomnych do pokazania (domyślnie: 12)\n --json Strukturalne wyjście JSON\n\nWyjście:\n Ślad aplikacji to bezpośredni fizyczny ślad procesu cmux z rozliczania procesów macOS.\n Child RSS to rekurencyjna pamięć rezydentna potomków procesu aplikacji cmux,\n grupowana według nazwy polecenia i przypisywana do obszaru roboczego, panelu i powierzchni, gdy są znane.\n\nPrzykład:\n cmux memory\n cmux memory --groups 20\n cmux --json memory --all"}},"pt-BR": {"stringUnit": {"state": "translated","value": "Uso: cmux memory [flags]\n\nDiagnostica a memória do app cmux separadamente do RSS recursivo dos processos filhos do terminal.\n\nOpções:\n --all Incluir todas as janelas (padrão: somente a janela atual)\n --workspace Limitar o contexto do workspace para rótulos de atribuição\n --groups Número de grupos de comandos filhos a mostrar (padrão: 12)\n --json Saída JSON estruturada\n\nSaída:\n A pegada do app é a pegada física direta do processo cmux pela contabilidade de processos do macOS.\n Child RSS é a memória residente recursiva dos descendentes do processo do app cmux,\n agrupada por nome de comando e atribuída ao workspace, painel e superfície quando conhecidos.\n\nExemplo:\n cmux memory\n cmux memory --groups 20\n cmux --json memory --all"}},"ru": {"stringUnit": {"state": "translated","value": "Использование: cmux memory [flags]\n\nДиагностирует память приложения cmux отдельно от рекурсивного RSS дочерних процессов терминала.\n\nФлаги:\n --all Включить все окна (по умолчанию: только текущее окно)\n --workspace Ограничить контекст рабочей области для меток атрибуции\n --groups Количество групп дочерних команд для показа (по умолчанию: 12)\n --json Структурированный вывод JSON\n\nВывод:\n Отпечаток приложения — это прямой физический отпечаток процесса cmux по учету процессов macOS.\n Child RSS — это рекурсивная резидентная память потомков процесса приложения cmux,\n сгруппированная по имени команды и связанная с рабочей областью, панелью и поверхностью, если они известны.\n\nПример:\n cmux memory\n cmux memory --groups 20\n cmux --json memory --all"}},"th": {"stringUnit": {"state": "translated","value": "การใช้: cmux memory [flags]\n\nวินิจฉัยหน่วยความจำของแอป cmux แยกจาก RSS แบบเรียกซ้ำของโปรเซสลูกในเทอร์มินัล\n\nแฟล็ก:\n --all รวมหน้าต่างทั้งหมด (ค่าเริ่มต้น: เฉพาะหน้าต่างปัจจุบัน)\n --workspace จำกัดบริบทเวิร์กสเปซสำหรับป้ายกำกับการระบุที่มา\n --groups จำนวนกลุ่มคำสั่งโปรเซสลูกที่จะแสดง (ค่าเริ่มต้น: 12)\n --json เอาต์พุต JSON แบบมีโครงสร้าง\n\nเอาต์พุต:\n footprint ของแอปคือ footprint ทางกายภาพโดยตรงของโปรเซส cmux จากการบัญชีโปรเซสของ macOS\n Child RSS คือหน่วยความจำ resident แบบเรียกซ้ำของโปรเซสสืบทอดจากโปรเซสแอป cmux,\n จัดกลุ่มตามชื่อคำสั่งและระบุที่มาไปยังเวิร์กสเปซ พาเนล และพื้นผิวเมื่อทราบ\n\nตัวอย่าง:\n cmux memory\n cmux memory --groups 20\n cmux --json memory --all"}},"tr": {"stringUnit": {"state": "translated","value": "Kullanım: cmux memory [flags]\n\ncmux uygulama belleğini terminal alt süreçlerinin özyinelemeli RSS değerinden ayrı tanılar.\n\nBayraklar:\n --all Tüm pencereleri dahil et (varsayılan: yalnızca geçerli pencere)\n --workspace Atıf etiketleri için çalışma alanı bağlamını sınırla\n --groups Gösterilecek alt komut grubu sayısı (varsayılan: 12)\n --json Yapılandırılmış JSON çıktısı\n\nÇıktı:\n Uygulama footprint değeri, macOS süreç muhasebesinden cmux sürecinin doğrudan fiziksel footprint değeridir.\n Child RSS, cmux uygulama sürecinin alt soylarının özyinelemeli yerleşik belleğidir,\n komut adına göre gruplanır ve bilindiğinde çalışma alanı, panel ve yüzeye atanır.\n\nÖrnek:\n cmux memory\n cmux memory --groups 20\n cmux --json memory --all"}},"uk": {"stringUnit": {"state": "translated","value": "Використання: cmux memory [flags]\n\nДіагностує пам’ять застосунку cmux окремо від рекурсивного RSS дочірніх процесів термінала.\n\nПрапорці:\n --all Включити всі вікна (типово: лише поточне вікно)\n --workspace Обмежити контекст робочої області для міток атрибуції\n --groups Кількість груп дочірніх команд для показу (типово: 12)\n --json Структурований вивід JSON\n\nВивід:\n Відбиток застосунку — це прямий фізичний відбиток процесу cmux за обліком процесів macOS.\n Child RSS — це рекурсивна резидентна пам’ять нащадків процесу застосунку cmux,\n згрупована за назвою команди й прив’язана до робочої області, панелі та поверхні, коли вони відомі.\n\nПриклад:\n cmux memory\n cmux memory --groups 20\n cmux --json memory --all"}},"zh-Hans": {"stringUnit": {"state": "translated","value": "用法:cmux memory [flags]\n\n将 cmux 应用内存与终端子进程的递归 RSS 分开诊断。\n\n标志:\n --all 包含所有窗口(默认:仅当前窗口)\n --workspace 限制归因标签的工作区上下文\n --groups 要显示的子命令组数量(默认:12)\n --json 结构化 JSON 输出\n\n输出:\n 应用 footprint 是 macOS 进程统计中 cmux 进程的直接物理 footprint。\n Child RSS 是 cmux 应用进程后代的递归驻留内存,\n 按命令名分组,并在已知时归因到工作区、面板和 surface。\n\n示例:\n cmux memory\n cmux memory --groups 20\n cmux --json memory --all"}},"zh-Hant": {"stringUnit": {"state": "translated","value": "用法:cmux memory [flags]\n\n將 cmux 應用程式記憶體與終端機子行程的遞迴 RSS 分開診斷。\n\n旗標:\n --all 包含所有視窗(預設:僅目前視窗)\n --workspace 限制歸因標籤的工作區情境\n --groups 要顯示的子命令群組數量(預設:12)\n --json 結構化 JSON 輸出\n\n輸出:\n 應用程式 footprint 是 macOS 行程統計中 cmux 行程的直接實體 footprint。\n Child RSS 是 cmux 應用程式行程後代的遞迴常駐記憶體,\n 依命令名稱分組,並在已知時歸因到工作區、面板和 surface。\n\n範例:\n cmux memory\n cmux memory --groups 20\n cmux --json memory --all"}}}}, - "cli.memory.error.workspaceRequiresValue": {"extractionState": "manual","localizations": {"ar": {"stringUnit": {"state": "translated","value": "يتطلب memory --workspace "}},"bs": {"stringUnit": {"state": "translated","value": "memory zahtijeva --workspace "}},"da": {"stringUnit": {"state": "translated","value": "memory kræver --workspace "}},"de": {"stringUnit": {"state": "translated","value": "memory erfordert --workspace "}},"en": {"stringUnit": {"state": "translated","value": "memory requires --workspace "}},"es": {"stringUnit": {"state": "translated","value": "memory requiere --workspace "}},"fr": {"stringUnit": {"state": "translated","value": "memory nécessite --workspace "}},"it": {"stringUnit": {"state": "translated","value": "memory richiede --workspace "}},"ja": {"stringUnit": {"state": "translated","value": "memory には --workspace が必要です"}},"ko": {"stringUnit": {"state": "translated","value": "memory에는 --workspace 가 필요합니다"}},"nb": {"stringUnit": {"state": "translated","value": "memory krever --workspace "}},"pl": {"stringUnit": {"state": "translated","value": "memory wymaga --workspace "}},"pt-BR": {"stringUnit": {"state": "translated","value": "memory requer --workspace "}},"ru": {"stringUnit": {"state": "translated","value": "memory требует --workspace "}},"th": {"stringUnit": {"state": "translated","value": "memory ต้องมี --workspace "}},"tr": {"stringUnit": {"state": "translated","value": "memory için --workspace gerekir"}},"uk": {"stringUnit": {"state": "translated","value": "memory потребує --workspace "}},"zh-Hans": {"stringUnit": {"state": "translated","value": "memory 需要 --workspace "}},"zh-Hant": {"stringUnit": {"state": "translated","value": "memory 需要 --workspace "}}}}, - "cli.memory.error.invalidWorkspace": {"extractionState": "manual","localizations": {"ar": {"stringUnit": {"state": "translated","value": "memory: معرّف مساحة العمل '%@' غير صالح"}},"bs": {"stringUnit": {"state": "translated","value": "memory: neispravan identifikator radnog prostora '%@'"}},"da": {"stringUnit": {"state": "translated","value": "memory: ugyldigt arbejdsområdehåndtag '%@'"}},"de": {"stringUnit": {"state": "translated","value": "memory: ungültiger Workspace-Bezeichner '%@'"}},"en": {"stringUnit": {"state": "translated","value": "memory: invalid workspace handle '%@'"}},"es": {"stringUnit": {"state": "translated","value": "memory: identificador de espacio de trabajo no válido '%@'"}},"fr": {"stringUnit": {"state": "translated","value": "memory : identifiant d’espace de travail non valide '%@'"}},"it": {"stringUnit": {"state": "translated","value": "memory: handle area di lavoro non valido '%@'"}},"ja": {"stringUnit": {"state": "translated","value": "memory: ワークスペース指定 '%@' は無効です"}},"ko": {"stringUnit": {"state": "translated","value": "memory: 잘못된 워크스페이스 핸들 '%@'"}},"nb": {"stringUnit": {"state": "translated","value": "memory: ugyldig arbeidsområdehåndtak '%@'"}},"pl": {"stringUnit": {"state": "translated","value": "memory: nieprawidłowy uchwyt obszaru roboczego '%@'"}},"pt-BR": {"stringUnit": {"state": "translated","value": "memory: identificador de workspace inválido '%@'"}},"ru": {"stringUnit": {"state": "translated","value": "memory: недопустимый дескриптор рабочей области '%@'"}},"th": {"stringUnit": {"state": "translated","value": "memory: แฮนเดิลเวิร์กสเปซไม่ถูกต้อง '%@'"}},"tr": {"stringUnit": {"state": "translated","value": "memory: geçersiz çalışma alanı tanıtıcısı '%@'"}},"uk": {"stringUnit": {"state": "translated","value": "memory: неприпустимий дескриптор робочої області '%@'"}},"zh-Hans": {"stringUnit": {"state": "translated","value": "memory:无效的工作区句柄 '%@'"}},"zh-Hant": {"stringUnit": {"state": "translated","value": "memory:無效的工作區控制代碼 '%@'"}}}}, - "cli.memory.error.groupsRequiresValue": {"extractionState": "manual","localizations": {"ar": {"stringUnit": {"state": "translated","value": "يتطلب memory --groups "}},"bs": {"stringUnit": {"state": "translated","value": "memory zahtijeva --groups "}},"da": {"stringUnit": {"state": "translated","value": "memory kræver --groups "}},"de": {"stringUnit": {"state": "translated","value": "memory erfordert --groups "}},"en": {"stringUnit": {"state": "translated","value": "memory requires --groups "}},"es": {"stringUnit": {"state": "translated","value": "memory requiere --groups "}},"fr": {"stringUnit": {"state": "translated","value": "memory nécessite --groups "}},"it": {"stringUnit": {"state": "translated","value": "memory richiede --groups "}},"ja": {"stringUnit": {"state": "translated","value": "memory には --groups が必要です"}},"ko": {"stringUnit": {"state": "translated","value": "memory에는 --groups 가 필요합니다"}},"nb": {"stringUnit": {"state": "translated","value": "memory krever --groups "}},"pl": {"stringUnit": {"state": "translated","value": "memory wymaga --groups "}},"pt-BR": {"stringUnit": {"state": "translated","value": "memory requer --groups "}},"ru": {"stringUnit": {"state": "translated","value": "memory требует --groups "}},"th": {"stringUnit": {"state": "translated","value": "memory ต้องมี --groups "}},"tr": {"stringUnit": {"state": "translated","value": "memory için --groups gerekir"}},"uk": {"stringUnit": {"state": "translated","value": "memory потребує --groups "}},"zh-Hans": {"stringUnit": {"state": "translated","value": "memory 需要 --groups "}},"zh-Hant": {"stringUnit": {"state": "translated","value": "memory 需要 --groups "}}}}, - "cli.memory.error.unknownFlag": {"extractionState": "manual","localizations": {"ar": {"stringUnit": {"state": "translated","value": "memory: خيار غير معروف '%@'. الخيارات المعروفة: --all --workspace --groups --json"}},"bs": {"stringUnit": {"state": "translated","value": "memory: nepoznata opcija '%@'. Poznate opcije: --all --workspace --groups --json"}},"da": {"stringUnit": {"state": "translated","value": "memory: ukendt flag '%@'. Kendte flag: --all --workspace --groups --json"}},"de": {"stringUnit": {"state": "translated","value": "memory: unbekannte Option '%@'. Bekannte Optionen: --all --workspace --groups --json"}},"en": {"stringUnit": {"state": "translated","value": "memory: unknown flag '%@'. Known flags: --all --workspace --groups --json"}},"es": {"stringUnit": {"state": "translated","value": "memory: opción desconocida '%@'. Opciones conocidas: --all --workspace --groups --json"}},"fr": {"stringUnit": {"state": "translated","value": "memory : option inconnue '%@'. Options connues : --all --workspace --groups --json"}},"it": {"stringUnit": {"state": "translated","value": "memory: opzione sconosciuta '%@'. Opzioni note: --all --workspace --groups --json"}},"ja": {"stringUnit": {"state": "translated","value": "memory: 不明なフラグ '%@'。既知のフラグ: --all --workspace --groups --json"}},"ko": {"stringUnit": {"state": "translated","value": "memory: 알 수 없는 플래그 '%@'. 알려진 플래그: --all --workspace --groups --json"}},"nb": {"stringUnit": {"state": "translated","value": "memory: ukjent flagg '%@'. Kjente flagg: --all --workspace --groups --json"}},"pl": {"stringUnit": {"state": "translated","value": "memory: nieznana opcja '%@'. Znane opcje: --all --workspace --groups --json"}},"pt-BR": {"stringUnit": {"state": "translated","value": "memory: opção desconhecida '%@'. Opções conhecidas: --all --workspace --groups --json"}},"ru": {"stringUnit": {"state": "translated","value": "memory: неизвестный флаг '%@'. Известные флаги: --all --workspace --groups --json"}},"th": {"stringUnit": {"state": "translated","value": "memory: แฟล็กที่ไม่รู้จัก '%@'. แฟล็กที่รู้จัก: --all --workspace --groups --json"}},"tr": {"stringUnit": {"state": "translated","value": "memory: bilinmeyen bayrak '%@'. Bilinen bayraklar: --all --workspace --groups --json"}},"uk": {"stringUnit": {"state": "translated","value": "memory: невідомий прапорець '%@'. Відомі прапорці: --all --workspace --groups --json"}},"zh-Hans": {"stringUnit": {"state": "translated","value": "memory:未知标志 '%@'。已知标志:--all --workspace --groups --json"}},"zh-Hant": {"stringUnit": {"state": "translated","value": "memory:未知旗標 '%@'。已知旗標:--all --workspace --groups --json"}}}}, - "cli.memory.error.unexpectedArgument": {"extractionState": "manual","localizations": {"ar": {"stringUnit": {"state": "translated","value": "memory: وسيطة غير متوقعة '%@'"}},"bs": {"stringUnit": {"state": "translated","value": "memory: neočekivan argument '%@'"}},"da": {"stringUnit": {"state": "translated","value": "memory: uventet argument '%@'"}},"de": {"stringUnit": {"state": "translated","value": "memory: unerwartetes Argument '%@'"}},"en": {"stringUnit": {"state": "translated","value": "memory: unexpected argument '%@'"}},"es": {"stringUnit": {"state": "translated","value": "memory: argumento inesperado '%@'"}},"fr": {"stringUnit": {"state": "translated","value": "memory : argument inattendu '%@'"}},"it": {"stringUnit": {"state": "translated","value": "memory: argomento inatteso '%@'"}},"ja": {"stringUnit": {"state": "translated","value": "memory: 予期しない引数 '%@'"}},"ko": {"stringUnit": {"state": "translated","value": "memory: 예상치 못한 인수 '%@'"}},"nb": {"stringUnit": {"state": "translated","value": "memory: uventet argument '%@'"}},"pl": {"stringUnit": {"state": "translated","value": "memory: nieoczekiwany argument '%@'"}},"pt-BR": {"stringUnit": {"state": "translated","value": "memory: argumento inesperado '%@'"}},"ru": {"stringUnit": {"state": "translated","value": "memory: неожиданный аргумент '%@'"}},"th": {"stringUnit": {"state": "translated","value": "memory: อาร์กิวเมนต์ที่ไม่คาดคิด '%@'"}},"tr": {"stringUnit": {"state": "translated","value": "memory: beklenmeyen argüman '%@'"}},"uk": {"stringUnit": {"state": "translated","value": "memory: неочікуваний аргумент '%@'"}},"zh-Hans": {"stringUnit": {"state": "translated","value": "memory:意外参数 '%@'"}},"zh-Hant": {"stringUnit": {"state": "translated","value": "memory:非預期的引數 '%@'"}}}}, - "cli.memory.error.invalidGroups": {"extractionState": "manual","localizations": {"ar": {"stringUnit": {"state": "translated","value": "memory: قيمة --groups '%@' غير صالحة. استخدم عددا صحيحا من 1 إلى 100"}},"bs": {"stringUnit": {"state": "translated","value": "memory: neispravna --groups vrijednost '%@'. Koristite cijeli broj od 1 do 100"}},"da": {"stringUnit": {"state": "translated","value": "memory: ugyldig --groups-værdi '%@'. Brug et heltal fra 1 til 100"}},"de": {"stringUnit": {"state": "translated","value": "memory: ungültiger --groups-Wert '%@'. Verwenden Sie eine Ganzzahl von 1 bis 100"}},"en": {"stringUnit": {"state": "translated","value": "memory: invalid --groups value '%@'. Use an integer from 1 to 100"}},"es": {"stringUnit": {"state": "translated","value": "memory: valor de --groups no válido '%@'. Use un entero de 1 a 100"}},"fr": {"stringUnit": {"state": "translated","value": "memory : valeur --groups non valide '%@'. Utilisez un entier de 1 à 100"}},"it": {"stringUnit": {"state": "translated","value": "memory: valore --groups non valido '%@'. Usa un intero da 1 a 100"}},"ja": {"stringUnit": {"state": "translated","value": "memory: --groups の値 '%@' は無効です。1 から 100 の整数を指定してください"}},"ko": {"stringUnit": {"state": "translated","value": "memory: 잘못된 --groups 값 '%@'. 1부터 100까지의 정수를 사용하세요"}},"nb": {"stringUnit": {"state": "translated","value": "memory: ugyldig --groups-verdi '%@'. Bruk et heltall fra 1 til 100"}},"pl": {"stringUnit": {"state": "translated","value": "memory: nieprawidłowa wartość --groups '%@'. Użyj liczby całkowitej od 1 do 100"}},"pt-BR": {"stringUnit": {"state": "translated","value": "memory: valor inválido para --groups '%@'. Use um inteiro de 1 a 100"}},"ru": {"stringUnit": {"state": "translated","value": "memory: недопустимое значение --groups '%@'. Используйте целое число от 1 до 100"}},"th": {"stringUnit": {"state": "translated","value": "memory: ค่า --groups '%@' ไม่ถูกต้อง ใช้จำนวนเต็มตั้งแต่ 1 ถึง 100"}},"tr": {"stringUnit": {"state": "translated","value": "memory: geçersiz --groups değeri '%@'. 1 ile 100 arasında bir tam sayı kullanın"}},"uk": {"stringUnit": {"state": "translated","value": "memory: неприпустиме значення --groups '%@'. Використайте ціле число від 1 до 100"}},"zh-Hans": {"stringUnit": {"state": "translated","value": "memory:无效的 --groups 值 '%@'。请使用 1 到 100 的整数"}},"zh-Hant": {"stringUnit": {"state": "translated","value": "memory:無效的 --groups 值 '%@'。請使用 1 到 100 的整數"}}}}, - "cli.memory.output.noDiagnostic": {"extractionState": "manual","localizations": {"ar": {"stringUnit": {"state": "translated","value": "لا يوجد تشخيص ذاكرة متاح"}},"bs": {"stringUnit": {"state": "translated","value": "Nema dostupne dijagnostike memorije"}},"da": {"stringUnit": {"state": "translated","value": "Ingen hukommelsesdiagnostik tilgængelig"}},"de": {"stringUnit": {"state": "translated","value": "Keine Speicherdiagnose verfügbar"}},"en": {"stringUnit": {"state": "translated","value": "No memory diagnostic available"}},"es": {"stringUnit": {"state": "translated","value": "No hay diagnóstico de memoria disponible"}},"fr": {"stringUnit": {"state": "translated","value": "Aucun diagnostic mémoire disponible"}},"it": {"stringUnit": {"state": "translated","value": "Nessuna diagnostica memoria disponibile"}},"ja": {"stringUnit": {"state": "translated","value": "利用できるメモリ診断がありません"}},"ko": {"stringUnit": {"state": "translated","value": "사용 가능한 메모리 진단이 없습니다"}},"nb": {"stringUnit": {"state": "translated","value": "Ingen minnediagnostikk tilgjengelig"}},"pl": {"stringUnit": {"state": "translated","value": "Brak dostępnej diagnostyki pamięci"}},"pt-BR": {"stringUnit": {"state": "translated","value": "Nenhum diagnóstico de memória disponível"}},"ru": {"stringUnit": {"state": "translated","value": "Диагностика памяти недоступна"}},"th": {"stringUnit": {"state": "translated","value": "ไม่มีการวินิจฉัยหน่วยความจำ"}},"tr": {"stringUnit": {"state": "translated","value": "Bellek tanılaması yok"}},"uk": {"stringUnit": {"state": "translated","value": "Діагностика пам’яті недоступна"}},"zh-Hans": {"stringUnit": {"state": "translated","value": "没有可用的内存诊断"}},"zh-Hant": {"stringUnit": {"state": "translated","value": "沒有可用的記憶體診斷"}}}}, - "cli.memory.output.appHeader": {"extractionState": "manual","localizations": {"ar": {"stringUnit": {"state": "translated","value": "التطبيق"}},"bs": {"stringUnit": {"state": "translated","value": "APLIKACIJA"}},"da": {"stringUnit": {"state": "translated","value": "PROGRAM"}},"de": {"stringUnit": {"state": "translated","value": "ANWENDUNG"}},"en": {"stringUnit": {"state": "translated","value": "APP"}},"es": {"stringUnit": {"state": "translated","value": "APLICACIÓN"}},"fr": {"stringUnit": {"state": "translated","value": "APPLICATION"}},"it": {"stringUnit": {"state": "translated","value": "APPLICAZIONE"}},"ja": {"stringUnit": {"state": "translated","value": "APP"}},"ko": {"stringUnit": {"state": "translated","value": "앱"}},"nb": {"stringUnit": {"state": "translated","value": "PROGRAM"}},"pl": {"stringUnit": {"state": "translated","value": "APLIKACJA"}},"pt-BR": {"stringUnit": {"state": "translated","value": "APLICATIVO"}},"ru": {"stringUnit": {"state": "translated","value": "ПРИЛОЖЕНИЕ"}},"th": {"stringUnit": {"state": "translated","value": "แอป"}},"tr": {"stringUnit": {"state": "translated","value": "UYGULAMA"}},"uk": {"stringUnit": {"state": "translated","value": "ЗАСТОСУНОК"}},"zh-Hans": {"stringUnit": {"state": "translated","value": "应用"}},"zh-Hant": {"stringUnit": {"state": "translated","value": "應用程式"}}}}, - "cli.memory.output.appFootprint": {"extractionState": "manual","localizations": {"ar": {"stringUnit": {"state": "translated","value": " البصمة %@"}},"bs": {"stringUnit": {"state": "translated","value": " otisak %@"}},"da": {"stringUnit": {"state": "translated","value": " fodaftryk %@"}},"de": {"stringUnit": {"state": "translated","value": " Footprint %@"}},"en": {"stringUnit": {"state": "translated","value": " footprint %@"}},"es": {"stringUnit": {"state": "translated","value": " huella %@"}},"fr": {"stringUnit": {"state": "translated","value": " empreinte %@"}},"it": {"stringUnit": {"state": "translated","value": " impronta %@"}},"ja": {"stringUnit": {"state": "translated","value": " フットプリント %@"}},"ko": {"stringUnit": {"state": "translated","value": " 앱 사용량 %@"}},"nb": {"stringUnit": {"state": "translated","value": " avtrykk %@"}},"pl": {"stringUnit": {"state": "translated","value": " ślad %@"}},"pt-BR": {"stringUnit": {"state": "translated","value": " pegada %@"}},"ru": {"stringUnit": {"state": "translated","value": " отпечаток %@"}},"th": {"stringUnit": {"state": "translated","value": " รอยใช้หน่วยความจำ %@"}},"tr": {"stringUnit": {"state": "translated","value": " bellek izi %@"}},"uk": {"stringUnit": {"state": "translated","value": " відбиток %@"}},"zh-Hans": {"stringUnit": {"state": "translated","value": " 应用占用 %@"}},"zh-Hant": {"stringUnit": {"state": "translated","value": " 應用占用 %@"}}}}, - "cli.memory.output.appRSS": {"extractionState": "manual","localizations": {"ar": {"stringUnit": {"state": "translated","value": " RSS %@"}},"bs": {"stringUnit": {"state": "translated","value": " RSS %@"}},"da": {"stringUnit": {"state": "translated","value": " RSS %@"}},"de": {"stringUnit": {"state": "translated","value": " RSS %@"}},"en": {"stringUnit": {"state": "translated","value": " rss %@"}},"es": {"stringUnit": {"state": "translated","value": " RSS %@"}},"fr": {"stringUnit": {"state": "translated","value": " RSS %@"}},"it": {"stringUnit": {"state": "translated","value": " RSS %@"}},"ja": {"stringUnit": {"state": "translated","value": " RSS %@"}},"ko": {"stringUnit": {"state": "translated","value": " RSS %@"}},"nb": {"stringUnit": {"state": "translated","value": " RSS %@"}},"pl": {"stringUnit": {"state": "translated","value": " RSS %@"}},"pt-BR": {"stringUnit": {"state": "translated","value": " RSS %@"}},"ru": {"stringUnit": {"state": "translated","value": " RSS %@"}},"th": {"stringUnit": {"state": "translated","value": " RSS %@"}},"tr": {"stringUnit": {"state": "translated","value": " RSS %@"}},"uk": {"stringUnit": {"state": "translated","value": " RSS %@"}},"zh-Hans": {"stringUnit": {"state": "translated","value": " RSS %@"}},"zh-Hant": {"stringUnit": {"state": "translated","value": " RSS %@"}}}}, - "cli.memory.output.childrenHeader": {"extractionState": "manual","localizations": {"ar": {"stringUnit": {"state": "translated","value": "العمليات الفرعية"}},"bs": {"stringUnit": {"state": "translated","value": "PODPROCESI"}},"da": {"stringUnit": {"state": "translated","value": "UNDERPROCESSER"}},"de": {"stringUnit": {"state": "translated","value": "KINDPROZESSE"}},"en": {"stringUnit": {"state": "translated","value": "CHILD PROCESSES"}},"es": {"stringUnit": {"state": "translated","value": "PROCESOS SECUNDARIOS"}},"fr": {"stringUnit": {"state": "translated","value": "PROCESSUS ENFANTS"}},"it": {"stringUnit": {"state": "translated","value": "PROCESSI FIGLI"}},"ja": {"stringUnit": {"state": "translated","value": "子プロセス"}},"ko": {"stringUnit": {"state": "translated","value": "하위 프로세스"}},"nb": {"stringUnit": {"state": "translated","value": "UNDERPROSESSER"}},"pl": {"stringUnit": {"state": "translated","value": "PROCESY POTOMNE"}},"pt-BR": {"stringUnit": {"state": "translated","value": "PROCESSOS FILHOS"}},"ru": {"stringUnit": {"state": "translated","value": "ДОЧЕРНИЕ ПРОЦЕССЫ"}},"th": {"stringUnit": {"state": "translated","value": "โปรเซสลูก"}},"tr": {"stringUnit": {"state": "translated","value": "ALT SÜREÇLER"}},"uk": {"stringUnit": {"state": "translated","value": "ДОЧІРНІ ПРОЦЕСИ"}},"zh-Hans": {"stringUnit": {"state": "translated","value": "子进程"}},"zh-Hant": {"stringUnit": {"state": "translated","value": "子行程"}}}}, - "cli.memory.output.recursiveRSS": {"extractionState": "manual","localizations": {"ar": {"stringUnit": {"state": "translated","value": " RSS عودي %@ عبر %@"}},"bs": {"stringUnit": {"state": "translated","value": " rekurzivni RSS %@ kroz %@"}},"da": {"stringUnit": {"state": "translated","value": " rekursiv RSS %@ på tværs af %@"}},"de": {"stringUnit": {"state": "translated","value": " rekursives RSS %@ über %@"}},"en": {"stringUnit": {"state": "translated","value": " recursive RSS %@ across %@"}},"es": {"stringUnit": {"state": "translated","value": " RSS recursivo %@ en %@"}},"fr": {"stringUnit": {"state": "translated","value": " RSS récursif %@ sur %@"}},"it": {"stringUnit": {"state": "translated","value": " RSS ricorsivo %@ su %@"}},"ja": {"stringUnit": {"state": "translated","value": " 再帰的 RSS %@(%@)"}},"ko": {"stringUnit": {"state": "translated","value": " 재귀 RSS %@ / %@"}},"nb": {"stringUnit": {"state": "translated","value": " rekursiv RSS %@ over %@"}},"pl": {"stringUnit": {"state": "translated","value": " rekurencyjny RSS %@ w %@"}},"pt-BR": {"stringUnit": {"state": "translated","value": " RSS recursivo %@ em %@"}},"ru": {"stringUnit": {"state": "translated","value": " рекурсивный RSS %@ по %@"}},"th": {"stringUnit": {"state": "translated","value": " RSS แบบเรียกซ้ำ %@ ใน %@"}},"tr": {"stringUnit": {"state": "translated","value": " özyinelemeli RSS %@ / %@"}},"uk": {"stringUnit": {"state": "translated","value": " рекурсивний RSS %@ у %@"}},"zh-Hans": {"stringUnit": {"state": "translated","value": " 递归 RSS %@,跨 %@"}},"zh-Hant": {"stringUnit": {"state": "translated","value": " 遞迴 RSS %@,跨 %@"}}}}, - "cli.memory.output.processCount.one": {"extractionState": "manual","localizations": {"ar": {"stringUnit": {"state": "translated","value": "عملية واحدة"}},"bs": {"stringUnit": {"state": "translated","value": "1 proces"}},"da": {"stringUnit": {"state": "translated","value": "1 proces"}},"de": {"stringUnit": {"state": "translated","value": "1 Prozess"}},"en": {"stringUnit": {"state": "translated","value": "1 process"}},"es": {"stringUnit": {"state": "translated","value": "1 proceso"}},"fr": {"stringUnit": {"state": "translated","value": "1 processus"}},"it": {"stringUnit": {"state": "translated","value": "1 processo"}},"ja": {"stringUnit": {"state": "translated","value": "1 個のプロセス"}},"ko": {"stringUnit": {"state": "translated","value": "프로세스 1개"}},"nb": {"stringUnit": {"state": "translated","value": "1 prosess"}},"pl": {"stringUnit": {"state": "translated","value": "1 proces"}},"pt-BR": {"stringUnit": {"state": "translated","value": "1 processo"}},"ru": {"stringUnit": {"state": "translated","value": "1 процесс"}},"th": {"stringUnit": {"state": "translated","value": "1 โปรเซส"}},"tr": {"stringUnit": {"state": "translated","value": "1 süreç"}},"uk": {"stringUnit": {"state": "translated","value": "1 процес"}},"zh-Hans": {"stringUnit": {"state": "translated","value": "1 个进程"}},"zh-Hant": {"stringUnit": {"state": "translated","value": "1 個行程"}}}}, - "cli.memory.output.processCount.other": {"extractionState": "manual","localizations": {"ar": {"stringUnit": {"state": "translated","value": "%lld عملية"}},"bs": {"stringUnit": {"state": "translated","value": "%lld procesa"}},"da": {"stringUnit": {"state": "translated","value": "%lld processer"}},"de": {"stringUnit": {"state": "translated","value": "%lld Prozesse"}},"en": {"stringUnit": {"state": "translated","value": "%lld processes"}},"es": {"stringUnit": {"state": "translated","value": "%lld procesos"}},"fr": {"stringUnit": {"state": "translated","value": "%lld processus"}},"it": {"stringUnit": {"state": "translated","value": "%lld processi"}},"ja": {"stringUnit": {"state": "translated","value": "%lld 個のプロセス"}},"ko": {"stringUnit": {"state": "translated","value": "프로세스 %lld개"}},"nb": {"stringUnit": {"state": "translated","value": "%lld prosesser"}},"pl": {"stringUnit": {"state": "translated","value": "%lld procesów"}},"pt-BR": {"stringUnit": {"state": "translated","value": "%lld processos"}},"ru": {"stringUnit": {"state": "translated","value": "%lld процессов"}},"th": {"stringUnit": {"state": "translated","value": "%lld โปรเซส"}},"tr": {"stringUnit": {"state": "translated","value": "%lld süreç"}},"uk": {"stringUnit": {"state": "translated","value": "%lld процесів"}},"zh-Hans": {"stringUnit": {"state": "translated","value": "%lld 个进程"}},"zh-Hant": {"stringUnit": {"state": "translated","value": "%lld 個行程"}}}}, - "cli.memory.output.noChildGroups": {"extractionState": "manual","localizations": {"ar": {"stringUnit": {"state": "translated","value": " لا توجد مجموعات عمليات فرعية"}},"bs": {"stringUnit": {"state": "translated","value": " nema grupa podprocesa"}},"da": {"stringUnit": {"state": "translated","value": " ingen underprocesgrupper"}},"de": {"stringUnit": {"state": "translated","value": " keine Kindprozessgruppen"}},"en": {"stringUnit": {"state": "translated","value": " no child process groups"}},"es": {"stringUnit": {"state": "translated","value": " no hay grupos de procesos secundarios"}},"fr": {"stringUnit": {"state": "translated","value": " aucun groupe de processus enfants"}},"it": {"stringUnit": {"state": "translated","value": " nessun gruppo di processi figli"}},"ja": {"stringUnit": {"state": "translated","value": " 子プロセスグループはありません"}},"ko": {"stringUnit": {"state": "translated","value": " 하위 프로세스 그룹 없음"}},"nb": {"stringUnit": {"state": "translated","value": " ingen underprosessgrupper"}},"pl": {"stringUnit": {"state": "translated","value": " brak grup procesów potomnych"}},"pt-BR": {"stringUnit": {"state": "translated","value": " nenhum grupo de processos filhos"}},"ru": {"stringUnit": {"state": "translated","value": " нет групп дочерних процессов"}},"th": {"stringUnit": {"state": "translated","value": " ไม่มีกลุ่มโปรเซสลูก"}},"tr": {"stringUnit": {"state": "translated","value": " alt süreç grubu yok"}},"uk": {"stringUnit": {"state": "translated","value": " немає груп дочірніх процесів"}},"zh-Hans": {"stringUnit": {"state": "translated","value": " 没有子进程组"}},"zh-Hant": {"stringUnit": {"state": "translated","value": " 沒有子行程群組"}}}}, - "cli.memory.output.topGroupsHeader": {"extractionState": "manual","localizations": {"ar": {"stringUnit": {"state": "translated","value": "أعلى مجموعات العمليات الفرعية"}},"bs": {"stringUnit": {"state": "translated","value": "NAJVEĆE GRUPE PODPROCESA"}},"da": {"stringUnit": {"state": "translated","value": "STØRSTE UNDERPROCESGRUPPER"}},"de": {"stringUnit": {"state": "translated","value": "GRÖSSTE KINDPROZESSGRUPPEN"}},"en": {"stringUnit": {"state": "translated","value": "TOP CHILD GROUPS"}},"es": {"stringUnit": {"state": "translated","value": "PRINCIPALES GRUPOS SECUNDARIOS"}},"fr": {"stringUnit": {"state": "translated","value": "PRINCIPAUX GROUPES ENFANTS"}},"it": {"stringUnit": {"state": "translated","value": "GRUPPI FIGLI PRINCIPALI"}},"ja": {"stringUnit": {"state": "translated","value": "上位の子プロセスグループ"}},"ko": {"stringUnit": {"state": "translated","value": "상위 하위 프로세스 그룹"}},"nb": {"stringUnit": {"state": "translated","value": "STØRSTE UNDERPROSESSGRUPPER"}},"pl": {"stringUnit": {"state": "translated","value": "NAJWIĘKSZE GRUPY POTOMNE"}},"pt-BR": {"stringUnit": {"state": "translated","value": "PRINCIPAIS GRUPOS FILHOS"}},"ru": {"stringUnit": {"state": "translated","value": "КРУПНЕЙШИЕ ДОЧЕРНИЕ ГРУППЫ"}},"th": {"stringUnit": {"state": "translated","value": "กลุ่มโปรเซสลูกสูงสุด"}},"tr": {"stringUnit": {"state": "translated","value": "EN BÜYÜK ALT SÜREÇ GRUPLARI"}},"uk": {"stringUnit": {"state": "translated","value": "НАЙБІЛЬШІ ДОЧІРНІ ГРУПИ"}},"zh-Hans": {"stringUnit": {"state": "translated","value": "主要子进程组"}},"zh-Hant": {"stringUnit": {"state": "translated","value": "主要子行程群組"}}}}, - "cli.memory.output.topGroupsColumns": {"extractionState": "manual","localizations": {"ar": {"stringUnit": {"state": "translated","value": " RSS PROC الأمر الإسناد"}},"bs": {"stringUnit": {"state": "translated","value": " RSS PROC NAREDBA PRIPISIVANJE"}},"da": {"stringUnit": {"state": "translated","value": " RSS PROC KOMMANDO TILSKRIVNING"}},"de": {"stringUnit": {"state": "translated","value": " RSS PROC BEFEHL ZUORDNUNG"}},"en": {"stringUnit": {"state": "translated","value": " RSS PROC COMMAND ATTRIBUTION"}},"es": {"stringUnit": {"state": "translated","value": " RSS PROC COMANDO ATRIBUCIÓN"}},"fr": {"stringUnit": {"state": "translated","value": " RSS PROC COMMANDE ATTRIBUTION"}},"it": {"stringUnit": {"state": "translated","value": " RSS PROC COMANDO ATTRIBUZIONE"}},"ja": {"stringUnit": {"state": "translated","value": " RSS PROC COMMAND ATTRIBUTION"}},"ko": {"stringUnit": {"state": "translated","value": " RSS PROC 명령 귀속"}},"nb": {"stringUnit": {"state": "translated","value": " RSS PROC KOMMANDO TILORDNING"}},"pl": {"stringUnit": {"state": "translated","value": " RSS PROC POLECENIE PRZYPISANIE"}},"pt-BR": {"stringUnit": {"state": "translated","value": " RSS PROC COMANDO ATRIBUIÇÃO"}},"ru": {"stringUnit": {"state": "translated","value": " RSS PROC КОМАНДА АТРИБУЦИЯ"}},"th": {"stringUnit": {"state": "translated","value": " RSS PROC คำสั่ง การระบุที่มา"}},"tr": {"stringUnit": {"state": "translated","value": " RSS PROC KOMUT ATIF"}},"uk": {"stringUnit": {"state": "translated","value": " RSS PROC КОМАНДА АТРИБУЦІЯ"}},"zh-Hans": {"stringUnit": {"state": "translated","value": " RSS PROC 命令 归因"}},"zh-Hant": {"stringUnit": {"state": "translated","value": " RSS PROC 命令 歸因"}}}}, - "cli.memory.output.unattributed": {"extractionState": "manual","localizations": {"ar": {"stringUnit": {"state": "translated","value": "غير مسند"}},"bs": {"stringUnit": {"state": "translated","value": "nepripisano"}},"da": {"stringUnit": {"state": "translated","value": "ikke tilskrevet"}},"de": {"stringUnit": {"state": "translated","value": "nicht zugeordnet"}},"en": {"stringUnit": {"state": "translated","value": "unattributed"}},"es": {"stringUnit": {"state": "translated","value": "sin atribuir"}},"fr": {"stringUnit": {"state": "translated","value": "non attribué"}},"it": {"stringUnit": {"state": "translated","value": "non attribuito"}},"ja": {"stringUnit": {"state": "translated","value": "未割り当て"}},"ko": {"stringUnit": {"state": "translated","value": "미귀속"}},"nb": {"stringUnit": {"state": "translated","value": "ikke tilordnet"}},"pl": {"stringUnit": {"state": "translated","value": "nieprzypisane"}},"pt-BR": {"stringUnit": {"state": "translated","value": "sem atribuição"}},"ru": {"stringUnit": {"state": "translated","value": "без атрибуции"}},"th": {"stringUnit": {"state": "translated","value": "ไม่ระบุที่มา"}},"tr": {"stringUnit": {"state": "translated","value": "atıfsız"}},"uk": {"stringUnit": {"state": "translated","value": "без атрибуції"}},"zh-Hans": {"stringUnit": {"state": "translated","value": "未归因"}},"zh-Hant": {"stringUnit": {"state": "translated","value": "未歸因"}}}}, - "cli.memory.output.workspaceAttribution": {"extractionState": "manual","localizations": {"ar": {"stringUnit": {"state": "translated","value": "مساحة العمل %@"}},"bs": {"stringUnit": {"state": "translated","value": "radni prostor %@"}},"da": {"stringUnit": {"state": "translated","value": "arbejdsområde %@"}},"de": {"stringUnit": {"state": "translated","value": "Workspace %@"}},"en": {"stringUnit": {"state": "translated","value": "workspace %@"}},"es": {"stringUnit": {"state": "translated","value": "espacio de trabajo %@"}},"fr": {"stringUnit": {"state": "translated","value": "espace de travail %@"}},"it": {"stringUnit": {"state": "translated","value": "area di lavoro %@"}},"ja": {"stringUnit": {"state": "translated","value": "ワークスペース %@"}},"ko": {"stringUnit": {"state": "translated","value": "워크스페이스 %@"}},"nb": {"stringUnit": {"state": "translated","value": "arbeidsområde %@"}},"pl": {"stringUnit": {"state": "translated","value": "obszar roboczy %@"}},"pt-BR": {"stringUnit": {"state": "translated","value": "espaço de trabalho %@"}},"ru": {"stringUnit": {"state": "translated","value": "рабочая область %@"}},"th": {"stringUnit": {"state": "translated","value": "เวิร์กสเปซ %@"}},"tr": {"stringUnit": {"state": "translated","value": "çalışma alanı %@"}},"uk": {"stringUnit": {"state": "translated","value": "робоча область %@"}},"zh-Hans": {"stringUnit": {"state": "translated","value": "工作区 %@"}},"zh-Hant": {"stringUnit": {"state": "translated","value": "工作區 %@"}}}}, - "cli.memory.output.paneAttribution": {"extractionState": "manual","localizations": {"ar": {"stringUnit": {"state": "translated","value": "جزء %@"}},"bs": {"stringUnit": {"state": "translated","value": "panel %@"}},"da": {"stringUnit": {"state": "translated","value": "rude %@"}},"de": {"stringUnit": {"state": "translated","value": "Bereich %@"}},"en": {"stringUnit": {"state": "translated","value": "pane %@"}},"es": {"stringUnit": {"state": "translated","value": "panel %@"}},"fr": {"stringUnit": {"state": "translated","value": "panneau %@"}},"it": {"stringUnit": {"state": "translated","value": "pannello %@"}},"ja": {"stringUnit": {"state": "translated","value": "ペイン %@"}},"ko": {"stringUnit": {"state": "translated","value": "패널 %@"}},"nb": {"stringUnit": {"state": "translated","value": "rute %@"}},"pl": {"stringUnit": {"state": "translated","value": "panel %@"}},"pt-BR": {"stringUnit": {"state": "translated","value": "painel %@"}},"ru": {"stringUnit": {"state": "translated","value": "панель %@"}},"th": {"stringUnit": {"state": "translated","value": "พาเนล %@"}},"tr": {"stringUnit": {"state": "translated","value": "panel %@"}},"uk": {"stringUnit": {"state": "translated","value": "панель %@"}},"zh-Hans": {"stringUnit": {"state": "translated","value": "面板 %@"}},"zh-Hant": {"stringUnit": {"state": "translated","value": "面板 %@"}}}}, - "cli.memory.output.surfaceAttribution": {"extractionState": "manual","localizations": {"ar": {"stringUnit": {"state": "translated","value": "سطح %@"}},"bs": {"stringUnit": {"state": "translated","value": "površina %@"}},"da": {"stringUnit": {"state": "translated","value": "flade %@"}},"de": {"stringUnit": {"state": "translated","value": "Oberfläche %@"}},"en": {"stringUnit": {"state": "translated","value": "surface %@"}},"es": {"stringUnit": {"state": "translated","value": "superficie %@"}},"fr": {"stringUnit": {"state": "translated","value": "zone %@"}},"it": {"stringUnit": {"state": "translated","value": "superficie %@"}},"ja": {"stringUnit": {"state": "translated","value": "サーフェス %@"}},"ko": {"stringUnit": {"state": "translated","value": "서피스 %@"}},"nb": {"stringUnit": {"state": "translated","value": "flate %@"}},"pl": {"stringUnit": {"state": "translated","value": "powierzchnia %@"}},"pt-BR": {"stringUnit": {"state": "translated","value": "superfície %@"}},"ru": {"stringUnit": {"state": "translated","value": "поверхность %@"}},"th": {"stringUnit": {"state": "translated","value": "พื้นผิว %@"}},"tr": {"stringUnit": {"state": "translated","value": "yüzey %@"}},"uk": {"stringUnit": {"state": "translated","value": "поверхня %@"}},"zh-Hans": {"stringUnit": {"state": "translated","value": "界面 %@"}},"zh-Hant": {"stringUnit": {"state": "translated","value": "介面 %@"}}}}, - "memoryDiagnostic.summary.base": {"extractionState": "manual","localizations": {"ar": {"stringUnit": {"state": "translated","value": "%@ بصمة التطبيق + %@ RSS فرعي"}},"bs": {"stringUnit": {"state": "translated","value": "%@ otisak aplikacije + %@ RSS podprocesa"}},"da": {"stringUnit": {"state": "translated","value": "%@ app-fodaftryk + %@ child RSS"}},"de": {"stringUnit": {"state": "translated","value": "%@ App-Footprint + %@ Child RSS"}},"en": {"stringUnit": {"state": "translated","value": "%@ app footprint + %@ child RSS"}},"es": {"stringUnit": {"state": "translated","value": "%@ de huella de app + %@ de RSS secundario"}},"fr": {"stringUnit": {"state": "translated","value": "%@ d’empreinte app + %@ de RSS enfant"}},"it": {"stringUnit": {"state": "translated","value": "%@ impronta app + %@ RSS figli"}},"ja": {"stringUnit": {"state": "translated","value": "%@ アプリフットプリント + %@ 子プロセスRSS"}},"ko": {"stringUnit": {"state": "translated","value": "%@ 앱 footprint + %@ 하위 RSS"}},"nb": {"stringUnit": {"state": "translated","value": "%@ appavtrykk + %@ child RSS"}},"pl": {"stringUnit": {"state": "translated","value": "%@ ślad aplikacji + %@ RSS potomnych"}},"pt-BR": {"stringUnit": {"state": "translated","value": "%@ de pegada do app + %@ de RSS filho"}},"ru": {"stringUnit": {"state": "translated","value": "%@ отпечаток приложения + %@ дочерний RSS"}},"th": {"stringUnit": {"state": "translated","value": "%@ footprint แอป + %@ RSS ลูก"}},"tr": {"stringUnit": {"state": "translated","value": "%@ uygulama footprint + %@ alt RSS"}},"uk": {"stringUnit": {"state": "translated","value": "%@ відбиток застосунку + %@ дочірній RSS"}},"zh-Hans": {"stringUnit": {"state": "translated","value": "%@ 应用 footprint + %@ 子进程 RSS"}},"zh-Hant": {"stringUnit": {"state": "translated","value": "%@ 應用程式 footprint + %@ 子行程 RSS"}}}}, - "memoryDiagnostic.summary.topGroup": {"extractionState": "manual","localizations": {"ar": {"stringUnit": {"state": "translated","value": "; أعلى مجموعة فرعية: %@ %@"}},"bs": {"stringUnit": {"state": "translated","value": "; najveća grupa podprocesa: %@ %@"}},"da": {"stringUnit": {"state": "translated","value": "; største underprocesgruppe: %@ %@"}},"de": {"stringUnit": {"state": "translated","value": "; größte Kindprozessgruppe: %@ %@"}},"en": {"stringUnit": {"state": "translated","value": "; top child group: %@ %@"}},"es": {"stringUnit": {"state": "translated","value": "; principal grupo secundario: %@ %@"}},"fr": {"stringUnit": {"state": "translated","value": "; principal groupe enfant : %@ %@"}},"it": {"stringUnit": {"state": "translated","value": "; gruppo figlio principale: %@ %@"}},"ja": {"stringUnit": {"state": "translated","value": "; 上位の子プロセスグループ: %@ %@"}},"ko": {"stringUnit": {"state": "translated","value": "; 상위 하위 그룹: %@ %@"}},"nb": {"stringUnit": {"state": "translated","value": "; største underprosessgruppe: %@ %@"}},"pl": {"stringUnit": {"state": "translated","value": "; największa grupa potomna: %@ %@"}},"pt-BR": {"stringUnit": {"state": "translated","value": "; principal grupo filho: %@ %@"}},"ru": {"stringUnit": {"state": "translated","value": "; крупнейшая дочерняя группа: %@ %@"}},"th": {"stringUnit": {"state": "translated","value": "; กลุ่มลูกสูงสุด: %@ %@"}},"tr": {"stringUnit": {"state": "translated","value": "; en büyük alt grup: %@ %@"}},"uk": {"stringUnit": {"state": "translated","value": "; найбільша дочірня група: %@ %@"}},"zh-Hans": {"stringUnit": {"state": "translated","value": ";主要子进程组:%@ %@"}},"zh-Hant": {"stringUnit": {"state": "translated","value": ";主要子行程群組:%@ %@"}}}}, - "memoryDiagnostic.summary.workspace": {"extractionState": "manual","localizations": {"ar": {"stringUnit": {"state": "translated","value": " من مساحة العمل %@"}},"bs": {"stringUnit": {"state": "translated","value": " iz radnog prostora %@"}},"da": {"stringUnit": {"state": "translated","value": " fra workspace %@"}},"de": {"stringUnit": {"state": "translated","value": " aus Workspace %@"}},"en": {"stringUnit": {"state": "translated","value": " from workspace %@"}},"es": {"stringUnit": {"state": "translated","value": " desde el espacio de trabajo %@"}},"fr": {"stringUnit": {"state": "translated","value": " depuis l’espace de travail %@"}},"it": {"stringUnit": {"state": "translated","value": " dall’area di lavoro %@"}},"ja": {"stringUnit": {"state": "translated","value": "(ワークスペース %@)"}},"ko": {"stringUnit": {"state": "translated","value": " 워크스페이스 %@에서"}},"nb": {"stringUnit": {"state": "translated","value": " fra arbeidsområde %@"}},"pl": {"stringUnit": {"state": "translated","value": " z obszaru roboczego %@"}},"pt-BR": {"stringUnit": {"state": "translated","value": " do workspace %@"}},"ru": {"stringUnit": {"state": "translated","value": " из рабочей области %@"}},"th": {"stringUnit": {"state": "translated","value": " จากเวิร์กสเปซ %@"}},"tr": {"stringUnit": {"state": "translated","value": " çalışma alanı %@ kaynağından"}},"uk": {"stringUnit": {"state": "translated","value": " з робочої області %@"}},"zh-Hans": {"stringUnit": {"state": "translated","value": " 来自工作区 %@"}},"zh-Hant": {"stringUnit": {"state": "translated","value": " 來自工作區 %@"}}}}, "taskManager.summary.cpu": { "extractionState": "manual", "localizations": { @@ -114781,9 +114167,13 @@ "ja": { "stringUnit": { "state": "translated", "value": "CPU" } } } }, - "taskManager.summary.memory": {"extractionState": "manual","localizations": {"ar": {"stringUnit": {"state": "translated","value": "الذاكرة"}},"bs": {"stringUnit": {"state": "translated","value": "Memorija"}},"da": {"stringUnit": {"state": "translated","value": "Hukommelse"}},"de": {"stringUnit": {"state": "translated","value": "Speicher"}},"en": {"stringUnit": {"state": "translated","value": "Memory"}},"es": {"stringUnit": {"state": "translated","value": "Memoria"}},"fr": {"stringUnit": {"state": "translated","value": "Mémoire"}},"it": {"stringUnit": {"state": "translated","value": "Memoria"}},"ja": {"stringUnit": {"state": "translated","value": "メモリ"}},"ko": {"stringUnit": {"state": "translated","value": "메모리"}},"nb": {"stringUnit": {"state": "translated","value": "Minne"}},"pl": {"stringUnit": {"state": "translated","value": "Pamięć"}},"pt-BR": {"stringUnit": {"state": "translated","value": "Memória"}},"ru": {"stringUnit": {"state": "translated","value": "Память"}},"th": {"stringUnit": {"state": "translated","value": "หน่วยความจำ"}},"tr": {"stringUnit": {"state": "translated","value": "Bellek"}},"uk": {"stringUnit": {"state": "translated","value": "Пам’ять"}},"zh-Hans": {"stringUnit": {"state": "translated","value": "内存"}},"zh-Hant": {"stringUnit": {"state": "translated","value": "記憶體"}}}}, - "taskManager.summary.appFootprint": {"extractionState": "manual","localizations": {"ar": {"stringUnit": {"state": "translated","value": "بصمة التطبيق"}},"bs": {"stringUnit": {"state": "translated","value": "Otisak aplikacije"}},"da": {"stringUnit": {"state": "translated","value": "App-fodaftryk"}},"de": {"stringUnit": {"state": "translated","value": "App-Footprint"}},"en": {"stringUnit": {"state": "translated","value": "App Footprint"}},"es": {"stringUnit": {"state": "translated","value": "Huella de la app"}},"fr": {"stringUnit": {"state": "translated","value": "Empreinte de l’app"}},"it": {"stringUnit": {"state": "translated","value": "Impronta app"}},"ja": {"stringUnit": {"state": "translated","value": "アプリフットプリント"}},"ko": {"stringUnit": {"state": "translated","value": "앱 footprint"}},"nb": {"stringUnit": {"state": "translated","value": "Appavtrykk"}},"pl": {"stringUnit": {"state": "translated","value": "Ślad aplikacji"}},"pt-BR": {"stringUnit": {"state": "translated","value": "Pegada do app"}},"ru": {"stringUnit": {"state": "translated","value": "Отпечаток приложения"}},"th": {"stringUnit": {"state": "translated","value": "Footprint แอป"}},"tr": {"stringUnit": {"state": "translated","value": "Uygulama footprint"}},"uk": {"stringUnit": {"state": "translated","value": "Відбиток застосунку"}},"zh-Hans": {"stringUnit": {"state": "translated","value": "应用 footprint"}},"zh-Hant": {"stringUnit": {"state": "translated","value": "應用程式 footprint"}}}}, - "taskManager.summary.childRSS": {"extractionState": "manual","localizations": {"ar": {"stringUnit": {"state": "translated","value": "RSS فرعي"}},"bs": {"stringUnit": {"state": "translated","value": "RSS podprocesa"}},"da": {"stringUnit": {"state": "translated","value": "Underproces-RSS"}},"de": {"stringUnit": {"state": "translated","value": "Kindprozess-RSS"}},"en": {"stringUnit": {"state": "translated","value": "Child RSS"}},"es": {"stringUnit": {"state": "translated","value": "RSS secundario"}},"fr": {"stringUnit": {"state": "translated","value": "RSS enfant"}},"it": {"stringUnit": {"state": "translated","value": "RSS figli"}},"ja": {"stringUnit": {"state": "translated","value": "子プロセスRSS"}},"ko": {"stringUnit": {"state": "translated","value": "하위 RSS"}},"nb": {"stringUnit": {"state": "translated","value": "Underprosess-RSS"}},"pl": {"stringUnit": {"state": "translated","value": "RSS potomnych"}},"pt-BR": {"stringUnit": {"state": "translated","value": "RSS filho"}},"ru": {"stringUnit": {"state": "translated","value": "Дочерний RSS"}},"th": {"stringUnit": {"state": "translated","value": "RSS ลูก"}},"tr": {"stringUnit": {"state": "translated","value": "Alt RSS"}},"uk": {"stringUnit": {"state": "translated","value": "Дочірній RSS"}},"zh-Hans": {"stringUnit": {"state": "translated","value": "子进程 RSS"}},"zh-Hant": {"stringUnit": {"state": "translated","value": "子行程 RSS"}}}}, + "taskManager.summary.memory": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", "value": "Memory" } }, + "ja": { "stringUnit": { "state": "translated", "value": "メモリ" } } + } + }, "taskManager.summary.processes": { "extractionState": "manual", "localizations": { @@ -114812,7 +114202,13 @@ "ja": { "stringUnit": { "state": "translated", "value": "CPU" } } } }, - "taskManager.column.memory": {"extractionState": "manual","localizations": {"ar": {"stringUnit": {"state": "translated","value": "الذاكرة"}},"bs": {"stringUnit": {"state": "translated","value": "Memorija"}},"da": {"stringUnit": {"state": "translated","value": "Hukommelse"}},"de": {"stringUnit": {"state": "translated","value": "Speicher"}},"en": {"stringUnit": {"state": "translated","value": "Memory"}},"es": {"stringUnit": {"state": "translated","value": "Memoria"}},"fr": {"stringUnit": {"state": "translated","value": "Mémoire"}},"it": {"stringUnit": {"state": "translated","value": "Memoria"}},"ja": {"stringUnit": {"state": "translated","value": "メモリ"}},"ko": {"stringUnit": {"state": "translated","value": "메모리"}},"nb": {"stringUnit": {"state": "translated","value": "Minne"}},"pl": {"stringUnit": {"state": "translated","value": "Pamięć"}},"pt-BR": {"stringUnit": {"state": "translated","value": "Memória"}},"ru": {"stringUnit": {"state": "translated","value": "Память"}},"th": {"stringUnit": {"state": "translated","value": "หน่วยความจำ"}},"tr": {"stringUnit": {"state": "translated","value": "Bellek"}},"uk": {"stringUnit": {"state": "translated","value": "Пам’ять"}},"zh-Hans": {"stringUnit": {"state": "translated","value": "内存"}},"zh-Hant": {"stringUnit": {"state": "translated","value": "記憶體"}}}}, + "taskManager.column.memory": { + "extractionState": "manual", + "localizations": { + "en": { "stringUnit": { "state": "translated", "value": "Memory" } }, + "ja": { "stringUnit": { "state": "translated", "value": "メモリ" } } + } + }, "taskManager.column.processes": { "extractionState": "manual", "localizations": { @@ -114834,7 +114230,6 @@ "ja": { "stringUnit": { "state": "translated", "value": "プログラム合計" } } } }, - "taskManager.section.childProcessRSS": {"extractionState": "manual","localizations": {"ar": {"stringUnit": {"state": "translated","value": "RSS العمليات الفرعية"}},"bs": {"stringUnit": {"state": "translated","value": "RSS podprocesa"}},"da": {"stringUnit": {"state": "translated","value": "Underproces-RSS"}},"de": {"stringUnit": {"state": "translated","value": "Kindprozess-RSS"}},"en": {"stringUnit": {"state": "translated","value": "Child Process RSS"}},"es": {"stringUnit": {"state": "translated","value": "RSS de procesos secundarios"}},"fr": {"stringUnit": {"state": "translated","value": "RSS des processus enfants"}},"it": {"stringUnit": {"state": "translated","value": "RSS dei processi figli"}},"ja": {"stringUnit": {"state": "translated","value": "子プロセスRSS"}},"ko": {"stringUnit": {"state": "translated","value": "하위 프로세스 RSS"}},"nb": {"stringUnit": {"state": "translated","value": "Underprosess-RSS"}},"pl": {"stringUnit": {"state": "translated","value": "RSS procesów potomnych"}},"pt-BR": {"stringUnit": {"state": "translated","value": "RSS de processos filhos"}},"ru": {"stringUnit": {"state": "translated","value": "RSS дочерних процессов"}},"th": {"stringUnit": {"state": "translated","value": "RSS ของโปรเซสลูก"}},"tr": {"stringUnit": {"state": "translated","value": "Alt süreç RSS"}},"uk": {"stringUnit": {"state": "translated","value": "RSS дочірніх процесів"}},"zh-Hans": {"stringUnit": {"state": "translated","value": "子进程 RSS"}},"zh-Hant": {"stringUnit": {"state": "translated","value": "子行程 RSS"}}}}, "taskManager.section.hierarchy": { "extractionState": "manual", "localizations": { @@ -114842,10 +114237,6 @@ "ja": { "stringUnit": { "state": "translated", "value": "階層" } } } }, - "taskManager.memory.unattributed": {"extractionState": "manual","localizations": {"ar": {"stringUnit": {"state": "translated","value": "غير مسند"}},"bs": {"stringUnit": {"state": "translated","value": "Nepripisano"}},"da": {"stringUnit": {"state": "translated","value": "Ikke tilskrevet"}},"de": {"stringUnit": {"state": "translated","value": "Nicht zugeordnet"}},"en": {"stringUnit": {"state": "translated","value": "Unattributed"}},"es": {"stringUnit": {"state": "translated","value": "Sin atribuir"}},"fr": {"stringUnit": {"state": "translated","value": "Non attribué"}},"it": {"stringUnit": {"state": "translated","value": "Non attribuito"}},"ja": {"stringUnit": {"state": "translated","value": "未割り当て"}},"ko": {"stringUnit": {"state": "translated","value": "미귀속"}},"nb": {"stringUnit": {"state": "translated","value": "Ikke tilordnet"}},"pl": {"stringUnit": {"state": "translated","value": "Nieprzypisane"}},"pt-BR": {"stringUnit": {"state": "translated","value": "Sem atribuição"}},"ru": {"stringUnit": {"state": "translated","value": "Без атрибуции"}},"th": {"stringUnit": {"state": "translated","value": "ไม่ระบุที่มา"}},"tr": {"stringUnit": {"state": "translated","value": "Atıfsız"}},"uk": {"stringUnit": {"state": "translated","value": "Без атрибуції"}},"zh-Hans": {"stringUnit": {"state": "translated","value": "未归因"}},"zh-Hant": {"stringUnit": {"state": "translated","value": "未歸因"}}}}, - "taskManager.memory.workspace": {"extractionState": "manual","localizations": {"ar": {"stringUnit": {"state": "translated","value": "مساحة العمل %@"}},"bs": {"stringUnit": {"state": "translated","value": "Radni prostor %@"}},"da": {"stringUnit": {"state": "translated","value": "Arbejdsområde %@"}},"de": {"stringUnit": {"state": "translated","value": "Arbeitsbereich %@"}},"en": {"stringUnit": {"state": "translated","value": "Workspace %@"}},"es": {"stringUnit": {"state": "translated","value": "Espacio de trabajo %@"}},"fr": {"stringUnit": {"state": "translated","value": "Espace de travail %@"}},"it": {"stringUnit": {"state": "translated","value": "Area di lavoro %@"}},"ja": {"stringUnit": {"state": "translated","value": "ワークスペース %@"}},"ko": {"stringUnit": {"state": "translated","value": "워크스페이스 %@"}},"nb": {"stringUnit": {"state": "translated","value": "Arbeidsområde %@"}},"pl": {"stringUnit": {"state": "translated","value": "Obszar roboczy %@"}},"pt-BR": {"stringUnit": {"state": "translated","value": "Espaço de trabalho %@"}},"ru": {"stringUnit": {"state": "translated","value": "Рабочая область %@"}},"th": {"stringUnit": {"state": "translated","value": "เวิร์กสเปซ %@"}},"tr": {"stringUnit": {"state": "translated","value": "Çalışma alanı %@"}},"uk": {"stringUnit": {"state": "translated","value": "Робоча область %@"}},"zh-Hans": {"stringUnit": {"state": "translated","value": "工作区 %@"}},"zh-Hant": {"stringUnit": {"state": "translated","value": "工作區 %@"}}}}, - "taskManager.memory.pane": {"extractionState": "manual","localizations": {"ar": {"stringUnit": {"state": "translated","value": "جزء %@"}},"bs": {"stringUnit": {"state": "translated","value": "Panel %@"}},"da": {"stringUnit": {"state": "translated","value": "Rude %@"}},"de": {"stringUnit": {"state": "translated","value": "Bereich %@"}},"en": {"stringUnit": {"state": "translated","value": "Pane %@"}},"es": {"stringUnit": {"state": "translated","value": "Panel %@"}},"fr": {"stringUnit": {"state": "translated","value": "Panneau %@"}},"it": {"stringUnit": {"state": "translated","value": "Pannello %@"}},"ja": {"stringUnit": {"state": "translated","value": "ペイン %@"}},"ko": {"stringUnit": {"state": "translated","value": "패널 %@"}},"nb": {"stringUnit": {"state": "translated","value": "Rute %@"}},"pl": {"stringUnit": {"state": "translated","value": "Panel %@"}},"pt-BR": {"stringUnit": {"state": "translated","value": "Painel %@"}},"ru": {"stringUnit": {"state": "translated","value": "Панель %@"}},"th": {"stringUnit": {"state": "translated","value": "พาเนล %@"}},"tr": {"stringUnit": {"state": "translated","value": "Panel %@"}},"uk": {"stringUnit": {"state": "translated","value": "Панель %@"}},"zh-Hans": {"stringUnit": {"state": "translated","value": "面板 %@"}},"zh-Hant": {"stringUnit": {"state": "translated","value": "面板 %@"}}}}, - "taskManager.memory.surface": {"extractionState": "manual","localizations": {"ar": {"stringUnit": {"state": "translated","value": "سطح %@"}},"bs": {"stringUnit": {"state": "translated","value": "Površina %@"}},"da": {"stringUnit": {"state": "translated","value": "Flade %@"}},"de": {"stringUnit": {"state": "translated","value": "Oberfläche %@"}},"en": {"stringUnit": {"state": "translated","value": "Surface %@"}},"es": {"stringUnit": {"state": "translated","value": "Superficie %@"}},"fr": {"stringUnit": {"state": "translated","value": "Zone %@"}},"it": {"stringUnit": {"state": "translated","value": "Superficie %@"}},"ja": {"stringUnit": {"state": "translated","value": "サーフェス %@"}},"ko": {"stringUnit": {"state": "translated","value": "서피스 %@"}},"nb": {"stringUnit": {"state": "translated","value": "Flate %@"}},"pl": {"stringUnit": {"state": "translated","value": "Powierzchnia %@"}},"pt-BR": {"stringUnit": {"state": "translated","value": "Superfície %@"}},"ru": {"stringUnit": {"state": "translated","value": "Поверхность %@"}},"th": {"stringUnit": {"state": "translated","value": "พื้นผิว %@"}},"tr": {"stringUnit": {"state": "translated","value": "Yüzey %@"}},"uk": {"stringUnit": {"state": "translated","value": "Поверхня %@"}},"zh-Hans": {"stringUnit": {"state": "translated","value": "界面 %@"}},"zh-Hant": {"stringUnit": {"state": "translated","value": "介面 %@"}}}}, "taskManager.aggregate.processCount.one": { "extractionState": "manual", "localizations": { diff --git a/Resources/bin/claude b/Resources/bin/claude index 7bfa0550450d..44431169f0ec 100755 --- a/Resources/bin/claude +++ b/Resources/bin/claude @@ -466,9 +466,7 @@ fi # This is Claude Code's native blocking decision hook. It covers # permissions, ExitPlanMode, and AskUserQuestion without using # PreToolUse denial as a side channel. -# - SubagentStop: feed telemetry only. It must not run the visible Stop -# hook because a subagent finishing should not notify like the parent. -HOOKS_JSON='{"preferredNotifChannel":"notifications_disabled","hooks":{"SessionStart":[{"matcher":"","hooks":[{"type":"command","command":"\"${CMUX_CLAUDE_HOOK_CMUX_BIN:-cmux}\" hooks claude session-start","timeout":10}]}],"Stop":[{"matcher":"","hooks":[{"type":"command","command":"\"${CMUX_CLAUDE_HOOK_CMUX_BIN:-cmux}\" hooks claude stop","timeout":10}]},{"matcher":"","hooks":[{"type":"command","command":"\"${CMUX_CLAUDE_HOOK_CMUX_BIN:-cmux}\" hooks feed --source claude","timeout":10,"async":true}]}],"SubagentStop":[{"matcher":"","hooks":[{"type":"command","command":"\"${CMUX_CLAUDE_HOOK_CMUX_BIN:-cmux}\" hooks feed --source claude","timeout":10,"async":true}]}],"SessionEnd":[{"matcher":"","hooks":[{"type":"command","command":"\"${CMUX_CLAUDE_HOOK_CMUX_BIN:-cmux}\" hooks claude session-end","timeout":1}]}],"Notification":[{"matcher":"","hooks":[{"type":"command","command":"\"${CMUX_CLAUDE_HOOK_CMUX_BIN:-cmux}\" hooks claude notification","timeout":10}]}],"UserPromptSubmit":[{"matcher":"","hooks":[{"type":"command","command":"\"${CMUX_CLAUDE_HOOK_CMUX_BIN:-cmux}\" hooks claude prompt-submit","timeout":10}]}],"PreToolUse":[{"matcher":"CronCreate","hooks":[{"type":"command","command":"\"${CMUX_CLAUDE_HOOK_CMUX_BIN:-cmux}\" hooks claude cron-create-guard","timeout":5}]},{"matcher":"","hooks":[{"type":"command","command":"\"${CMUX_CLAUDE_HOOK_CMUX_BIN:-cmux}\" hooks claude pre-tool-use","timeout":5,"async":true}]}],"PermissionRequest":[{"matcher":"","hooks":[{"type":"command","command":"\"${CMUX_CLAUDE_HOOK_CMUX_BIN:-cmux}\" hooks feed --source claude","timeout":125}]}]}}' +HOOKS_JSON='{"preferredNotifChannel":"notifications_disabled","hooks":{"SessionStart":[{"matcher":"","hooks":[{"type":"command","command":"\"${CMUX_CLAUDE_HOOK_CMUX_BIN:-cmux}\" hooks claude session-start","timeout":10}]}],"Stop":[{"matcher":"","hooks":[{"type":"command","command":"\"${CMUX_CLAUDE_HOOK_CMUX_BIN:-cmux}\" hooks claude stop","timeout":10}]},{"matcher":"","hooks":[{"type":"command","command":"\"${CMUX_CLAUDE_HOOK_CMUX_BIN:-cmux}\" hooks feed --source claude","timeout":10,"async":true}]}],"SessionEnd":[{"matcher":"","hooks":[{"type":"command","command":"\"${CMUX_CLAUDE_HOOK_CMUX_BIN:-cmux}\" hooks claude session-end","timeout":1}]}],"Notification":[{"matcher":"","hooks":[{"type":"command","command":"\"${CMUX_CLAUDE_HOOK_CMUX_BIN:-cmux}\" hooks claude notification","timeout":10}]}],"UserPromptSubmit":[{"matcher":"","hooks":[{"type":"command","command":"\"${CMUX_CLAUDE_HOOK_CMUX_BIN:-cmux}\" hooks claude prompt-submit","timeout":10}]}],"PreToolUse":[{"matcher":"CronCreate","hooks":[{"type":"command","command":"\"${CMUX_CLAUDE_HOOK_CMUX_BIN:-cmux}\" hooks claude cron-create-guard","timeout":5}]},{"matcher":"","hooks":[{"type":"command","command":"\"${CMUX_CLAUDE_HOOK_CMUX_BIN:-cmux}\" hooks claude pre-tool-use","timeout":5,"async":true}]}],"PermissionRequest":[{"matcher":"","hooks":[{"type":"command","command":"\"${CMUX_CLAUDE_HOOK_CMUX_BIN:-cmux}\" hooks feed --source claude","timeout":125}]}]}}' if [[ "$SKIP_SESSION_ID" == true ]]; then exec "$REAL_CLAUDE" --settings "$HOOKS_JSON" "$@" diff --git a/Resources/bin/grok b/Resources/bin/grok deleted file mode 100755 index 9856cd8e57e5..000000000000 --- a/Resources/bin/grok +++ /dev/null @@ -1,169 +0,0 @@ -#!/usr/bin/env bash -# cmux grok wrapper - installs cmux hooks and captures launch metadata. - -find_real_grok() { - local self_dir - self_dir="$(cd "$(dirname "$0")" && pwd)" - local names=(grok grok-macos-aarch64 grok-macos-aarch) - local IFS=: - for d in $PATH; do - [[ "$d" == "$self_dir" ]] && continue - local name candidate - for name in "${names[@]}"; do - candidate="$d/$name" - [[ -x "$candidate" ]] || continue - if [[ "$candidate" -ef "$0" ]]; then - continue - fi - printf '%s' "$candidate" - return 0 - done - done - return 1 -} - -resolve_cmux_bin() { - local bundled_cli self_dir - bundled_cli="${CMUX_BUNDLED_CLI_PATH:-}" - if [[ -n "$bundled_cli" && -x "$bundled_cli" ]]; then - printf '%s' "$bundled_cli" - return 0 - fi - - self_dir="$(cd "$(dirname "$0")" && pwd)" - bundled_cli="$self_dir/cmux" - if [[ -x "$bundled_cli" ]]; then - printf '%s' "$bundled_cli" - return 0 - fi - - bundled_cli="$(command -v cmux || true)" - if [[ -n "$bundled_cli" ]]; then - printf '%s' "$bundled_cli" - return 0 - fi - - return 1 -} - -cmux_socket_available() { - local socket="${CMUX_SOCKET_PATH:-}" - [[ -n "$socket" && -S "$socket" ]] || return 1 - - local cmux_bin - cmux_bin="$(resolve_cmux_bin)" || return 1 - CMUXTERM_CLI_RESPONSE_TIMEOUT_SEC=0.75 \ - "$cmux_bin" --socket "$socket" ping >/dev/null 2>&1 -} - -encode_launch_argv() { - { - printf '%s\0' "$REAL_GROK" - if (( $# > 0 )); then - printf '%s\0' "$@" - fi - } | base64 | tr -d '\n' -} - -grok_option_consumes_value() { - case "$1" in - --cwd|--model|-m|--permission-mode|--prompt-file|--prompt-json|\ - --sandbox|--settings|--config|--profile|--resume|-r) - return 0 - ;; - esac - return 1 -} - -grok_passthrough_option_flag() { - case "$1" in - --help|-h|--version|-v|--single|--single=*|-p|--prompt-file|\ - --prompt-file=*|--prompt-json|--prompt-json=*|--output-format|\ - --output-format=*|--best-of-n|--best-of-n=*) - return 0 - ;; - esac - return 1 -} - -grok_builtin_command_name() { - case "$1" in - auth|completion|completions|config|help|login|logout|models|sessions|\ - setup|update|upgrade|version) - return 0 - ;; - esac - return 1 -} - -grok_command_like_invocation() { - local candidate="$1" - [[ -n "$candidate" ]] || return 1 - case "$candidate" in - *[![:alnum:]_-]*) - return 1 - ;; - esac - grok_builtin_command_name "$candidate" -} - -should_install_grok_hooks() { - (( $# == 0 )) && return 0 - - local arg - local skip_next=false - for arg in "$@"; do - if [[ "$skip_next" == true ]]; then - skip_next=false - continue - fi - case "$arg" in - --) - return 0 - ;; - --resume=*|-r=*) - return 0 - ;; - -*) - if grok_passthrough_option_flag "$arg"; then - return 1 - fi - if [[ "$arg" != *=* ]] && grok_option_consumes_value "$arg"; then - skip_next=true - fi - continue - ;; - *) - if grok_command_like_invocation "$arg"; then - return 1 - fi - return 0 - ;; - esac - done - - return 0 -} - -REAL_GROK="$(find_real_grok)" || { echo "Error: grok not found in PATH" >&2; exit 127; } - -IN_CMUX=0 -if [[ -n "${CMUX_SURFACE_ID:-}" ]]; then - IN_CMUX=1 -fi - -if [[ "$IN_CMUX" == "1" && "${CMUX_GROK_HOOKS_DISABLED:-}" != "1" ]] \ - && cmux_socket_available \ - && should_install_grok_hooks "$@"; then - CMUX_BIN="$(resolve_cmux_bin || true)" - if [[ -n "$CMUX_BIN" ]]; then - CMUXTERM_CLI_RESPONSE_TIMEOUT_SEC=2 \ - "$CMUX_BIN" --socket "$CMUX_SOCKET_PATH" hooks grok install --yes >/dev/null 2>&1 || true - fi - export CMUX_AGENT_LAUNCH_KIND="grok" - export CMUX_AGENT_LAUNCH_EXECUTABLE="$REAL_GROK" - export CMUX_AGENT_LAUNCH_ARGV_B64="$(encode_launch_argv "$@")" - export CMUX_AGENT_LAUNCH_CWD="$PWD" -fi - -exec "$REAL_GROK" "$@" diff --git a/Resources/shell-integration/cmux-bash-integration.bash b/Resources/shell-integration/cmux-bash-integration.bash index 75b116dca138..6d5c0f65c542 100644 --- a/Resources/shell-integration/cmux-bash-integration.bash +++ b/Resources/shell-integration/cmux-bash-integration.bash @@ -145,34 +145,30 @@ _cmux_restore_scrollback_once() { } _cmux_restore_scrollback_once _CMUX_CLAUDE_WRAPPER="${_CMUX_CLAUDE_WRAPPER:-}" -_CMUX_GROK_WRAPPER="${_CMUX_GROK_WRAPPER:-}" -_cmux_install_cli_wrapper() { - local command_name="$1" - local wrapper_variable="$2" +_cmux_install_claude_wrapper() { local integration_dir="${CMUX_SHELL_INTEGRATION_DIR:-}" local existing_type="" [[ -n "$integration_dir" ]] || return 0 integration_dir="${integration_dir%/}" local bundle_dir="${integration_dir%/shell-integration}" - local wrapper_path="$bundle_dir/bin/$command_name" + local wrapper_path="$bundle_dir/bin/claude" [[ -x "$wrapper_path" ]] || return 0 - existing_type="$(type -t "$command_name" 2>/dev/null || true)" + existing_type="$(type -t claude 2>/dev/null || true)" case "$existing_type" in alias|function) return 0 ;; esac - # Keep the bundled wrapper ahead of later PATH mutations. Install it - # via eval so an existing alias cannot break parsing. - printf -v "$wrapper_variable" '%s' "$wrapper_path" - unalias "$command_name" >/dev/null 2>&1 || true - eval "$command_name() { \"\${$wrapper_variable}\" \"\$@\"; }" + # Keep the bundled claude wrapper ahead of later PATH mutations. Install it + # via eval so an existing `alias claude=...` cannot break parsing. + _CMUX_CLAUDE_WRAPPER="$wrapper_path" + unalias claude >/dev/null 2>&1 || true + eval 'claude() { "$_CMUX_CLAUDE_WRAPPER" "$@"; }' } -_cmux_install_cli_wrapper claude _CMUX_CLAUDE_WRAPPER -_cmux_install_cli_wrapper grok _CMUX_GROK_WRAPPER +_cmux_install_claude_wrapper _cmux_now() { printf '%s\n' "${EPOCHSECONDS:-$SECONDS}" } @@ -327,7 +323,7 @@ _cmux_tmux_sync_cmux_environment() { _cmux_git_resolve_head_path() { # Resolve the HEAD file path without invoking git (fast; works for worktrees). - local dir="${1:-$PWD}" + local dir="$PWD" while :; do if [[ -d "$dir/.git" ]]; then printf '%s\n' "$dir/.git/HEAD" @@ -352,14 +348,6 @@ _cmux_git_resolve_head_path() { return 1 } -_cmux_git_resolve_git_dir() { - local repo_path="${1:-$PWD}" - local head_path - head_path="$(_cmux_git_resolve_head_path "$repo_path" 2>/dev/null || true)" - [[ -n "$head_path" ]] || return 1 - dirname "$head_path" -} - _cmux_git_head_signature() { local head_path="$1" [[ -n "$head_path" && -r "$head_path" ]] || return 1 @@ -368,16 +356,6 @@ _cmux_git_head_signature() { printf '%s\n' "$line" } -_cmux_git_branch_for_path() { - local repo_path="$1" - local head_path="" head_line="" prefix="ref: refs/heads/" - head_path="$(_cmux_git_resolve_head_path "$repo_path" 2>/dev/null || true)" - [[ -n "$head_path" && -r "$head_path" ]] || return 1 - IFS= read -r head_line < "$head_path" || return 1 - [[ "$head_line" == "$prefix"* ]] || return 1 - printf '%s\n' "${head_line#$prefix}" -} - _cmux_report_tty_payload() { [[ -n "$CMUX_TAB_ID" ]] || return 0 [[ -n "$_CMUX_TTY_NAME" ]] || return 0 @@ -454,7 +432,6 @@ _cmux_ports_kick() { } _cmux_clear_pr_for_panel() { - [[ "${CMUX_NO_GIT_WATCH:-}" == "1" ]] && return 0 [[ -S "$CMUX_SOCKET_PATH" ]] || return 0 [[ -n "$CMUX_TAB_ID" ]] || return 0 [[ -n "$CMUX_PANEL_ID" ]] || return 0 @@ -560,238 +537,12 @@ _cmux_pr_output_indicates_no_pull_request() { || "$output" == *"no pull request associated"* ]] } -_cmux_git_config_resolve_include_path() { - local path="$1" config_dir="$2" - case "$path" in - "~") - printf '%s\n' "$HOME" ;; - "~/"*) - printf '%s/%s\n' "$HOME" "${path#~/}" ;; - /*) - printf '%s\n' "$path" ;; - *) - printf '%s/%s\n' "$config_dir" "$path" ;; - esac -} - -_cmux_git_config_gitdir_pattern_matches() { - local pattern="$1" repo_path="$2" git_dir="$3" common_dir="$4" case_insensitive="$5" - local expanded="$pattern" candidate cmp_candidate cmp_pattern prefix - - case "$expanded" in - "~") - expanded="$HOME" ;; - "~/"*) - expanded="$HOME/${expanded#~/}" ;; - esac - if [[ "$expanded" == */ ]]; then - prefix="$expanded" - [[ "$case_insensitive" == "1" ]] && prefix="$(printf '%s' "$prefix" | tr '[:upper:]' '[:lower:]')" - for candidate in "$git_dir" "$common_dir" "$repo_path"; do - cmp_candidate="$candidate" - [[ "$case_insensitive" == "1" ]] && cmp_candidate="$(printf '%s' "$cmp_candidate" | tr '[:upper:]' '[:lower:]')" - [[ "$cmp_candidate" == "${prefix%/}" || "$cmp_candidate/" == "$prefix"* ]] && return 0 - done - return 1 - fi - if [[ "$expanded" == */'**' ]]; then - prefix="${expanded%/\*\*}/" - [[ "$case_insensitive" == "1" ]] && prefix="$(printf '%s' "$prefix" | tr '[:upper:]' '[:lower:]')" - for candidate in "$git_dir" "$common_dir" "$repo_path"; do - cmp_candidate="$candidate" - [[ "$case_insensitive" == "1" ]] && cmp_candidate="$(printf '%s' "$cmp_candidate" | tr '[:upper:]' '[:lower:]')" - [[ "$cmp_candidate" == "${prefix%/}" || "$cmp_candidate/" == "$prefix"* ]] && return 0 - done - return 1 - fi - - cmp_pattern="$expanded" - [[ "$case_insensitive" == "1" ]] && cmp_pattern="$(printf '%s' "$cmp_pattern" | tr '[:upper:]' '[:lower:]')" - for candidate in "$git_dir" "$common_dir" "$repo_path"; do - cmp_candidate="$candidate" - [[ "$case_insensitive" == "1" ]] && cmp_candidate="$(printf '%s' "$cmp_candidate" | tr '[:upper:]' '[:lower:]')" - [[ "$cmp_candidate" == $cmp_pattern || "$cmp_candidate/" == $cmp_pattern ]] && return 0 - done - return 1 -} - -_cmux_git_config_include_condition_matches() { - local condition="$1" repo_path="$2" git_dir="$3" common_dir="$4" - local lower pattern - lower="$(printf '%s' "$condition" | tr '[:upper:]' '[:lower:]')" - case "$lower" in - gitdir/i:*) - pattern="${condition#gitdir/i:}" - _cmux_git_config_gitdir_pattern_matches "$pattern" "$repo_path" "$git_dir" "$common_dir" 1 ;; - gitdir:*) - pattern="${condition#gitdir:}" - _cmux_git_config_gitdir_pattern_matches "$pattern" "$repo_path" "$git_dir" "$common_dir" 0 ;; - *) - return 1 ;; - esac -} - -_cmux_git_origin_url_read_config_file() { - local repo_path="$1" git_dir="$2" common_dir="$3" config_file="$4" - local config_dir="" output="" - local kind="" entry_payload="" entry_value="" include_path="" - - [[ -r "$config_file" ]] || return 0 - case "$_cmux_git_origin_url_seen" in - *$'\n'"$config_file"$'\n'*) return 0 ;; - esac - _cmux_git_origin_url_depth=$(( _cmux_git_origin_url_depth + 1 )) - [[ "$_cmux_git_origin_url_depth" -le 32 ]] || return 0 - _cmux_git_origin_url_seen+="$config_file"$'\n' - - config_dir="$(dirname "$config_file")" - output="$(awk ' - function trim(s) { - sub(/^[[:space:]]+/, "", s) - sub(/[[:space:]]+$/, "", s) - return s - } - function strip_inline_comment(s, i, c, out, previous_was_space, in_quote, escaped) { - out = "" - previous_was_space = 1 - in_quote = 0 - escaped = 0 - for (i = 1; i <= length(s); i++) { - c = substr(s, i, 1) - if (escaped) { - out = out c - escaped = 0 - previous_was_space = (c ~ /[[:space:]]/) - continue - } - if (in_quote && c == "\\") { - out = out c - escaped = 1 - previous_was_space = 0 - continue - } - if (c == "\"") { - out = out c - in_quote = !in_quote - previous_was_space = 0 - continue - } - if (!in_quote && previous_was_space && (c == "#" || c == ";")) { - break - } - out = out c - previous_was_space = (c ~ /[[:space:]]/) - } - return out - } - function unquote_config_value(s, i, c, out, escaped) { - s = trim(s) - if (length(s) >= 2 && substr(s, 1, 1) == "\"" && substr(s, length(s), 1) == "\"") { - out = "" - escaped = 0 - for (i = 2; i < length(s); i++) { - c = substr(s, i, 1) - if (escaped) { - out = out c - escaped = 0 - continue - } - if (c == "\\") { - escaped = 1 - continue - } - out = out c - } - if (escaped) { - out = out "\\" - } - return out - } - return s - } - function path_value(line) { - sub(/^[^=]*=/, "", line) - return unquote_config_value(line) - } - { - line = strip_inline_comment($0) - trimmed = trim(line) - if (trimmed ~ /^\[remote[[:space:]]+"origin"\][[:space:]]*$/) { - section = "remote" - condition = "" - next - } - if (trimmed == "[include]") { - section = "include" - condition = "" - next - } - if (trimmed ~ /^\[includeIf[[:space:]]+"/) { - section = "includeIf" - condition = trimmed - sub(/^\[includeIf[[:space:]]+"/, "", condition) - sub(/"\][[:space:]]*$/, "", condition) - next - } - if (trimmed ~ /^\[/) { - section = "" - condition = "" - next - } - if (section == "remote" && line ~ /^[[:space:]]*url[[:space:]]*=/) { - print "remote\t" path_value(line) "\t" - } - if (section == "include" && line ~ /^[[:space:]]*path[[:space:]]*=/) { - print "include\t" path_value(line) "\t" - } - if (section == "includeIf" && line ~ /^[[:space:]]*path[[:space:]]*=/) { - print "includeIf\t" condition "\t" path_value(line) - } - } - ' "$config_file" 2>/dev/null)" - - while IFS=$'\t' read -r kind entry_payload entry_value; do - case "$kind" in - remote) - [[ -n "$entry_payload" ]] && _cmux_git_origin_url_result="$entry_payload" ;; - include) - include_path="$(_cmux_git_config_resolve_include_path "$entry_payload" "$config_dir")" - [[ -r "$include_path" ]] && _cmux_git_origin_url_read_config_file "$repo_path" "$git_dir" "$common_dir" "$include_path" ;; - includeIf) - if _cmux_git_config_include_condition_matches "$entry_payload" "$repo_path" "$git_dir" "$common_dir"; then - include_path="$(_cmux_git_config_resolve_include_path "$entry_value" "$config_dir")" - [[ -r "$include_path" ]] && _cmux_git_origin_url_read_config_file "$repo_path" "$git_dir" "$common_dir" "$include_path" - fi ;; - esac - done <<< "$output" -} - -_cmux_git_origin_url_from_config_files() { - local repo_path="$1" git_dir="$2" common_dir="$3" - local _cmux_git_origin_url_seen=$'\n' - local _cmux_git_origin_url_depth=0 - local _cmux_git_origin_url_result="" - - [[ -r "$common_dir/config" ]] && _cmux_git_origin_url_read_config_file "$repo_path" "$git_dir" "$common_dir" "$common_dir/config" - [[ "$git_dir" != "$common_dir" && -r "$git_dir/config" ]] && _cmux_git_origin_url_read_config_file "$repo_path" "$git_dir" "$common_dir" "$git_dir/config" - [[ -n "$_cmux_git_origin_url_result" ]] && printf '%s\n' "$_cmux_git_origin_url_result" -} - _cmux_github_repo_slug_for_path() { local repo_path="$1" - local git_dir="" common_dir="" remote_url="" path_part="" + local remote_url="" path_part="" [[ -n "$repo_path" ]] || return 0 - git_dir="$(_cmux_git_resolve_git_dir "$repo_path" 2>/dev/null || true)" - [[ -n "$git_dir" ]] || return 0 - common_dir="$git_dir" - if [[ -r "$git_dir/commondir" ]]; then - IFS= read -r common_dir < "$git_dir/commondir" || common_dir="" - common_dir="${common_dir## }" - common_dir="${common_dir%% }" - [[ "$common_dir" != /* ]] && common_dir="$git_dir/$common_dir" - fi - remote_url="$(_cmux_git_origin_url_from_config_files "$repo_path" "$git_dir" "$common_dir")" + remote_url="$(git -C "$repo_path" remote get-url origin 2>/dev/null)" [[ -n "$remote_url" ]] || return 0 case "$remote_url" in @@ -886,7 +637,7 @@ _cmux_report_pr_for_path() { local cache_branch="" cache_result="" cache_no_pr_branch="" local -a gh_repo_args=() now="$(_cmux_now)" - branch="$(_cmux_git_branch_for_path "$repo_path" 2>/dev/null || true)" + branch="$(git -C "$repo_path" branch --show-current 2>/dev/null)" if [[ -z "$branch" ]] || ! command -v gh >/dev/null 2>&1; then _cmux_pr_debug_log "$branch" "cache-miss:clear" _cmux_pr_cache_clear @@ -1070,7 +821,6 @@ _cmux_stop_pr_poll_loop() { } _cmux_start_pr_poll_loop() { - [[ "${CMUX_NO_GIT_WATCH:-}" == "1" ]] && return 0 [[ -S "$CMUX_SOCKET_PATH" ]] || return 0 [[ -n "$CMUX_TAB_ID" ]] || return 0 [[ -n "$CMUX_PANEL_ID" ]] || return 0 @@ -1271,41 +1021,25 @@ _cmux_prompt_command() { # Branch can change via aliases/tools while an older probe is still in flight. # Track .git/HEAD content so we can restart stale probes immediately. local git_head_changed=0 - if [[ "${CMUX_NO_GIT_WATCH:-}" == "1" ]]; then - _cmux_stop_pr_poll_loop - if [[ -n "$_CMUX_GIT_JOB_PID" ]] && kill -0 "$_CMUX_GIT_JOB_PID" 2>/dev/null; then - kill "$_CMUX_GIT_JOB_PID" >/dev/null 2>&1 || true - fi - _CMUX_GIT_JOB_PID="" - _CMUX_GIT_JOB_STARTED_AT=0 - _CMUX_GIT_HEAD_LAST_PWD="" - _CMUX_GIT_HEAD_PATH="" + if [[ "$pwd" != "$_CMUX_GIT_HEAD_LAST_PWD" ]]; then + _CMUX_GIT_HEAD_LAST_PWD="$pwd" + _CMUX_GIT_HEAD_PATH="$(_cmux_git_resolve_head_path 2>/dev/null || true)" _CMUX_GIT_HEAD_SIGNATURE="" - _CMUX_GIT_LAST_PWD="" - _CMUX_PR_FORCE=0 - _CMUX_LAST_PR_ACTION="" - _CMUX_LAST_PR_TARGET="" - else - if [[ "$pwd" != "$_CMUX_GIT_HEAD_LAST_PWD" ]]; then - _CMUX_GIT_HEAD_LAST_PWD="$pwd" - _CMUX_GIT_HEAD_PATH="$(_cmux_git_resolve_head_path "$pwd" 2>/dev/null || true)" - _CMUX_GIT_HEAD_SIGNATURE="" - fi - if [[ -n "$_CMUX_GIT_HEAD_PATH" ]]; then - local head_signature - head_signature="$(_cmux_git_head_signature "$_CMUX_GIT_HEAD_PATH" 2>/dev/null || true)" - if [[ -n "$head_signature" ]]; then - if [[ -z "$_CMUX_GIT_HEAD_SIGNATURE" ]]; then - # The first observed HEAD value is just the session baseline. - # Treating it as a branch change clears restore-seeded PR badges - # before the first background probe can confirm the current PR. - _CMUX_GIT_HEAD_SIGNATURE="$head_signature" - elif [[ "$head_signature" != "$_CMUX_GIT_HEAD_SIGNATURE" ]]; then - _CMUX_GIT_HEAD_SIGNATURE="$head_signature" - git_head_changed=1 - # Also invalidate the PR poller so it refreshes with the new branch. - _CMUX_PR_FORCE=1 - fi + fi + if [[ -n "$_CMUX_GIT_HEAD_PATH" ]]; then + local head_signature + head_signature="$(_cmux_git_head_signature "$_CMUX_GIT_HEAD_PATH" 2>/dev/null || true)" + if [[ -n "$head_signature" ]]; then + if [[ -z "$_CMUX_GIT_HEAD_SIGNATURE" ]]; then + # The first observed HEAD value is just the session baseline. + # Treating it as a branch change clears restore-seeded PR badges + # before the first background probe can confirm the current PR. + _CMUX_GIT_HEAD_SIGNATURE="$head_signature" + elif [[ "$head_signature" != "$_CMUX_GIT_HEAD_SIGNATURE" ]]; then + _CMUX_GIT_HEAD_SIGNATURE="$head_signature" + git_head_changed=1 + # Also invalidate the PR poller so it refreshes with the new branch. + _CMUX_PR_FORCE=1 fi fi fi @@ -1314,7 +1048,7 @@ _cmux_prompt_command() { # so update on every prompt (still async + de-duped by the running-job check). # When pwd changes (cd into a different repo), kill the old probe and start fresh # so the sidebar picks up the new branch immediately. - if [[ "${CMUX_NO_GIT_WATCH:-}" != "1" && -n "$_CMUX_GIT_JOB_PID" ]] && kill -0 "$_CMUX_GIT_JOB_PID" 2>/dev/null; then + if [[ -n "$_CMUX_GIT_JOB_PID" ]] && kill -0 "$_CMUX_GIT_JOB_PID" 2>/dev/null; then if [[ "$pwd" != "$_CMUX_GIT_LAST_PWD" || "$git_head_changed" == "1" ]]; then kill "$_CMUX_GIT_JOB_PID" >/dev/null 2>&1 || true _CMUX_GIT_JOB_PID="" @@ -1322,13 +1056,18 @@ _cmux_prompt_command() { fi fi - if [[ "${CMUX_NO_GIT_WATCH:-}" != "1" ]] && { [[ -z "$_CMUX_GIT_JOB_PID" ]] || ! kill -0 "$_CMUX_GIT_JOB_PID" 2>/dev/null; }; then + if [[ -z "$_CMUX_GIT_JOB_PID" ]] || ! kill -0 "$_CMUX_GIT_JOB_PID" 2>/dev/null; then _CMUX_GIT_LAST_PWD="$pwd" _CMUX_GIT_LAST_RUN=$now { - local branch dirty_opt="--status=unknown" - branch="$(_cmux_git_branch_for_path "$pwd" 2>/dev/null || true)" + # Skip git operations if not in a git repository to avoid TCC prompts + git rev-parse --git-dir >/dev/null 2>&1 || return 0 + local branch dirty_opt="" + branch=$(git branch --show-current 2>/dev/null) if [[ -n "$branch" ]]; then + local first + first=$(git status --porcelain -uno 2>/dev/null | head -1) + [[ -n "$first" ]] && dirty_opt="--status=dirty" _cmux_send "report_git_branch $branch $dirty_opt --tab=$CMUX_TAB_ID --panel=$CMUX_PANEL_ID" else _cmux_send "clear_git_branch --tab=$CMUX_TAB_ID --panel=$CMUX_PANEL_ID" @@ -1343,7 +1082,7 @@ _cmux_prompt_command() { _cmux_pr_cache_clear _cmux_clear_pr_for_panel fi - if [[ "${CMUX_NO_GIT_WATCH:-}" != "1" ]] && (( last_status == 0 )); then + if (( last_status == 0 )); then _cmux_emit_pr_command_hint else _CMUX_LAST_PR_ACTION="" diff --git a/Resources/shell-integration/cmux-zsh-integration.zsh b/Resources/shell-integration/cmux-zsh-integration.zsh index 6cd9dd4ac0ee..d7c0f7e59958 100644 --- a/Resources/shell-integration/cmux-zsh-integration.zsh +++ b/Resources/shell-integration/cmux-zsh-integration.zsh @@ -157,26 +157,22 @@ _cmux_now() { } typeset -g _CMUX_CLAUDE_WRAPPER="" -typeset -g _CMUX_GROK_WRAPPER="" -_cmux_install_cli_wrapper() { - local command_name="$1" - local wrapper_variable="$2" +_cmux_install_claude_wrapper() { local integration_dir="${CMUX_SHELL_INTEGRATION_DIR:-}" [[ -n "$integration_dir" ]] || return 0 integration_dir="${integration_dir%/}" local bundle_dir="${integration_dir%/shell-integration}" - local wrapper_path="$bundle_dir/bin/$command_name" + local wrapper_path="$bundle_dir/bin/claude" [[ -x "$wrapper_path" ]] || return 0 - # Keep the bundled wrapper ahead of later PATH mutations. Install it - # via eval so an existing alias cannot break parsing. - typeset -g "$wrapper_variable=$wrapper_path" - builtin unalias "$command_name" >/dev/null 2>&1 || true - eval "$command_name() { \"\${$wrapper_variable}\" \"\$@\"; }" + # Keep the bundled claude wrapper ahead of later PATH mutations. Install it + # via eval so an existing `alias claude=...` cannot break parsing. + _CMUX_CLAUDE_WRAPPER="$wrapper_path" + builtin unalias claude >/dev/null 2>&1 || true + eval 'claude() { "$_CMUX_CLAUDE_WRAPPER" "$@"; }' } -_cmux_install_cli_wrapper claude _CMUX_CLAUDE_WRAPPER -_cmux_install_cli_wrapper grok _CMUX_GROK_WRAPPER +_cmux_install_claude_wrapper _cmux_normalize_claude_config_dir() { [[ -n "${CLAUDE_CONFIG_DIR:-}" && -n "${HOME:-}" ]] || return 0 @@ -451,7 +447,7 @@ _cmux_install_winch_guard _cmux_git_resolve_head_path() { # Resolve the HEAD file path without invoking git (fast; works for worktrees). - local dir="${1:-$PWD}" + local dir="$PWD" while true; do if [[ -d "$dir/.git" ]]; then print -r -- "$dir/.git/HEAD" @@ -476,14 +472,6 @@ _cmux_git_resolve_head_path() { return 1 } -_cmux_git_resolve_git_dir() { - local repo_path="${1:-$PWD}" - local head_path - head_path="$(_cmux_git_resolve_head_path "$repo_path" 2>/dev/null || true)" - [[ -n "$head_path" ]] || return 1 - print -r -- "${head_path:h}" -} - _cmux_git_head_signature() { local head_path="$1" [[ -n "$head_path" && -r "$head_path" ]] || return 1 @@ -495,16 +483,6 @@ _cmux_git_head_signature() { return 1 } -_cmux_git_branch_for_path() { - local repo_path="$1" - local head_path="" head_line="" prefix="ref: refs/heads/" - head_path="$(_cmux_git_resolve_head_path "$repo_path" 2>/dev/null || true)" - [[ -n "$head_path" && -r "$head_path" ]] || return 1 - head_line="$(<"$head_path")" - [[ "$head_line" == "$prefix"* ]] || return 1 - print -r -- "${head_line#$prefix}" -} - _cmux_report_tty_payload() { [[ -n "$CMUX_TAB_ID" ]] || return 0 [[ -n "$_CMUX_TTY_NAME" ]] || return 0 @@ -576,15 +554,19 @@ _cmux_ports_kick() { _cmux_report_git_branch_for_path() { local repo_path="$1" - [[ "${CMUX_NO_GIT_WATCH:-}" == "1" ]] && return 0 [[ -n "$repo_path" ]] || return 0 [[ -S "$CMUX_SOCKET_PATH" ]] || return 0 [[ -n "$CMUX_TAB_ID" ]] || return 0 [[ -n "$CMUX_PANEL_ID" ]] || return 0 - local branch dirty_opt="--status=unknown" - branch="$(_cmux_git_branch_for_path "$repo_path" 2>/dev/null || true)" + # Skip git operations if not in a git repository to avoid TCC prompts + git -C "$repo_path" rev-parse --git-dir >/dev/null 2>&1 || return 0 + + local branch dirty_opt="" first + branch="$(git -C "$repo_path" branch --show-current 2>/dev/null)" if [[ -n "$branch" ]]; then + first="$(git -C "$repo_path" status --porcelain -uno 2>/dev/null | head -1)" + [[ -n "$first" ]] && dirty_opt="--status=dirty" _cmux_send "report_git_branch $branch $dirty_opt --tab=$CMUX_TAB_ID --panel=$CMUX_PANEL_ID" else _cmux_send "clear_git_branch --tab=$CMUX_TAB_ID --panel=$CMUX_PANEL_ID" @@ -678,7 +660,6 @@ _cmux_emit_pr_command_hint() { } _cmux_clear_pr_for_panel() { - [[ "${CMUX_NO_GIT_WATCH:-}" == "1" ]] && return 0 [[ -S "$CMUX_SOCKET_PATH" ]] || return 0 [[ -n "$CMUX_TAB_ID" ]] || return 0 [[ -n "$CMUX_PANEL_ID" ]] || return 0 @@ -693,238 +674,12 @@ _cmux_pr_output_indicates_no_pull_request() { || "$output" == *"no pull request associated"* ]] } -_cmux_git_config_resolve_include_path() { - local path="$1" config_dir="$2" - case "$path" in - "~") - printf '%s\n' "$HOME" ;; - "~/"*) - printf '%s/%s\n' "$HOME" "${path#~/}" ;; - /*) - printf '%s\n' "$path" ;; - *) - printf '%s/%s\n' "$config_dir" "$path" ;; - esac -} - -_cmux_git_config_gitdir_pattern_matches() { - local pattern="$1" repo_path="$2" git_dir="$3" common_dir="$4" case_insensitive="$5" - local expanded="$pattern" candidate cmp_candidate cmp_pattern prefix - - case "$expanded" in - "~") - expanded="$HOME" ;; - "~/"*) - expanded="$HOME/${expanded#~/}" ;; - esac - if [[ "$expanded" == */ ]]; then - prefix="$expanded" - [[ "$case_insensitive" == "1" ]] && prefix="$(printf '%s' "$prefix" | tr '[:upper:]' '[:lower:]')" - for candidate in "$git_dir" "$common_dir" "$repo_path"; do - cmp_candidate="$candidate" - [[ "$case_insensitive" == "1" ]] && cmp_candidate="$(printf '%s' "$cmp_candidate" | tr '[:upper:]' '[:lower:]')" - [[ "$cmp_candidate" == "${prefix%/}" || "$cmp_candidate/" == "$prefix"* ]] && return 0 - done - return 1 - fi - if [[ "$expanded" == */'**' ]]; then - prefix="${expanded%/\*\*}/" - [[ "$case_insensitive" == "1" ]] && prefix="$(printf '%s' "$prefix" | tr '[:upper:]' '[:lower:]')" - for candidate in "$git_dir" "$common_dir" "$repo_path"; do - cmp_candidate="$candidate" - [[ "$case_insensitive" == "1" ]] && cmp_candidate="$(printf '%s' "$cmp_candidate" | tr '[:upper:]' '[:lower:]')" - [[ "$cmp_candidate" == "${prefix%/}" || "$cmp_candidate/" == "$prefix"* ]] && return 0 - done - return 1 - fi - - cmp_pattern="$expanded" - [[ "$case_insensitive" == "1" ]] && cmp_pattern="$(printf '%s' "$cmp_pattern" | tr '[:upper:]' '[:lower:]')" - for candidate in "$git_dir" "$common_dir" "$repo_path"; do - cmp_candidate="$candidate" - [[ "$case_insensitive" == "1" ]] && cmp_candidate="$(printf '%s' "$cmp_candidate" | tr '[:upper:]' '[:lower:]')" - [[ "$cmp_candidate" == $cmp_pattern || "$cmp_candidate/" == $cmp_pattern ]] && return 0 - done - return 1 -} - -_cmux_git_config_include_condition_matches() { - local condition="$1" repo_path="$2" git_dir="$3" common_dir="$4" - local lower pattern - lower="$(printf '%s' "$condition" | tr '[:upper:]' '[:lower:]')" - case "$lower" in - gitdir/i:*) - pattern="${condition#gitdir/i:}" - _cmux_git_config_gitdir_pattern_matches "$pattern" "$repo_path" "$git_dir" "$common_dir" 1 ;; - gitdir:*) - pattern="${condition#gitdir:}" - _cmux_git_config_gitdir_pattern_matches "$pattern" "$repo_path" "$git_dir" "$common_dir" 0 ;; - *) - return 1 ;; - esac -} - -_cmux_git_origin_url_read_config_file() { - local repo_path="$1" git_dir="$2" common_dir="$3" config_file="$4" - local config_dir="" output="" - local kind="" entry_payload="" entry_value="" include_path="" - - [[ -r "$config_file" ]] || return 0 - case "$_cmux_git_origin_url_seen" in - *$'\n'"$config_file"$'\n'*) return 0 ;; - esac - _cmux_git_origin_url_depth=$(( _cmux_git_origin_url_depth + 1 )) - [[ "$_cmux_git_origin_url_depth" -le 32 ]] || return 0 - _cmux_git_origin_url_seen+="$config_file"$'\n' - - config_dir="$(dirname "$config_file")" - output="$(awk ' - function trim(s) { - sub(/^[[:space:]]+/, "", s) - sub(/[[:space:]]+$/, "", s) - return s - } - function strip_inline_comment(s, i, c, out, previous_was_space, in_quote, escaped) { - out = "" - previous_was_space = 1 - in_quote = 0 - escaped = 0 - for (i = 1; i <= length(s); i++) { - c = substr(s, i, 1) - if (escaped) { - out = out c - escaped = 0 - previous_was_space = (c ~ /[[:space:]]/) - continue - } - if (in_quote && c == "\\") { - out = out c - escaped = 1 - previous_was_space = 0 - continue - } - if (c == "\"") { - out = out c - in_quote = !in_quote - previous_was_space = 0 - continue - } - if (!in_quote && previous_was_space && (c == "#" || c == ";")) { - break - } - out = out c - previous_was_space = (c ~ /[[:space:]]/) - } - return out - } - function unquote_config_value(s, i, c, out, escaped) { - s = trim(s) - if (length(s) >= 2 && substr(s, 1, 1) == "\"" && substr(s, length(s), 1) == "\"") { - out = "" - escaped = 0 - for (i = 2; i < length(s); i++) { - c = substr(s, i, 1) - if (escaped) { - out = out c - escaped = 0 - continue - } - if (c == "\\") { - escaped = 1 - continue - } - out = out c - } - if (escaped) { - out = out "\\" - } - return out - } - return s - } - function path_value(line) { - sub(/^[^=]*=/, "", line) - return unquote_config_value(line) - } - { - line = strip_inline_comment($0) - trimmed = trim(line) - if (trimmed ~ /^\[remote[[:space:]]+"origin"\][[:space:]]*$/) { - section = "remote" - condition = "" - next - } - if (trimmed == "[include]") { - section = "include" - condition = "" - next - } - if (trimmed ~ /^\[includeIf[[:space:]]+"/) { - section = "includeIf" - condition = trimmed - sub(/^\[includeIf[[:space:]]+"/, "", condition) - sub(/"\][[:space:]]*$/, "", condition) - next - } - if (trimmed ~ /^\[/) { - section = "" - condition = "" - next - } - if (section == "remote" && line ~ /^[[:space:]]*url[[:space:]]*=/) { - print "remote\t" path_value(line) "\t" - } - if (section == "include" && line ~ /^[[:space:]]*path[[:space:]]*=/) { - print "include\t" path_value(line) "\t" - } - if (section == "includeIf" && line ~ /^[[:space:]]*path[[:space:]]*=/) { - print "includeIf\t" condition "\t" path_value(line) - } - } - ' "$config_file" 2>/dev/null)" - - while IFS=$'\t' read -r kind entry_payload entry_value; do - case "$kind" in - remote) - [[ -n "$entry_payload" ]] && _cmux_git_origin_url_result="$entry_payload" ;; - include) - include_path="$(_cmux_git_config_resolve_include_path "$entry_payload" "$config_dir")" - [[ -r "$include_path" ]] && _cmux_git_origin_url_read_config_file "$repo_path" "$git_dir" "$common_dir" "$include_path" ;; - includeIf) - if _cmux_git_config_include_condition_matches "$entry_payload" "$repo_path" "$git_dir" "$common_dir"; then - include_path="$(_cmux_git_config_resolve_include_path "$entry_value" "$config_dir")" - [[ -r "$include_path" ]] && _cmux_git_origin_url_read_config_file "$repo_path" "$git_dir" "$common_dir" "$include_path" - fi ;; - esac - done <<< "$output" -} - -_cmux_git_origin_url_from_config_files() { - local repo_path="$1" git_dir="$2" common_dir="$3" - local _cmux_git_origin_url_seen=$'\n' - local _cmux_git_origin_url_depth=0 - local _cmux_git_origin_url_result="" - - [[ -r "$common_dir/config" ]] && _cmux_git_origin_url_read_config_file "$repo_path" "$git_dir" "$common_dir" "$common_dir/config" - [[ "$git_dir" != "$common_dir" && -r "$git_dir/config" ]] && _cmux_git_origin_url_read_config_file "$repo_path" "$git_dir" "$common_dir" "$git_dir/config" - [[ -n "$_cmux_git_origin_url_result" ]] && printf '%s\n' "$_cmux_git_origin_url_result" -} - _cmux_github_repo_slug_for_path() { local repo_path="$1" - local git_dir="" common_dir="" remote_url="" path_part="" + local remote_url="" path_part="" [[ -n "$repo_path" ]] || return 0 - git_dir="$(_cmux_git_resolve_git_dir "$repo_path" 2>/dev/null || true)" - [[ -n "$git_dir" ]] || return 0 - common_dir="$git_dir" - if [[ -r "$git_dir/commondir" ]]; then - common_dir="$(<"$git_dir/commondir")" - common_dir="${common_dir## }" - common_dir="${common_dir%% }" - [[ "$common_dir" != /* ]] && common_dir="$git_dir/$common_dir" - fi - remote_url="$(_cmux_git_origin_url_from_config_files "$repo_path" "$git_dir" "$common_dir")" + remote_url="$(git -C "$repo_path" remote get-url origin 2>/dev/null)" [[ -n "$remote_url" ]] || return 0 case "$remote_url" in @@ -1019,7 +774,7 @@ _cmux_report_pr_for_path() { local cache_branch="" cache_result="" cache_no_pr_branch="" local -a gh_repo_args gh_repo_args=() - branch="$(_cmux_git_branch_for_path "$repo_path" 2>/dev/null || true)" + branch="$(git -C "$repo_path" branch --show-current 2>/dev/null)" if [[ -z "$branch" ]] || ! command -v gh >/dev/null 2>&1; then _cmux_pr_debug_log "$branch" "cache-miss:clear" _cmux_pr_cache_clear @@ -1202,7 +957,6 @@ _cmux_stop_pr_poll_loop() { } _cmux_start_pr_poll_loop() { - [[ "${CMUX_NO_GIT_WATCH:-}" == "1" ]] && return 0 [[ -S "$CMUX_SOCKET_PATH" ]] || return 0 [[ -n "$CMUX_TAB_ID" ]] || return 0 [[ -n "$CMUX_PANEL_ID" ]] || return 0 @@ -1258,14 +1012,13 @@ _cmux_stop_git_head_watch() { } _cmux_start_git_head_watch() { - [[ "${CMUX_NO_GIT_WATCH:-}" == "1" ]] && return 0 [[ -S "$CMUX_SOCKET_PATH" ]] || return 0 [[ -n "$CMUX_TAB_ID" ]] || return 0 [[ -n "$CMUX_PANEL_ID" ]] || return 0 local watch_pwd="$PWD" local watch_head_path - watch_head_path="$(_cmux_git_resolve_head_path "$watch_pwd" 2>/dev/null || true)" + watch_head_path="$(_cmux_git_resolve_head_path 2>/dev/null || true)" [[ -n "$watch_head_path" ]] || return 0 local watch_head_signature @@ -1460,46 +1213,28 @@ _cmux_precmd() { # Git branch can change without a `git ...`-prefixed command (aliases like `gco`, # tools like `gh pr checkout`, etc.). Detect HEAD changes and force a refresh. - if [[ "${CMUX_NO_GIT_WATCH:-}" == "1" ]]; then - _cmux_stop_pr_poll_loop - _cmux_stop_git_head_watch - if [[ -n "$_CMUX_GIT_JOB_PID" ]] && kill -0 "$_CMUX_GIT_JOB_PID" 2>/dev/null; then - kill "$_CMUX_GIT_JOB_PID" >/dev/null 2>&1 || true - fi - _CMUX_GIT_JOB_PID="" - _CMUX_GIT_JOB_STARTED_AT=0 - _CMUX_GIT_FORCE=0 - _CMUX_GIT_HEAD_LAST_PWD="" - _CMUX_GIT_HEAD_PATH="" + if [[ "$pwd" != "$_CMUX_GIT_HEAD_LAST_PWD" ]]; then + _CMUX_GIT_HEAD_LAST_PWD="$pwd" + _CMUX_GIT_HEAD_PATH="$(_cmux_git_resolve_head_path 2>/dev/null || true)" _CMUX_GIT_HEAD_SIGNATURE="" - _CMUX_GIT_LAST_PWD="" - _CMUX_PR_FORCE=0 - _CMUX_LAST_PR_ACTION="" - _CMUX_LAST_PR_TARGET="" - else - if [[ "$pwd" != "$_CMUX_GIT_HEAD_LAST_PWD" ]]; then - _CMUX_GIT_HEAD_LAST_PWD="$pwd" - _CMUX_GIT_HEAD_PATH="$(_cmux_git_resolve_head_path "$pwd" 2>/dev/null || true)" - _CMUX_GIT_HEAD_SIGNATURE="" - fi - if [[ -n "$_CMUX_GIT_HEAD_PATH" ]]; then - local head_signature - head_signature="$(_cmux_git_head_signature "$_CMUX_GIT_HEAD_PATH" 2>/dev/null || true)" - if [[ -n "$head_signature" ]]; then - if [[ -z "$_CMUX_GIT_HEAD_SIGNATURE" ]]; then - # The first observed HEAD value establishes the baseline for this - # shell session. Don't treat it as a branch change or we'll clear - # restore-seeded PR badges before the first background probe runs. - _CMUX_GIT_HEAD_SIGNATURE="$head_signature" - elif [[ "$head_signature" != "$_CMUX_GIT_HEAD_SIGNATURE" ]]; then - _CMUX_GIT_HEAD_SIGNATURE="$head_signature" - git_head_changed=1 - # Treat HEAD file change like a git command — force-replace any - # running probe so the sidebar picks up the new branch immediately. - _CMUX_GIT_FORCE=1 - _CMUX_PR_FORCE=1 - should_git=1 - fi + fi + if [[ -n "$_CMUX_GIT_HEAD_PATH" ]]; then + local head_signature + head_signature="$(_cmux_git_head_signature "$_CMUX_GIT_HEAD_PATH" 2>/dev/null || true)" + if [[ -n "$head_signature" ]]; then + if [[ -z "$_CMUX_GIT_HEAD_SIGNATURE" ]]; then + # The first observed HEAD value establishes the baseline for this + # shell session. Don't treat it as a branch change or we'll clear + # restore-seeded PR badges before the first background probe runs. + _CMUX_GIT_HEAD_SIGNATURE="$head_signature" + elif [[ "$head_signature" != "$_CMUX_GIT_HEAD_SIGNATURE" ]]; then + _CMUX_GIT_HEAD_SIGNATURE="$head_signature" + git_head_changed=1 + # Treat HEAD file change like a git command — force-replace any + # running probe so the sidebar picks up the new branch immediately. + _CMUX_GIT_FORCE=1 + _CMUX_PR_FORCE=1 + should_git=1 fi fi fi @@ -1512,7 +1247,7 @@ _cmux_precmd() { should_git=1 fi - if [[ "${CMUX_NO_GIT_WATCH:-}" != "1" ]] && (( should_git )); then + if (( should_git )); then local can_launch_git=1 if [[ -n "$_CMUX_GIT_JOB_PID" ]] && kill -0 "$_CMUX_GIT_JOB_PID" 2>/dev/null; then # If a stale probe is still running but the cwd changed (or we just ran @@ -1545,7 +1280,7 @@ _cmux_precmd() { _cmux_pr_cache_clear _cmux_clear_pr_for_panel fi - if [[ "${CMUX_NO_GIT_WATCH:-}" != "1" ]] && (( last_status == 0 )); then + if (( last_status == 0 )); then _cmux_emit_pr_command_hint else _CMUX_LAST_PR_ACTION="" diff --git a/Sources/AgentForkSupport.swift b/Sources/AgentForkSupport.swift index 2fe957a121b6..f94ee5236d87 100644 --- a/Sources/AgentForkSupport.swift +++ b/Sources/AgentForkSupport.swift @@ -2,38 +2,6 @@ import Foundation import CMUXAgentLaunch import Darwin -/// Coordinates cancellation with `Process.run()`: Foundation raises an -/// Objective-C exception if termination APIs touch a task before launch. -/// `@unchecked Sendable` is safe here because all mutable state is protected by `lock`. -final class ProcessTerminationGate: @unchecked Sendable { - private let lock = NSLock() - private var didLaunch = false - private var didFinish = false - private var terminationRequested = false - - func requestTermination() -> Bool { - lock.lock() - defer { lock.unlock() } - guard !didFinish else { return false } - terminationRequested = true - return didLaunch - } - - func markLaunched() -> Bool { - lock.lock() - defer { lock.unlock() } - guard !didFinish else { return false } - didLaunch = true - return terminationRequested - } - - func markFinished() { - lock.lock() - defer { lock.unlock() } - didFinish = true - } -} - private actor OpenCodeVersionProbeCache { private var valuesByKey: [String: Bool] = [:] @@ -82,7 +50,6 @@ enum AgentForkSupport { private var timeoutTimer: DispatchSourceTimer? private var killTimer: DispatchSourceTimer? private var continuation: CheckedContinuation? - private let terminationGate = ProcessTerminationGate() private var completed = false private var timedOut = false @@ -123,13 +90,13 @@ enum AgentForkSupport { if completed || timedOut { completed = true lock.unlock() - terminationGate.markFinished() pipe.fileHandleForReading.readabilityHandler = nil process.terminationHandler = nil continuation.resume(returning: nil) return } self.continuation = continuation + self.process = process self.pipe = pipe lock.unlock() @@ -138,26 +105,16 @@ enum AgentForkSupport { do { try process.run() } catch { - terminationGate.markFinished() markFailedBeforeLaunch() return } lock.lock() - if completed { - lock.unlock() - terminationGate.markFinished() - process.terminationHandler = nil - return - } - self.process = process + let shouldTerminateAfterStart = timedOut && !completed lock.unlock() - - if terminationGate.markLaunched() { - if process.isRunning { - process.terminate() - startKillTimer(processIdentifier: process.processIdentifier) - } + if shouldTerminateAfterStart { + process.terminate() + startKillTimer(processIdentifier: process.processIdentifier) } } @@ -191,21 +148,16 @@ enum AgentForkSupport { } private func markTimedOutAndTerminate() { + let process: Process? lock.lock() guard !completed else { lock.unlock() return } timedOut = true - lock.unlock() - - guard terminationGate.requestTermination() else { - return - } - let process: Process? - lock.lock() process = self.process lock.unlock() + guard let process else { return } @@ -267,7 +219,6 @@ enum AgentForkSupport { timedOut = self.timedOut lock.unlock() - terminationGate.markFinished() timeoutTimer?.cancel() killTimer?.cancel() process?.terminationHandler = nil diff --git a/Sources/App/CmuxMainWindow.swift b/Sources/App/CmuxMainWindow.swift index 4b1d2ea228bc..04901bbc7eba 100644 --- a/Sources/App/CmuxMainWindow.swift +++ b/Sources/App/CmuxMainWindow.swift @@ -7,7 +7,6 @@ final class MainWindowHostingView: NSHostingView { override var safeAreaInsets: NSEdgeInsets { NSEdgeInsetsZero } override var safeAreaRect: NSRect { bounds } override var safeAreaLayoutGuide: NSLayoutGuide { zeroSafeAreaLayoutGuide } - override var mouseDownCanMoveWindow: Bool { false } required init(rootView: Content) { super.init(rootView: rootView) @@ -28,12 +27,6 @@ final class MainWindowHostingView: NSHostingView { } } -@MainActor -func configureCmuxMainWindowDragBehavior(_ window: NSWindow) { - window.isMovableByWindowBackground = false - window.isMovable = false -} - @MainActor final class CmuxMainWindow: NSWindow { private var isSoftHiddenForVisibilityController = false diff --git a/Sources/App/GhosttySurfaceConfigurationRefresh.swift b/Sources/App/GhosttySurfaceConfigurationRefresh.swift index bbe57c4e741b..3887daf302ba 100644 --- a/Sources/App/GhosttySurfaceConfigurationRefresh.swift +++ b/Sources/App/GhosttySurfaceConfigurationRefresh.swift @@ -1,50 +1,15 @@ @MainActor enum GhosttySurfaceConfigurationRefresh { nonisolated static let forceRefreshReason = "appDelegate.refreshAfterGhosttyConfigReload" - nonisolated static let cmuxThemeReloadLegacySource = "distributed.cmux.themes" - nonisolated static let cmuxThemeReloadPreviewSource = "distributed.cmux.themes.preview" - nonisolated static let cmuxThemeReloadFinalSource = "distributed.cmux.themes.final" - nonisolated static let cmuxThemePreviewReloadDebounceMilliseconds = 180 - - nonisolated static func cmuxThemeReloadSource(phase: String?) -> String { - switch phase { - case "final", "apply": - return cmuxThemeReloadFinalSource - case "preview": - return cmuxThemeReloadPreviewSource - default: - return cmuxThemeReloadLegacySource - } - } - - nonisolated static func shouldDebounceCmuxThemeReload(source: String) -> Bool { - switch source { - case cmuxThemeReloadLegacySource, cmuxThemeReloadPreviewSource: - return true - default: - return false - } - } - - nonisolated static func isCmuxThemeReloadSource(_ source: String) -> Bool { - switch source { - case cmuxThemeReloadLegacySource, cmuxThemeReloadPreviewSource, cmuxThemeReloadFinalSource: - return true - default: - return false - } - } static func applyAfterAppConfigReload( to surface: ghostty_surface_t?, source: String, reloadSurfaceConfiguration: (ghostty_surface_t, Bool, String) -> Void, - applySurfaceColorScheme: () -> Void, refreshHostBackground: () -> Void, forceRefresh: (String) -> Void ) { if let surface { - applySurfaceColorScheme() reloadSurfaceConfiguration(surface, true, source) } refreshHostBackground() diff --git a/Sources/App/ShortcutRoutingSupport.swift b/Sources/App/ShortcutRoutingSupport.swift index 62969f121c14..6c833d7ed402 100644 --- a/Sources/App/ShortcutRoutingSupport.swift +++ b/Sources/App/ShortcutRoutingSupport.swift @@ -1,5 +1,4 @@ import AppKit -import Bonsplit import Foundation func browserOmnibarSelectionDeltaForControlNavigation( @@ -757,52 +756,3 @@ func shouldSuppressWindowMoveForFolderDrag(window: NSWindow, event: NSEvent) -> let hitView = contentView.hitTest(contentPoint) return shouldSuppressWindowMoveForFolderDrag(hitView: hitView) } - -enum WindowMoveSuppressionReason: String { - case folderDrag - case bonsplitPaneTabDrag -} - -func shouldSuppressWindowMoveForBonsplitPaneTabDrag(window: NSWindow, event: NSEvent) -> Bool { - guard event.type == .leftMouseDown else { - return false - } - - return BonsplitTabItemHitRegionRegistry.containsWindowPoint(event.locationInWindow, in: window) -} - -func windowMoveSuppressionReason(window: NSWindow, event: NSEvent) -> WindowMoveSuppressionReason? { - if shouldSuppressWindowMoveForFolderDrag(window: window, event: event) { - return .folderDrag - } - if shouldSuppressWindowMoveForBonsplitPaneTabDrag(window: window, event: event) { - return .bonsplitPaneTabDrag - } - return nil -} - -func beginOrContinueWindowMoveSuppressionSequenceForEvent( - window: NSWindow, - event: NSEvent, - pressedMouseButtons: Int = NSEvent.pressedMouseButtons -) -> WindowMoveSuppressionReason? { - if let activeReason = activeWindowMoveSuppressionSequenceReason(window: window) { - if event.type == .leftMouseDown { - _ = finishWindowMoveSuppressionSequence(window: window) - } else if event.type == .leftMouseUp || event.type == .leftMouseDragged || (pressedMouseButtons & 0x1) != 0 { - ensureWindowMoveSuppressionSequenceIsImmovable(window: window) - return activeReason - } else { - _ = finishWindowMoveSuppressionSequence(window: window) - } - } - - guard let reason = windowMoveSuppressionReason(window: window, event: event) else { - return nil - } - return beginWindowMoveSuppressionSequence(window: window, reason: reason) -} - -func shouldFinishWindowMoveSuppressionSequenceAfterDispatch(window: NSWindow, event: NSEvent) -> Bool { - activeWindowMoveSuppressionSequenceReason(window: window) != nil && event.type == .leftMouseUp -} diff --git a/Sources/App/WorkspaceRuntimeSettings.swift b/Sources/App/WorkspaceRuntimeSettings.swift index 848c1635b5ec..cbc10bb6f8d3 100644 --- a/Sources/App/WorkspaceRuntimeSettings.swift +++ b/Sources/App/WorkspaceRuntimeSettings.swift @@ -109,6 +109,43 @@ enum TerminalScrollBarSettings { } } +enum TerminalTimestampsSettings { + static let showTimestampsKey = "terminal.showTimestamps" + static let defaultShowTimestamps = false + static let didChangeNotification = Notification.Name("cmux.terminalTimestampsSettingsDidChange") + + static func isVisible(defaults: UserDefaults = .standard) -> Bool { + if defaults.object(forKey: showTimestampsKey) == nil { + return defaultShowTimestamps + } + return defaults.bool(forKey: showTimestampsKey) + } + + @discardableResult + static func setVisible( + _ visible: Bool, + defaults: UserDefaults = .standard, + notificationCenter: NotificationCenter = .default + ) -> Bool { + guard isVisible(defaults: defaults) != visible else { return visible } + defaults.set(visible, forKey: showTimestampsKey) + notifyDidChange(notificationCenter: notificationCenter) + return visible + } + + @discardableResult + static func toggle( + defaults: UserDefaults = .standard, + notificationCenter: NotificationCenter = .default + ) -> Bool { + setVisible(!isVisible(defaults: defaults), defaults: defaults, notificationCenter: notificationCenter) + } + + static func notifyDidChange(notificationCenter: NotificationCenter = .default) { + notificationCenter.post(name: didChangeNotification, object: nil) + } +} + enum AgentSessionAutoResumeSettings { static let autoResumeAgentSessionsKey = "terminal.autoResumeAgentSessions" static let defaultAutoResumeAgentSessions = true diff --git a/Sources/AppDelegate.swift b/Sources/AppDelegate.swift index 438df7b3d609..c175ba32e139 100644 --- a/Sources/AppDelegate.swift +++ b/Sources/AppDelegate.swift @@ -21,44 +21,6 @@ func cmuxJavaScriptStringLiteral(_ value: String?) -> String? { return String(arrayLiteral.dropFirst().dropLast()) } -private struct MultiWindowRouteCLIResult { - let status: String - let stdout: String - let stderr: String -} - -private func runMultiWindowRouteCLI( - cliURL: URL, - socketPath: String, - processEnv: [String: String], - arguments: [String] -) -> MultiWindowRouteCLIResult { - let process = Process() - process.executableURL = cliURL - process.arguments = ["--socket", socketPath] + arguments - process.environment = processEnv - - let stdoutPipe = Pipe() - let stderrPipe = Pipe() - process.standardOutput = stdoutPipe - process.standardError = stderrPipe - - do { - try process.run() - } catch { - return MultiWindowRouteCLIResult(status: "-1", stdout: "", stderr: String(describing: error)) - } - process.waitUntilExit() - - let stdoutData = stdoutPipe.fileHandleForReading.readDataToEndOfFile() - let stderrData = stderrPipe.fileHandleForReading.readDataToEndOfFile() - return MultiWindowRouteCLIResult( - status: String(process.terminationStatus), - stdout: String(data: stdoutData, encoding: .utf8) ?? "", - stderr: String(data: stderrData, encoding: .utf8) ?? "" - ) -} - /// Caches `AXWindows` responses so repeated AX polls can reuse the same /// snapshot while the app window graph is unchanged. Only `.windows` is /// cached; `.children` and `.visibleChildren` fall through to AppKit so the @@ -555,8 +517,6 @@ final class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCent private var isRunningUnderXCTestCached: Bool { Self.cachedIsRunningUnderXCTest } - private var cmuxThemePreviewReloadGeneration = 0 - private var cmuxThemePreviewReloadWorkItem: DispatchWorkItem? private static func detectRunningUnderXCTest(_ env: [String: String]) -> Bool { if env["XCTestConfigurationFilePath"] != nil { return true } @@ -726,6 +686,7 @@ final class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCent private var pendingConfiguredShortcutChord: PendingConfiguredShortcutChord? var activeConfiguredShortcutChordPrefixForCurrentEvent: ShortcutStroke? var shortcutEventFocusContextCache: ShortcutEventFocusContextCache? + private var configuredShortcutChordActions: [KeyboardShortcutSettings.Action] = [] private var ghosttyConfigObserver: NSObjectProtocol? private var ghosttyGotoSplitLeftShortcut: StoredShortcut? private var ghosttyGotoSplitRightShortcut: StoredShortcut? @@ -1058,7 +1019,6 @@ final class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCent ] ) AppIconLaunchState.markDidFinishLaunching() - AppearanceSettingsUserDefaultsObserver.shared.startObserving() if isRunningUnderXCTest { NSApp.setActivationPolicy(.regular) } else { @@ -5089,10 +5049,7 @@ final class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCent return nil } - func refreshTerminalSurfacesAfterGhosttyConfigReload( - source: String, - preferredColorScheme: GhosttyConfig.ColorSchemePreference - ) { + func refreshTerminalSurfacesAfterGhosttyConfigReload(source: String) { var refreshedCount = 0 forEachTerminalPanel { terminalPanel in let liveSurface = terminalPanel.surface.liveSurfaceForGhosttyAccess( @@ -5102,17 +5059,7 @@ final class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCent to: liveSurface, source: source, reloadSurfaceConfiguration: { surface, soft, source in - GhosttyApp.shared.reloadSurfaceConfiguration( - surface, - soft: soft, - source: source, - preferredColorScheme: preferredColorScheme - ) - }, - applySurfaceColorScheme: { - terminalPanel.hostedView.reapplySurfaceColorSchemeAfterGhosttyConfigReload( - preferredColorScheme: preferredColorScheme - ) + GhosttyApp.shared.reloadSurfaceConfiguration(surface, soft: soft, source: source) }, refreshHostBackground: { terminalPanel.hostedView.refreshHostBackgroundAfterGhosttyConfigReload() @@ -5633,10 +5580,6 @@ final class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCent #endif private func mainWindowForShortcutEvent(_ event: NSEvent) -> NSWindow? { - if let context = mainWindowContext(forShortcutEvent: event, debugSource: "shortcut.window"), - let window = resolvedWindow(for: context) { - return window - } if let window = resolvedShortcutEventWindow(event), isMainTerminalWindow(window) { return window @@ -5934,9 +5877,7 @@ final class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCent return .ok case .focus: - // Remote focus should preserve the currently selected sidebar mode - // instead of reviving a stale keyboard-focus memory. - guard focusRightSidebarInActiveMainWindow(mode: state.mode, preferredWindow: preferredWindow) else { + guard focusRightSidebarInActiveMainWindow(preferredWindow: preferredWindow) else { return .failure(String(localized: "rightSidebar.remote.error.focusFailed", defaultValue: "ERROR: Failed to focus right sidebar")) } return .ok @@ -5952,7 +5893,6 @@ final class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCent } else { state.setVisible(true) state.mode = mode - context?.keyboardFocusCoordinator.rememberRightSidebarMode(mode) } return .ok @@ -6284,7 +6224,8 @@ final class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCent case .rightSidebarFileSearch: result = context.keyboardFocusCoordinator.focusFileSearch() case .mainPanelFind: - result = context.tabManager.startSearch() + context.tabManager.startSearch() + result = context.tabManager.isFindVisible case .none: result = false } @@ -7385,7 +7326,13 @@ final class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCent // cmux persists and restores main windows itself. Disable AppKit window // restoration so the OS cannot resurrect stale duplicate main windows. window.isRestorable = false - configureCmuxMainWindowDragBehavior(window) + window.isMovableByWindowBackground = false + // Keep background dragging disabled so app content gestures and titlebar + // controls still receive clicks, while the OS-level movable flag lets + // macOS tiling and window-management tools such as Swish treat cmux as + // a movable/resizable window. Empty titlebar drags are routed through + // WindowDragHandleView instead of background dragging. + window.isMovable = true let explicitInitialFrame = restoredFrame ?? persistedGeometryFrame if let explicitInitialFrame { window.setFrame(explicitInitialFrame, display: false) @@ -7443,20 +7390,8 @@ final class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCent ) } if shouldTemporarilyDisallowFullScreenTiling { - let clearFullScreenTilingOptOut: () -> Void = { [weak window] in - guard let window else { return } - window.collectionBehavior.remove(.fullScreenDisallowsTiling) - if window.collectionBehavior.contains(.fullScreenDisallowsTiling) { - var behavior = window.collectionBehavior - behavior.remove(.fullScreenDisallowsTiling) - window.collectionBehavior = behavior - } - } - RunLoop.main.perform { - clearFullScreenTilingOptOut() - } - DispatchQueue.main.async { - clearFullScreenTilingOptOut() + DispatchQueue.main.async { [weak window] in + window?.collectionBehavior.remove(.fullScreenDisallowsTiling) } } if let explicitInitialFrame { @@ -10495,11 +10430,7 @@ final class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCent tabId: tabId1, surfaceId: surfaceId1 ) - self.publishMultiWindowNotificationSocketStateIfNeeded( - at: path, - window1Id: window1.windowId, - window2Id: window2.windowId - ) + self.publishMultiWindowNotificationSocketStateIfNeeded(at: path) } } } @@ -10640,110 +10571,7 @@ final class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCent attemptFocus() } - private func runMultiWindowWindowRouteCLIIfNeeded( - at path: String, - window1Id: UUID, - window2Id: UUID, - socketPath: String - ) { - let env = ProcessInfo.processInfo.environment - guard env["CMUX_UI_TEST_WINDOW_ROUTE_CLI"] == "1" else { return } - let currentStatus = loadMultiWindowNotificationTestData(at: path)["windowRouteStatus"] ?? "" - guard currentStatus.isEmpty else { return } - - let title = env["CMUX_UI_TEST_WINDOW_ROUTE_CLI_TITLE"] ?? "window-route-\(UUID().uuidString.prefix(8))" - writeMultiWindowNotificationTestData([ - "windowRouteTitle": title, - "windowRouteStatus": "pending", - "windowRouteFailure": "", - ], at: path) - - guard let cliURL = Bundle.main.resourceURL?.appendingPathComponent("bin/cmux"), - FileManager.default.isExecutableFile(atPath: cliURL.path) else { - writeMultiWindowNotificationTestData([ - "windowRouteStatus": "0", - "windowRouteFailure": "missing_cli", - ], at: path) - return - } - - let processEnv = env.merging([ - "CMUXTERM_CLI_RESPONSE_TIMEOUT_SEC": "6", - ]) { _, new in new } - - let health = TerminalController.shared.socketListenerHealth(expectedSocketPath: socketPath) - guard health.socketPathExists else { - writeMultiWindowNotificationTestData([ - "windowRouteStatus": "0", - "windowRouteFailure": "socket_not_ready", - ], at: path) - return - } - - DispatchQueue.global(qos: .userInitiated).async { [weak self] in - let create = runMultiWindowRouteCLI( - cliURL: cliURL, - socketPath: socketPath, - processEnv: processEnv, - arguments: [ - "new-workspace", - "--window", - window2Id.uuidString, - "--name", - title, - "--focus", - "false", - ] - ) - let window2List = runMultiWindowRouteCLI( - cliURL: cliURL, - socketPath: socketPath, - processEnv: processEnv, - arguments: [ - "--json", - "--id-format", - "uuids", - "list-workspaces", - "--window", - window2Id.uuidString, - ] - ) - let window1List = runMultiWindowRouteCLI( - cliURL: cliURL, - socketPath: socketPath, - processEnv: processEnv, - arguments: [ - "--json", - "--id-format", - "uuids", - "list-workspaces", - "--window", - window1Id.uuidString, - ] - ) - - DispatchQueue.main.async { - self?.writeMultiWindowNotificationTestData([ - "windowRouteStatus": "1", - "windowRouteCreateStatus": create.status, - "windowRouteCreateStdout": create.stdout, - "windowRouteCreateStderr": create.stderr, - "windowRouteWindow2Status": window2List.status, - "windowRouteWindow2Stdout": window2List.stdout, - "windowRouteWindow2Stderr": window2List.stderr, - "windowRouteWindow1Status": window1List.status, - "windowRouteWindow1Stdout": window1List.stdout, - "windowRouteWindow1Stderr": window1List.stderr, - ], at: path) - } - } - } - - private func publishMultiWindowNotificationSocketStateIfNeeded( - at path: String, - window1Id: UUID? = nil, - window2Id: UUID? = nil - ) { + private func publishMultiWindowNotificationSocketStateIfNeeded(at path: String) { let env = ProcessInfo.processInfo.environment guard env["CMUX_UI_TEST_SOCKET_SANITY"] == "1" else { return } @@ -10805,14 +10633,6 @@ final class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCent "socketPathOwnedByListener": health.socketPathOwnedByListener ? "1" : "0", "socketFailureSignals": failureSignals, ], at: dataPath) - if isReady, let window1Id, let window2Id { - self.runMultiWindowWindowRouteCLIIfNeeded( - at: dataPath, - window1Id: window1Id, - window2Id: window2Id, - socketPath: socketPath - ) - } guard isReady || isTimedOut else { return } timeoutWorkItem?.cancel() if let observer { @@ -11070,7 +10890,6 @@ final class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCent static func installWindowResponderSwizzlesForTesting() { _ = didInstallApplicationAccessibilitySwizzle _ = didInstallApplicationSendActionSwizzle - _ = didInstallApplicationSendEventSwizzle _ = didInstallWindowKeyEquivalentSwizzle _ = didInstallWindowFirstResponderSwizzle _ = didInstallWindowSendEventSwizzle @@ -11181,30 +11000,20 @@ final class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCent private func installShortcutDefaultsObserver() { guard shortcutDefaultsObserver == nil else { return } + refreshConfiguredShortcutChordActions() shortcutDefaultsObserver = NotificationCenter.default.addObserver( forName: KeyboardShortcutSettings.didChangeNotification, object: nil, - queue: nil + queue: .main ) { [weak self] _ in - if Thread.isMainThread { - MainActor.assumeIsolated { - self?.handleShortcutDefaultsDidChange() - } - } else { - Task { @MainActor [weak self] in - self?.handleShortcutDefaultsDidChange() - } - } + self?.refreshConfiguredShortcutChordActions() + self?.clearConfiguredShortcutChordState() + self?.scheduleSplitButtonTooltipRefreshAcrossWorkspaces() } } - private func handleShortcutDefaultsDidChange() { - clearConfiguredShortcutChordState() - scheduleSplitButtonTooltipRefreshAcrossWorkspaces() - } - - private func currentConfiguredShortcutChordActions() -> [KeyboardShortcutSettings.Action] { - KeyboardShortcutSettings.Action.allCases.filter { action in + private func refreshConfiguredShortcutChordActions() { + configuredShortcutChordActions = KeyboardShortcutSettings.Action.allCases.filter { action in // System-wide hotkeys are dispatched via Carbon RegisterEventHotKey // and never routed through AppKit's local key handler. If a managed // cmux.json entry somehow stores one as a chord, arming the prefix @@ -11885,23 +11694,12 @@ final class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCent return false } - if activeConfiguredShortcutChordPrefixForCurrentEvent == nil { - let focusContext = shortcutEventFocusContext(event) - let availableChordActions = currentConfiguredShortcutChordActions().filter { action in - action.shortcutContext.isAlwaysAvailable || action.shortcutContext.isAvailable(focusContext) - } - if armConfiguredShortcutChordIfNeeded(event: event, actions: availableChordActions) { - return true - } - } - let configuredCmuxShortcutContext = preferredMainWindowContextForShortcutRouting(event: event) let configuredCmuxShortcutActions = configuredCmuxShortcutActions(for: configuredCmuxShortcutContext) if activeConfiguredShortcutChordPrefixForCurrentEvent == nil, armConfiguredShortcutChordIfNeeded( event: event, - actions: [], shortcuts: configuredCmuxShortcutActions.compactMap(\.shortcut) ) { return true @@ -11950,7 +11748,7 @@ final class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCent // Primary UI shortcuts if matchConfiguredShortcut(event: event, action: .toggleSidebar) { - _ = toggleSidebarInActiveMainWindow(preferredWindow: mainWindowForShortcutEvent(event)) + _ = toggleSidebarInActiveMainWindow() return true } @@ -11990,7 +11788,7 @@ final class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCent // deferring the toggle, NSAnimationContext implicitly animates the // layout change. let preferredWindow = mainWindowForShortcutEvent(event) ?? event.window ?? NSApp.keyWindow ?? NSApp.mainWindow - DispatchQueue.main.async { [weak self, weak preferredWindow] in + Task { @MainActor [weak self, weak preferredWindow] in _ = self?.toggleRightSidebarInActiveMainWindow(preferredWindow: preferredWindow) } return true @@ -12060,8 +11858,7 @@ final class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCent // Flash the currently focused panel so the user can visually confirm focus. if matchConfiguredShortcut(event: event, action: .triggerFlash) { - let targetManager = preferredMainWindowContextForShortcutRouting(event: event)?.tabManager ?? tabManager - targetManager?.triggerFocusFlash() + tabManager?.triggerFocusFlash() return true } @@ -12088,6 +11885,17 @@ final class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCent return handled } + if matchConfiguredShortcut(event: event, action: .toggleTerminalTimestamps) { + let enabled = TerminalTimestampsSettings.toggle() +#if DEBUG + cmuxDebugLog( + "shortcut.action name=toggleTerminalTimestamps enabled=\(enabled ? 1 : 0) " + + "\(debugShortcutRouteSnapshot(event: event))" + ) +#endif + return true + } + // Workspace navigation: Cmd+Ctrl+] / Cmd+Ctrl+[ if matchConfiguredShortcut(event: event, action: .nextSidebarTab) { #if DEBUG @@ -12190,7 +11998,7 @@ final class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCent } if matchConfiguredShortcut(event: event, action: .closeWindow) { - guard let targetWindow = mainWindowForShortcutEvent(event) ?? event.window ?? NSApp.keyWindow ?? NSApp.mainWindow else { + guard let targetWindow = event.window ?? NSApp.keyWindow ?? NSApp.mainWindow else { NSSound.beep() return true } @@ -13301,13 +13109,6 @@ final class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCent /// through the same app-level shortcut handler used by the local key monitor. @discardableResult func handleBrowserSurfaceKeyEquivalent(_ event: NSEvent) -> Bool { - handleConfiguredShortcutKeyEquivalent(event) - } - - /// Route AppKit key-equivalent fallbacks through the same configured shortcut - /// dispatcher as the local key monitor before any stale menu item can run. - @discardableResult - func handleConfiguredShortcutKeyEquivalent(_ event: NSEvent) -> Bool { handleCustomShortcut(event: event) } @@ -13372,18 +13173,6 @@ final class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCent return clearEscapeSuppressionForKeyUp(event: event, consumeIfSuppressed: true) } - func debugMatchesConfiguredShortcut( - event: NSEvent, - action: KeyboardShortcutSettings.Action - ) -> Bool { - matchConfiguredShortcut(event: event, action: action) - } - - func debugResetShortcutRoutingStateForTesting() { - clearConfiguredShortcutChordState() - shortcutEventFocusContextCache = nil - } - func debugMarkCommandPaletteOpenPending(window: NSWindow) { markCommandPaletteOpenRequested(for: window) } @@ -13573,11 +13362,11 @@ final class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCent private func armConfiguredShortcutChordIfNeeded( event: NSEvent, - actions: [KeyboardShortcutSettings.Action], + actions: [KeyboardShortcutSettings.Action]? = nil, shortcuts: [StoredShortcut] = [] ) -> Bool { var seen = Set() - let configuredShortcuts = actions.map { + let configuredShortcuts = (actions ?? configuredShortcutChordActions).map { KeyboardShortcutSettings.shortcut(for: $0) } + shortcuts for shortcut in configuredShortcuts { @@ -13748,54 +13537,25 @@ final class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCent .subtracting([.numericPad, .function, .capsLock]) guard flags.contains(.command) else { return false } - let staleDefaultActions = KeyboardShortcutSettings.Action.allCases.filter { action in - isMenuBackedShortcutAction(action) && - matchesKeyboardShortcutEvent(event, action: action, shortcut: action.defaultShortcut) - } - guard !staleDefaultActions.isEmpty else { return false } - - for action in staleDefaultActions { - if currentShortcutMatchesKeyboardShortcutEvent(event, action: action) { - return false - } - } - - if staleDefaultActions.contains(where: isCloseShortcutAction) { - return true - } - for action in KeyboardShortcutSettings.Action.allCases { - if currentShortcutMatchesKeyboardShortcutEvent(event, action: action) { + let currentShortcut = KeyboardShortcutSettings.shortcut(for: action) + if matchesKeyboardShortcutEvent(event, action: action, shortcut: currentShortcut) { return false } } - return true - } - private func currentShortcutMatchesKeyboardShortcutEvent( - _ event: NSEvent, - action: KeyboardShortcutSettings.Action - ) -> Bool { - let currentShortcut = KeyboardShortcutSettings.shortcut(for: action) - if action.usesNumberedDigitMatching { - return numberedShortcutDigit(event: event, shortcut: currentShortcut) != nil + for action in KeyboardShortcutSettings.Action.allCases where isMenuBackedShortcutAction(action) { + if matchesKeyboardShortcutEvent(event, action: action, shortcut: action.defaultShortcut) { + return true + } } - return matchesKeyboardShortcutEvent(event, action: action, shortcut: currentShortcut) + return false } private func isMenuBackedShortcutAction(_ action: KeyboardShortcutSettings.Action) -> Bool { action != .showHideAllWindows && action != .globalSearch } - private func isCloseShortcutAction(_ action: KeyboardShortcutSettings.Action) -> Bool { - switch action { - case .closeTab, .closeWorkspace, .closeWindow: - return true - default: - return false - } - } - private func numberedShortcutDigit(event: NSEvent, stroke: ShortcutStroke) -> Int? { let flags = event.modifierFlags.intersection(.deviceIndependentFlagsMask) .subtracting([.numericPad, .function, .capsLock]) @@ -14985,12 +14745,6 @@ private extension NSApplication { return } if AppDelegate.shared?.shouldSuppressStaleCmuxMenuShortcut(event: event) == true { - if AppDelegate.shared?.handleConfiguredShortcutKeyEquivalent(event) == true { -#if DEBUG - cmuxDebugLog("app.sendEvent routed configured shortcut before stale cmux menu shortcut") -#endif - return - } let responder = event.window?.firstResponder ?? keyWindow?.firstResponder ?? mainWindow?.firstResponder @@ -15156,51 +14910,10 @@ private extension AppDelegate { } @objc func handleThemesReloadNotification(_ notification: Notification) { - let targetBundleIdentifier = - notification.userInfo?["bundleIdentifier"] as? String - ?? notification.object as? String - if let targetBundleIdentifier, - let bundleIdentifier = Bundle.main.bundleIdentifier, - !targetBundleIdentifier.isEmpty, - targetBundleIdentifier != bundleIdentifier { - return - } - - let source = GhosttySurfaceConfigurationRefresh.cmuxThemeReloadSource( - phase: notification.userInfo?["phase"] as? String - ) DispatchQueue.main.async { - self.reloadGhosttyConfigurationForCmuxThemeSource(source) + GhosttyApp.shared.reloadConfiguration(source: "distributed.cmux.themes") } } - - func reloadGhosttyConfigurationForCmuxThemeSource(_ source: String) { - if GhosttySurfaceConfigurationRefresh.shouldDebounceCmuxThemeReload(source: source) { - cmuxThemePreviewReloadGeneration += 1 - let generation = cmuxThemePreviewReloadGeneration - cmuxThemePreviewReloadWorkItem?.cancel() - - let workItem = DispatchWorkItem { [weak self] in - guard let self, - self.cmuxThemePreviewReloadGeneration == generation else { return } - self.cmuxThemePreviewReloadWorkItem = nil - GhosttyApp.shared.reloadConfiguration(source: source) - } - cmuxThemePreviewReloadWorkItem = workItem - DispatchQueue.main.asyncAfter( - deadline: .now() + .milliseconds( - GhosttySurfaceConfigurationRefresh.cmuxThemePreviewReloadDebounceMilliseconds - ), - execute: workItem - ) - return - } - - cmuxThemePreviewReloadGeneration += 1 - cmuxThemePreviewReloadWorkItem?.cancel() - cmuxThemePreviewReloadWorkItem = nil - GhosttyApp.shared.reloadConfiguration(source: source) - } } private extension NSWindow { @@ -15485,9 +15198,8 @@ private extension NSWindow { cmuxFirstResponderGuardContextWindowNumber = previousContextWindowNumber } - let suppressionReason = beginOrContinueWindowMoveSuppressionSequenceForEvent(window: self, event: event) - let hasActiveSuppressionSequence = activeWindowMoveSuppressionSequenceReason(window: self) != nil - guard suppressionReason != nil || hasActiveSuppressionSequence else { + guard shouldSuppressWindowMoveForFolderDrag(window: self, event: event), + let contentView = self.contentView else { #if DEBUG if event.type == .keyDown { folderGuardMs = (ProcessInfo.processInfo.systemUptime - folderGuardStart) * 1000.0 @@ -15506,33 +15218,21 @@ private extension NSWindow { } let originalDispatchStart = event.type == .keyDown ? ProcessInfo.processInfo.systemUptime : 0 #endif - let shouldFinishSuppression = shouldFinishWindowMoveSuppressionSequenceAfterDispatch(window: self, event: event) -#if DEBUG - let hitView = Self.cmuxHitViewForEventDispatch(in: self, event: event) -#endif + let contentPoint = contentView.convert(event.locationInWindow, from: nil) + let hitView = contentView.hitTest(contentPoint) + let previousMovableState = temporarilyDisableWindowDragging(window: self) defer { - let finishedReason: WindowMoveSuppressionReason? - if shouldFinishSuppression { - finishedReason = finishWindowMoveSuppressionSequence(window: self) - } else { - finishedReason = nil - } + restoreWindowDragging(window: self, previousMovableState: previousMovableState) #if DEBUG - let reasonDescription = finishedReason?.rawValue ?? suppressionReason?.rawValue ?? "activeSequence" - if shouldFinishSuppression { - cmuxDebugLog("window.sendEvent.\(reasonDescription) finish nowMovable=\(isMovable)") - } else { - cmuxDebugLog("window.sendEvent.\(reasonDescription) keepSuppressed nowMovable=\(isMovable)") - } + cmuxDebugLog("window.sendEvent.folderDown restore nowMovable=\(isMovable)") #endif } #if DEBUG let hitDesc = hitView.map { String(describing: type(of: $0)) } ?? "nil" - let depth = windowDragSuppressionDepth(window: self) - let reasonDescription = suppressionReason?.rawValue ?? "activeSequence" - cmuxDebugLog("window.sendEvent.\(reasonDescription) suppress=1 hit=\(hitDesc) movable=\(isMovable) depth=\(depth)") + let previousMovableDescription = previousMovableState.map { String($0) } ?? "nil" + cmuxDebugLog("window.sendEvent.folderDown suppress=1 hit=\(hitDesc) wasMovable=\(previousMovableDescription)") #endif cmux_sendEvent(event) @@ -15595,12 +15295,6 @@ private extension NSWindow { return true } if AppDelegate.shared?.shouldSuppressStaleCmuxMenuShortcut(event: event) == true { - if AppDelegate.shared?.handleConfiguredShortcutKeyEquivalent(event) == true { -#if DEBUG - cmuxDebugLog(" → consumed by configured shortcut before stale cmux menu shortcut") -#endif - return true - } if let firstResponderGhosttyView { firstResponderGhosttyView.keyDown(with: event) #if DEBUG diff --git a/Sources/AppearanceSettings.swift b/Sources/AppearanceSettings.swift index fc4977121e73..7c8d752a14de 100644 --- a/Sources/AppearanceSettings.swift +++ b/Sources/AppearanceSettings.swift @@ -223,88 +223,6 @@ enum AppearanceSettings { } } -final class AppearanceSettingsUserDefaultsObserver { - struct Environment { - let addDefaultsObserver: (@escaping () -> Void) -> NSObjectProtocol - let removeObserver: (NSObjectProtocol) -> Void - let currentRawValue: () -> String? - let applyStoredMode: (String?, String) -> AppearanceMode - - static func live( - defaults: UserDefaults = .standard, - notificationCenter: NotificationCenter = .default - ) -> Environment { - Environment( - addDefaultsObserver: { handler in - notificationCenter.addObserver( - forName: UserDefaults.didChangeNotification, - object: nil, - queue: .main - ) { _ in - handler() - } - }, - removeObserver: { observer in - notificationCenter.removeObserver(observer) - }, - currentRawValue: { - defaults.string(forKey: AppearanceSettings.appearanceModeKey) - }, - applyStoredMode: { rawValue, source in - AppearanceSettings.applyStoredMode( - rawValue: rawValue, - defaults: defaults, - source: source - ) - } - ) - } - } - - static let shared = AppearanceSettingsUserDefaultsObserver() - - private let environment: Environment - private var defaultsObserver: NSObjectProtocol? - private var lastObservedRawValue: String? - private var source: String - - init( - environment: Environment = .live(), - source: String = "cmuxApp.appearanceDefaultsChanged" - ) { - self.environment = environment - self.source = source - } - - deinit { - stopObserving() - } - - func startObserving(source: String? = nil) { - if let source { - self.source = source - } - lastObservedRawValue = environment.currentRawValue() - guard defaultsObserver == nil else { return } - defaultsObserver = environment.addDefaultsObserver { [weak self] in - self?.applyIfChanged() - } - } - - func stopObserving() { - guard let defaultsObserver else { return } - environment.removeObserver(defaultsObserver) - self.defaultsObserver = nil - } - - private func applyIfChanged() { - let rawValue = environment.currentRawValue() - guard rawValue != lastObservedRawValue else { return } - let appliedMode = environment.applyStoredMode(rawValue, source) - lastObservedRawValue = appliedMode.rawValue - } -} - private struct AppearanceColorSchemeModifier: ViewModifier { @Environment(\.colorScheme) private var colorScheme let rawValue: String? diff --git a/Sources/CmuxApplicationSupportDirectories.swift b/Sources/CmuxApplicationSupportDirectories.swift index fd3f9d669040..85829a53bf17 100644 --- a/Sources/CmuxApplicationSupportDirectories.swift +++ b/Sources/CmuxApplicationSupportDirectories.swift @@ -36,142 +36,3 @@ enum CmuxApplicationSupportDirectories { return urls } } - -enum CmuxGhosttyConfigPathResolver { - static let releaseBundleIdentifier = "com.cmuxterm.app" - private static let releaseFallbackChannelSuffixes = ["debug", "nightly", "staging"] - - static func editableConfigURL( - currentBundleIdentifier: String?, - appSupportDirectory: URL - ) -> URL { - configDirectoryURL( - currentBundleIdentifier: currentBundleIdentifier, - appSupportDirectory: appSupportDirectory - ) - .appendingPathComponent("config.ghostty", isDirectory: false) - } - - static func activeOrEditableConfigURL( - currentBundleIdentifier: String?, - appSupportDirectory: URL, - fileManager: FileManager = .default - ) -> URL { - loadConfigURLs( - currentBundleIdentifier: currentBundleIdentifier, - appSupportDirectory: appSupportDirectory, - fileManager: fileManager - ) - .first - ?? editableConfigURL( - currentBundleIdentifier: currentBundleIdentifier, - appSupportDirectory: appSupportDirectory - ) - } - - static func loadConfigURLs( - currentBundleIdentifier: String?, - appSupportDirectory: URL, - fileManager: FileManager = .default - ) -> [URL] { - guard let currentBundleIdentifier, !currentBundleIdentifier.isEmpty else { - return preferredExistingConfigURLs( - for: releaseBundleIdentifier, - appSupportDirectory: appSupportDirectory, - fileManager: fileManager - ) - } - - let currentURLs = preferredExistingConfigURLs( - for: currentBundleIdentifier, - appSupportDirectory: appSupportDirectory, - fileManager: fileManager - ) - if !currentURLs.isEmpty { - return currentURLs - } - if allowsReleaseFallback(currentBundleIdentifier) { - let releaseURLs = preferredExistingConfigURLs( - for: releaseBundleIdentifier, - appSupportDirectory: appSupportDirectory, - fileManager: fileManager - ) - if !releaseURLs.isEmpty { - return releaseURLs - } - } - return [] - } - - static func configDirectoryURL( - currentBundleIdentifier: String?, - appSupportDirectory: URL - ) -> URL { - guard let currentBundleIdentifier, !currentBundleIdentifier.isEmpty else { - return appSupportDirectory.appendingPathComponent(releaseBundleIdentifier, isDirectory: true) - } - return appSupportDirectory.appendingPathComponent(currentBundleIdentifier, isDirectory: true) - } - - private static func preferredExistingConfigURLs( - for bundleIdentifier: String, - appSupportDirectory: URL, - fileManager: FileManager - ) -> [URL] { - let directory = appSupportDirectory.appendingPathComponent(bundleIdentifier, isDirectory: true) - let legacyConfig = directory.appendingPathComponent("config", isDirectory: false) - let configGhostty = directory.appendingPathComponent("config.ghostty", isDirectory: false) - if isNonEmptyConfigFile(configGhostty, fileManager: fileManager) { - // Do not layer legacy config under config.ghostty. Older builds wrote - // explicit dark colors there, which blocks appearance-driven themes. - return [configGhostty] - } - if isNonEmptyConfigFile(legacyConfig, fileManager: fileManager) { - return [legacyConfig] - } - return [] - } - - private static func isNonEmptyConfigFile(_ url: URL, fileManager: FileManager) -> Bool { - var isDirectory = ObjCBool(false) - guard fileManager.fileExists(atPath: url.path, isDirectory: &isDirectory), - !isDirectory.boolValue else { - return false - } - - if (try? url.resourceValues(forKeys: [.isSymbolicLinkKey]).isSymbolicLink) == true { - return isNonEmptySymlinkTarget(url, fileManager: fileManager) - } - - return isNonEmptyRegularFile(url, fileManager: fileManager) - } - - private static func isNonEmptySymlinkTarget(_ url: URL, fileManager: FileManager) -> Bool { - isNonEmptyRegularFile(url.resolvingSymlinksInPath(), fileManager: fileManager) - } - - private static func isNonEmptyRegularFile(_ url: URL, fileManager: FileManager) -> Bool { - guard let attrs = try? fileManager.attributesOfItem(atPath: url.path), - let type = attrs[.type] as? FileAttributeType, - type == .typeRegular, - let size = attrs[.size] as? NSNumber else { - return false - } - return size.intValue > 0 - } - - private static func allowsReleaseFallback(_ bundleIdentifier: String) -> Bool { - releaseFallbackChannelSuffixes.contains { channelSuffix in - matchesChannelBundleIdentifier(bundleIdentifier, channelSuffix: channelSuffix) - } - } - - private static func matchesChannelBundleIdentifier( - _ bundleIdentifier: String, - channelSuffix: String - ) -> Bool { - let channelBundleIdentifier = "\(releaseBundleIdentifier).\(channelSuffix)" - return bundleIdentifier == channelBundleIdentifier - || bundleIdentifier.hasPrefix("\(channelBundleIdentifier).") - } -} diff --git a/Sources/CmuxSettingsJSONPathSupport.swift b/Sources/CmuxSettingsJSONPathSupport.swift index 872758d3b1f0..7c96209ed531 100644 --- a/Sources/CmuxSettingsJSONPathSupport.swift +++ b/Sources/CmuxSettingsJSONPathSupport.swift @@ -3,7 +3,6 @@ import Foundation enum SidebarWorkspaceDetailDefaults { static let showBranchDirectoryKey = "sidebarShowBranchDirectory" static let showPullRequestsKey = "sidebarShowPullRequest" - static let watchGitStatusKey = "sidebarWatchGitStatus" static let showSSHKey = "sidebarShowSSH" static let showPortsKey = "sidebarShowPorts" static let showLogKey = "sidebarShowLog" @@ -12,7 +11,6 @@ enum SidebarWorkspaceDetailDefaults { static let showBranchDirectory = true static let showPullRequests = true - static let watchGitStatus = true static let showSSH = true static let showPorts = true static let showLog = true @@ -31,10 +29,6 @@ extension SidebarWorkspaceDetailDefaults { static func showPullRequestsValue(defaults: UserDefaults) -> Bool { boolValue(defaults: defaults, key: showPullRequestsKey, defaultValue: showPullRequests) } - - static func watchGitStatusValue(defaults: UserDefaults) -> Bool { - boolValue(defaults: defaults, key: watchGitStatusKey, defaultValue: watchGitStatus) - } } enum AutomationSettings { @@ -68,6 +62,7 @@ extension CmuxSettingsFileStore { "app.renameSelectsExistingName", "app.commandPaletteSearchesAllSurfaces", "terminal.showScrollBar", + "terminal.showTimestamps", "terminal.autoResumeAgentSessions", "terminal.resumeCommands", "notifications.dockBadge", @@ -85,7 +80,6 @@ extension CmuxSettingsFileStore { "sidebar.showNotificationMessage", "sidebar.showBranchDirectory", "sidebar.showPullRequests", - "sidebar.watchGitStatus", "sidebar.makePullRequestsClickable", "sidebar.openPullRequestLinksInCmuxBrowser", "sidebar.openPortLinksInCmuxBrowser", @@ -110,7 +104,6 @@ extension CmuxSettingsFileStore { "automation.claudeCodeIntegration", "automation.claudeBinaryPath", "automation.ripgrepBinaryPath", - "automation.suppressSubagentNotifications", "automation.cursorIntegration", "automation.geminiIntegration", "automation.portBase", diff --git a/Sources/CmuxTopMemoryDiagnostics.swift b/Sources/CmuxTopMemoryDiagnostics.swift deleted file mode 100644 index 0e33b06e0928..000000000000 --- a/Sources/CmuxTopMemoryDiagnostics.swift +++ /dev/null @@ -1,254 +0,0 @@ -import Darwin -import Foundation - -nonisolated let cmuxTopMemoryDiagnosticDefaultGroupLimit = 12 - -nonisolated struct CmuxTopProcessAttribution: Hashable, Sendable { - let workspaceID: UUID? - let workspaceRef: String? - let paneID: UUID? - let paneRef: String? - let surfaceID: UUID? - let surfaceRef: String? - let surfaceType: String? - let reason: String - - func payload() -> [String: Any] { - [ - "workspace_id": workspaceID?.uuidString as Any? ?? NSNull(), - "workspace_ref": workspaceRef as Any? ?? NSNull(), - "pane_id": paneID?.uuidString as Any? ?? NSNull(), - "pane_ref": paneRef as Any? ?? NSNull(), - "surface_id": surfaceID?.uuidString as Any? ?? NSNull(), - "surface_ref": surfaceRef as Any? ?? NSNull(), - "surface_type": surfaceType as Any? ?? NSNull(), - "reason": reason - ] - } -} - -nonisolated extension CmuxTopProcessSnapshot { - func memoryDiagnosticPayload( - appPID: Int = Int(Darwin.getpid()), - topGroupLimit: Int = cmuxTopMemoryDiagnosticDefaultGroupLimit, - attributionByPID: [Int: CmuxTopProcessAttribution] = [:] - ) -> [String: Any] { - let appResources = summaryPayload(for: [appPID], rootPIDs: [appPID]) - let appProcess = processesByPID[appPID] - let childPIDs = descendantPIDs(rootPID: appPID, includeRoot: false) - .filter { processesByPID[$0] != nil } - let childSummary = summary(for: childPIDs) - let groups = memoryDiagnosticGroups( - for: childPIDs, - topGroupLimit: topGroupLimit, - attributionByPID: attributionByPID - ) - let topGroup = groups.first - - return [ - "sampled_at": ISO8601DateFormatter().string(from: sampledAt), - "app": [ - "pid": appPID, - "name": appProcess?.name ?? "cmux", - "path": appProcess?.path as Any? ?? NSNull(), - "resources": appResources, - "physical_footprint_bytes": appProcess?.memoryBytes ?? 0, - "resident_bytes": appProcess?.residentBytes ?? 0, - "memory_source": appProcess?.memorySource.rawValue ?? CmuxTopProcessMemorySource.unavailable.rawValue, - "resident_memory_source": appProcess?.residentMemorySource.rawValue ?? CmuxTopProcessMemorySource.unavailable.rawValue - ] as [String: Any], - "children": [ - "root_pid": appPID, - "recursive_rss_bytes": childSummary.residentBytes, - "process_count": childSummary.processCount, - "pids": childSummary.pids, - "groups": groups - ] as [String: Any], - "summary": memoryDiagnosticSummaryText( - appFootprintBytes: appProcess?.memoryBytes ?? 0, - childRSSBytes: childSummary.residentBytes, - topGroup: topGroup - ) - ] - } - - private struct MemoryDiagnosticGroupAccumulator { - let id: String - let name: String - var rssBytes: Int64 = 0 - var processIDs: [Int] = [] - var attributions: [CmuxTopProcessAttribution: MemoryDiagnosticAttributionAccumulator] = [:] - - mutating func append( - process: CmuxTopProcessInfo, - attribution: CmuxTopProcessAttribution? - ) { - rssBytes = CmuxTopProcessSnapshot.clampedAdd(rssBytes, process.residentBytes) - processIDs.append(process.pid) - guard let attribution else { return } - if attributions[attribution] == nil { - attributions[attribution] = MemoryDiagnosticAttributionAccumulator(attribution: attribution) - } - attributions[attribution]?.append(process: process) - } - - func payload() -> [String: Any] { - let sortedProcessIDs = processIDs.sorted() - let attributionPayloads = attributions.values - .sorted { - if $0.rssBytes != $1.rssBytes { - return $0.rssBytes > $1.rssBytes - } - return $0.displayKey < $1.displayKey - } - .map { $0.payload() } - let topAttribution: Any = attributionPayloads.first.map { $0 as Any } ?? NSNull() - return [ - "id": id, - "name": name, - "rss_bytes": rssBytes, - "resident_bytes": rssBytes, - "process_count": sortedProcessIDs.count, - "pids": sortedProcessIDs, - "top_attribution": topAttribution, - "attributions": attributionPayloads - ] - } - } - - private struct MemoryDiagnosticAttributionAccumulator { - let attribution: CmuxTopProcessAttribution - var rssBytes: Int64 = 0 - var processIDs: [Int] = [] - - var displayKey: String { - [ - attribution.workspaceRef, - attribution.paneRef, - attribution.surfaceRef, - attribution.workspaceID?.uuidString, - attribution.paneID?.uuidString, - attribution.surfaceID?.uuidString - ] - .compactMap { $0 } - .joined(separator: "/") - } - - mutating func append(process: CmuxTopProcessInfo) { - rssBytes = CmuxTopProcessSnapshot.clampedAdd(rssBytes, process.residentBytes) - processIDs.append(process.pid) - } - - func payload() -> [String: Any] { - var payload = attribution.payload() - let sortedProcessIDs = processIDs.sorted() - payload["rss_bytes"] = rssBytes - payload["resident_bytes"] = rssBytes - payload["process_count"] = sortedProcessIDs.count - payload["pids"] = sortedProcessIDs - return payload - } - } - - private func memoryDiagnosticGroups( - for pids: Set, - topGroupLimit: Int, - attributionByPID: [Int: CmuxTopProcessAttribution] - ) -> [[String: Any]] { - var groups: [String: MemoryDiagnosticGroupAccumulator] = [:] - for pid in pids.sorted() { - guard let process = processesByPID[pid] else { continue } - let name = process.name.trimmingCharacters(in: .whitespacesAndNewlines) - let displayName = name.isEmpty ? "pid-\(pid)" : name - let key = displayName.lowercased() - if groups[key] == nil { - groups[key] = MemoryDiagnosticGroupAccumulator(id: key, name: displayName) - } - groups[key]?.append( - process: process, - attribution: nearestCMUXAttribution( - for: pid, - attributionByPID: attributionByPID - ) - ) - } - - let limit = max(1, topGroupLimit) - return groups.values - .sorted { - if $0.rssBytes != $1.rssBytes { - return $0.rssBytes > $1.rssBytes - } - return $0.name.localizedStandardCompare($1.name) == .orderedAscending - } - .prefix(limit) - .map { $0.payload() } - } - - private func nearestCMUXAttribution( - for pid: Int, - attributionByPID: [Int: CmuxTopProcessAttribution] - ) -> CmuxTopProcessAttribution? { - var visited: Set = [] - var currentPID = pid - while currentPID > 0, visited.insert(currentPID).inserted { - if let attribution = attributionByPID[currentPID] { - return attribution - } - guard let process = processesByPID[currentPID] else { return nil } - if process.cmuxWorkspaceID != nil || process.cmuxSurfaceID != nil { - return CmuxTopProcessAttribution( - workspaceID: process.cmuxWorkspaceID, - workspaceRef: nil, - paneID: nil, - paneRef: nil, - surfaceID: process.cmuxSurfaceID, - surfaceRef: nil, - surfaceType: nil, - reason: process.cmuxAttributionReason ?? "cmux-process-scope" - ) - } - currentPID = process.parentPID - } - return nil - } - - private func memoryDiagnosticSummaryText( - appFootprintBytes: Int64, - childRSSBytes: Int64, - topGroup: [String: Any]? - ) -> String { - var summary = String.localizedStringWithFormat( - String(localized: "memoryDiagnostic.summary.base", defaultValue: "%@ app footprint + %@ child RSS"), - Self.formatDiagnosticBytes(appFootprintBytes), - Self.formatDiagnosticBytes(childRSSBytes) - ) - guard let topGroup, - let name = topGroup["name"] as? String, - let rssBytes = topGroup["rss_bytes"] as? Int64 ?? (topGroup["rss_bytes"] as? NSNumber)?.int64Value else { - return summary - } - - summary += String.localizedStringWithFormat( - String(localized: "memoryDiagnostic.summary.topGroup", defaultValue: "; top child group: %@ %@"), - name, - Self.formatDiagnosticBytes(rssBytes) - ) - if let attribution = topGroup["top_attribution"] as? [String: Any], - let workspace = attribution["workspace_ref"] as? String ?? attribution["workspace_id"] as? String, - !workspace.isEmpty { - summary += String.localizedStringWithFormat( - String(localized: "memoryDiagnostic.summary.workspace", defaultValue: " from workspace %@"), - workspace - ) - } - return summary - } - - private static func formatDiagnosticBytes(_ bytes: Int64) -> String { - let formatter = ByteCountFormatter() - formatter.countStyle = .memory - formatter.allowedUnits = .useAll - return formatter.string(fromByteCount: max(0, bytes)) - } -} diff --git a/Sources/CmuxTopProcessEnumeration.swift b/Sources/CmuxTopProcessEnumeration.swift deleted file mode 100644 index bbc91d530ad2..000000000000 --- a/Sources/CmuxTopProcessEnumeration.swift +++ /dev/null @@ -1,245 +0,0 @@ -import Darwin -import Foundation - -private nonisolated let cmuxTopPIDPathBufferSize = 4096 - -nonisolated extension CmuxTopProcessSnapshot { - static func allProcesses(includeProcessDetails: Bool) -> [CmuxTopProcessInfo] { - let sampledProcesses = allBSDProcesses() - guard !sampledProcesses.isEmpty else { return [] } - - var scopeKeyByPID: [Int: CmuxTopProcessScopeCacheKey] = [:] - scopeKeyByPID.reserveCapacity(sampledProcesses.count) - for process in sampledProcesses { - scopeKeyByPID[Int(process.pbi_pid)] = scopeCacheKey(from: process) - } - let activeScopeKeys = Set(scopeKeyByPID.values) - var parentScopeKeys: [CmuxTopProcessScopeCacheKey: CmuxTopProcessScopeCacheKey] = [:] - parentScopeKeys.reserveCapacity(sampledProcesses.count) - for process in sampledProcesses { - let key = scopeCacheKey(from: process) - let parentPID = Int(process.pbi_ppid) - guard let parentKey = scopeKeyByPID[parentPID] else { continue } - parentScopeKeys[key] = parentKey - } - let sampledAtNanoseconds = cpuSampleClockNanoseconds() - var currentCPUSamples: [CmuxTopProcessScopeCacheKey: CmuxTopProcessCPUSample] = [:] - var processRecords: [(info: CmuxTopProcessInfo, cpuSampleKey: CmuxTopProcessScopeCacheKey?)] = [] - processRecords.reserveCapacity(sampledProcesses.count) - for process in sampledProcesses { - guard let processRecord = processInfo( - from: process, - includeProcessDetails: includeProcessDetails, - sampledAtNanoseconds: sampledAtNanoseconds, - currentCPUSamples: ¤tCPUSamples - ) else { - continue - } - processRecords.append(processRecord) - } - let cpuPercentages = cpuPercentages( - for: currentCPUSamples, - activeKeys: activeScopeKeys, - parentKeysByKey: parentScopeKeys, - sampledAtNanoseconds: sampledAtNanoseconds - ) - for index in processRecords.indices { - guard let key = processRecords[index].cpuSampleKey, - let cpuPercent = cpuPercentages[key] else { continue } - processRecords[index].info.cpuPercent = cpuPercent - } - pruneCMUXScopeCache(activeKeys: activeScopeKeys) - return processRecords.map(\.info) - } - - static func deviceIdentifier(forTTYName ttyName: String) -> Int64? { - let trimmed = ttyName.trimmingCharacters(in: .whitespacesAndNewlines) - guard !trimmed.isEmpty, trimmed != "not a tty" else { - return nil - } - - let path: String - if trimmed.hasPrefix("/dev/") { - path = trimmed - } else { - path = "/dev/\(trimmed)" - } - - var statInfo = stat() - guard stat(path, &statInfo) == 0 else { - return nil - } - return Int64(statInfo.st_rdev) - } - - private static func processInfo( - from bsdInfo: proc_bsdinfo, - includeProcessDetails: Bool, - sampledAtNanoseconds: UInt64, - currentCPUSamples: inout [CmuxTopProcessScopeCacheKey: CmuxTopProcessCPUSample] - ) -> (info: CmuxTopProcessInfo, cpuSampleKey: CmuxTopProcessScopeCacheKey?)? { - let pid = Int(bsdInfo.pbi_pid) - guard pid > 0 else { return nil } - - let taskInfo = taskInfo(for: pid) - let resourceUsage = resourceUsage(for: pid) - let cacheKey = scopeCacheKey(from: bsdInfo) - let fallbackName = fixedString(bsdInfo.pbi_comm) - let name = includeProcessDetails ? processName(pid: pid, fallback: fallbackName) : fallbackName - let path = includeProcessDetails ? processPath(pid: pid) : nil - let rawTTY = Int64(bsdInfo.e_tdev) - let ttyDevice = rawTTY > 0 ? rawTTY : nil - let cmuxScope = cachedCMUXScope(for: pid, cacheKey: cacheKey) - let rawProcessGroupID = Int(bsdInfo.pbi_pgid) - let processGroupID = rawProcessGroupID > 0 ? rawProcessGroupID : nil - let rawTerminalProcessGroupID = Int(bsdInfo.e_tpgid) - let terminalProcessGroupID = rawTerminalProcessGroupID > 0 ? rawTerminalProcessGroupID : nil - let memoryBytes: Int64 - let memorySource: CmuxTopProcessMemorySource - if let resourceUsage { - memoryBytes = int64Clamped(resourceUsage.ri_phys_footprint) - memorySource = .physicalFootprint - } else if let taskInfo { - memoryBytes = int64Clamped(taskInfo.pti_resident_size) - memorySource = .residentSize - } else { - memoryBytes = 0 - memorySource = .unavailable - } - let residentBytes: Int64 - let residentMemorySource: CmuxTopProcessMemorySource - if let taskInfo { - residentBytes = int64Clamped(taskInfo.pti_resident_size) - residentMemorySource = .residentSize - } else if let resourceUsage { - residentBytes = int64Clamped(resourceUsage.ri_resident_size) - residentMemorySource = .rusageResidentSize - } else { - residentBytes = 0 - residentMemorySource = .unavailable - } - let cpuSampleKey: CmuxTopProcessScopeCacheKey? - if let taskInfo { - let currentCPUSample = cpuSample(from: taskInfo, sampledAtNanoseconds: sampledAtNanoseconds) - currentCPUSamples[cacheKey] = currentCPUSample - cpuSampleKey = cacheKey - } else { - cpuSampleKey = nil - } - - return (CmuxTopProcessInfo( - pid: pid, - parentPID: Int(bsdInfo.pbi_ppid), - name: name.isEmpty ? "pid-\(pid)" : name, - path: path, - ttyDevice: ttyDevice, - cmuxWorkspaceID: cmuxScope?.workspaceID, - cmuxSurfaceID: cmuxScope?.surfaceID, - cmuxAttributionReason: cmuxScope?.attributionReason, - processGroupID: processGroupID, - terminalProcessGroupID: terminalProcessGroupID, - cpuPercent: 0, - memoryBytes: memoryBytes, - memorySource: memorySource, - residentBytes: residentBytes, - residentMemorySource: residentMemorySource, - virtualBytes: int64Clamped(taskInfo?.pti_virtual_size ?? 0), - threadCount: Int(taskInfo?.pti_threadnum ?? 0) - ), cpuSampleKey) - } - - private static func allBSDProcesses() -> [proc_bsdinfo] { - let pidStride = MemoryLayout.stride - func bsdInfos(from pids: [pid_t], count: Int) -> [proc_bsdinfo] { - pids.prefix(count).compactMap { pid in - guard pid > 0 else { return nil } - return bsdInfo(for: Int(pid)) - } - } - - // proc_listallpids returns a PID count; the buffer size argument is bytes. - let initialPIDCount = Int(proc_listallpids(nil, 0)) - guard initialPIDCount > 0 else { return [] } - var capacity = max(1, initialPIDCount + 32) - var lastPIDs: [pid_t] = [] - var lastCount = 0 - for _ in 0..<3 { - var pids = Array(repeating: pid_t(), count: capacity) - let returnedCount = pids.withUnsafeMutableBufferPointer { buffer in - proc_listallpids(buffer.baseAddress, Int32(buffer.count * pidStride)) - } - guard returnedCount >= 0 else { - return lastCount > 0 ? bsdInfos(from: lastPIDs, count: lastCount) : [] - } - let returnedPIDCount = Int(returnedCount) - let count = min(pids.count, returnedPIDCount) - if count > 0 { - lastPIDs = pids - lastCount = count - } - if returnedPIDCount < pids.count { - return bsdInfos(from: pids, count: count) - } - capacity = max(pids.count * 2, returnedPIDCount + 32) - } - return lastCount > 0 ? bsdInfos(from: lastPIDs, count: lastCount) : [] - } - - private static func bsdInfo(for pid: Int) -> proc_bsdinfo? { - var info = proc_bsdinfo() - let expectedSize = MemoryLayout.stride - let size = proc_pidinfo(pid_t(pid), PROC_PIDTBSDINFO, 0, &info, Int32(expectedSize)) - return size == expectedSize ? info : nil - } - - private static func taskInfo(for pid: Int) -> proc_taskinfo? { - var info = proc_taskinfo() - let expectedSize = MemoryLayout.stride - let size = proc_pidinfo(pid_t(pid), PROC_PIDTASKINFO, 0, &info, Int32(expectedSize)) - return size == expectedSize ? info : nil - } - - private static func resourceUsage(for pid: Int) -> rusage_info_v4? { - var info = rusage_info_v4() - let result = withUnsafeMutableBytes(of: &info) { rawBuffer -> Int32 in - guard let baseAddress = rawBuffer.baseAddress else { return -1 } - // proc_pid_rusage imports as rusage_info_t *; callers pass the concrete - // rusage struct address cast to that opaque buffer type. - let buffer = baseAddress.assumingMemoryBound(to: rusage_info_t?.self) - return proc_pid_rusage( - pid_t(pid), - RUSAGE_INFO_V4, - buffer - ) - } - return result == 0 ? info : nil - } - - private static func processName(pid: Int, fallback: String) -> String { - var buffer = [CChar](repeating: 0, count: Int(MAXCOMLEN + 1)) - let length = proc_name(pid_t(pid), &buffer, UInt32(buffer.count)) - guard length > 0 else { return fallback } - let name = String(cString: buffer).trimmingCharacters(in: .whitespacesAndNewlines) - return name.isEmpty ? fallback : name - } - - private static func processPath(pid: Int) -> String? { - var buffer = [CChar](repeating: 0, count: cmuxTopPIDPathBufferSize) - let length = proc_pidpath(pid_t(pid), &buffer, UInt32(buffer.count)) - guard length > 0 else { return nil } - let path = String(cString: buffer).trimmingCharacters(in: .whitespacesAndNewlines) - return path.isEmpty ? nil : path - } - - private static func fixedString(_ value: T) -> String { - withUnsafeBytes(of: value) { rawBuffer in - let endIndex = rawBuffer.firstIndex(of: 0) ?? rawBuffer.endIndex - return String(decoding: rawBuffer[.. Int64 { - value > UInt64(Int64.max) ? Int64.max : Int64(value) - } -} diff --git a/Sources/CmuxTopProcessSnapshotCache.swift b/Sources/CmuxTopProcessSnapshotCache.swift deleted file mode 100644 index 9244cf4eb91e..000000000000 --- a/Sources/CmuxTopProcessSnapshotCache.swift +++ /dev/null @@ -1,58 +0,0 @@ -import Foundation -import os - -private nonisolated struct CmuxTopProcessSnapshotCacheState { - var snapshot: CmuxTopProcessSnapshot? - var includeProcessDetails = false -} - -// libproc snapshots are a short-lived platform bridge shared by the CLI, socket, -// and Task Manager paths; keep the cache here so ownership stays with capture(). -private nonisolated let cmuxTopProcessSnapshotCache = OSAllocatedUnfairLock( - initialState: CmuxTopProcessSnapshotCacheState() -) - -nonisolated extension CmuxTopProcessSnapshot { - static func captureCached( - includeProcessDetails: Bool = false, - maximumAge: TimeInterval - ) -> CmuxTopProcessSnapshot { - let now = Date() - if let cached = cmuxTopProcessSnapshotCache.withLock({ state -> CmuxTopProcessSnapshot? in - guard let snapshot = state.snapshot, - Self.cachedSnapshotDetailsSatisfy( - state.includeProcessDetails, - requested: includeProcessDetails - ), - now.timeIntervalSince(snapshot.sampledAt) <= maximumAge else { - return nil - } - return snapshot - }) { - return cached - } - - let snapshot = capture(includeProcessDetails: includeProcessDetails) - return cmuxTopProcessSnapshotCache.withLock { state in - let storeTime = Date() - if let cached = state.snapshot, - Self.cachedSnapshotDetailsSatisfy( - state.includeProcessDetails, - requested: includeProcessDetails - ), - storeTime.timeIntervalSince(cached.sampledAt) <= maximumAge { - return cached - } - state.snapshot = snapshot - state.includeProcessDetails = includeProcessDetails - return snapshot - } - } - - private static func cachedSnapshotDetailsSatisfy( - _ cachedIncludesProcessDetails: Bool, - requested: Bool - ) -> Bool { - cachedIncludesProcessDetails || !requested - } -} diff --git a/Sources/CmuxTopSnapshot.swift b/Sources/CmuxTopSnapshot.swift index 62f912205d60..0e48118d0fd0 100644 --- a/Sources/CmuxTopSnapshot.swift +++ b/Sources/CmuxTopSnapshot.swift @@ -1,5 +1,7 @@ -import Darwin import Foundation +import Darwin + +private nonisolated let cmuxTopPIDPathBufferSize = 4096 nonisolated struct CmuxTopResourceSummary: Sendable { var cpuPercent: Double = 0 @@ -46,9 +48,9 @@ nonisolated struct CmuxTopResourceSummary: Sendable { } nonisolated enum CmuxTopProcessMemorySource: String, Sendable { - case physicalFootprint = "proc_pid_rusage.RUSAGE_INFO_V4.ri_phys_footprint" + case physicalFootprint = "proc_pid_rusage.RUSAGE_INFO_V2.ri_phys_footprint" case residentSize = "proc_pidinfo.PROC_PIDTASKINFO.pti_resident_size" - case rusageResidentSize = "proc_pid_rusage.RUSAGE_INFO_V4.ri_resident_size" + case rusageResidentSize = "proc_pid_rusage.RUSAGE_INFO_V2.ri_resident_size" case mixed case unavailable } @@ -132,7 +134,7 @@ nonisolated struct CmuxTopProcessScope: Sendable { nonisolated final class CmuxTopProcessSnapshot: @unchecked Sendable { let sampledAt: Date private let includesProcessDetails: Bool - let processesByPID: [Int: CmuxTopProcessInfo] + private let processesByPID: [Int: CmuxTopProcessInfo] private let childrenByParentPID: [Int: [Int]] private let pidsByTTYDevice: [Int64: [Int]] private let pidsByCMUXSurfaceID: [UUID: [Int]] @@ -186,7 +188,7 @@ nonisolated final class CmuxTopProcessSnapshot: @unchecked Sendable { let residentMemorySourceNames = residentMemorySources.map(\.rawValue) return [ "sampled_at": ISO8601DateFormatter().string(from: sampledAt), - "source": "proc_listallpids+proc_pidinfo", + "source": "sysctl+proc_pidinfo", "cpu_source": "proc_pidinfo.PROC_PIDTASKINFO.pti_total_user+pti_total_system", "memory_source": CmuxTopProcessMemorySource.physicalFootprint.rawValue, "memory_fallback_source": CmuxTopProcessMemorySource.residentSize.rawValue, @@ -238,10 +240,6 @@ nonisolated final class CmuxTopProcessSnapshot: @unchecked Sendable { .sorted { $0.pid < $1.pid } } - func process(pid: Int) -> CmuxTopProcessInfo? { - processesByPID[pid] - } - func expandedPIDs(rootPIDs: Set) -> Set { var result: Set = [] var stack = Array(rootPIDs.filter { $0 > 0 }) @@ -254,56 +252,6 @@ nonisolated final class CmuxTopProcessSnapshot: @unchecked Sendable { return result } - func descendantPIDs(rootPID: Int, includeRoot: Bool = false) -> Set { - guard rootPID > 0 else { return [] } - - var result: Set = includeRoot && processesByPID[rootPID] != nil ? [rootPID] : [] - var visited: Set = [] - var stack = childrenByParentPID[rootPID] ?? [] - stack.append(contentsOf: Self.listedChildPIDs(parentPID: rootPID)) - while let pid = stack.popLast() { - guard visited.insert(pid).inserted else { continue } - guard result.insert(pid).inserted else { continue } - stack.append(contentsOf: childrenByParentPID[pid] ?? []) - stack.append(contentsOf: Self.listedChildPIDs(parentPID: pid)) - } - return result - } - - private static func listedChildPIDs(parentPID: Int) -> [Int] { - guard parentPID > 0 else { return [] } - - let pidStride = MemoryLayout.stride - var capacity = 16 - var lastChildren: [Int] = [] - for _ in 0..<4 { - var pids = Array(repeating: pid_t(), count: capacity) - let returnedCount = pids.withUnsafeMutableBufferPointer { buffer in - proc_listchildpids( - pid_t(parentPID), - buffer.baseAddress, - Int32(buffer.count * pidStride) - ) - } - guard returnedCount >= 0 else { - return lastChildren - } - - let count = min(pids.count, Int(returnedCount)) - lastChildren = pids - .prefix(count) - .compactMap { pid in - let intPID = Int(pid) - return intPID > 0 ? intPID : nil - } - if Int(returnedCount) < pids.count { - return lastChildren - } - capacity = max(pids.count * 2, Int(returnedCount) + 16) - } - return lastChildren - } - func summaryPayload(for pids: Set, rootPIDs: Set = []) -> [String: Any] { summary(for: pids, rootPIDs: rootPIDs).payload() } @@ -640,10 +588,225 @@ nonisolated final class CmuxTopProcessSnapshot: @unchecked Sendable { return "\(process?.name ?? ""):\(pid)" } - static func clampedAdd(_ lhs: Int64, _ rhs: Int64) -> Int64 { + private static func allProcesses(includeProcessDetails: Bool) -> [CmuxTopProcessInfo] { + var mib: [Int32] = [CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0] + let stride = MemoryLayout.stride + + for _ in 0..<3 { + var length = 0 + guard sysctl(&mib, u_int(mib.count), nil, &length, nil, 0) == 0, length > 0 else { + return [] + } + + var processes = Array(repeating: kinfo_proc(), count: max(1, (length / stride) + 32)) + let result = processes.withUnsafeMutableBufferPointer { buffer in + sysctl(&mib, u_int(mib.count), buffer.baseAddress, &length, nil, 0) + } + if result == 0 { + let count = min(processes.count, length / stride) + let sampledProcesses = Array(processes.prefix(count)) + var scopeKeyByPID: [Int: CmuxTopProcessScopeCacheKey] = [:] + scopeKeyByPID.reserveCapacity(sampledProcesses.count) + for process in sampledProcesses { + scopeKeyByPID[Int(process.kp_proc.p_pid)] = scopeCacheKey(from: process) + } + let activeScopeKeys = Set(scopeKeyByPID.values) + var parentScopeKeys: [CmuxTopProcessScopeCacheKey: CmuxTopProcessScopeCacheKey] = [:] + parentScopeKeys.reserveCapacity(sampledProcesses.count) + for process in sampledProcesses { + let key = scopeCacheKey(from: process) + let parentPID = Int(process.kp_eproc.e_ppid) + guard let parentKey = scopeKeyByPID[parentPID] else { continue } + parentScopeKeys[key] = parentKey + } + let sampledAtNanoseconds = cpuSampleClockNanoseconds() + var currentCPUSamples: [CmuxTopProcessScopeCacheKey: CmuxTopProcessCPUSample] = [:] + var processRecords: [(info: CmuxTopProcessInfo, cpuSampleKey: CmuxTopProcessScopeCacheKey?)] = [] + processRecords.reserveCapacity(sampledProcesses.count) + for process in sampledProcesses { + guard let processRecord = processInfo( + from: process, + includeProcessDetails: includeProcessDetails, + sampledAtNanoseconds: sampledAtNanoseconds, + currentCPUSamples: ¤tCPUSamples + ) else { + continue + } + processRecords.append(processRecord) + } + let cpuPercentages = cpuPercentages( + for: currentCPUSamples, + activeKeys: activeScopeKeys, + parentKeysByKey: parentScopeKeys, + sampledAtNanoseconds: sampledAtNanoseconds + ) + for index in processRecords.indices { + guard let key = processRecords[index].cpuSampleKey, + let cpuPercent = cpuPercentages[key] else { continue } + processRecords[index].info.cpuPercent = cpuPercent + } + pruneCMUXScopeCache(activeKeys: activeScopeKeys) + return processRecords.map(\.info) + } + + guard errno == ENOMEM else { + return [] + } + } + return [] + } + + private static func processInfo( + from kinfo: kinfo_proc, + includeProcessDetails: Bool, + sampledAtNanoseconds: UInt64, + currentCPUSamples: inout [CmuxTopProcessScopeCacheKey: CmuxTopProcessCPUSample] + ) -> (info: CmuxTopProcessInfo, cpuSampleKey: CmuxTopProcessScopeCacheKey?)? { + let pid = Int(kinfo.kp_proc.p_pid) + guard pid > 0 else { return nil } + + let taskInfo = taskInfo(for: pid) + let resourceUsage = resourceUsage(for: pid) + let cacheKey = scopeCacheKey(from: kinfo) + let fallbackName = fixedString(kinfo.kp_proc.p_comm) + let name = includeProcessDetails ? processName(pid: pid, fallback: fallbackName) : fallbackName + let path = includeProcessDetails ? processPath(pid: pid) : nil + let rawTTY = Int64(kinfo.kp_eproc.e_tdev) + let ttyDevice = rawTTY > 0 ? rawTTY : nil + let cmuxScope = cachedCMUXScope(for: pid, cacheKey: cacheKey) + let rawProcessGroupID = Int(kinfo.kp_eproc.e_pgid) + let processGroupID = rawProcessGroupID > 0 ? rawProcessGroupID : nil + let rawTerminalProcessGroupID = Int(kinfo.kp_eproc.e_tpgid) + let terminalProcessGroupID = rawTerminalProcessGroupID > 0 ? rawTerminalProcessGroupID : nil + let memoryBytes: Int64 + let memorySource: CmuxTopProcessMemorySource + if let resourceUsage { + memoryBytes = int64Clamped(resourceUsage.ri_phys_footprint) + memorySource = .physicalFootprint + } else if let taskInfo { + memoryBytes = int64Clamped(taskInfo.pti_resident_size) + memorySource = .residentSize + } else { + memoryBytes = 0 + memorySource = .unavailable + } + let residentBytes: Int64 + let residentMemorySource: CmuxTopProcessMemorySource + if let taskInfo { + residentBytes = int64Clamped(taskInfo.pti_resident_size) + residentMemorySource = .residentSize + } else if let resourceUsage { + residentBytes = int64Clamped(resourceUsage.ri_resident_size) + residentMemorySource = .rusageResidentSize + } else { + residentBytes = 0 + residentMemorySource = .unavailable + } + let cpuSampleKey: CmuxTopProcessScopeCacheKey? + if let taskInfo { + let currentCPUSample = cpuSample(from: taskInfo, sampledAtNanoseconds: sampledAtNanoseconds) + currentCPUSamples[cacheKey] = currentCPUSample + cpuSampleKey = cacheKey + } else { + cpuSampleKey = nil + } + + return (CmuxTopProcessInfo( + pid: pid, + parentPID: Int(kinfo.kp_eproc.e_ppid), + name: name.isEmpty ? "pid-\(pid)" : name, + path: path, + ttyDevice: ttyDevice, + cmuxWorkspaceID: cmuxScope?.workspaceID, + cmuxSurfaceID: cmuxScope?.surfaceID, + cmuxAttributionReason: cmuxScope?.attributionReason, + processGroupID: processGroupID, + terminalProcessGroupID: terminalProcessGroupID, + cpuPercent: 0, + memoryBytes: memoryBytes, + memorySource: memorySource, + residentBytes: residentBytes, + residentMemorySource: residentMemorySource, + virtualBytes: int64Clamped(taskInfo?.pti_virtual_size ?? 0), + threadCount: Int(taskInfo?.pti_threadnum ?? 0) + ), cpuSampleKey) + } + + private static func deviceIdentifier(forTTYName ttyName: String) -> Int64? { + let trimmed = ttyName.trimmingCharacters(in: .whitespacesAndNewlines) + guard !trimmed.isEmpty, trimmed != "not a tty" else { + return nil + } + + let path: String + if trimmed.hasPrefix("/dev/") { + path = trimmed + } else { + path = "/dev/\(trimmed)" + } + + var statInfo = stat() + guard stat(path, &statInfo) == 0 else { + return nil + } + return Int64(statInfo.st_rdev) + } + + private static func clampedAdd(_ lhs: Int64, _ rhs: Int64) -> Int64 { if rhs > 0, lhs > Int64.max - rhs { return Int64.max } return lhs + rhs } + + private static func taskInfo(for pid: Int) -> proc_taskinfo? { + var info = proc_taskinfo() + let expectedSize = MemoryLayout.stride + let size = proc_pidinfo(pid_t(pid), PROC_PIDTASKINFO, 0, &info, Int32(expectedSize)) + return size == expectedSize ? info : nil + } + + private static func resourceUsage(for pid: Int) -> rusage_info_v2? { + var info = rusage_info_v2() + let result = withUnsafeMutableBytes(of: &info) { rawBuffer -> Int32 in + guard let baseAddress = rawBuffer.baseAddress else { return -1 } + // proc_pid_rusage imports as rusage_info_t *; callers pass the concrete + // rusage struct address cast to that opaque buffer type. + let buffer = baseAddress.assumingMemoryBound(to: rusage_info_t?.self) + return proc_pid_rusage( + pid_t(pid), + RUSAGE_INFO_V2, + buffer + ) + } + return result == 0 ? info : nil + } + + private static func processName(pid: Int, fallback: String) -> String { + var buffer = [CChar](repeating: 0, count: Int(MAXCOMLEN + 1)) + let length = proc_name(pid_t(pid), &buffer, UInt32(buffer.count)) + guard length > 0 else { return fallback } + let name = String(cString: buffer).trimmingCharacters(in: .whitespacesAndNewlines) + return name.isEmpty ? fallback : name + } + + private static func processPath(pid: Int) -> String? { + var buffer = [CChar](repeating: 0, count: cmuxTopPIDPathBufferSize) + let length = proc_pidpath(pid_t(pid), &buffer, UInt32(buffer.count)) + guard length > 0 else { return nil } + let path = String(cString: buffer).trimmingCharacters(in: .whitespacesAndNewlines) + return path.isEmpty ? nil : path + } + + private static func fixedString(_ value: T) -> String { + withUnsafeBytes(of: value) { rawBuffer in + let endIndex = rawBuffer.firstIndex(of: 0) ?? rawBuffer.endIndex + return String(decoding: rawBuffer[.. Int64 { + value > UInt64(Int64.max) ? Int64.max : Int64(value) + } } diff --git a/Sources/CmuxTopSnapshotScopeCache.swift b/Sources/CmuxTopSnapshotScopeCache.swift index 628b6f1d5e81..67832eaa6acb 100644 --- a/Sources/CmuxTopSnapshotScopeCache.swift +++ b/Sources/CmuxTopSnapshotScopeCache.swift @@ -30,14 +30,6 @@ nonisolated extension CmuxTopProcessSnapshot { ) } - static func scopeCacheKey(from bsdInfo: proc_bsdinfo) -> CmuxTopProcessScopeCacheKey { - CmuxTopProcessScopeCacheKey( - pid: Int(bsdInfo.pbi_pid), - startSeconds: Int(bsdInfo.pbi_start_tvsec), - startMicroseconds: Int(bsdInfo.pbi_start_tvusec) - ) - } - static func cachedCMUXScope( for pid: Int, cacheKey: CmuxTopProcessScopeCacheKey diff --git a/Sources/CommandPalette/CommandPaletteSettingsToggle.swift b/Sources/CommandPalette/CommandPaletteSettingsToggle.swift index 8905a83d020d..c30733d73af5 100644 --- a/Sources/CommandPalette/CommandPaletteSettingsToggle.swift +++ b/Sources/CommandPalette/CommandPaletteSettingsToggle.swift @@ -461,18 +461,6 @@ enum CommandPaletteSettingsToggleCommands { defaultsKey: SidebarWorkspaceDetailDefaults.showPullRequestsKey, isAvailable: sidebarDetailsAvailable ), - CommandPaletteSettingToggleDescriptor( - commandId: commandIdPrefix + "watchGitStatusInSidebar", - settingsKey: "sidebar.watchGitStatus", - title: { - String(localized: "settings.app.watchGitStatus", defaultValue: "Watch Git Status in Sidebar") - }, - sectionTitle: sidebar, - keywords: ["sidebar.watchGitStatus", "sidebar", "git", "status", "branch", "watcher", "index", "lock"], - defaultValue: SidebarWorkspaceDetailDefaults.watchGitStatus, - defaultsKey: SidebarWorkspaceDetailDefaults.watchGitStatusKey, - isAvailable: sidebarDetailsAvailable - ), CommandPaletteSettingToggleDescriptor( commandId: commandIdPrefix + "makeSidebarPullRequestsClickable", settingsKey: "sidebar.makePullRequestsClickable", @@ -603,29 +591,6 @@ enum CommandPaletteSettingsToggleCommands { defaultValue: ClaudeCodeIntegrationSettings.defaultHooksEnabled, defaultsKey: ClaudeCodeIntegrationSettings.hooksEnabledKey ), - CommandPaletteSettingToggleDescriptor( - commandId: commandIdPrefix + "suppressSubagentNotifications", - settingsKey: "automation.suppressSubagentNotifications", - title: { - String( - localized: "settings.automation.suppressSubagentNotifications", - defaultValue: "Suppress Subagent Notifications" - ) - }, - sectionTitle: automation, - keywords: [ - "automation.suppressSubagentNotifications", - "subagent", - "nested", - "agent", - "codex", - "claude", - "notifications", - "hooks", - ], - defaultValue: AgentSubagentNotificationSettings.defaultSuppressNotifications, - defaultsKey: AgentSubagentNotificationSettings.suppressNotificationsKey - ), CommandPaletteSettingToggleDescriptor( commandId: commandIdPrefix + "cursorIntegration", settingsKey: "automation.cursorIntegration", diff --git a/Sources/ContentView+RightSidebarCommandPalette.swift b/Sources/ContentView+RightSidebarCommandPalette.swift index 8876c7e4c6b3..c24ec3b6d1e6 100644 --- a/Sources/ContentView+RightSidebarCommandPalette.swift +++ b/Sources/ContentView+RightSidebarCommandPalette.swift @@ -71,6 +71,8 @@ extension ContentView { return .hideFind case "palette.terminalUseSelectionForFind": return .useSelectionForFind + case "palette.toggleTerminalTimestamps": + return .toggleTerminalTimestamps case "palette.toggleSplitZoom": return .toggleSplitZoom case "palette.equalizeSplits": diff --git a/Sources/ContentView.swift b/Sources/ContentView.swift index e7e58e8dc44f..1dff42343665 100644 --- a/Sources/ContentView.swift +++ b/Sources/ContentView.swift @@ -1985,7 +1985,6 @@ struct ContentView: View { debugSource: "titlebar.hiddenNewWorkspace" ) }, - observedWindow: observedWindow, selection: $sidebarSelectionState.selection, selectedTabIds: $selectedTabIds, lastSidebarSelectionIndex: $lastSidebarSelectionIndex @@ -2138,7 +2137,6 @@ struct ContentView: View { ZStack(alignment: alignment) { sidebarBackdropLayer(width: width, role: role, appearance: appearance) content() - .environment(\.colorScheme, appearance.sidebarContentColorScheme) } .frame(width: width) } @@ -2608,7 +2606,6 @@ struct ContentView: View { .overlay(alignment: .topLeading) { if isFullScreen && sidebarState.isVisible && !isMinimalMode { fullscreenControls - .environment(\.colorScheme, appearance.sidebarContentColorScheme) .padding(.leading, 10) .padding(.top, 4) } @@ -3198,10 +3195,12 @@ struct ContentView: View { window.isRestorable = false setMinimalModeSidebarTitlebarControlsAvailable(sidebarState.isVisible, in: window) window.titlebarAppearsTransparent = true - // Native AppKit titlebar dragging steals pane-tab drags in minimal - // mode. Keep the main window immovable by default; explicit chrome - // drag zones temporarily enable performDrag for real app moves. - configureCmuxMainWindowDragBehavior(window) + // Keep background dragging disabled so app content gestures and + // minimal-mode titlebar controls still receive clicks, while the + // window itself stays movable for macOS tiling and third-party + // window managers. + window.isMovableByWindowBackground = false + window.isMovable = true window.styleMask.insert(.fullSizeContentView) // Track this window for fullscreen notifications @@ -5700,11 +5699,7 @@ struct ContentView: View { // without being blocked by the palette-visibility guard. DispatchQueue.main.async { _ = AppDelegate.shared?.focusMainWindow(windowId: windowId) - tabManager.focusTab( - workspaceId, - suppressFlash: true, - dismissRestoredUnreadOnResume: true - ) + tabManager.focusTab(workspaceId, suppressFlash: true) } } @@ -5716,12 +5711,7 @@ struct ContentView: View { ) { DispatchQueue.main.async { _ = AppDelegate.shared?.focusMainWindow(windowId: windowId) - tabManager.focusTab( - workspaceId, - surfaceId: panelId, - suppressFlash: true, - dismissRestoredUnreadOnResume: true - ) + tabManager.focusTab(workspaceId, surfaceId: panelId, suppressFlash: true) } } @@ -6195,6 +6185,8 @@ struct ContentView: View { return "⌥⌘⇧F" case "palette.terminalUseSelectionForFind": return "⌘E" + case "palette.toggleTerminalTimestamps": + return "⌥⌘⇧E" case "palette.toggleFullScreen": return "\u{2303}\u{2318}F" default: @@ -7126,6 +7118,16 @@ struct ContentView: View { when: { $0.bool(CommandPaletteContextKeys.panelIsTerminal) } ) ) + contributions.append( + CommandPaletteCommandContribution( + commandId: "palette.toggleTerminalTimestamps", + title: constant(String(localized: "command.terminalToggleTimestamps.title", defaultValue: "Toggle Terminal Timestamps")), + subtitle: terminalPanelSubtitle, + shortcutHint: "⌥⌘⇧E", + keywords: ["terminal", "timestamps", "time", "output"], + when: { $0.bool(CommandPaletteContextKeys.panelIsTerminal) } + ) + ) contributions.append( CommandPaletteCommandContribution( commandId: "palette.terminalSplitRight", @@ -7770,6 +7772,9 @@ struct ContentView: View { registry.register(commandId: "palette.terminalUseSelectionForFind") { tabManager.searchSelection() } + registry.register(commandId: "palette.toggleTerminalTimestamps") { + _ = TerminalTimestampsSettings.toggle() + } registry.register(commandId: "palette.terminalSplitRight") { if !executeConfiguredAction(id: CmuxSurfaceTabBarBuiltInAction.splitRight.configID) { tabManager.createSplit(direction: .right) @@ -8688,12 +8693,7 @@ struct ContentView: View { if let window = observedWindow, !window.isKeyWindow { window.makeKeyAndOrderFront(nil) } - tabManager.focusTab( - target.workspaceId, - surfaceId: target.panelId, - suppressFlash: true, - dismissRestoredUnreadOnResume: true - ) + tabManager.focusTab(target.workspaceId, surfaceId: target.panelId, suppressFlash: true) guard let context = focusedPanelContext, context.workspace.id == target.workspaceId, @@ -9402,7 +9402,6 @@ struct VerticalTabsSidebar: View { let onSendFeedback: () -> Void let onToggleSidebar: () -> Void let onNewTab: () -> Void - let observedWindow: NSWindow? @EnvironmentObject var tabManager: TabManager @EnvironmentObject var notificationStore: TerminalNotificationStore @Binding var selection: SidebarSelection @@ -9441,13 +9440,6 @@ struct VerticalTabsSidebar: View { WorkspacePresentationModeSettings.mode(for: workspacePresentationMode) == .minimal } - private var minimalModeSidebarTitlebarControlsTopPadding: CGFloat { - guard let observedWindow else { - return MinimalModeSidebarTitlebarControlsMetrics.topInset - } - return minimalModeSidebarTitlebarControlsTopInset(in: observedWindow) - } - private var showsSidebarNotificationMessage: Bool { tabItemSettingsStore.snapshot.showsNotificationMessage } @@ -9718,7 +9710,7 @@ struct VerticalTabsSidebar: View { ) .padding( .top, - minimalModeSidebarTitlebarControlsTopPadding + MinimalModeTitlebarDebugSettings.leftControlsTopInset() ) } } @@ -12445,20 +12437,6 @@ private struct TabItemView: View, Equatable { settings.notificationBadgeColorHex } - private var selectedWorkspaceBackgroundNSColor: NSColor { - sidebarSelectedWorkspaceBackgroundNSColor( - for: colorScheme, - sidebarSelectionColorHex: sidebarSelectionColorHex - ) - } - - private func selectedWorkspaceForegroundNSColor(opacity: CGFloat) -> NSColor { - sidebarSelectedWorkspaceForegroundNSColor( - on: selectedWorkspaceBackgroundNSColor, - opacity: opacity - ) - } - private var openSidebarPullRequestLinksInCmuxBrowser: Bool { settings.openPullRequestLinksInCmuxBrowser } @@ -12500,13 +12478,13 @@ private struct TabItemView: View, Equatable { private var activePrimaryTextColor: Color { usesInvertedActiveForeground - ? Color(nsColor: selectedWorkspaceForegroundNSColor(opacity: 1.0)) + ? Color(nsColor: sidebarSelectedWorkspaceForegroundNSColor(opacity: 1.0)) : .primary } private func activeSecondaryColor(_ opacity: Double = 0.75) -> Color { usesInvertedActiveForeground - ? Color(nsColor: selectedWorkspaceForegroundNSColor(opacity: CGFloat(opacity))) + ? Color(nsColor: sidebarSelectedWorkspaceForegroundNSColor(opacity: CGFloat(opacity))) : .secondary } @@ -12514,19 +12492,15 @@ private struct TabItemView: View, Equatable { if let hex = sidebarNotificationBadgeColorHex, let nsColor = NSColor(hex: hex) { return Color(nsColor: nsColor) } - return usesInvertedActiveForeground ? activePrimaryTextColor.opacity(0.25) : cmuxAccentColor() - } - - private var activeUnreadBadgeTextColor: Color { - usesInvertedActiveForeground ? activePrimaryTextColor : .white + return usesInvertedActiveForeground ? Color.white.opacity(0.25) : cmuxAccentColor() } private var activeProgressTrackColor: Color { - usesInvertedActiveForeground ? activeSecondaryColor(0.15) : Color.secondary.opacity(0.2) + usesInvertedActiveForeground ? Color.white.opacity(0.15) : Color.secondary.opacity(0.2) } private var activeProgressFillColor: Color { - usesInvertedActiveForeground ? activeSecondaryColor(0.8) : cmuxAccentColor() + usesInvertedActiveForeground ? Color.white.opacity(0.8) : cmuxAccentColor() } private var shortcutHintEmphasis: Double { @@ -12674,7 +12648,7 @@ private struct TabItemView: View, Equatable { .fill(activeUnreadBadgeFillColor) Text("\(unreadCount)") .font(.system(size: 9, weight: .semibold)) - .foregroundColor(activeUnreadBadgeTextColor) + .foregroundColor(.white) } .frame(width: 16, height: 16) } @@ -12698,8 +12672,7 @@ private struct TabItemView: View, Equatable { if let description = workspaceSnapshot.customDescription { SidebarWorkspaceDescriptionText( markdown: description, - isActive: usesInvertedActiveForeground, - activeForegroundColor: activeSecondaryColor(0.84) + isActive: usesInvertedActiveForeground ) .id(description) } @@ -12722,8 +12695,6 @@ private struct TabItemView: View, Equatable { SidebarMetadataRows( entries: metadataEntries, isActive: usesInvertedActiveForeground, - activeForegroundColor: activeSecondaryColor(0.95), - activeSecondaryForegroundColor: activeSecondaryColor(0.65), onFocus: { updateSelection() } ) .transition(.opacity.combined(with: .move(edge: .top))) @@ -12732,8 +12703,6 @@ private struct TabItemView: View, Equatable { SidebarMetadataMarkdownBlocks( blocks: metadataBlocks, isActive: usesInvertedActiveForeground, - activeForegroundColor: activeSecondaryColor(0.8), - activeSecondaryForegroundColor: activeSecondaryColor(0.65), onFocus: { updateSelection() } ) .transition(.opacity.combined(with: .move(edge: .top))) @@ -12849,7 +12818,6 @@ private struct TabItemView: View, Equatable { if settings.makesPullRequestsClickable { Button(action: { openPullRequestLink(pullRequest.url) }) { rowContent } .buttonStyle(.plain) - .tint(pullRequestForegroundColor) .safeHelp(String(localized: "sidebar.pullRequest.openTooltip", defaultValue: "Open \(pullRequestTitle)")) .accessibilityIdentifier("SidebarPullRequestRow") } else { @@ -13814,7 +13782,7 @@ private struct TabItemView: View, Equatable { } private var pullRequestForegroundColor: Color { - isActive ? activeSecondaryColor(0.75) : .secondary + isActive ? .white.opacity(0.75) : .secondary } private func openPullRequestLink(_ url: URL) { @@ -13872,15 +13840,15 @@ private struct TabItemView: View, Equatable { if isActive { switch level { case .info: - return activeSecondaryColor(0.5) + return Color(nsColor: sidebarSelectedWorkspaceForegroundNSColor(opacity: 0.5)) case .progress: - return activeSecondaryColor(0.8) + return Color(nsColor: sidebarSelectedWorkspaceForegroundNSColor(opacity: 0.8)) case .success: - return activeSecondaryColor(0.9) + return Color(nsColor: sidebarSelectedWorkspaceForegroundNSColor(opacity: 0.9)) case .warning: - return activeSecondaryColor(0.9) + return Color(nsColor: sidebarSelectedWorkspaceForegroundNSColor(opacity: 0.9)) case .error: - return activeSecondaryColor(0.9) + return Color(nsColor: sidebarSelectedWorkspaceForegroundNSColor(opacity: 0.9)) } } switch level { @@ -14089,7 +14057,6 @@ private struct TabItemView: View, Equatable { private struct SidebarWorkspaceDescriptionText: View { let markdown: String let isActive: Bool - let activeForegroundColor: Color var body: some View { let renderedMarkdown = SidebarMarkdownRenderer.renderWorkspaceDescription(markdown) @@ -14136,7 +14103,7 @@ private struct SidebarWorkspaceDescriptionText: View { } private var foregroundColor: Color { - isActive ? activeForegroundColor : .secondary.opacity(0.95) + isActive ? .white.opacity(0.84) : .secondary.opacity(0.95) } private func accessibilityText(renderedMarkdown: AttributedString?) -> String { @@ -14159,8 +14126,6 @@ enum SidebarMarkdownRenderer { private struct SidebarMetadataRows: View { let entries: [SidebarStatusEntry] let isActive: Bool - let activeForegroundColor: Color - let activeSecondaryForegroundColor: Color let onFocus: () -> Void @State private var isExpanded: Bool = false @@ -14169,12 +14134,7 @@ private struct SidebarMetadataRows: View { var body: some View { VStack(alignment: .leading, spacing: 2) { ForEach(visibleEntries, id: \.key) { entry in - SidebarMetadataEntryRow( - entry: entry, - isActive: isActive, - activeForegroundColor: activeForegroundColor, - onFocus: onFocus - ) + SidebarMetadataEntryRow(entry: entry, isActive: isActive, onFocus: onFocus) } if shouldShowToggle { @@ -14186,13 +14146,17 @@ private struct SidebarMetadataRows: View { } .buttonStyle(.plain) .font(.system(size: 10, weight: .semibold)) - .foregroundColor(isActive ? activeSecondaryForegroundColor : .secondary.opacity(0.9)) + .foregroundColor(isActive ? activeSecondaryTextColor : .secondary.opacity(0.9)) .frame(maxWidth: .infinity, alignment: .leading) } } .safeHelp(helpText) } + private var activeSecondaryTextColor: Color { + Color(nsColor: sidebarSelectedWorkspaceForegroundNSColor(opacity: 0.65)) + } + private var visibleEntries: [SidebarStatusEntry] { guard !isExpanded, entries.count > collapsedEntryLimit else { return entries } return Array(entries.prefix(collapsedEntryLimit)) @@ -14214,7 +14178,6 @@ private struct SidebarMetadataRows: View { private struct SidebarMetadataEntryRow: View { let entry: SidebarStatusEntry let isActive: Bool - let activeForegroundColor: Color let onFocus: () -> Void var body: some View { @@ -14256,12 +14219,12 @@ private struct SidebarMetadataEntryRow: View { if isActive, let raw = entry.color, Color(hex: raw) != nil { - return activeForegroundColor + return Color(nsColor: sidebarSelectedWorkspaceForegroundNSColor(opacity: 0.95)) } if let raw = entry.color, let explicit = Color(hex: raw) { return explicit } - return isActive ? activeForegroundColor.opacity(0.84) : .secondary + return isActive ? .white.opacity(0.8) : .secondary } private var iconView: AnyView? { @@ -14312,8 +14275,6 @@ private struct SidebarMetadataEntryRow: View { private struct SidebarMetadataMarkdownBlocks: View { let blocks: [SidebarMetadataBlock] let isActive: Bool - let activeForegroundColor: Color - let activeSecondaryForegroundColor: Color let onFocus: () -> Void @State private var isExpanded: Bool = false @@ -14325,7 +14286,6 @@ private struct SidebarMetadataMarkdownBlocks: View { SidebarMetadataMarkdownBlockRow( block: block, isActive: isActive, - activeForegroundColor: activeForegroundColor, onFocus: onFocus ) } @@ -14339,7 +14299,7 @@ private struct SidebarMetadataMarkdownBlocks: View { } .buttonStyle(.plain) .font(.system(size: 10, weight: .semibold)) - .foregroundColor(isActive ? activeSecondaryForegroundColor : .secondary.opacity(0.9)) + .foregroundColor(isActive ? .white.opacity(0.65) : .secondary.opacity(0.9)) .frame(maxWidth: .infinity, alignment: .leading) } } @@ -14358,7 +14318,6 @@ private struct SidebarMetadataMarkdownBlocks: View { private struct SidebarMetadataMarkdownBlockRow: View { let block: SidebarMetadataBlock let isActive: Bool - let activeForegroundColor: Color let onFocus: () -> Void @State private var renderedMarkdown: AttributedString? @@ -14385,7 +14344,7 @@ private struct SidebarMetadataMarkdownBlockRow: View { } private var foregroundColor: Color { - isActive ? activeForegroundColor : .secondary + isActive ? .white.opacity(0.8) : .secondary } private func renderMarkdown() { @@ -15157,11 +15116,7 @@ private struct WindowBackdropLayer: View { } } case .clear: - if let sidebarOverlay = snapshot.sidebarContrastOverlayColor(for: role) { - Color(nsColor: sidebarOverlay) - } else { - Color.clear - } + Color.clear } } } diff --git a/Sources/FileExplorerStore.swift b/Sources/FileExplorerStore.swift index c0eefda57038..5909d8c44be1 100644 --- a/Sources/FileExplorerStore.swift +++ b/Sources/FileExplorerStore.swift @@ -437,7 +437,6 @@ final class ProcessSSHFileExplorerTransport: SSHFileExplorerTransport { private let outPipe = Pipe() private let errPipe = Pipe() private let lock = NSLock() - private let terminationGate = ProcessTerminationGate() private var cancelled = false init(connection: SSHFileExplorerConnection, command: String) { @@ -455,35 +454,18 @@ final class ProcessSSHFileExplorerTransport: SSHFileExplorerTransport { throw CancellationError() } - do { - try process.run() - } catch { - terminationGate.markFinished() - throw error - } + try process.run() lock.lock() - let shouldTerminate = cancelled + let shouldTerminate = cancelled && process.isRunning lock.unlock() - if terminationGate.markLaunched() || shouldTerminate { - guard process.isRunning else { - process.waitUntilExit() - terminationGate.markFinished() - throw CancellationError() - } + if shouldTerminate { process.terminate() } let data = outPipe.fileHandleForReading.readDataToEndOfFile() let stderrData = errPipe.fileHandleForReading.readDataToEndOfFile() process.waitUntilExit() - terminationGate.markFinished() - lock.lock() - let cancelledAfterExit = cancelled - lock.unlock() - if cancelledAfterExit { - throw CancellationError() - } return SSHCommandResult( stdout: String(data: data, encoding: .utf8) ?? "", @@ -495,15 +477,12 @@ final class ProcessSSHFileExplorerTransport: SSHFileExplorerTransport { func terminate() { lock.lock() cancelled = true + let isRunning = process.isRunning lock.unlock() - guard terminationGate.requestTermination() else { - return - } - guard process.isRunning else { - return + if isRunning { + process.terminate() } - process.terminate() } } diff --git a/Sources/GhosttyApp+SurfaceConfigurationReload.swift b/Sources/GhosttyApp+SurfaceConfigurationReload.swift index 60c01d1367c4..740fff57be54 100644 --- a/Sources/GhosttyApp+SurfaceConfigurationReload.swift +++ b/Sources/GhosttyApp+SurfaceConfigurationReload.swift @@ -12,7 +12,7 @@ extension GhosttyApp { } guard let newConfig = ghostty_config_new() else { return } - let reloadColorScheme = preferredColorScheme ?? effectiveTerminalColorSchemePreference + let reloadColorScheme = preferredColorScheme ?? GhosttyConfig.currentColorSchemePreference() _ = loadDefaultConfigFilesWithLegacyFallback( newConfig, preferredColorScheme: reloadColorScheme diff --git a/Sources/GhosttyConfig.swift b/Sources/GhosttyConfig.swift index b6215dbdad6c..93380595922b 100644 --- a/Sources/GhosttyConfig.swift +++ b/Sources/GhosttyConfig.swift @@ -579,39 +579,6 @@ struct GhosttyConfig { return rawThemeValue.trimmingCharacters(in: .whitespacesAndNewlines) } - static func themeValueUsesSameResolvedThemeInBothColorSchemes(_ rawThemeValue: String) -> Bool { - let lightTheme = resolveThemeName(from: rawThemeValue, preferredColorScheme: .light) - .trimmingCharacters(in: .whitespacesAndNewlines) - let darkTheme = resolveThemeName(from: rawThemeValue, preferredColorScheme: .dark) - .trimmingCharacters(in: .whitespacesAndNewlines) - guard !lightTheme.isEmpty, !darkTheme.isEmpty else { return false } - return lightTheme.caseInsensitiveCompare(darkTheme) == .orderedSame - } - - static func lastThemeDirective(in contents: String) -> String? { - var lastValue: String? - - for line in contents.components(separatedBy: .newlines) { - let trimmed = line.trimmingCharacters(in: .whitespacesAndNewlines) - if trimmed.isEmpty || trimmed.hasPrefix("#") { - continue - } - - let parts = trimmed.split(separator: "=", maxSplits: 1).map(String.init) - guard parts.count == 2 else { continue } - guard parts[0].trimmingCharacters(in: .whitespacesAndNewlines) == "theme" else { continue } - - let value = parts[1] - .trimmingCharacters(in: .whitespacesAndNewlines) - .trimmingCharacters(in: CharacterSet(charactersIn: "\"")) - if !value.isEmpty { - lastValue = value - } - } - - return lastValue - } - static func themeNameCandidates(from rawName: String) -> [String] { var candidates: [String] = [] let compatibilityAliasGroups: [[String]] = [ diff --git a/Sources/GhosttyNSView+IMEComposition.swift b/Sources/GhosttyNSView+IMEComposition.swift index 843139177d23..0f4c60be13af 100644 --- a/Sources/GhosttyNSView+IMEComposition.swift +++ b/Sources/GhosttyNSView+IMEComposition.swift @@ -140,49 +140,6 @@ extension GhosttyNSView { return flags.isEmpty || flags == [.shift] } - /// When `macos-option-as-alt` strips Option for terminal fallback encoding, - /// AppKit still needs the original Option event for dead-key composition - /// (`Option+n` then `a` -> `ã`). Use the original event only for text - /// interpretation; Ghostty fallback continues to use the translated event. - func textInputInterpretationEvent(original event: NSEvent, translated translationEvent: NSEvent) -> NSEvent { - shouldPreserveOriginalOptionDeadKeyEvent( - original: event, - translated: translationEvent - ) ? event : translationEvent - } - - private func shouldPreserveOriginalOptionDeadKeyEvent( - original event: NSEvent, - translated translationEvent: NSEvent - ) -> Bool { - let originalFlags = textInputRelevantFlags(event.modifierFlags) - let translatedFlags = textInputRelevantFlags(translationEvent.modifierFlags) - - guard originalFlags.contains(.option), - !translatedFlags.contains(.option), - !originalFlags.contains(.command), - !originalFlags.contains(.control) else { - return false - } - - guard (event.characters ?? "").isEmpty, - let unmodifiedText = event.charactersIgnoringModifiers, - unmodifiedText.count == 1, - let scalar = unmodifiedText.unicodeScalars.first else { - return false - } - - return scalar.value >= 0x20 - && scalar.value != 0x7F - && !(0xF700...0xF8FF).contains(scalar.value) - } - - private func textInputRelevantFlags(_ flags: NSEvent.ModifierFlags) -> NSEvent.ModifierFlags { - flags - .intersection(.deviceIndependentFlagsMask) - .subtracting([.numericPad, .function, .capsLock]) - } - func shouldBufferBopomofoInsertedPreedit(_ text: String, inputSourceId: String? = nil) -> Bool { guard !text.isEmpty else { return false } guard isBopomofoInputSource(inputSourceId ?? KeyboardLayout.id) else { return false } diff --git a/Sources/GhosttyTerminalAppearance.swift b/Sources/GhosttyTerminalAppearance.swift index c6c8c78e4c7b..a16e00a02a43 100644 --- a/Sources/GhosttyTerminalAppearance.swift +++ b/Sources/GhosttyTerminalAppearance.swift @@ -91,6 +91,8 @@ final class GhosttyDefaultBackgroundNotificationDispatcher { enum GhosttyNotificationKey { static let scrollbar = "ghostty.scrollbar" + static let scrollbarUpdateIntent = "ghostty.scrollbarUpdateIntent" + static let scrollbarWasKeyboardInitiated = "ghostty.scrollbarWasKeyboardInitiated" static let cellSize = "ghostty.cellSize" static let tabId = "ghostty.tabId" static let surfaceId = "ghostty.surfaceId" diff --git a/Sources/GhosttyTerminalView.swift b/Sources/GhosttyTerminalView.swift index 793377d31385..eef88af0457c 100644 --- a/Sources/GhosttyTerminalView.swift +++ b/Sources/GhosttyTerminalView.swift @@ -1363,6 +1363,33 @@ enum TerminalKeyboardCopyModeAction: Equatable { case searchNext case searchPrevious case adjustSelection(TerminalKeyboardCopyModeSelectionMove) + + var shouldTreatScrollbarUpdatesAsKeyboardInitiated: Bool { + scrollbarUpdateIntent.contains(.keyboardInitiated) + } + + var scrollbarUpdateIntent: GhosttyScrollbarUpdateIntent { + switch self { + case .scrollLines, .scrollPage, .scrollHalfPage, .scrollToTop, .scrollToBottom, .jumpToPrompt: + return [.keyboardInitiated, .explicitSync] + case .searchNext, .searchPrevious: + return [.explicitSync] + case .exit, .startSelection, .clearSelection, .copyAndExit, .copyLineAndExit, .startSearch, + .adjustSelection: + return [] + } + } + + var shouldCarryScrollbarUpdateIntentAfterBindingAction: Bool { + shouldTreatScrollbarUpdatesAsKeyboardInitiated + } +} + +struct GhosttyScrollbarUpdateIntent: OptionSet { + let rawValue: Int + + static let keyboardInitiated = GhosttyScrollbarUpdateIntent(rawValue: 1 << 0) + static let explicitSync = GhosttyScrollbarUpdateIntent(rawValue: 1 << 1) } struct TerminalKeyboardCopyModeInputState: Equatable { @@ -1696,10 +1723,6 @@ class GhosttyApp { private(set) var defaultCursorTextColor: NSColor = GhosttyApp.fallbackAppearanceConfig.cursorTextColor private(set) var defaultSelectionBackground: NSColor = GhosttyApp.fallbackAppearanceConfig.selectionBackground private(set) var defaultSelectionForeground: NSColor = GhosttyApp.fallbackAppearanceConfig.selectionForeground - private(set) var effectiveTerminalColorSchemePreference: GhosttyConfig.ColorSchemePreference = .dark - private var appliedGhosttyRuntimeColorScheme: ghostty_color_scheme_e? - private var runtimeColorSchemeSynchronizationDepth = 0 - private var reloadConfigurationDepth = 0 private(set) var usesHostLayerBackground = false private(set) var userGhosttyShellIntegrationMode: String = "detect" private static func resolveBackgroundLogURL( @@ -2170,7 +2193,7 @@ class GhosttyApp { } // Notify observers that a usable config is available (initial load). - synchronizeGhosttyRuntimeColorScheme(effectiveTerminalColorSchemePreference, source: "initialize") + synchronizeGhosttyRuntimeColorScheme(initialColorScheme, source: "initialize") lastAppearanceColorScheme = initialColorScheme GhosttyConfig.invalidateLoadCache() NotificationCenter.default.post(name: .ghosttyConfigDidReload, object: nil) @@ -3013,22 +3036,6 @@ class GhosttyApp { } } - enum RuntimeColorSchemeSynchronizationDecision: Equatable { - case apply - case skipReentrant - } - - static func runtimeColorSchemeSynchronizationDecision( - applied _: ghostty_color_scheme_e?, - requested _: ghostty_color_scheme_e, - isSynchronizing: Bool - ) -> RuntimeColorSchemeSynchronizationDecision { - if isSynchronizing { - return .skipReentrant - } - return .apply - } - static func appearanceSynchronizationPlan( previousColorScheme: GhosttyConfig.ColorSchemePreference?, currentColorScheme: GhosttyConfig.ColorSchemePreference @@ -3057,27 +3064,6 @@ class GhosttyApp { } } - static func terminalRuntimeColorSchemePreference( - forBackgroundColor backgroundColor: NSColor - ) -> GhosttyConfig.ColorSchemePreference { - cmuxReadableColorScheme(for: backgroundColor) == .light ? .light : .dark - } - - static func runtimeColorSchemeForConfigLoad( - source: String, - requestedColorScheme: GhosttyConfig.ColorSchemePreference, - effectiveTerminalColorScheme: GhosttyConfig.ColorSchemePreference, - cmuxThemeValue: String? - ) -> GhosttyConfig.ColorSchemePreference { - guard GhosttySurfaceConfigurationRefresh.isCmuxThemeReloadSource(source), - let cmuxThemeValue, - GhosttyConfig.themeValueUsesSameResolvedThemeInBothColorSchemes(cmuxThemeValue) else { - return requestedColorScheme - } - - return effectiveTerminalColorScheme - } - static func shouldCaptureScrollLagEvent( samples: Int, averageMs: Double, @@ -3124,33 +3110,7 @@ class GhosttyApp { cmuxDebugLog( "loaded cmux app support ghostty config from: \(urls.map(\.path).joined(separator: ", "))" ) - #endif - #endif - } - - private func currentCmuxAppSupportThemeValue() -> String? { - #if os(macOS) - let fm = FileManager.default - guard let appSupport = fm.urls(for: .applicationSupportDirectory, in: .userDomainMask).first else { - return nil - } - let urls = Self.cmuxAppSupportConfigURLs( - currentBundleIdentifier: Bundle.main.bundleIdentifier, - appSupportDirectory: appSupport, - fileManager: fm - ) - - var lastValue: String? - for url in urls { - guard let contents = try? String(contentsOf: url, encoding: .utf8), - let value = GhosttyConfig.lastThemeDirective(in: contents) else { - continue - } - lastValue = value - } - return lastValue - #else - return nil +#endif #endif } @@ -3222,13 +3182,6 @@ class GhosttyApp { reloadSettingsFromFile: Bool = true, preferredColorScheme: GhosttyConfig.ColorSchemePreference? = nil ) { - guard reloadConfigurationDepth == 0 else { - logThemeAction("reload skipped source=\(source) soft=\(soft) reason=reentrant") - return - } - reloadConfigurationDepth += 1 - defer { reloadConfigurationDepth -= 1 } - if reloadSettingsFromFile { KeyboardShortcutSettings.settingsFileStore.reload() } @@ -3246,29 +3199,14 @@ class GhosttyApp { logThemeAction("reload skipped source=\(source) soft=\(soft) reason=no_app") return } - // Use the appearance preference while loading conditional theme pairs. For cmux - // single-theme reloads, keep the resolved terminal scheme stable until the new - // background is known so same-scheme theme changes do not flash through app mode. - let loadColorScheme = Self.runtimeColorSchemeForConfigLoad( - source: source, - requestedColorScheme: reloadColorScheme, - effectiveTerminalColorScheme: effectiveTerminalColorSchemePreference, - cmuxThemeValue: currentCmuxAppSupportThemeValue() - ) - synchronizeGhosttyRuntimeColorScheme(loadColorScheme, source: "reloadConfiguration:\(source):load") logThemeAction("reload begin source=\(source) soft=\(soft)") resetDefaultBackgroundUpdateScope(source: "reloadConfiguration(source=\(source))") if soft, let config { - let effectiveReloadColorScheme = effectiveTerminalColorSchemePreference - synchronizeGhosttyRuntimeColorScheme(effectiveReloadColorScheme, source: "reloadConfiguration:\(source):resolved") ghostty_app_update_config(app, config) lastAppearanceColorScheme = reloadColorScheme GhosttyConfig.invalidateLoadCache() NotificationCenter.default.post(name: .ghosttyConfigDidReload, object: nil) - scheduleSurfaceRefreshAfterConfigurationReload( - source: source, - preferredColorScheme: effectiveReloadColorScheme - ) + scheduleSurfaceRefreshAfterConfigurationReload(source: source) logThemeAction("reload end source=\(source) soft=\(soft) mode=soft") return } @@ -3281,15 +3219,13 @@ class GhosttyApp { newConfig, preferredColorScheme: reloadColorScheme ) + ghostty_app_update_config(app, newConfig) updateDefaultBackground( from: newConfig, source: "reloadConfiguration(source=\(source))", scope: .unscoped, forceNotify: renderingModeChanged ) - let effectiveReloadColorScheme = effectiveTerminalColorSchemePreference - synchronizeGhosttyRuntimeColorScheme(effectiveReloadColorScheme, source: "reloadConfiguration:\(source):resolved") - ghostty_app_update_config(app, newConfig) DispatchQueue.main.async { self.applyBackgroundToKeyWindow() } @@ -3300,22 +3236,13 @@ class GhosttyApp { lastAppearanceColorScheme = reloadColorScheme GhosttyConfig.invalidateLoadCache() NotificationCenter.default.post(name: .ghosttyConfigDidReload, object: nil) - scheduleSurfaceRefreshAfterConfigurationReload( - source: source, - preferredColorScheme: effectiveReloadColorScheme - ) + scheduleSurfaceRefreshAfterConfigurationReload(source: source) logThemeAction("reload end source=\(source) soft=\(soft) mode=full") } - private func scheduleSurfaceRefreshAfterConfigurationReload( - source: String, - preferredColorScheme: GhosttyConfig.ColorSchemePreference - ) { + private func scheduleSurfaceRefreshAfterConfigurationReload(source: String) { DispatchQueue.main.async { - AppDelegate.shared?.refreshTerminalSurfacesAfterGhosttyConfigReload( - source: source, - preferredColorScheme: preferredColorScheme - ) + AppDelegate.shared?.refreshTerminalSurfacesAfterGhosttyConfigReload(source: source) } } @@ -3373,29 +3300,6 @@ class GhosttyApp { source: String ) { guard let app else { return } - let decision = Self.runtimeColorSchemeSynchronizationDecision( - applied: appliedGhosttyRuntimeColorScheme, - requested: runtimeColorScheme, - isSynchronizing: runtimeColorSchemeSynchronizationDepth > 0 - ) - guard decision == .apply else { - if backgroundLogEnabled { - let schemeLabel = colorScheme == .dark ? "dark" : "light" - let reason: String - switch decision { - case .apply: - reason = "apply" - case .skipReentrant: - reason = "reentrant" - } - logBackground("app color scheme skipped source=\(source) scheme=\(schemeLabel) reason=\(reason)") - } - return - } - - appliedGhosttyRuntimeColorScheme = runtimeColorScheme - runtimeColorSchemeSynchronizationDepth += 1 - defer { runtimeColorSchemeSynchronizationDepth -= 1 } ghostty_app_set_color_scheme(app, runtimeColorScheme) if backgroundLogEnabled { let schemeLabel = colorScheme == .dark ? "dark" : "light" @@ -3403,15 +3307,6 @@ class GhosttyApp { } } - private func shouldProcessGhosttyReloadAction(source: String, soft: Bool) -> Bool { - guard reloadConfigurationDepth == 0, - runtimeColorSchemeSynchronizationDepth == 0 else { - logThemeAction("reload request skipped source=\(source) soft=\(soft) reason=reentrant") - return false - } - return true - } - func openConfigurationInTextEdit() { #if os(macOS) let environment = ConfigSourceEnvironment.live() @@ -3627,13 +3522,9 @@ class GhosttyApp { let previousCursorTextHex = defaultCursorTextColor.hexString() let previousSelectionBackgroundHex = defaultSelectionBackground.hexString() let previousSelectionForegroundHex = defaultSelectionForeground.hexString() - let previousColorScheme = effectiveTerminalColorSchemePreference defaultBackgroundColor = color defaultBackgroundOpacity = opacity defaultBackgroundBlur = backgroundBlur - effectiveTerminalColorSchemePreference = Self.terminalRuntimeColorSchemePreference( - forBackgroundColor: color - ) if let foregroundColor { defaultForegroundColor = foregroundColor } @@ -3657,14 +3548,13 @@ class GhosttyApp { previousCursorHex != defaultCursorColor.hexString() || previousCursorTextHex != defaultCursorTextColor.hexString() || previousSelectionBackgroundHex != defaultSelectionBackground.hexString() || - previousSelectionForegroundHex != defaultSelectionForeground.hexString() || - previousColorScheme != effectiveTerminalColorSchemePreference + previousSelectionForegroundHex != defaultSelectionForeground.hexString() if hasChanged { notifyDefaultBackgroundDidChange(source: source) } if backgroundLogEnabled { logBackground( - "default appearance updated source=\(source) scope=\(scope.logLabel) previousScope=\(previousScope.logLabel) previousScopeSource=\(previousScopeSource) previousBg=\(previousHex) previousFg=\(previousForegroundHex) previousOpacity=\(String(format: "%.3f", previousOpacity)) previousBlur=\(previousBlur) previousScheme=\(previousColorScheme) bg=\(defaultBackgroundColor.hexString()) fg=\(defaultForegroundColor.hexString()) cursor=\(defaultCursorColor.hexString()) cursorText=\(defaultCursorTextColor.hexString()) selectionBg=\(defaultSelectionBackground.hexString()) selectionFg=\(defaultSelectionForeground.hexString()) opacity=\(String(format: "%.3f", defaultBackgroundOpacity)) blur=\(defaultBackgroundBlur) scheme=\(effectiveTerminalColorSchemePreference) changed=\(hasChanged) forced=\(forceNotify)" + "default appearance updated source=\(source) scope=\(scope.logLabel) previousScope=\(previousScope.logLabel) previousScopeSource=\(previousScopeSource) previousBg=\(previousHex) previousFg=\(previousForegroundHex) previousOpacity=\(String(format: "%.3f", previousOpacity)) previousBlur=\(previousBlur) bg=\(defaultBackgroundColor.hexString()) fg=\(defaultForegroundColor.hexString()) cursor=\(defaultCursorColor.hexString()) cursorText=\(defaultCursorTextColor.hexString()) selectionBg=\(defaultSelectionBackground.hexString()) selectionFg=\(defaultSelectionForeground.hexString()) opacity=\(String(format: "%.3f", defaultBackgroundOpacity)) blur=\(defaultBackgroundBlur) changed=\(hasChanged) forced=\(forceNotify)" ) } } @@ -3989,12 +3879,6 @@ class GhosttyApp { let soft = action.action.reload_config.soft logThemeAction("reload request target=app soft=\(soft)") performOnMain { - guard self.shouldProcessGhosttyReloadAction( - source: "action.reload_config.app", - soft: soft - ) else { - return - } self.reloadConfiguration(soft: soft, source: "action.reload_config.app") } return true @@ -4013,10 +3897,6 @@ class GhosttyApp { source: "action.config_change.app", scope: .app ) - synchronizeGhosttyRuntimeColorScheme( - effectiveTerminalColorSchemePreference, - source: "action.config_change.app:resolved" - ) DispatchQueue.main.async { self.applyBackgroundToKeyWindow() } @@ -4141,7 +4021,7 @@ class GhosttyApp { } case GHOSTTY_ACTION_SCROLLBAR: let scrollbar = GhosttyScrollbar(c: action.action.scrollbar) - surfaceView.enqueueScrollbarUpdate(scrollbar) + surfaceView.enqueueScrollbarActionUpdate(scrollbar) return true case GHOSTTY_ACTION_CELL_SIZE: let cellSize = CGSize( @@ -4289,17 +4169,6 @@ class GhosttyApp { source: "action.config_change.surface tab=\(surfaceView.tabId?.uuidString ?? "nil") surface=\(surfaceView.terminalSurface?.id.uuidString ?? "nil")", scope: .surface ) - let effectiveConfigChangeColorScheme = effectiveTerminalColorSchemePreference - synchronizeGhosttyRuntimeColorScheme( - effectiveConfigChangeColorScheme, - source: "action.config_change.surface:resolved" - ) - DispatchQueue.main.async { - surfaceView.applySurfaceColorScheme( - force: true, - preferredColorScheme: effectiveConfigChangeColorScheme - ) - } if backgroundLogEnabled { logBackground( "surface config change deferred terminal bg apply tab=\(surfaceView.tabId?.uuidString ?? "nil") surface=\(surfaceView.terminalSurface?.id.uuidString ?? "nil") override=\(surfaceView.backgroundColor?.hexString() ?? "nil") default=\(defaultBackgroundColor.hexString())" @@ -4308,24 +4177,11 @@ class GhosttyApp { return true case GHOSTTY_ACTION_RELOAD_CONFIG: let soft = action.action.reload_config.soft - let source = "action.reload_config.surface tab=\(surfaceView.tabId?.uuidString ?? "nil") surface=\(surfaceView.terminalSurface?.id.uuidString ?? "nil")" logThemeAction( "reload request target=surface tab=\(surfaceView.tabId?.uuidString ?? "nil") surface=\(surfaceView.terminalSurface?.id.uuidString ?? "nil") soft=\(soft)" ) return performOnMain { - guard self.shouldProcessGhosttyReloadAction(source: source, soft: soft) else { - return true - } - let preferredColorScheme = self.effectiveTerminalColorSchemePreference - surfaceView.terminalSurface?.hostedView.reapplySurfaceColorSchemeAfterGhosttyConfigReload( - preferredColorScheme: preferredColorScheme - ) - self.reloadSurfaceConfiguration( - target.target.surface, - soft: soft, - source: source, - preferredColorScheme: preferredColorScheme - ) + self.reloadSurfaceConfiguration(target.target.surface, soft: soft, source: "action.reload_config.surface tab=\(surfaceView.tabId?.uuidString ?? "nil") surface=\(surfaceView.terminalSurface?.id.uuidString ?? "nil")") surfaceView.terminalSurface?.hostedView.refreshHostBackgroundAfterGhosttyConfigReload() surfaceView.terminalSurface?.forceRefresh(reason: "surface.reloadConfig") return true @@ -4919,11 +4775,6 @@ final class TerminalSurface: Identifiable, ObservableObject { private(set) var lastSearchNeedle = "" private var searchNeedleCancellable: AnyCancellable? var currentKeyStateIndicatorText: String? { surfaceView.currentKeyStateIndicatorText } - - func startupEnvironmentValue(_ key: String) -> String? { - additionalEnvironment[key] ?? initialEnvironmentOverrides[key] - } - init( tabId: UUID, context: ghostty_surface_context_e, @@ -5710,10 +5561,6 @@ final class TerminalSurface: Identifiable, ObservableObject { if let customClaudePath = ClaudeCodeIntegrationSettings.customClaudePath() { setManagedEnvironmentValue("CMUX_CUSTOM_CLAUDE_PATH", customClaudePath) } - setManagedEnvironmentValue( - AgentSubagentNotificationSettings.environmentKey, - AgentSubagentNotificationSettings.suppressNotifications() ? "1" : "0" - ) if !CursorIntegrationSettings.hooksEnabled() { setManagedEnvironmentValue("CMUX_CURSOR_HOOKS_DISABLED", "1") } @@ -5738,11 +5585,6 @@ final class TerminalSurface: Identifiable, ObservableObject { let integrationDir = Bundle.main.resourceURL?.appendingPathComponent("shell-integration").path { setManagedEnvironmentValue("CMUX_SHELL_INTEGRATION", "1") setManagedEnvironmentValue("CMUX_SHELL_INTEGRATION_DIR", integrationDir) - Self.applyManagedGitWatchEnvironment( - watchGitStatusEnabled: SidebarWorkspaceDetailDefaults.watchGitStatusValue(defaults: .standard), - to: &env, - protectedKeys: &protectedStartupEnvironmentKeys - ) let shell = (env["SHELL"]?.isEmpty == false ? env["SHELL"] : nil) ?? getenv("SHELL").map { String(cString: $0) } @@ -6800,7 +6642,10 @@ class GhosttyNSView: NSView, NSUserInterfaceValidations { /// Access is guarded by `_scrollbarLock` because the action callback /// fires on Ghostty's I/O thread while the flush runs on main. private var _pendingScrollbar: GhosttyScrollbar? + private var _pendingScrollbarIntent: GhosttyScrollbarUpdateIntent = [] private var _scrollbarFlushScheduled = false + private var _pendingScrollbarActionIntent: GhosttyScrollbarUpdateIntent = [] + private var _scrollbarActionIntentStack: [GhosttyScrollbarUpdateIntent] = [] private let _scrollbarLock = NSLock() var cellSize: CGSize = .zero private var lastKnownMousePointInView: NSPoint? @@ -6809,11 +6654,12 @@ class GhosttyNSView: NSView, NSUserInterfaceValidations { /// dispatch. The action callback (which may fire thousands of times per /// second during bulk output like `seq 1 100000`) stores the latest value /// and schedules exactly one async flush. - func enqueueScrollbarUpdate(_ newValue: GhosttyScrollbar) { + func enqueueScrollbarUpdate(_ newValue: GhosttyScrollbar, intent: GhosttyScrollbarUpdateIntent = []) { _scrollbarLock.lock() defer { _scrollbarLock.unlock() } // Store the latest value (always overwrites — only the newest matters). _pendingScrollbar = newValue + _pendingScrollbarIntent.formUnion(intent) let needsSchedule = !_scrollbarFlushScheduled if needsSchedule { _scrollbarFlushScheduled = true } @@ -6825,11 +6671,24 @@ class GhosttyNSView: NSView, NSUserInterfaceValidations { } } + func enqueueScrollbarUpdate(_ newValue: GhosttyScrollbar, wasKeyboardInitiated: Bool) { + enqueueScrollbarUpdate( + newValue, + intent: wasKeyboardInitiated ? [.keyboardInitiated, .explicitSync] : [] + ) + } + + func enqueueScrollbarActionUpdate(_ newValue: GhosttyScrollbar) { + enqueueScrollbarUpdate(newValue, intent: consumeScrollbarActionIntent()) + } + private func flushPendingScrollbar() { _scrollbarLock.lock() _scrollbarFlushScheduled = false let pending = _pendingScrollbar + let pendingIntent = _pendingScrollbarIntent _pendingScrollbar = nil + _pendingScrollbarIntent = [] _scrollbarLock.unlock() guard let pending else { return } @@ -6837,10 +6696,74 @@ class GhosttyNSView: NSView, NSUserInterfaceValidations { NotificationCenter.default.post( name: .ghosttyDidUpdateScrollbar, object: self, - userInfo: [GhosttyNotificationKey.scrollbar: pending] + userInfo: [ + GhosttyNotificationKey.scrollbar: pending, + GhosttyNotificationKey.scrollbarUpdateIntent: pendingIntent, + GhosttyNotificationKey.scrollbarWasKeyboardInitiated: + pendingIntent.contains(.keyboardInitiated), + ] ) } + private func beginScrollbarActionIntent( + _ intent: GhosttyScrollbarUpdateIntent, + carryAcrossAction: Bool + ) { + _scrollbarLock.lock() + _scrollbarActionIntentStack.append(intent) + if carryAcrossAction { + _pendingScrollbarActionIntent.formUnion(intent) + } + _scrollbarLock.unlock() + } + + private func endScrollbarActionIntent() { + _scrollbarLock.lock() + if !_scrollbarActionIntentStack.isEmpty { + _ = _scrollbarActionIntentStack.removeLast() + } + _scrollbarLock.unlock() + } + + private func beginKeyboardInitiatedScrollAction() { + beginScrollbarActionIntent([.keyboardInitiated, .explicitSync], carryAcrossAction: true) + } + + private func endKeyboardInitiatedScrollAction() { + endScrollbarActionIntent() + } + + func consumeScrollbarActionIntent() -> GhosttyScrollbarUpdateIntent { + _scrollbarLock.lock() + defer { _scrollbarLock.unlock() } + var intent = _pendingScrollbarActionIntent + for activeIntent in _scrollbarActionIntentStack { + intent.formUnion(activeIntent) + } + if !intent.isEmpty { + _pendingScrollbarActionIntent = [] + } + return intent + } + + private func withScrollbarActionIntent( + _ intent: GhosttyScrollbarUpdateIntent, + carryAcrossAction: Bool, + _ body: () -> T + ) -> T { + beginScrollbarActionIntent(intent, carryAcrossAction: carryAcrossAction) + defer { endScrollbarActionIntent() } + return body() + } + +#if DEBUG + func debugEnqueueScrollbarUpdateAfterKeyboardScrollIntent(_ newValue: GhosttyScrollbar) { + beginScrollbarActionIntent([.keyboardInitiated, .explicitSync], carryAcrossAction: true) + endScrollbarActionIntent() + enqueueScrollbarActionUpdate(newValue) + } +#endif + var desiredFocus: Bool = false var suppressingReparentFocus: Bool = false var tabId: UUID? @@ -6919,13 +6842,13 @@ class GhosttyNSView: NSView, NSUserInterfaceValidations { return true } - // Visibility is used for focus gating. Explicit portal visibility transitions - // also drive Ghostty occlusion so hidden workspace/split surfaces pause and - // queue a redraw when they become visible again. - fileprivate var isVisibleInUI: Bool { visibleInUI } - fileprivate func setVisibleInUI(_ visible: Bool) { - visibleInUI = visible - } + // Visibility is used for focus gating. Explicit portal visibility transitions + // also drive Ghostty occlusion so hidden workspace/split surfaces pause and + // queue a redraw when they become visible again. + fileprivate var isVisibleInUI: Bool { visibleInUI } + fileprivate func setVisibleInUI(_ visible: Bool) { + visibleInUI = visible + } override init(frame frameRect: NSRect) { super.init(frame: frameRect) @@ -7440,20 +7363,17 @@ class GhosttyNSView: NSView, NSUserInterfaceValidations { terminalSurface?.surface } - fileprivate func applySurfaceColorScheme( - force: Bool = false, - preferredColorScheme: GhosttyConfig.ColorSchemePreference? = nil - ) { + private func applySurfaceColorScheme(force: Bool = false) { guard let surface else { return } let bestMatch = effectiveAppearance.bestMatch(from: [.darkAqua, .aqua]) - let preferredColorScheme = preferredColorScheme - ?? GhosttyApp.shared.effectiveTerminalColorSchemePreference - let scheme = GhosttyApp.ghosttyRuntimeColorScheme(for: preferredColorScheme) + let scheme: ghostty_color_scheme_e = bestMatch == .darkAqua + ? GHOSTTY_COLOR_SCHEME_DARK + : GHOSTTY_COLOR_SCHEME_LIGHT if !force, appliedColorScheme == scheme { if GhosttyApp.shared.backgroundLogEnabled { let schemeLabel = scheme == GHOSTTY_COLOR_SCHEME_DARK ? "dark" : "light" GhosttyApp.shared.logBackground( - "surface color scheme tab=\(tabId?.uuidString ?? "nil") surface=\(terminalSurface?.id.uuidString ?? "nil") bestMatch=\(bestMatch?.rawValue ?? "nil") preferred=\(schemeLabel) scheme=\(schemeLabel) force=\(force) applied=false" + "surface color scheme tab=\(tabId?.uuidString ?? "nil") surface=\(terminalSurface?.id.uuidString ?? "nil") bestMatch=\(bestMatch?.rawValue ?? "nil") scheme=\(schemeLabel) force=\(force) applied=false" ) } return @@ -7463,7 +7383,7 @@ class GhosttyNSView: NSView, NSUserInterfaceValidations { if GhosttyApp.shared.backgroundLogEnabled { let schemeLabel = scheme == GHOSTTY_COLOR_SCHEME_DARK ? "dark" : "light" GhosttyApp.shared.logBackground( - "surface color scheme tab=\(tabId?.uuidString ?? "nil") surface=\(terminalSurface?.id.uuidString ?? "nil") bestMatch=\(bestMatch?.rawValue ?? "nil") preferred=\(schemeLabel) scheme=\(schemeLabel) force=\(force) applied=true" + "surface color scheme tab=\(tabId?.uuidString ?? "nil") surface=\(terminalSurface?.id.uuidString ?? "nil") bestMatch=\(bestMatch?.rawValue ?? "nil") scheme=\(schemeLabel) force=\(force) applied=true" ) } } @@ -7506,6 +7426,12 @@ class GhosttyNSView: NSView, NSUserInterfaceValidations { } } + private func performKeyboardInitiatedScrollBindingAction(_ action: String) -> Bool { + withScrollbarActionIntent([.keyboardInitiated, .explicitSync], carryAcrossAction: true) { + performBindingAction(action) + } + } + @discardableResult func toggleKeyboardCopyMode() -> Bool { guard surface != nil else { return false } @@ -7542,6 +7468,34 @@ class GhosttyNSView: NSView, NSUserInterfaceValidations { } } + private func performKeyboardInitiatedScrollBindingAction(_ action: String, repeatCount: Int) { + let count = terminalKeyboardCopyModeClampCount(repeatCount) + for _ in 0 ..< count { + _ = performKeyboardInitiatedScrollBindingAction(action) + } + } + + private func performKeyboardCopyModeBindingAction( + _ bindingAction: String, + copyModeAction: TerminalKeyboardCopyModeAction, + repeatCount: Int = 1 + ) { + let intent = copyModeAction.scrollbarUpdateIntent + if !intent.isEmpty { + let count = terminalKeyboardCopyModeClampCount(repeatCount) + for _ in 0 ..< count { + _ = withScrollbarActionIntent( + intent, + carryAcrossAction: copyModeAction.shouldCarryScrollbarUpdateIntentAfterBindingAction + ) { + performBindingAction(bindingAction) + } + } + } else { + performBindingAction(bindingAction, repeatCount: repeatCount) + } + } + private func currentKeyboardCopyModeViewportRow(surface: ghostty_surface_t) -> Int { let rows = max(Int(ghostty_surface_size(surface).rows), 1) let fallback = rows - 1 @@ -7680,34 +7634,60 @@ class GhosttyNSView: NSView, NSUserInterfaceValidations { _ = ghostty_surface_clear_selection_compat(surface) setKeyboardCopyModeActive(false) case let .scrollLines(delta): - _ = performBindingAction("scroll_page_lines:\(delta * count)") + performKeyboardCopyModeBindingAction( + "scroll_page_lines:\(delta * count)", + copyModeAction: action + ) refreshKeyboardCopyModeViewportRowFromVisibleAnchor(surface: surface) case let .scrollPage(delta): - performBindingAction(delta > 0 ? "scroll_page_down" : "scroll_page_up", repeatCount: count) + performKeyboardCopyModeBindingAction( + delta > 0 ? "scroll_page_down" : "scroll_page_up", + copyModeAction: action, + repeatCount: count + ) refreshKeyboardCopyModeViewportRowFromVisibleAnchor(surface: surface) case let .scrollHalfPage(delta): let fraction = delta > 0 ? 0.5 : -0.5 - performBindingAction("scroll_page_fractional:\(fraction)", repeatCount: count) + performKeyboardCopyModeBindingAction( + "scroll_page_fractional:\(fraction)", + copyModeAction: action, + repeatCount: count + ) refreshKeyboardCopyModeViewportRowFromVisibleAnchor(surface: surface) case .scrollToTop: keyboardCopyModeViewportRow = 0 - _ = performBindingAction("scroll_to_top") + performKeyboardCopyModeBindingAction("scroll_to_top", copyModeAction: action) case .scrollToBottom: keyboardCopyModeViewportRow = max(Int(ghostty_surface_size(surface).rows) - 1, 0) - _ = performBindingAction("scroll_to_bottom") + performKeyboardCopyModeBindingAction("scroll_to_bottom", copyModeAction: action) case let .jumpToPrompt(delta): - _ = performBindingAction("jump_to_prompt:\(delta * count)") + performKeyboardCopyModeBindingAction( + "jump_to_prompt:\(delta * count)", + copyModeAction: action + ) refreshKeyboardCopyModeViewportRowFromVisibleAnchor(surface: surface) case .startSearch: _ = performBindingAction("start_search") case .searchNext: - performBindingAction("navigate_search:next", repeatCount: count) + performKeyboardCopyModeBindingAction( + "navigate_search:next", + copyModeAction: action, + repeatCount: count + ) refreshKeyboardCopyModeViewportRowFromVisibleAnchor(surface: surface) case .searchPrevious: - performBindingAction("navigate_search:previous", repeatCount: count) + performKeyboardCopyModeBindingAction( + "navigate_search:previous", + copyModeAction: action, + repeatCount: count + ) refreshKeyboardCopyModeViewportRowFromVisibleAnchor(surface: surface) case let .adjustSelection(direction): - performBindingAction("adjust_selection:\(direction.rawValue)", repeatCount: count) + performKeyboardCopyModeBindingAction( + "adjust_selection:\(direction.rawValue)", + copyModeAction: action, + repeatCount: count + ) } return true } @@ -8052,6 +8032,17 @@ class GhosttyNSView: NSView, NSUserInterfaceValidations { performKeyEquivalent(with: event, shouldRetryMainMenu: false) } + private func keyEventMayTriggerKeyboardScrollAction(_ event: NSEvent) -> Bool { + let flags = ShortcutStroke.normalizedModifierFlags(from: event.modifierFlags) + guard flags.isDisjoint(with: [.command, .control, .option]) else { return false } + switch Int(event.keyCode) { + case kVK_PageUp, kVK_PageDown: + return true + default: + return false + } + } + private func performKeyEquivalent(with event: NSEvent, shouldRetryMainMenu: Bool) -> Bool { #if DEBUG let typingTimingStart = CmuxTypingTiming.start() @@ -8299,6 +8290,16 @@ class GhosttyNSView: NSView, NSUserInterfaceValidations { ) #endif + let shouldTrackKeyboardScrollAction = keyEventMayTriggerKeyboardScrollAction(event) + if shouldTrackKeyboardScrollAction { + beginKeyboardInitiatedScrollAction() + } + defer { + if shouldTrackKeyboardScrollAction { + endKeyboardInitiatedScrollAction() + } + } + // Fast path for control-modified terminal input (for example Ctrl+D). // // These keys are terminal control input, not text composition, so we bypass @@ -8406,10 +8407,6 @@ class GhosttyNSView: NSView, NSUserInterfaceValidations { keyCode: event.keyCode ) ?? event } - let textInputEvent = textInputInterpretationEvent( - original: event, - translated: translationEvent - ) // Set up text accumulator for interpretKeyEvents keyTextAccumulator = [] @@ -8427,7 +8424,7 @@ class GhosttyNSView: NSView, NSUserInterfaceValidations { let interpretTimingStart = CmuxTypingTiming.start() let interpretPhaseStart = ProcessInfo.processInfo.systemUptime #endif - interpretKeyEvents([textInputEvent]) + interpretKeyEvents([translationEvent]) #if DEBUG interpretMs = (ProcessInfo.processInfo.systemUptime - interpretPhaseStart) * 1000.0 CmuxTypingTiming.logDuration( @@ -8465,7 +8462,7 @@ class GhosttyNSView: NSView, NSUserInterfaceValidations { before: markedStateBefore, after: (markedText.string, markedSelectedRange), accumulatedText: accumulatedText, - event: textInputEvent, + event: event, inputSourceId: keyboardIdBefore ) { imeConsumedKeyUps.insert(event.keyCode) @@ -8545,7 +8542,7 @@ class GhosttyNSView: NSView, NSUserInterfaceValidations { } if shouldSendCommittedIMEConfirmKey( - event: textInputEvent, + event: translationEvent, markedTextBefore: markedTextBefore ) { keyEvent.consumed_mods = GHOSTTY_MODS_NONE @@ -10398,6 +10395,112 @@ private final class GhosttyFlashOverlayView: NSView { } } +private final class TerminalTimestampGutterView: NSView { + private struct DrawStyle { + let fontSize: CGFloat + let attributes: [NSAttributedString.Key: Any] + let lineHeight: CGFloat + let separatorColor: NSColor + } + + private let formatter: DateFormatter = { + let formatter = DateFormatter() + formatter.dateStyle = .none + formatter.timeStyle = .medium + return formatter + }() + + var onMouseDown: (() -> Void)? + private var rows: [TerminalTimestampVisibleRow] = [] + private var visibleTopRow: CGFloat = 0 + private var cellHeight: CGFloat = 0 + private var cachedDrawStyle: DrawStyle? + + override init(frame frameRect: NSRect) { + super.init(frame: frameRect) + wantsLayer = true + layer?.backgroundColor = NSColor.clear.cgColor + layer?.isOpaque = false + setAccessibilityRole(.group) + setAccessibilityLabel( + String(localized: "terminal.timestamps.gutter.accessibility", defaultValue: "Terminal timestamps") + ) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) not implemented") + } + + override var acceptsFirstResponder: Bool { false } + override var isOpaque: Bool { false } + + override func viewDidChangeEffectiveAppearance() { + super.viewDidChangeEffectiveAppearance() + cachedDrawStyle = nil + needsDisplay = true + } + + func update( + rows: [TerminalTimestampVisibleRow], + visibleTopRow: CGFloat, + cellHeight: CGFloat + ) { + self.rows = rows + self.visibleTopRow = visibleTopRow + self.cellHeight = cellHeight + needsDisplay = true + } + + override func mouseDown(with event: NSEvent) { + onMouseDown?() + } + + private func drawStyle(for cellHeight: CGFloat) -> DrawStyle { + let fontSize = min(11, max(9, cellHeight * 0.58)) + if let cachedDrawStyle, cachedDrawStyle.fontSize == fontSize { + return cachedDrawStyle + } + + let font = NSFont.monospacedDigitSystemFont(ofSize: fontSize, weight: .regular) + let paragraph = NSMutableParagraphStyle() + paragraph.alignment = .right + paragraph.lineBreakMode = .byClipping + let style = DrawStyle( + fontSize: fontSize, + attributes: [ + .font: font, + .foregroundColor: NSColor.secondaryLabelColor.withAlphaComponent(0.72), + .paragraphStyle: paragraph, + ], + lineHeight: font.ascender - font.descender + font.leading, + separatorColor: NSColor.separatorColor.withAlphaComponent(0.35) + ) + cachedDrawStyle = style + return style + } + + override func draw(_ dirtyRect: NSRect) { + super.draw(dirtyRect) + + let style = drawStyle(for: cellHeight) + style.separatorColor.setFill() + NSRect(x: bounds.maxX - 1, y: 0, width: 1, height: bounds.height).fill() + + guard cellHeight > 0, !rows.isEmpty else { return } + + let textWidth = max(0, bounds.width - 12) + + for row in rows { + let rowOffset = CGFloat(row.row) - visibleTopRow + let rowTopFromBottom = bounds.height - ((rowOffset + 1) * cellHeight) + let textY = floor(rowTopFromBottom + ((cellHeight - style.lineHeight) / 2)) + let textRect = NSRect(x: 4, y: textY, width: textWidth, height: style.lineHeight) + guard textRect.intersects(dirtyRect) else { continue } + formatter.string(from: row.timestamp).draw(in: textRect, withAttributes: style.attributes) + } + } +} + final class GhosttySurfaceScrollView: NSView { enum FlashStyle { case navigation @@ -10408,7 +10511,7 @@ final class GhosttySurfaceScrollView: NSView { switch reason { case .navigation: return .navigation - case .notificationArrival, .notificationDismiss, .unreadIndicatorDismiss, .debug: + case .notificationArrival, .notificationDismiss, .manualUnreadDismiss, .debug: return .notification } } @@ -10422,6 +10525,8 @@ final class GhosttySurfaceScrollView: NSView { } } + private static let timestampGutterWidth: CGFloat = 88 + private enum NotificationRingMetrics { static let inset = PanelOverlayRingMetrics.inset static let cornerRadius = PanelOverlayRingMetrics.cornerRadius @@ -10429,6 +10534,7 @@ final class GhosttySurfaceScrollView: NSView { } private let backgroundView: NSView + private let timestampGutterView: TerminalTimestampGutterView private let scrollView: GhosttyScrollView private let documentView: NSView private let surfaceView: GhosttyNSView @@ -10468,6 +10574,7 @@ final class GhosttySurfaceScrollView: NSView { private var imageTransferIndicatorShowWorkItem: DispatchWorkItem? private var activeImageTransferOperation: TerminalImageTransferOperation? private var activeImageTransferCancelHandler: (() -> Void)? + private let timestampStore = TerminalTimestampStore() private var lastSearchOverlayStateID: ObjectIdentifier? private weak var cachedOwningWorkspace: Workspace? private weak var observedWorkspaceTerminalScrollBar: Workspace? @@ -10683,6 +10790,7 @@ final class GhosttySurfaceScrollView: NSView { self.surfaceView = surfaceView backgroundView = NSView(frame: .zero) + timestampGutterView = TerminalTimestampGutterView(frame: .zero) scrollView = GhosttyScrollView() inactiveOverlayView = GhosttyFlashOverlayView(frame: .zero) dropZoneOverlayView = GhosttyFlashOverlayView(frame: .zero) @@ -10723,6 +10831,11 @@ final class GhosttySurfaceScrollView: NSView { backgroundView.layer?.isOpaque = false addSubview(backgroundView) addSubview(scrollView) + timestampGutterView.isHidden = !TerminalTimestampsSettings.isVisible() + timestampGutterView.onMouseDown = { [weak self] in + self?.moveFocus() + } + addSubview(timestampGutterView) paneDropTargetView.hostedView = self addSubview(paneDropTargetView, positioned: .above, relativeTo: nil) synchronizeScrollbarAppearance() @@ -10982,6 +11095,7 @@ final class GhosttySurfaceScrollView: NSView { queue: .main ) { [weak self] _ in self?.synchronizeScrollView() + self?.refreshTimestampGutter() }) observers.append(NotificationCenter.default.addObserver( @@ -11002,6 +11116,14 @@ final class GhosttySurfaceScrollView: NSView { self?.handleTerminalScrollBarPreferenceChange() }) + observers.append(NotificationCenter.default.addObserver( + forName: TerminalTimestampsSettings.didChangeNotification, + object: nil, + queue: .main + ) { [weak self] _ in + self?.handleTerminalTimestampsPreferenceChange() + }) + } required init?(coder: NSCoder) { @@ -11115,8 +11237,20 @@ final class GhosttySurfaceScrollView: NSView { let didScrollbarAppearanceChange = synchronizeScrollbarAppearance() let previousSurfaceSize = surfaceView.frame.size + let timestampGutterWidth = terminalTimestampGutterWidth() _ = setFrameIfNeeded(backgroundView, to: bounds) - _ = setFrameIfNeeded(scrollView, to: bounds) + _ = setFrameIfNeeded( + timestampGutterView, + to: CGRect(x: 0, y: 0, width: timestampGutterWidth, height: bounds.height) + ) + timestampGutterView.isHidden = timestampGutterWidth <= 0 + let scrollFrame = CGRect( + x: timestampGutterWidth, + y: 0, + width: max(0, bounds.width - timestampGutterWidth), + height: bounds.height + ) + _ = setFrameIfNeeded(scrollView, to: scrollFrame) let targetSize = scrollView.bounds.size #if DEBUG logLayoutDuringActiveDrag(targetSize: targetSize) @@ -11167,6 +11301,7 @@ final class GhosttySurfaceScrollView: NSView { synchronizeScrollView() synchronizeSurfaceView() let didCoreSurfaceChange = synchronizeCoreSurface() + refreshTimestampGutter() return !sizeApproximatelyEqual(previousSurfaceSize, targetSize) || didCoreSurfaceChange } @@ -11788,15 +11923,6 @@ final class GhosttySurfaceScrollView: NSView { surfaceView.applyWindowBackgroundIfActive() } - func reapplySurfaceColorSchemeAfterGhosttyConfigReload( - preferredColorScheme: GhosttyConfig.ColorSchemePreference - ) { - surfaceView.applySurfaceColorScheme( - force: true, - preferredColorScheme: preferredColorScheme - ) - } - private func dropZoneOverlayFrame(for zone: DropZone, in size: CGSize) -> CGRect { let localFrame = PaneDropRouting.compactOverlayFrame(for: zone, in: size) @@ -12174,6 +12300,10 @@ final class GhosttySurfaceScrollView: NSView { surfaceView.debugRegisteredDropTypes() } + func debugTimestampVisibleRows(for scrollbar: GhosttyScrollbar) -> [TerminalTimestampVisibleRow] { + timestampStore.visibleRows(for: TerminalTimestampScrollbarState(scrollbar)) + } + func debugInactiveOverlayState() -> (isHidden: Bool, alpha: CGFloat) { ( inactiveOverlayView.isHidden, @@ -13271,6 +13401,40 @@ final class GhosttySurfaceScrollView: NSView { // Intentionally no-op (no retry loops). } + private func terminalTimestampGutterWidth() -> CGFloat { + TerminalTimestampsSettings.isVisible() ? Self.timestampGutterWidth : 0 + } + + private func currentVisibleTopRow(cellHeight: CGFloat) -> CGFloat { + guard cellHeight > 0 else { return 0 } + let visibleRect = scrollView.contentView.documentVisibleRect + let scrollOffset = documentView.frame.height - visibleRect.origin.y - visibleRect.height + return max(0, scrollOffset / cellHeight) + } + + private func refreshTimestampGutter() { + guard TerminalTimestampsSettings.isVisible(), + let scrollbar = surfaceView.scrollbar, + surfaceView.cellSize.height > 0 else { + timestampGutterView.update(rows: [], visibleTopRow: 0, cellHeight: 0) + return + } + + let visibleTopRow = currentVisibleTopRow(cellHeight: surfaceView.cellSize.height) + let state = TerminalTimestampScrollbarState.visibleWindow( + total: Int(clamping: scrollbar.total), + fallbackLen: Int(clamping: scrollbar.len), + visibleTopRow: visibleTopRow, + viewportHeight: scrollView.contentView.documentVisibleRect.height, + cellHeight: surfaceView.cellSize.height + ) + timestampGutterView.update( + rows: timestampStore.visibleRows(for: state), + visibleTopRow: visibleTopRow, + cellHeight: surfaceView.cellSize.height + ) + } + private func synchronizeSurfaceView() { let visibleRect = scrollView.contentView.documentVisibleRect guard !pointApproximatelyEqual(surfaceView.frame.origin, visibleRect.origin) else { return } @@ -13388,6 +13552,7 @@ final class GhosttySurfaceScrollView: NSView { private func handleScrollChange() { synchronizeSurfaceView() + refreshTimestampGutter() } private func handleLiveScroll() { @@ -13417,7 +13582,23 @@ final class GhosttySurfaceScrollView: NSView { return } let wasVisible = scrollView.hasVerticalScroller - if pendingExplicitWheelScroll { + let legacyKeyboardInitiated = + notification.userInfo?[GhosttyNotificationKey.scrollbarWasKeyboardInitiated] as? Bool ?? false + var scrollbarIntent = + notification.userInfo?[GhosttyNotificationKey.scrollbarUpdateIntent] as? GhosttyScrollbarUpdateIntent + ?? [] + if legacyKeyboardInitiated { + scrollbarIntent.formUnion([.keyboardInitiated, .explicitSync]) + } + let shouldExplicitlySyncScrollbar = pendingExplicitWheelScroll || scrollbarIntent.contains(.explicitSync) + let isUserInitiatedScroll = shouldExplicitlySyncScrollbar || isLiveScrolling + let shouldMarkVisibleTimestampRows = !isUserInitiatedScroll && !userScrolledAwayFromBottom + timestampStore.record( + scrollbar: TerminalTimestampScrollbarState(scrollbar), + at: .now, + markVisibleRows: shouldMarkVisibleTimestampRows + ) + if shouldExplicitlySyncScrollbar { userScrolledAwayFromBottom = scrollbar.offset + scrollbar.len < scrollbar.total allowExplicitScrollbarSync = true pendingExplicitWheelScroll = false @@ -13429,6 +13610,7 @@ final class GhosttySurfaceScrollView: NSView { return } synchronizeScrollView() + refreshTimestampGutter() } @discardableResult @@ -13475,6 +13657,17 @@ final class GhosttySurfaceScrollView: NSView { _ = synchronizeGeometryAndContent() } + private func handleTerminalTimestampsPreferenceChange() { + if TerminalTimestampsSettings.isVisible(), let scrollbar = surfaceView.scrollbar { + timestampStore.record( + scrollbar: TerminalTimestampScrollbarState(scrollbar), + at: .now, + markVisibleRows: true + ) + } + _ = synchronizeGeometryAndContent() + } + private func updateWorkspaceTerminalScrollBarObserver(_ workspace: Workspace?) { if let observedWorkspaceTerminalScrollBar, observedWorkspaceTerminalScrollBar === workspace, diff --git a/Sources/KeyboardShortcutSettings.swift b/Sources/KeyboardShortcutSettings.swift index 6686e0a82521..4c0a105fa32a 100644 --- a/Sources/KeyboardShortcutSettings.swift +++ b/Sources/KeyboardShortcutSettings.swift @@ -106,6 +106,7 @@ enum KeyboardShortcutSettings { case reopenClosedBrowserPanel case newSurface case toggleTerminalCopyMode + case toggleTerminalTimestamps // Panes / splits case focusLeft @@ -189,6 +190,7 @@ enum KeyboardShortcutSettings { case .reopenClosedBrowserPanel: return String(localized: "menu.file.reopenClosedBrowserPanel", defaultValue: "Reopen Closed Browser Panel") case .newSurface: return String(localized: "shortcut.newSurface.label", defaultValue: "New Surface") case .toggleTerminalCopyMode: return String(localized: "shortcut.toggleTerminalCopyMode.label", defaultValue: "Toggle Terminal Copy Mode") + case .toggleTerminalTimestamps: return String(localized: "shortcut.toggleTerminalTimestamps.label", defaultValue: "Toggle Terminal Timestamps") case .focusLeft: return String(localized: "shortcut.focusPaneLeft.label", defaultValue: "Focus Pane Left") case .focusRight: return String(localized: "shortcut.focusPaneRight.label", defaultValue: "Focus Pane Right") case .focusUp: return String(localized: "shortcut.focusPaneUp.label", defaultValue: "Focus Pane Up") @@ -343,6 +345,8 @@ enum KeyboardShortcutSettings { return StoredShortcut(key: "t", command: true, shift: false, option: false, control: false) case .toggleTerminalCopyMode: return StoredShortcut(key: "m", command: true, shift: true, option: false, control: false) + case .toggleTerminalTimestamps: + return StoredShortcut(key: "e", command: true, shift: true, option: true, control: false) case .selectWorkspaceByNumber: return StoredShortcut(key: "1", command: true, shift: false, option: false, control: false) case .toggleRightSidebar: @@ -456,13 +460,7 @@ enum KeyboardShortcutSettings { return normalized } - // Preserve invalid settings-file values for the show/hide hotkey so managed - // configuration remains visible instead of silently falling back to defaults. - // Runtime registration still rejects unsupported Carbon hotkey shapes. - if usesNumberedDigitMatching || self == .globalSearch { - return nil - } - return shortcut + return usesNumberedDigitMatching || self == .showHideAllWindows || self == .globalSearch ? nil : shortcut } func resolvedRecordedShortcutIgnoringConflicts(_ shortcut: StoredShortcut, checkingSystemWideConflicts: Bool = true) -> RecordedShortcutResolution { @@ -2180,7 +2178,7 @@ extension ShortcutStroke { private static func parseConfigKeyToken(_ rawValue: String) -> String? { let trimmed = rawValue.trimmingCharacters(in: .whitespacesAndNewlines) if trimmed.isEmpty { - return rawValue == " " ? "space" : nil + return !rawValue.isEmpty && rawValue.allSatisfy { $0 == " " } ? "space" : nil } let lowered = trimmed.lowercased() @@ -2281,10 +2279,8 @@ extension StoredShortcut { private static func isUnboundConfigToken(_ rawValue: String) -> Bool { if rawValue.isEmpty { return true } - if rawValue == " " { return false } let normalized = rawValue.trimmingCharacters(in: .whitespacesAndNewlines).lowercased() - guard !normalized.isEmpty else { return true } - return normalized == "none" || normalized == "clear" || normalized == "unbound" || normalized == "disabled" + return normalized.isEmpty || normalized == "none" || normalized == "clear" || normalized == "unbound" || normalized == "disabled" } } @@ -2315,25 +2311,8 @@ enum KeyboardShortcutRecorderActivity { } static func stopAllRecording(center: NotificationCenter = .default) { - let wasActive = isAnyRecorderActive center.post(name: stopAllNotification, object: nil) - guard activeRecorderCount > 0 else { return } - activeRecorderCount = 0 - if wasActive { - center.post(name: didChangeNotification, object: nil) - } } - -#if DEBUG - static func resetForTesting(center: NotificationCenter = .default) { - // Keep test isolation from broadcasting stop-all UI notifications into unrelated live windows. - let wasActive = isAnyRecorderActive - activeRecorderCount = 0 - if wasActive { - center.post(name: didChangeNotification, object: nil) - } - } -#endif } struct ShortcutRecorderRejectedAttempt: Equatable { diff --git a/Sources/KeyboardShortcutSettingsFileStore+Template.swift b/Sources/KeyboardShortcutSettingsFileStore+Template.swift index 30eb38b54bb3..1151829f2b7a 100644 --- a/Sources/KeyboardShortcutSettingsFileStore+Template.swift +++ b/Sources/KeyboardShortcutSettingsFileStore+Template.swift @@ -80,6 +80,7 @@ extension CmuxSettingsFileStore { [ "terminal": [ "showScrollBar": TerminalScrollBarSettings.defaultShowScrollBar, + "showTimestamps": TerminalTimestampsSettings.defaultShowTimestamps, "autoResumeAgentSessions": AgentSessionAutoResumeSettings.defaultAutoResumeAgentSessions, "resumeCommands": [], ], @@ -105,7 +106,6 @@ extension CmuxSettingsFileStore { "showNotificationMessage": SidebarWorkspaceDetailSettings.defaultShowNotificationMessage, "showBranchDirectory": SidebarWorkspaceDetailDefaults.showBranchDirectory, "showPullRequests": SidebarWorkspaceDetailDefaults.showPullRequests, - "watchGitStatus": SidebarWorkspaceDetailDefaults.watchGitStatus, "makePullRequestsClickable": SidebarPullRequestClickabilitySettings.defaultClickable, "openPullRequestLinksInCmuxBrowser": BrowserLinkOpenSettings.defaultOpenSidebarPullRequestLinksInCmuxBrowser, "openPortLinksInCmuxBrowser": BrowserLinkOpenSettings.defaultOpenSidebarPortLinksInCmuxBrowser, @@ -142,7 +142,6 @@ extension CmuxSettingsFileStore { "claudeCodeIntegration": ClaudeCodeIntegrationSettings.defaultHooksEnabled, "claudeBinaryPath": "", "ripgrepBinaryPath": "", - "suppressSubagentNotifications": AgentSubagentNotificationSettings.defaultSuppressNotifications, "cursorIntegration": CursorIntegrationSettings.defaultHooksEnabled, "geminiIntegration": GeminiIntegrationSettings.defaultHooksEnabled, "portBase": AutomationSettings.defaultPortBase, diff --git a/Sources/KeyboardShortcutSettingsFileStore.swift b/Sources/KeyboardShortcutSettingsFileStore.swift index d23945c28ecd..b49bf5f4d965 100644 --- a/Sources/KeyboardShortcutSettingsFileStore.swift +++ b/Sources/KeyboardShortcutSettingsFileStore.swift @@ -54,6 +54,7 @@ final class CmuxSettingsFileStore { private let fallbackPaths: [String] private let fileManager: FileManager private let notificationCenter: NotificationCenter + private let appearanceEnvironment: AppearanceSettings.LiveApplyEnvironment private let stateLock = NSLock() private var primaryWatcher: ShortcutSettingsFileWatcher? @@ -75,6 +76,7 @@ final class CmuxSettingsFileStore { additionalFallbackPaths: [String] = [CmuxSettingsFileStore.defaultApplicationSupportFallbackPath].compactMap { $0 }, fileManager: FileManager = .default, notificationCenter: NotificationCenter = .default, + appearanceEnvironment: AppearanceSettings.LiveApplyEnvironment = .live, startWatching: Bool = true ) { self.primaryPath = primaryPath @@ -82,13 +84,17 @@ final class CmuxSettingsFileStore { .filter { $0 != primaryPath } self.fileManager = fileManager self.notificationCenter = notificationCenter + self.appearanceEnvironment = appearanceEnvironment importedManagedDefaults = Self.loadImportedManagedDefaults() bootstrapPrimaryTemplateIfNeeded() // The app init path loads cmux.json before applying language/appearance // itself. Running live default side effects here can initialize UI/runtime // singletons while this store singleton is still in its dispatch_once. - reload(applyLiveDefaultSideEffects: false) + reload( + applyLiveDefaultSideEffects: false, + synchronizeManagedAppearanceTerminalTheme: false + ) guard startWatching else { return } primaryWatcher = ShortcutSettingsFileWatcher(path: primaryPath, fileManager: fileManager) { [weak self] in @@ -120,14 +126,20 @@ final class CmuxSettingsFileStore { } func reload() { - reload(applyLiveDefaultSideEffects: true) + reload( + applyLiveDefaultSideEffects: true, + synchronizeManagedAppearanceTerminalTheme: true + ) } func applyDeferredManagedDefaultSideEffects() { applyManagedDefaultBatchSideEffects(drainDeferredManagedDefaultSideEffects()) } - private func reload(applyLiveDefaultSideEffects: Bool) { + private func reload( + applyLiveDefaultSideEffects: Bool, + synchronizeManagedAppearanceTerminalTheme: Bool + ) { let previousState = synchronized { ( shortcuts: shortcutsByAction, @@ -143,7 +155,8 @@ final class CmuxSettingsFileStore { previous: previousState.importedManagedDefaults, next: resolved.managedUserDefaults ), - applyLiveDefaultSideEffects: applyLiveDefaultSideEffects + applyLiveDefaultSideEffects: applyLiveDefaultSideEffects, + synchronizeManagedAppearanceTerminalTheme: synchronizeManagedAppearanceTerminalTheme ) synchronized { shortcutsByAction = resolved.shortcuts @@ -235,7 +248,8 @@ final class CmuxSettingsFileStore { importedManagedDefaults: managedState.importedManagedDefaults, changedManagedDefaultKeys: [], updateBackups: false, - applyLiveDefaultSideEffects: true + applyLiveDefaultSideEffects: true, + synchronizeManagedAppearanceTerminalTheme: true ) } @@ -479,6 +493,12 @@ final class CmuxSettingsFileStore { logInvalid("terminal.showScrollBar", sourcePath: sourcePath) } + if let value = jsonBool(section["showTimestamps"]) { + snapshot.managedUserDefaults[TerminalTimestampsSettings.showTimestampsKey] = .bool(value) + } else if section.keys.contains("showTimestamps") { + logInvalid("terminal.showTimestamps", sourcePath: sourcePath) + } + if let value = jsonBool(section["autoResumeAgentSessions"]) { snapshot.managedUserDefaults[AgentSessionAutoResumeSettings.autoResumeAgentSessionsKey] = .bool(value) } else if section.keys.contains("autoResumeAgentSessions") { @@ -512,7 +532,6 @@ final class CmuxSettingsFileStore { } if let value = jsonBool(section["showBranchDirectory"]) { snapshot.managedUserDefaults["sidebarShowBranchDirectory"] = .bool(value) } if let value = jsonBool(section["showPullRequests"]) { snapshot.managedUserDefaults["sidebarShowPullRequest"] = .bool(value) } - if let value = jsonBool(section["watchGitStatus"]) { snapshot.managedUserDefaults[SidebarWorkspaceDetailDefaults.watchGitStatusKey] = .bool(value) } if let value = jsonBool(section["makePullRequestsClickable"]) { snapshot.managedUserDefaults[SidebarPullRequestClickabilitySettings.key] = .bool(value) } if let value = jsonBool(section["openPullRequestLinksInCmuxBrowser"]) { snapshot.managedUserDefaults[BrowserLinkOpenSettings.openSidebarPullRequestLinksInCmuxBrowserKey] = .bool(value) @@ -712,9 +731,6 @@ final class CmuxSettingsFileStore { if let raw = jsonString(section["ripgrepBinaryPath"]) { snapshot.managedUserDefaults[RipgrepIntegrationSettings.customRipgrepPathKey] = .string(raw) } - if let value = jsonBool(section["suppressSubagentNotifications"]) { - snapshot.managedUserDefaults[AgentSubagentNotificationSettings.suppressNotificationsKey] = .bool(value) - } if let value = jsonBool(section["cursorIntegration"]) { snapshot.managedUserDefaults[CursorIntegrationSettings.hooksEnabledKey] = .bool(value) } @@ -883,7 +899,8 @@ final class CmuxSettingsFileStore { importedManagedDefaults: [String: ManagedSettingsValue], changedManagedDefaultKeys: Set, updateBackups: Bool = true, - applyLiveDefaultSideEffects: Bool + applyLiveDefaultSideEffects: Bool, + synchronizeManagedAppearanceTerminalTheme: Bool ) { var backups = loadBackups() var sideEffects = ManagedDefaultBatchSideEffects() @@ -914,7 +931,8 @@ final class CmuxSettingsFileStore { sideEffects.merge( restoreBackup( backup, - for: identifier + for: identifier, + synchronizeManagedAppearanceTerminalTheme: synchronizeManagedAppearanceTerminalTheme ) ) backups.removeValue(forKey: identifier) @@ -926,7 +944,8 @@ final class CmuxSettingsFileStore { value, for: defaultsKey, importedDefault: importedManagedDefaults[defaultsKey], - forceApply: changedManagedDefaultKeys.contains(defaultsKey) + forceApply: changedManagedDefaultKeys.contains(defaultsKey), + synchronizeManagedAppearanceTerminalTheme: synchronizeManagedAppearanceTerminalTheme ) ) } @@ -977,7 +996,8 @@ final class CmuxSettingsFileStore { private func restoreBackup( _ backup: BackupValue, - for identifier: String + for identifier: String, + synchronizeManagedAppearanceTerminalTheme: Bool ) -> ManagedDefaultBatchSideEffects { switch identifier { case Self.socketPasswordBackupIdentifier: @@ -993,7 +1013,8 @@ final class CmuxSettingsFileStore { default: return restoreUserDefaultsBackup( backup, - for: identifier + for: identifier, + synchronizeManagedAppearanceTerminalTheme: synchronizeManagedAppearanceTerminalTheme ) } } @@ -1039,7 +1060,8 @@ final class CmuxSettingsFileStore { private func restoreUserDefaultsBackup( _ backup: BackupValue, - for defaultsKey: String + for defaultsKey: String, + synchronizeManagedAppearanceTerminalTheme: Bool ) -> ManagedDefaultBatchSideEffects { let defaults = UserDefaults.standard if defaultsKey == WorkspaceTabColorSettings.paletteKey { @@ -1094,7 +1116,11 @@ final class CmuxSettingsFileStore { } if didMutateStoredValue { - return managedDefaultSideEffects(for: defaultsKey) + return managedDefaultSideEffects( + for: defaultsKey, + source: "cmuxConfig.restoreUserDefault", + synchronizeAppearanceTerminalTheme: synchronizeManagedAppearanceTerminalTheme + ) } return ManagedDefaultBatchSideEffects() } @@ -1103,7 +1129,8 @@ final class CmuxSettingsFileStore { _ value: ManagedSettingsValue, for defaultsKey: String, importedDefault: ManagedSettingsValue?, - forceApply: Bool + forceApply: Bool, + synchronizeManagedAppearanceTerminalTheme: Bool ) -> ManagedDefaultBatchSideEffects { let defaults = UserDefaults.standard guard shouldApplyManagedUserDefaultsValue( @@ -1176,7 +1203,11 @@ final class CmuxSettingsFileStore { } if didMutateStoredValue { - return managedDefaultSideEffects(for: defaultsKey) + return managedDefaultSideEffects( + for: defaultsKey, + source: "cmuxConfig.applyManagedDefault", + synchronizeAppearanceTerminalTheme: synchronizeManagedAppearanceTerminalTheme + ) } return ManagedDefaultBatchSideEffects() } @@ -1253,16 +1284,17 @@ final class CmuxSettingsFileStore { } } - private func managedDefaultSideEffects(for defaultsKey: String) -> ManagedDefaultBatchSideEffects { - guard defaultsKey != AppearanceSettings.appearanceModeKey else { - // The app lifecycle-owned UserDefaults observer applies live - // appearance changes after launch. The settings file store only - // imports the default so it cannot reenter Ghostty while this - // singleton initializes. - return ManagedDefaultBatchSideEffects() - } + private func managedDefaultSideEffects( + for defaultsKey: String, + source: String, + synchronizeAppearanceTerminalTheme: Bool + ) -> ManagedDefaultBatchSideEffects { var sideEffects = ManagedDefaultBatchSideEffects() - sideEffects.append(defaultsKey: defaultsKey) + sideEffects.append( + defaultsKey: defaultsKey, + source: source, + synchronizeAppearanceTerminalTheme: synchronizeAppearanceTerminalTheme + ) return sideEffects } @@ -1277,6 +1309,10 @@ final class CmuxSettingsFileStore { TerminalScrollBarSettings.notifyDidChange(notificationCenter: notificationCenter) } + if change.defaultsKey == TerminalTimestampsSettings.showTimestampsKey { + TerminalTimestampsSettings.notifyDidChange(notificationCenter: notificationCenter) + } + if change.defaultsKey == AgentSessionAutoResumeSettings.autoResumeAgentSessionsKey { agentSessionAutoResumeDidChange = true } @@ -1284,6 +1320,14 @@ final class CmuxSettingsFileStore { if change.defaultsKey == LanguageSettings.languageKey { let rawValue = UserDefaults.standard.string(forKey: change.defaultsKey) ?? "" LanguageSettings.apply(AppLanguage(rawValue: rawValue) ?? .system) + } else if change.defaultsKey == AppearanceSettings.appearanceModeKey { + AppearanceSettings.applyStoredMode( + rawValue: UserDefaults.standard.string(forKey: change.defaultsKey), + source: change.source, + duringLaunch: !change.synchronizeAppearanceTerminalTheme, + synchronizeTerminalTheme: change.synchronizeAppearanceTerminalTheme, + environment: self.appearanceEnvironment + ) } else if change.defaultsKey == AppIconSettings.modeKey { AppIconSettings.applyIcon(AppIconSettings.resolvedMode()) } @@ -1416,6 +1460,8 @@ private struct ResolvedSettingsSnapshot { private struct ManagedDefaultSideEffect { let defaultsKey: String + let source: String + let synchronizeAppearanceTerminalTheme: Bool } private struct ManagedDefaultBatchSideEffects { @@ -1427,13 +1473,27 @@ private struct ManagedDefaultBatchSideEffects { mutating func merge(_ other: ManagedDefaultBatchSideEffects) { for change in other.changes { - append(defaultsKey: change.defaultsKey) + append( + defaultsKey: change.defaultsKey, + source: change.source, + synchronizeAppearanceTerminalTheme: change.synchronizeAppearanceTerminalTheme + ) } } - mutating func append(defaultsKey: String) { + mutating func append( + defaultsKey: String, + source: String, + synchronizeAppearanceTerminalTheme: Bool + ) { changes.removeAll { $0.defaultsKey == defaultsKey } - changes.append(ManagedDefaultSideEffect(defaultsKey: defaultsKey)) + changes.append( + ManagedDefaultSideEffect( + defaultsKey: defaultsKey, + source: source, + synchronizeAppearanceTerminalTheme: synchronizeAppearanceTerminalTheme + ) + ) } } diff --git a/Sources/MainWindowFocusController.swift b/Sources/MainWindowFocusController.swift index 98b1f9bc7b7d..191b686690c6 100644 --- a/Sources/MainWindowFocusController.swift +++ b/Sources/MainWindowFocusController.swift @@ -136,14 +136,6 @@ final class MainWindowFocusController { publishFeedFocusSnapshot() } - func rememberRightSidebarMode(_ mode: RightSidebarMode) { - rememberedRightSidebarMode = mode - if mode != .feed { - feedSelectedItemId = nil - } - publishFeedFocusSnapshot() - } - func noteTerminalInteraction(workspaceId: UUID, panelId: UUID) { noteMainPanelInteraction(workspaceId: workspaceId, panelId: panelId) } diff --git a/Sources/Panels/BrowserPanel.swift b/Sources/Panels/BrowserPanel.swift index 07ce2d538d79..00c3b6d3273a 100644 --- a/Sources/Panels/BrowserPanel.swift +++ b/Sources/Panels/BrowserPanel.swift @@ -1543,10 +1543,6 @@ final class BrowserHistoryStore: ObservableObject { private let maxEntries: Int = 5000 private let saveDebounceNanoseconds: UInt64 = 120_000_000 - var isLoaded: Bool { - didLoad - } - private struct SuggestionCandidate { let entry: Entry let urlLower: String @@ -2777,7 +2773,6 @@ final class BrowserPanel: Panel, ObservableObject { private var restoredBackHistoryStack: [URL] = [] private var restoredForwardHistoryStack: [URL] = [] private var restoredHistoryCurrentURL: URL? - private var isMainFrameProvisionalNavigationActive: Bool = false /// Published estimated progress (0.0 - 1.0) @Published private(set) var estimatedProgress: Double = 0.0 @@ -3104,7 +3099,6 @@ final class BrowserPanel: Panel, ObservableObject { closeBackgroundPreloadHost(reason: "discardHiddenWebView") BrowserWindowPortalRegistry.detach(webView: oldWebView) oldWebView.stopLoading() - isMainFrameProvisionalNavigationActive = false oldWebView.navigationDelegate = nil oldWebView.uiDelegate = nil if let oldCmuxWebView = oldWebView as? CmuxWebView { @@ -3459,38 +3453,20 @@ final class BrowserPanel: Panel, ObservableObject { let boundWebViewInstanceID = webViewInstanceID let boundHistoryStore = historyStore - navigationDelegate.didStartProvisionalNavigation = { [weak self] webView in - MainActor.assumeIsolated { - guard let self, self.isCurrentWebView(webView, instanceID: boundWebViewInstanceID) else { return } - self.isMainFrameProvisionalNavigationActive = true - } - } - navigationDelegate.didCommit = { [weak self] webView in - MainActor.assumeIsolated { - guard let self, self.isCurrentWebView(webView, instanceID: boundWebViewInstanceID) else { return } - self.isMainFrameProvisionalNavigationActive = false - self.publishCommittedURL(from: webView) - } - } navigationDelegate.didFinish = { [weak self] webView in - MainActor.assumeIsolated { + Task { @MainActor [weak self] in guard let self, self.isCurrentWebView(webView, instanceID: boundWebViewInstanceID) else { return } - self.isMainFrameProvisionalNavigationActive = false - self.publishCommittedURL(from: webView) self.realignRestoredSessionHistoryToLiveCurrentIfPossible() boundHistoryStore.recordVisit(url: webView.url, title: webView.title) self.refreshFavicon(from: webView) // Keep find-in-page open through load completion and refresh matches for the new DOM. self.restoreFindStateAfterNavigation(replaySearch: true) + GlobalSearchCoordinator.shared.captureBrowserPanel(self) } } navigationDelegate.didFailNavigation = { [weak self] failedWebView, failedURL in - MainActor.assumeIsolated { + Task { @MainActor in guard let self, self.isCurrentWebView(failedWebView, instanceID: boundWebViewInstanceID) else { return } - self.isMainFrameProvisionalNavigationActive = false - if let url = URL(string: failedURL) { - self.currentURL = Self.remoteProxyDisplayURL(for: url) ?? url - } // Clear stale title/favicon from the previous page so the tab // shows the failed URL instead of the old page's branding. self.pageTitle = failedURL.isEmpty ? "" : failedURL @@ -3500,17 +3476,6 @@ final class BrowserPanel: Panel, ObservableObject { self.restoreFindStateAfterNavigation(replaySearch: false) } } - navigationDelegate.didCancelProvisionalNavigation = { [weak self] webView in - MainActor.assumeIsolated { - guard let self, self.isCurrentWebView(webView, instanceID: boundWebViewInstanceID) else { return } - self.isMainFrameProvisionalNavigationActive = false - } - } - } - - private func publishCommittedURL(from webView: WKWebView) { - currentURL = Self.remoteProxyDisplayURL(for: webView.url) - GlobalSearchCoordinator.shared.captureBrowserPanel(self) } private func isCurrentWebView(_ candidate: WKWebView, instanceID: UUID? = nil) -> Bool { @@ -3977,7 +3942,6 @@ final class BrowserPanel: Panel, ObservableObject { closeBackgroundPreloadHost(reason: "profileSwitch") BrowserWindowPortalRegistry.detach(webView: previousWebView) previousWebView.stopLoading() - isMainFrameProvisionalNavigationActive = false previousWebView.navigationDelegate = nil previousWebView.uiDelegate = nil if let previousCmuxWebView = previousWebView as? CmuxWebView { @@ -4200,12 +4164,10 @@ final class BrowserPanel: Panel, ObservableObject { let observedWebViewInstanceID = webViewInstanceID // URL changes - let urlObserver = webView.observe(\.url, options: [.new]) { [weak self] webView, change in - let observedURL = change.newValue ?? webView.url - MainActor.assumeIsolated { + let urlObserver = webView.observe(\.url, options: [.new]) { [weak self] webView, _ in + Task { @MainActor in guard let self, self.isCurrentWebView(webView, instanceID: observedWebViewInstanceID) else { return } - guard !self.isMainFrameProvisionalNavigationActive else { return } - self.currentURL = Self.remoteProxyDisplayURL(for: observedURL) + self.currentURL = Self.remoteProxyDisplayURL(for: webView.url) GlobalSearchCoordinator.shared.captureBrowserPanel(self) } } @@ -4346,7 +4308,6 @@ final class BrowserPanel: Panel, ObservableObject { closeBackgroundPreloadHost(reason: reason) BrowserWindowPortalRegistry.detach(webView: oldWebView) oldWebView.stopLoading() - isMainFrameProvisionalNavigationActive = false oldWebView.navigationDelegate = nil oldWebView.uiDelegate = nil if let oldCmuxWebView = oldWebView as? CmuxWebView { @@ -4498,7 +4459,6 @@ final class BrowserPanel: Panel, ObservableObject { } webView.stopLoading() - isMainFrameProvisionalNavigationActive = false webView.navigationDelegate = nil webView.uiDelegate = nil navigationDelegate = nil @@ -5300,7 +5260,6 @@ extension BrowserPanel { closeBackgroundPreloadHost(reason: "contextReset") BrowserWindowPortalRegistry.detach(webView: oldWebView) oldWebView.stopLoading() - isMainFrameProvisionalNavigationActive = false oldWebView.navigationDelegate = nil oldWebView.uiDelegate = nil if let oldCmuxWebView = oldWebView as? CmuxWebView { @@ -5373,17 +5332,11 @@ func resolveBrowserNavigableURL(_ input: String) -> URL? { } extension BrowserPanel { - private func cancelInFlightNavigationBeforeHistoryTraversal() { - guard webView.isLoading || isMainFrameProvisionalNavigationActive else { return } - webView.stopLoading() - isMainFrameProvisionalNavigationActive = false - } /// Go back in history func goBack() { guard canGoBack else { return } reactivateDiscardedWebViewWithoutNavigation(reason: "goBack") - cancelInFlightNavigationBeforeHistoryTraversal() if usesRestoredSessionHistory { realignRestoredSessionHistoryToLiveCurrentIfPossible() @@ -5418,7 +5371,6 @@ extension BrowserPanel { func goForward() { guard canGoForward else { return } reactivateDiscardedWebViewWithoutNavigation(reason: "goForward") - cancelInFlightNavigationBeforeHistoryTraversal() if usesRestoredSessionHistory { realignRestoredSessionHistoryToLiveCurrentIfPossible() @@ -5551,7 +5503,6 @@ extension BrowserPanel { /// Stop loading func stopLoading() { webView.stopLoading() - isMainFrameProvisionalNavigationActive = false } private static func windowContainsInspectorViews(_ root: NSView) -> Bool { @@ -7535,11 +7486,8 @@ func browserNavigationShouldOpenSimpleUserGesturePopupInCurrentTab( } private class BrowserNavigationDelegate: NSObject, WKNavigationDelegate { - var didStartProvisionalNavigation: ((WKWebView) -> Void)? - var didCommit: ((WKWebView) -> Void)? var didFinish: ((WKWebView) -> Void)? var didFailNavigation: ((WKWebView, String) -> Void)? - var didCancelProvisionalNavigation: ((WKWebView) -> Void)? var didTerminateWebContentProcess: ((WKWebView) -> Void)? var openInNewTab: ((URL) -> Void)? var requestNavigation: ((URLRequest, BrowserInsecureHTTPNavigationIntent) -> Void)? @@ -7554,11 +7502,6 @@ private class BrowserNavigationDelegate: NSObject, WKNavigationDelegate { func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) { lastAttemptedURL = webView.url - didStartProvisionalNavigation?(webView) - } - - func webView(_ webView: WKWebView, didCommit navigation: WKNavigation!) { - didCommit?(webView) } func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) { @@ -7579,7 +7522,6 @@ private class BrowserNavigationDelegate: NSObject, WKNavigationDelegate { // Cancelled navigations (e.g. rapid typing) are not real errors. if nsError.domain == NSURLErrorDomain, nsError.code == NSURLErrorCancelled { - didCancelProvisionalNavigation?(webView) return } @@ -7587,7 +7529,6 @@ private class BrowserNavigationDelegate: NSObject, WKNavigationDelegate { // navigation response is converted into a download via .download policy. // This is expected and should not show an error page. if nsError.domain == "WebKitErrorDomain", nsError.code == 102 { - didCancelProvisionalNavigation?(webView) return } @@ -8205,13 +8146,13 @@ enum BrowserImportScope: String, CaseIterable, Identifiable { } } -enum BrowserImportEngineFamily: String, Hashable, Sendable { +enum BrowserImportEngineFamily: String, Hashable { case chromium case firefox case webkit } -struct InstalledBrowserProfile: Identifiable, Hashable, Sendable { +struct InstalledBrowserProfile: Identifiable, Hashable { let displayName: String let rootURL: URL let isDefault: Bool @@ -8221,7 +8162,7 @@ struct InstalledBrowserProfile: Identifiable, Hashable, Sendable { } } -struct BrowserImportBrowserDescriptor: Hashable, Sendable { +struct BrowserImportBrowserDescriptor: Hashable { let id: String let displayName: String let family: BrowserImportEngineFamily @@ -8233,7 +8174,7 @@ struct BrowserImportBrowserDescriptor: Hashable, Sendable { let supportsDataOnlyDetection: Bool } -struct InstalledBrowserCandidate: Identifiable, Hashable, Sendable { +struct InstalledBrowserCandidate: Identifiable, Hashable { let descriptor: BrowserImportBrowserDescriptor let resolvedFamily: BrowserImportEngineFamily let homeDirectoryURL: URL @@ -8590,17 +8531,6 @@ enum InstalledBrowserDetector { } } - @MainActor - static func applicationBundleLookupSnapshot() -> [String: URL] { - var result: [String: URL] = [:] - for descriptor in allBrowserDescriptors { - for bundleIdentifier in descriptor.bundleIdentifiers where result[bundleIdentifier] == nil { - result[bundleIdentifier] = NSWorkspace.shared.urlForApplication(withBundleIdentifier: bundleIdentifier) - } - } - return result - } - static func summaryText(for browsers: [InstalledBrowserCandidate], limit: Int = 4) -> String { guard !browsers.isEmpty else { return String( diff --git a/Sources/Panels/BrowserPanelView.swift b/Sources/Panels/BrowserPanelView.swift index d80f5a7b652a..713351634ce8 100644 --- a/Sources/Panels/BrowserPanelView.swift +++ b/Sources/Panels/BrowserPanelView.swift @@ -438,9 +438,6 @@ struct BrowserPanelView: View { @State private var emptyStateImportBrowserRefreshTask: Task? @State private var emptyStateImportBrowserRefreshGeneration: UInt64 = 0 @State private var inlineCompletion: OmnibarInlineCompletion? - @State private var screenshotPageCopied: Bool = false - @State private var screenshotPageCaptureInProgress: Bool = false - @State private var screenshotPageCopiedTimer: Timer? @State private var omnibarSelectionRange: NSRange = NSRange(location: NSNotFound, length: 0) @State private var omnibarHasMarkedText: Bool = false @State private var suppressNextFocusLostRevert: Bool = false @@ -679,33 +676,6 @@ struct BrowserPanelView: View { panel.reload() } - private func handleScreenshotPageButtonAction() { - guard !screenshotPageCaptureInProgress else { return } - screenshotPageCaptureInProgress = true -#if DEBUG - cmuxDebugLog("browser.screenshot.page.toolbar panel=\(panel.id.uuidString.prefix(5))") -#endif - Task { @MainActor in - defer { - screenshotPageCaptureInProgress = false - } - let didCopy = await panel.captureScreenshotPageToClipboard() - guard didCopy else { return } - showScreenshotPageCopiedIndicator() - } - } - - private func showScreenshotPageCopiedIndicator() { - screenshotPageCopiedTimer?.invalidate() - screenshotPageCopied = true - screenshotPageCopiedTimer = Timer.scheduledTimer(withTimeInterval: 1.4, repeats: false) { _ in - MainActor.assumeIsolated { - screenshotPageCopiedTimer = nil - screenshotPageCopied = false - } - } - } - var body: some View { // Layering contract: browser find UI is mounted in the portal-hosted AppKit // container. Rendering it here can hide it behind the portal-hosted WKWebView. @@ -839,11 +809,6 @@ struct BrowserPanelView: View { logBrowserFocusState(event: "view.onAppear") #endif } - .onDisappear { - screenshotPageCopiedTimer?.invalidate() - screenshotPageCopiedTimer = nil - screenshotPageCopied = false - } .onChange(of: panel.focusFlashToken) { _ in triggerFocusFlashAnimation() } @@ -1029,7 +994,6 @@ struct BrowserPanelView: View { if shouldShowToolbarImportHintChip { browserImportHintToolbarChip } - screenshotPageButton reactGrabButton browserProfileButton browserThemeModeButton @@ -1110,53 +1074,6 @@ struct BrowserPanelView: View { } } - private var screenshotPageButton: some View { - Button(action: handleScreenshotPageButtonAction) { - Image(systemName: screenshotPageCopied ? "checkmark" : "camera") - .symbolRenderingMode(.monochrome) - .cmuxFlatSymbolColorRendering() - .font(.system(size: devToolsButtonIconSize, weight: .medium)) - .foregroundStyle(screenshotPageButtonColor) - .frame(width: addressBarButtonSize, height: addressBarButtonSize, alignment: .center) - } - .buttonStyle(OmnibarAddressButtonStyle()) - .frame(width: addressBarButtonSize, height: addressBarButtonSize, alignment: .center) - .disabled(!panel.shouldRenderWebView || screenshotPageCaptureInProgress) - .opacity(panel.shouldRenderWebView ? 1.0 : 0.4) - .safeHelp( - screenshotPageCopied - ? String(localized: "browser.screenshotPage.copied.help", defaultValue: "Screenshot copied to clipboard") - : String(localized: "browser.screenshotPage.copy.help", defaultValue: "Screenshot Page to Clipboard") - ) - .accessibilityIdentifier("BrowserScreenshotPageButton") - .overlay(alignment: .top) { - if screenshotPageCopied { - Label(String(localized: "browser.screenshotPage.copied", defaultValue: "Copied"), systemImage: "checkmark") - .font(.system(size: 11, weight: .medium)) - .labelStyle(.titleAndIcon) - .foregroundStyle(.primary) - .padding(.horizontal, 8) - .padding(.vertical, 4) - .background(.thinMaterial, in: Capsule()) - .overlay( - Capsule().stroke(Color.white.opacity(0.14), lineWidth: 1) - ) - .fixedSize() - .offset(y: -28) - .allowsHitTesting(false) - .transition(.opacity) - } - } - .animation(.easeOut(duration: 0.12), value: screenshotPageCopied) - } - - private var screenshotPageButtonColor: Color { - if screenshotPageCopied { - return .green - } - return panel.shouldRenderWebView ? devToolsColorOption.color : Color.secondary - } - private var reactGrabButton: some View { Button(action: { panel.clearReactGrabRoundTrip(reason: "toolbarButton.manualStart") diff --git a/Sources/Panels/BrowserScreenshot.swift b/Sources/Panels/BrowserScreenshot.swift deleted file mode 100644 index 4393409a4daa..000000000000 --- a/Sources/Panels/BrowserScreenshot.swift +++ /dev/null @@ -1,437 +0,0 @@ -import AppKit -import ObjectiveC -import QuartzCore - -@MainActor -private final class BrowserScreenshotFlashView: NSView, CAAnimationDelegate { - override init(frame frameRect: NSRect) { - super.init(frame: frameRect) - autoresizingMask = [.width, .height] - wantsLayer = true - layer?.backgroundColor = NSColor(calibratedWhite: 1, alpha: 0.36).cgColor - layer?.opacity = 0 - layer?.zPosition = 20_000 - } - - required init?(coder: NSCoder) { - nil - } - - override var isOpaque: Bool { false } - - func play() { - guard let layer else { - removeFromSuperview() - return - } - - let animation = CABasicAnimation(keyPath: "opacity") - animation.fromValue = 0.32 - animation.toValue = 0 - animation.duration = 0.20 - animation.timingFunction = CAMediaTimingFunction(name: .easeOut) - animation.delegate = self - layer.add(animation, forKey: "browserScreenshotFlash") - } - - nonisolated func animationDidStop(_ anim: CAAnimation, finished flag: Bool) { - Task { @MainActor [weak self] in - self?.removeFromSuperview() - } - } -} - -@MainActor -private enum BrowserScreenshotFlash { - static func show(over view: NSView) { - view.subviews - .compactMap { $0 as? BrowserScreenshotFlashView } - .forEach { $0.removeFromSuperview() } - - let flash = BrowserScreenshotFlashView(frame: view.bounds) - view.addSubview(flash, positioned: .above, relativeTo: nil) - flash.play() - } -} - -@MainActor -private final class BrowserScreenshotSelectionOverlayView: NSView { - private let onFinish: (NSRect?) -> Void - private let instructionBadgeView = FileDropHintBadgeView(frame: .zero) - private var dragStart: NSPoint? - private var dragCurrent: NSPoint? - private var dashPhase: CGFloat = 0 - private var dashTimer: Timer? - private var didFinish = false - - init(frame: NSRect, onFinish: @escaping (NSRect?) -> Void) { - self.onFinish = onFinish - super.init(frame: frame) - autoresizingMask = [.width, .height] - wantsLayer = true - layer?.zPosition = 10_000 - addSubview(instructionBadgeView) - } - - required init?(coder: NSCoder) { - nil - } - - deinit { - dashTimer?.invalidate() - } - - override var acceptsFirstResponder: Bool { true } - override var isOpaque: Bool { false } - - override func viewDidMoveToWindow() { - super.viewDidMoveToWindow() - if window != nil { - window?.makeFirstResponder(self) - startDashAnimation() - updateInstructionBadge() - } else { - dashTimer?.invalidate() - dashTimer = nil - } - } - - override func layout() { - super.layout() - updateInstructionBadge() - } - - override func resetCursorRects() { - addCursorRect(bounds, cursor: .crosshair) - } - - override func mouseDown(with event: NSEvent) { - instructionBadgeView.hide() - let point = clampedPoint(convert(event.locationInWindow, from: nil)) - dragStart = point - dragCurrent = point - needsDisplay = true - } - - override func mouseDragged(with event: NSEvent) { - guard dragStart != nil else { return } - dragCurrent = clampedPoint(convert(event.locationInWindow, from: nil)) - needsDisplay = true - } - - override func mouseUp(with event: NSEvent) { - guard dragStart != nil else { - cancel() - return - } - dragCurrent = clampedPoint(convert(event.locationInWindow, from: nil)) - guard let selection = selectionRect, selection.width >= 2, selection.height >= 2 else { - cancel() - return - } - finish(selection) - } - - override func rightMouseDown(with event: NSEvent) { - _ = event - cancel() - } - - override func keyDown(with event: NSEvent) { - if Self.isCancelEvent(event) { - cancel() - return - } - super.keyDown(with: event) - } - - override func performKeyEquivalent(with event: NSEvent) -> Bool { - if Self.isCancelEvent(event) { - cancel() - return true - } - return super.performKeyEquivalent(with: event) - } - - override func draw(_ dirtyRect: NSRect) { - _ = dirtyRect - guard let context = NSGraphicsContext.current?.cgContext else { return } - - context.saveGState() - NSColor.black.withAlphaComponent(0.42).setFill() - if let selection = selectionRect, selection.width > 0, selection.height > 0 { - let dimPath = NSBezierPath(rect: bounds) - dimPath.append(NSBezierPath(rect: selection)) - dimPath.windingRule = .evenOdd - dimPath.fill() - drawSelectionBorder(selection) - drawDimensionsTooltip(for: selection) - } else { - bounds.fill() - } - context.restoreGState() - } - - private var selectionRect: NSRect? { - guard let dragStart, let dragCurrent else { return nil } - return NSRect( - x: min(dragStart.x, dragCurrent.x), - y: min(dragStart.y, dragCurrent.y), - width: abs(dragCurrent.x - dragStart.x), - height: abs(dragCurrent.y - dragStart.y) - ) - } - - private static func isCancelEvent(_ event: NSEvent) -> Bool { - if event.keyCode == 53 { - return true - } - let modifiers = event.modifierFlags.intersection(.deviceIndependentFlagsMask) - return modifiers.contains(.command) && event.charactersIgnoringModifiers == "." - } - - private func clampedPoint(_ point: NSPoint) -> NSPoint { - NSPoint( - x: min(max(point.x, bounds.minX), bounds.maxX), - y: min(max(point.y, bounds.minY), bounds.maxY) - ) - } - - private func startDashAnimation() { - guard dashTimer == nil else { return } - dashTimer = Timer.scheduledTimer(withTimeInterval: 0.08, repeats: true) { [weak self] _ in - Task { @MainActor [weak self] in - guard let self else { return } - dashPhase = (dashPhase + 1).truncatingRemainder(dividingBy: 8) - needsDisplay = true - } - } - } - - private func drawSelectionBorder(_ selection: NSRect) { - let border = NSBezierPath(rect: selection.insetBy(dx: 0.5, dy: 0.5)) - border.lineWidth = 1 - - NSColor.white.setStroke() - var whitePattern: [CGFloat] = [4, 4] - border.setLineDash(&whitePattern, count: whitePattern.count, phase: dashPhase) - border.stroke() - - NSColor.black.setStroke() - var blackPattern: [CGFloat] = [4, 4] - border.setLineDash(&blackPattern, count: blackPattern.count, phase: dashPhase + 4) - border.stroke() - } - - private func drawDimensionsTooltip(for selection: NSRect) { - let text = "\(Int(selection.width)) x \(Int(selection.height))" - let attributes: [NSAttributedString.Key: Any] = [ - .font: NSFont.monospacedDigitSystemFont(ofSize: 11, weight: .medium), - .foregroundColor: NSColor.white, - ] - let attributed = NSAttributedString(string: text, attributes: attributes) - let textSize = attributed.size() - let padding = NSSize(width: 8, height: 4) - let tooltipSize = NSSize(width: textSize.width + padding.width * 2, height: textSize.height + padding.height * 2) - let origin = tooltipOrigin(for: tooltipSize, near: selection) - let backgroundRect = NSRect(origin: origin, size: tooltipSize) - - NSColor.black.withAlphaComponent(0.72).setFill() - NSBezierPath(roundedRect: backgroundRect, xRadius: 4, yRadius: 4).fill() - attributed.draw( - at: NSPoint( - x: backgroundRect.minX + padding.width, - y: backgroundRect.minY + padding.height - ) - ) - } - - private func updateInstructionBadge() { - guard dragStart == nil, window != nil, bounds.width > 0, bounds.height > 0 else { - instructionBadgeView.hide() - return - } - instructionBadgeView.show( - text: String( - localized: "browser.screenshotSection.instructions", - defaultValue: "Click and drag to select. Esc cancels." - ), - centeredIn: bounds, - clippedTo: bounds - ) - } - - private func tooltipOrigin(for tooltipSize: NSSize, near selection: NSRect) -> NSPoint { - let preferred = NSPoint( - x: selection.minX, - y: selection.minY - tooltipSize.height - 8 - ) - if bounds.contains(NSRect(origin: preferred, size: tooltipSize)) { - return preferred - } - - let fallbackY = min(bounds.maxY - tooltipSize.height - 8, selection.maxY + 8) - return NSPoint( - x: min(max(bounds.minX + 8, selection.minX), bounds.maxX - tooltipSize.width - 8), - y: max(bounds.minY + 8, fallbackY) - ) - } - - private func cancel() { - finish(nil) - } - - private func finish(_ selection: NSRect?) { - guard !didFinish else { return } - didFinish = true - dashTimer?.invalidate() - dashTimer = nil - removeFromSuperview() - onFinish(selection) - } -} - -private var cmuxWebViewScreenshotCaptureGateKey: UInt8 = 0 -private var cmuxWebViewScreenshotSelectionOverlayKey: UInt8 = 0 - -extension CmuxWebView { - @MainActor - private var screenshotCaptureGate: BrowserScreenshotCaptureGate { - if let gate = objc_getAssociatedObject(self, &cmuxWebViewScreenshotCaptureGateKey) as? BrowserScreenshotCaptureGate { - return gate - } - - let gate = BrowserScreenshotCaptureGate() - objc_setAssociatedObject( - self, - &cmuxWebViewScreenshotCaptureGateKey, - gate, - .OBJC_ASSOCIATION_RETAIN_NONATOMIC - ) - return gate - } - - private var screenshotSelectionOverlay: BrowserScreenshotSelectionOverlayView? { - get { - objc_getAssociatedObject(self, &cmuxWebViewScreenshotSelectionOverlayKey) as? BrowserScreenshotSelectionOverlayView - } - set { - objc_setAssociatedObject( - self, - &cmuxWebViewScreenshotSelectionOverlayKey, - newValue, - .OBJC_ASSOCIATION_RETAIN_NONATOMIC - ) - } - } - - func appendScreenshotContextMenuItems(to menu: NSMenu) { - let pageTitle = String(localized: "browser.contextMenu.screenshotPage", defaultValue: "Screenshot Page") - let sectionTitle = String(localized: "browser.contextMenu.screenshotSection", defaultValue: "Screenshot Section") - let items: [(title: String, action: Selector, symbolName: String)] = [ - (pageTitle, #selector(contextMenuScreenshotPage(_:)), "camera"), - (sectionTitle, #selector(contextMenuScreenshotSection(_:)), "viewfinder"), - ].filter { item in - !menu.items.contains { $0.action == item.action || $0.title == item.title } - } - - guard !items.isEmpty else { - return - } - - if !menu.items.isEmpty { - menu.addItem(.separator()) - } - for (title, action, symbolName) in items { - let item = NSMenuItem(title: title, action: action, keyEquivalent: "") - item.target = self - item.image = NSImage(systemSymbolName: symbolName, accessibilityDescription: title) - menu.addItem(item) - } - } - - @MainActor - func captureScreenshotPageToClipboard() async -> Bool { - do { - guard let _ = try await screenshotCaptureGate.run({ - try await BrowserScreenshotPipeline.captureAndWrite( - mode: .fullPage, - snapshot: { try await BrowserScreenshotWebViewSnapshotter.captureFullPage(from: self) }, - pasteboard: .general - ) - }) else { - #if DEBUG - cmuxDebugLog("browser.screenshot.page.ignored reason=captureInProgress") - #endif - return false - } - BrowserScreenshotFlash.show(over: self) - return true - } catch { - #if DEBUG - cmuxDebugLog("browser.screenshot.page.failed error=\(error.localizedDescription)") - #endif - NSSound.beep() - return false - } - } - - @objc func contextMenuScreenshotPage(_ sender: Any?) { - _ = sender - Task { @MainActor [weak self] in - _ = await self?.captureScreenshotPageToClipboard() - } - } - - @objc func contextMenuScreenshotSection(_ sender: Any?) { - _ = sender - beginScreenshotSectionSelection() - } - - private func beginScreenshotSectionSelection() { - screenshotSelectionOverlay?.removeFromSuperview() - - let overlay = BrowserScreenshotSelectionOverlayView(frame: bounds) { [weak self] selection in - guard let self else { return } - self.screenshotSelectionOverlay = nil - guard let selection else { return } - Task { @MainActor [weak self] in - guard let self else { return } - do { - guard let _ = try await self.screenshotCaptureGate.run({ - try await BrowserScreenshotPipeline.captureAndWrite( - mode: .section(selectionInView: selection, viewBounds: self.bounds), - snapshot: { try await BrowserScreenshotWebViewSnapshotter.captureVisibleViewport(from: self) }, - pasteboard: .general - ) - }) else { - #if DEBUG - cmuxDebugLog("browser.screenshot.section.ignored reason=captureInProgress") - #endif - return - } - BrowserScreenshotFlash.show(over: self) - } catch { - #if DEBUG - cmuxDebugLog("browser.screenshot.section.failed error=\(error.localizedDescription)") - #endif - NSSound.beep() - } - } - } - screenshotSelectionOverlay = overlay - addSubview(overlay, positioned: .above, relativeTo: nil) - window?.makeFirstResponder(overlay) - } -} - -extension BrowserPanel { - @MainActor - func captureScreenshotPageToClipboard() async -> Bool { - guard let webView = webView as? CmuxWebView else { - NSSound.beep() - return false - } - return await webView.captureScreenshotPageToClipboard() - } -} diff --git a/Sources/Panels/BrowserScreenshotPipeline.swift b/Sources/Panels/BrowserScreenshotPipeline.swift deleted file mode 100644 index 00fcac3b04ba..000000000000 --- a/Sources/Panels/BrowserScreenshotPipeline.swift +++ /dev/null @@ -1,193 +0,0 @@ -import AppKit -import UniformTypeIdentifiers - -enum BrowserScreenshotError: LocalizedError { - case captureAreaTooLarge - case emptySnapshot - case invalidSelection - case invalidImageRepresentation - case pasteboardWriteFailed - case webContentMetricsUnavailable - - var errorDescription: String? { - switch self { - case .captureAreaTooLarge: - return String( - localized: "browser.screenshot.error.captureAreaTooLarge", - defaultValue: "The page is too large to capture." - ) - case .emptySnapshot: - return String(localized: "browser.screenshot.error.emptySnapshot", defaultValue: "No screenshot was returned.") - case .invalidSelection: - return String( - localized: "browser.screenshot.error.invalidSelection", - defaultValue: "The screenshot selection is empty or outside the browser view." - ) - case .invalidImageRepresentation: - return String( - localized: "browser.screenshot.error.invalidImageRepresentation", - defaultValue: "The screenshot image could not be encoded." - ) - case .pasteboardWriteFailed: - return String( - localized: "browser.screenshot.error.pasteboardWriteFailed", - defaultValue: "The screenshot could not be written to the clipboard." - ) - case .webContentMetricsUnavailable: - return String( - localized: "browser.screenshot.error.webContentMetricsUnavailable", - defaultValue: "The page dimensions could not be read." - ) - } - } -} - -enum BrowserScreenshotCaptureMode { - case fullPage - case section(selectionInView: NSRect, viewBounds: NSRect) -} - -struct BrowserScreenshotResult { - let outputSize: NSSize -} - -@MainActor -final class BrowserScreenshotCaptureGate { - private var isRunning = false - - func run(_ operation: @MainActor () async throws -> T) async throws -> T? { - guard !isRunning else { - return nil - } - - isRunning = true - defer { - isRunning = false - } - return try await operation() - } -} - -enum BrowserScreenshotCrop { - static func imageRect( - forSelectionInView selection: NSRect, - viewBounds: NSRect, - imageSize: NSSize - ) throws -> NSRect { - let normalized = normalizedSelection(selection, in: viewBounds) - guard normalized.width > 0, - normalized.height > 0, - viewBounds.width > 0, - viewBounds.height > 0, - imageSize.width > 0, - imageSize.height > 0 else { - throw BrowserScreenshotError.invalidSelection - } - - let scaleX = imageSize.width / viewBounds.width - let scaleY = imageSize.height / viewBounds.height - let imageRect = NSRect( - x: (normalized.minX - viewBounds.minX) * scaleX, - y: (normalized.minY - viewBounds.minY) * scaleY, - width: normalized.width * scaleX, - height: normalized.height * scaleY - ) - return clamp(imageRect, to: NSRect(origin: .zero, size: imageSize)) - } - - static func croppedImage( - from image: NSImage, - selectionInView selection: NSRect, - viewBounds: NSRect - ) throws -> NSImage { - let cropRect = try imageRect( - forSelectionInView: selection, - viewBounds: viewBounds, - imageSize: image.size - ).integral - guard cropRect.width > 0, cropRect.height > 0 else { - throw BrowserScreenshotError.invalidSelection - } - - let cropped = NSImage(size: cropRect.size) - cropped.lockFocus() - image.draw( - in: NSRect(origin: .zero, size: cropRect.size), - from: cropRect, - operation: .copy, - fraction: 1.0 - ) - cropped.unlockFocus() - return cropped - } - - private static func normalizedSelection(_ selection: NSRect, in bounds: NSRect) -> NSRect { - let minX = min(selection.minX, selection.maxX) - let minY = min(selection.minY, selection.maxY) - let rect = NSRect( - x: minX, - y: minY, - width: abs(selection.width), - height: abs(selection.height) - ) - return clamp(rect, to: bounds) - } - - private static func clamp(_ rect: NSRect, to bounds: NSRect) -> NSRect { - let minX = max(bounds.minX, min(rect.minX, bounds.maxX)) - let maxX = max(bounds.minX, min(rect.maxX, bounds.maxX)) - let minY = max(bounds.minY, min(rect.minY, bounds.maxY)) - let maxY = max(bounds.minY, min(rect.maxY, bounds.maxY)) - return NSRect(x: minX, y: minY, width: max(0, maxX - minX), height: max(0, maxY - minY)) - } -} - -enum BrowserScreenshotPasteboardWriter { - static func write(_ image: NSImage, to pasteboard: NSPasteboard = .general) throws { - let item = try pasteboardItem(for: image) - pasteboard.clearContents() - guard pasteboard.writeObjects([item]) else { - throw BrowserScreenshotError.pasteboardWriteFailed - } - } - - static func pasteboardItem(for image: NSImage) throws -> NSPasteboardItem { - guard let tiffData = image.tiffRepresentation, - let bitmap = NSBitmapImageRep(data: tiffData), - let pngData = bitmap.representation(using: .png, properties: [:]) else { - throw BrowserScreenshotError.invalidImageRepresentation - } - - let item = NSPasteboardItem() - item.setData(pngData, forType: NSPasteboard.PasteboardType(UTType.png.identifier)) - item.setData(tiffData, forType: NSPasteboard.PasteboardType(UTType.tiff.identifier)) - return item - } -} - -enum BrowserScreenshotPipeline { - typealias SnapshotProvider = @MainActor () async throws -> NSImage - - @MainActor - static func captureAndWrite( - mode: BrowserScreenshotCaptureMode, - snapshot: SnapshotProvider, - pasteboard: NSPasteboard = .general - ) async throws -> BrowserScreenshotResult { - let captured = try await snapshot() - let output: NSImage - switch mode { - case .fullPage: - output = captured - case let .section(selectionInView, viewBounds): - output = try BrowserScreenshotCrop.croppedImage( - from: captured, - selectionInView: selectionInView, - viewBounds: viewBounds - ) - } - - try BrowserScreenshotPasteboardWriter.write(output, to: pasteboard) - return BrowserScreenshotResult(outputSize: output.size) - } -} diff --git a/Sources/Panels/BrowserScreenshotSnapshotter.swift b/Sources/Panels/BrowserScreenshotSnapshotter.swift deleted file mode 100644 index 712dbaac4925..000000000000 --- a/Sources/Panels/BrowserScreenshotSnapshotter.swift +++ /dev/null @@ -1,307 +0,0 @@ -import AppKit -import WebKit - -private struct BrowserScreenshotWebContentMetrics { - let contentSize: NSSize - let viewportSize: NSSize - let scrollOffset: NSPoint -} - -struct BrowserScreenshotTileDrawRects: Equatable { - let source: NSRect - let destination: NSRect -} - -enum BrowserScreenshotTilePlacement { - static func drawRects( - tileSize: NSSize, - origin: NSPoint, - contentSize: NSSize, - viewportSize: NSSize - ) -> BrowserScreenshotTileDrawRects? { - let drawWidth = min(viewportSize.width, tileSize.width, max(0, contentSize.width - origin.x)) - let drawHeight = min(viewportSize.height, tileSize.height, max(0, contentSize.height - origin.y)) - guard drawWidth > 0, drawHeight > 0 else { return nil } - - return BrowserScreenshotTileDrawRects( - source: NSRect( - x: 0, - y: max(0, tileSize.height - drawHeight), - width: drawWidth, - height: drawHeight - ), - destination: NSRect( - x: origin.x, - y: contentSize.height - origin.y - drawHeight, - width: drawWidth, - height: drawHeight - ) - ) - } -} - -enum BrowserScreenshotCaptureBounds { - static let maximumFullPagePixels: CGFloat = 100_000_000 - - static func validateFullPageSize(_ size: NSSize) throws { - guard size.width.isFinite, - size.height.isFinite, - size.width > 0, - size.height > 0 else { - throw BrowserScreenshotError.webContentMetricsUnavailable - } - - let pixelCount = ceil(size.width) * ceil(size.height) - guard pixelCount <= maximumFullPagePixels else { - throw BrowserScreenshotError.captureAreaTooLarge - } - } -} - -@MainActor -enum BrowserScreenshotWebViewSnapshotter { - static func captureFullPage(from webView: WKWebView) async throws -> NSImage { - let metrics = try await webContentMetrics(for: webView) - try BrowserScreenshotCaptureBounds.validateFullPageSize(metrics.contentSize) - do { - let image = try await captureSingleFullContentSnapshot(from: webView, metrics: metrics) - if isAcceptableFullContentSnapshot(image, metrics: metrics) { - return image - } - } catch { - #if DEBUG - cmuxDebugLog("browser.screenshot.fullPage.singleSnapshot.failed error=\(error.localizedDescription)") - #endif - } - - return try await captureStitchedFullPage(from: webView, metrics: metrics) - } - - static func captureVisibleViewport(from webView: WKWebView) async throws -> NSImage { - let configuration = WKSnapshotConfiguration() - configuration.afterScreenUpdates = true - return try await takeSnapshot(from: webView, configuration: configuration) - } - - private static func captureSingleFullContentSnapshot( - from webView: WKWebView, - metrics: BrowserScreenshotWebContentMetrics - ) async throws -> NSImage { - let configuration = WKSnapshotConfiguration() - configuration.afterScreenUpdates = true - configuration.snapshotWidth = nil - configuration.rect = NSRect(origin: .zero, size: metrics.contentSize) - return try await takeSnapshot(from: webView, configuration: configuration) - } - - private static func captureStitchedFullPage( - from webView: WKWebView, - metrics: BrowserScreenshotWebContentMetrics - ) async throws -> NSImage { - let contentSize = metrics.contentSize - let viewportSize = metrics.viewportSize - guard contentSize.width > 0, - contentSize.height > 0, - viewportSize.width > 0, - viewportSize.height > 0 else { - throw BrowserScreenshotError.webContentMetricsUnavailable - } - try BrowserScreenshotCaptureBounds.validateFullPageSize(contentSize) - - let xPositions = tileOrigins(contentLength: contentSize.width, viewportLength: viewportSize.width) - let yPositions = tileOrigins(contentLength: contentSize.height, viewportLength: viewportSize.height) - var captureError: Error? - var didCaptureTile = false - let output = blankImage(size: contentSize) - - do { - for y in yPositions { - for x in xPositions { - try await scroll(webView, to: NSPoint(x: x, y: y)) - let tile = try await captureVisibleViewport(from: webView) - drawTile( - tile, - at: NSPoint(x: x, y: y), - into: output, - contentSize: contentSize, - viewportSize: viewportSize - ) - didCaptureTile = true - } - } - } catch { - captureError = error - } - - try? await scroll(webView, to: metrics.scrollOffset) - if let captureError { - throw captureError - } - - guard didCaptureTile else { - throw BrowserScreenshotError.emptySnapshot - } - - return output - } - - private static func isAcceptableFullContentSnapshot( - _ image: NSImage, - metrics: BrowserScreenshotWebContentMetrics - ) -> Bool { - let contentSize = metrics.contentSize - guard contentSize.width > 0, contentSize.height > 0 else { return false } - let widthMatches = image.size.width >= contentSize.width * 0.95 - let heightMatches = image.size.height >= contentSize.height * 0.95 - return widthMatches && heightMatches - } - - private static func tileOrigins(contentLength: CGFloat, viewportLength: CGFloat) -> [CGFloat] { - guard contentLength > 0, viewportLength > 0 else { return [0] } - guard contentLength > viewportLength else { return [0] } - - var origins: [CGFloat] = [] - var next: CGFloat = 0 - let last = max(0, contentLength - viewportLength) - while next < last { - origins.append(next) - next += viewportLength - } - if origins.last.map({ abs($0 - last) > 0.5 }) ?? true { - origins.append(last) - } - return origins - } - - private static func blankImage(size: NSSize) -> NSImage { - let output = NSImage(size: size) - output.lockFocus() - NSColor.clear.setFill() - NSRect(origin: .zero, size: size).fill() - output.unlockFocus() - return output - } - - private static func drawTile( - _ tile: NSImage, - at origin: NSPoint, - into output: NSImage, - contentSize: NSSize, - viewportSize: NSSize - ) { - guard let rects = BrowserScreenshotTilePlacement.drawRects( - tileSize: tile.size, - origin: origin, - contentSize: contentSize, - viewportSize: viewportSize - ) else { - return - } - - output.lockFocus() - defer { output.unlockFocus() } - tile.draw( - in: rects.destination, - from: rects.source, - operation: .copy, - fraction: 1.0 - ) - } - - private static func webContentMetrics(for webView: WKWebView) async throws -> BrowserScreenshotWebContentMetrics { - let script = """ - (() => { - const doc = document.documentElement; - const body = document.body; - const contentWidth = Math.max( - doc ? doc.scrollWidth : 0, - body ? body.scrollWidth : 0, - doc ? doc.clientWidth : 0, - window.innerWidth || 0 - ); - const contentHeight = Math.max( - doc ? doc.scrollHeight : 0, - body ? body.scrollHeight : 0, - doc ? doc.clientHeight : 0, - window.innerHeight || 0 - ); - return { - contentWidth, - contentHeight, - viewportWidth: window.innerWidth || (doc ? doc.clientWidth : 0), - viewportHeight: window.innerHeight || (doc ? doc.clientHeight : 0), - scrollX: window.scrollX || 0, - scrollY: window.scrollY || 0 - }; - })(); - """ - - guard let value = try await webView.evaluateJavaScript(script, contentWorld: .page) as? [String: Any] else { - throw BrowserScreenshotError.webContentMetricsUnavailable - } - - let contentWidth = numberValue(value["contentWidth"]) - let contentHeight = numberValue(value["contentHeight"]) - let viewportWidth = max(numberValue(value["viewportWidth"]), webView.bounds.width) - let viewportHeight = max(numberValue(value["viewportHeight"]), webView.bounds.height) - guard contentWidth > 0, contentHeight > 0, viewportWidth > 0, viewportHeight > 0 else { - throw BrowserScreenshotError.webContentMetricsUnavailable - } - - return BrowserScreenshotWebContentMetrics( - contentSize: NSSize(width: contentWidth, height: contentHeight), - viewportSize: NSSize(width: viewportWidth, height: viewportHeight), - scrollOffset: NSPoint( - x: numberValue(value["scrollX"]), - y: numberValue(value["scrollY"]) - ) - ) - } - - private static func scroll(_ webView: WKWebView, to point: NSPoint) async throws { - _ = try await webView.callAsyncJavaScript( - """ - window.scrollTo(x, y); - await new Promise((resolve) => { - requestAnimationFrame(() => requestAnimationFrame(resolve)); - }); - return { x: window.scrollX || 0, y: window.scrollY || 0 }; - """, - arguments: [ - "x": Double(point.x), - "y": Double(point.y), - ], - in: nil, - contentWorld: .page - ) - } - - private static func takeSnapshot( - from webView: WKWebView, - configuration: WKSnapshotConfiguration - ) async throws -> NSImage { - try await withCheckedThrowingContinuation { continuation in - webView.takeSnapshot(with: configuration) { image, error in - if let image { - continuation.resume(returning: image) - return - } - - continuation.resume(throwing: error ?? BrowserScreenshotError.emptySnapshot) - } - } - } - - private static func numberValue(_ value: Any?) -> CGFloat { - switch value { - case let number as NSNumber: - return CGFloat(number.doubleValue) - case let double as Double: - return CGFloat(double) - case let int as Int: - return CGFloat(int) - default: - return 0 - } - } -} diff --git a/Sources/Panels/CmuxWebView.swift b/Sources/Panels/CmuxWebView.swift index 065522c83396..0d46285837fa 100644 --- a/Sources/Panels/CmuxWebView.swift +++ b/Sources/Panels/CmuxWebView.swift @@ -2127,7 +2127,6 @@ final class CmuxWebView: WKWebView { item.target = self menu.insertItem(item, at: min(openLinkInsertionIndex, menu.items.count)) } - appendScreenshotContextMenuItems(to: menu) appendMoveTabToNewWorkspaceContextMenuItem(to: menu) } @objc private func contextMenuOpenLinkInDefaultBrowser(_ sender: Any?) { diff --git a/Sources/Panels/FilePreviewPanel.swift b/Sources/Panels/FilePreviewPanel.swift index 15cfdfe9e88a..ea3caa67583e 100644 --- a/Sources/Panels/FilePreviewPanel.swift +++ b/Sources/Panels/FilePreviewPanel.swift @@ -4282,22 +4282,8 @@ private struct QuickLookPreviewView: NSViewRepresentable { let backgroundColor: NSColor let drawsBackground: Bool - final class Coordinator { - var quickLook: FilePreviewQuickLookSession? - - init(panel: FilePreviewPanel) { - quickLook = panel.nativeViewSessions.quickLook - } - } - - func makeCoordinator() -> Coordinator { - Coordinator(panel: panel) - } - func makeNSView(context: Context) -> NSView { - let quickLook = panel.nativeViewSessions.quickLook - context.coordinator.quickLook = quickLook - return quickLook.view( + panel.nativeViewSessions.quickLook.view( panel: panel, isVisibleInUI: isVisibleInUI, backgroundColor: backgroundColor, @@ -4306,9 +4292,7 @@ private struct QuickLookPreviewView: NSViewRepresentable { } func updateNSView(_ nsView: NSView, context: Context) { - let quickLook = panel.nativeViewSessions.quickLook - context.coordinator.quickLook = quickLook - quickLook.update( + panel.nativeViewSessions.quickLook.update( nsView, panel: panel, isVisibleInUI: isVisibleInUI, @@ -4316,11 +4300,6 @@ private struct QuickLookPreviewView: NSViewRepresentable { drawsBackground: drawsBackground ) } - - static func dismantleNSView(_ nsView: NSView, coordinator: Coordinator) { - coordinator.quickLook?.dismantle(nsView) - coordinator.quickLook = nil - } } private struct FilePreviewPointerObserver: NSViewRepresentable { diff --git a/Sources/Panels/FilePreviewQuickLookSession.swift b/Sources/Panels/FilePreviewQuickLookSession.swift index c0ccd50b98bc..1e28ec1a7177 100644 --- a/Sources/Panels/FilePreviewQuickLookSession.swift +++ b/Sources/Panels/FilePreviewQuickLookSession.swift @@ -22,7 +22,16 @@ private final class FilePreviewQLItem: NSObject, QLPreviewItem { @MainActor final class FilePreviewQuickLookSession { - private let liveViews = NSHashTable.weakObjects() + private let viewSession = PanelOwnedNativeViewSession( + makeView: FilePreviewQuickLookSession.makeView, + closeView: { view in + if let previewView = view as? QLPreviewView { + previewView.close() + previewView.previewItem = nil + } + view.removeFromSuperview() + } + ) private var item: FilePreviewQLItem? deinit { @@ -35,16 +44,15 @@ final class FilePreviewQuickLookSession { backgroundColor: NSColor, drawsBackground: Bool ) -> NSView { - let view = Self.makeView() - liveViews.add(view) - configure( - view, - panel: panel, - isVisibleInUI: isVisibleInUI, - backgroundColor: backgroundColor, - drawsBackground: drawsBackground - ) - return view + viewSession.view { + configure( + $0, + panel: panel, + isVisibleInUI: isVisibleInUI, + backgroundColor: backgroundColor, + drawsBackground: drawsBackground + ) + } } func update( @@ -54,30 +62,19 @@ final class FilePreviewQuickLookSession { backgroundColor: NSColor, drawsBackground: Bool ) { - guard liveViews.contains(view) else { return } - configure( - view, - panel: panel, - isVisibleInUI: isVisibleInUI, - backgroundColor: backgroundColor, - drawsBackground: drawsBackground - ) - } - - func dismantle(_ view: NSView) { - guard liveViews.contains(view) else { return } - liveViews.remove(view) - Self.releaseView(view) - if liveViews.allObjects.isEmpty { - item = nil + viewSession.update(view) { + configure( + $0, + panel: panel, + isVisibleInUI: isVisibleInUI, + backgroundColor: backgroundColor, + drawsBackground: drawsBackground + ) } } func close() { - for view in liveViews.allObjects { - Self.releaseView(view) - } - liveViews.removeAllObjects() + viewSession.close() item = nil } @@ -89,16 +86,6 @@ final class FilePreviewQuickLookSession { return previewView } - private static func releaseView(_ view: NSView) { - if let previewView = view as? QLPreviewView { - // QLPreviewView.close() asserts when the view is inactive and makes the - // view permanently reject future items. Session retirement handles stale - // updates; clearing the item releases the active preview. - previewView.previewItem = nil - } - view.removeFromSuperview() - } - private func configure( _ view: NSView, panel: FilePreviewPanel, diff --git a/Sources/Panels/Panel.swift b/Sources/Panels/Panel.swift index 146bde0a9c2a..9cc1d917ebb4 100644 --- a/Sources/Panels/Panel.swift +++ b/Sources/Panels/Panel.swift @@ -69,7 +69,7 @@ public enum WorkspaceAttentionFlashReason: String, Equatable, Sendable { case navigation case notificationArrival case notificationDismiss - case unreadIndicatorDismiss + case manualUnreadDismiss case debug } @@ -126,7 +126,7 @@ enum WorkspaceAttentionCoordinator { glowOpacity: 0.14, glowRadius: 3 ) - case .notificationArrival, .notificationDismiss, .unreadIndicatorDismiss, .debug: + case .notificationArrival, .notificationDismiss, .manualUnreadDismiss, .debug: return WorkspaceAttentionFlashPresentation( accent: .notificationBlue, glowOpacity: 0.6, @@ -144,7 +144,7 @@ enum WorkspaceAttentionCoordinator { switch reason { case .navigation: isAllowed = !persistentState.hasCompetingIndicator(for: targetPanelID) - case .notificationArrival, .notificationDismiss, .unreadIndicatorDismiss, .debug: + case .notificationArrival, .notificationDismiss, .manualUnreadDismiss, .debug: isAllowed = true } diff --git a/Sources/Panels/PanelOwnedNativeViewSession.swift b/Sources/Panels/PanelOwnedNativeViewSession.swift index 7b506753f96c..33bf045f94d2 100644 --- a/Sources/Panels/PanelOwnedNativeViewSession.swift +++ b/Sources/Panels/PanelOwnedNativeViewSession.swift @@ -4,19 +4,14 @@ import AppKit final class PanelOwnedNativeViewSession { private let makeView: @MainActor () -> View private let closeView: @MainActor (View) -> Void - private let dismantleView: @MainActor (View) -> Void private var ownedView: View? - private var retiredViews: Set = [] - private var dismantledViews: Set = [] init( makeView: @escaping @MainActor () -> View, - closeView: @escaping @MainActor (View) -> Void = { $0.removeFromSuperview() }, - dismantleView: (@MainActor (View) -> Void)? = nil + closeView: @escaping @MainActor (View) -> Void = { $0.removeFromSuperview() } ) { self.makeView = makeView self.closeView = closeView - self.dismantleView = dismantleView ?? closeView } deinit { @@ -25,9 +20,6 @@ final class PanelOwnedNativeViewSession { func view(configure: @MainActor (View) -> Void) -> View { let view = ownedView ?? makeView() - let viewId = ObjectIdentifier(view) - retiredViews.remove(viewId) - dismantledViews.remove(viewId) ownedView = view if view.superview != nil { view.removeFromSuperview() @@ -37,7 +29,6 @@ final class PanelOwnedNativeViewSession { } func update(_ view: View, configure: @MainActor (View) -> Void) { - guard !retiredViews.contains(ObjectIdentifier(view)) else { return } if ownedView == nil { ownedView = view } @@ -46,23 +37,8 @@ final class PanelOwnedNativeViewSession { func close() { if let ownedView { - retiredViews.insert(ObjectIdentifier(ownedView)) closeView(ownedView) } ownedView = nil } - - @discardableResult - func dismantle(_ view: View) -> Bool { - let viewId = ObjectIdentifier(view) - guard !dismantledViews.contains(viewId) else { return false } - retiredViews.insert(viewId) - dismantledViews.insert(viewId) - let dismantledOwnedView = ownedView === view - if dismantledOwnedView { - ownedView = nil - } - dismantleView(view) - return dismantledOwnedView - } } diff --git a/Sources/Panels/TerminalPanelView.swift b/Sources/Panels/TerminalPanelView.swift index 0cab106980b1..d0b69cbd291f 100644 --- a/Sources/Panels/TerminalPanelView.swift +++ b/Sources/Panels/TerminalPanelView.swift @@ -65,16 +65,12 @@ struct PanelAppearance { } static func fromConfig(_ config: GhosttyConfig, usesTransparentWindow: Bool) -> PanelAppearance { - let backgroundColor = GhosttyBackgroundTheme.color( - backgroundColor: config.backgroundColor, - opacity: config.backgroundOpacity - ) - return PanelAppearance( - backgroundColor: backgroundColor, - foregroundColor: cmuxReadableForegroundNSColor( - preferred: config.foregroundColor, - on: backgroundColor + PanelAppearance( + backgroundColor: GhosttyBackgroundTheme.color( + backgroundColor: config.backgroundColor, + opacity: config.backgroundOpacity ), + foregroundColor: config.foregroundColor, dividerColor: Color(nsColor: config.resolvedSplitDividerColor), unfocusedOverlayNSColor: config.unfocusedSplitOverlayFill, unfocusedOverlayOpacity: config.unfocusedSplitOverlayOpacity, diff --git a/Sources/RestorableAgentSession.swift b/Sources/RestorableAgentSession.swift index 68e6bf8f27ce..17d579ea99fb 100644 --- a/Sources/RestorableAgentSession.swift +++ b/Sources/RestorableAgentSession.swift @@ -193,15 +193,6 @@ enum AgentResumeCommandBuilder { if case .custom = kind { guard let customRegistration else { return nil } - if customRegistration.id == CmuxVaultAgentRegistration.builtInAntigravity.id { - return resumeWithOption( - kind: "antigravity", - launchCommand: launchCommand, - fallbackExecutable: customRegistration.defaultExecutable, - option: "--conversation", - sessionId: sessionId - ) - } let arguments = customResumeArguments( registration: customRegistration, sessionId: sessionId, @@ -260,14 +251,6 @@ enum AgentResumeCommandBuilder { option: "--resume", sessionId: sessionId ) - case .antigravity: - return resumeWithOption( - kind: "antigravity", - launchCommand: launchCommand, - fallbackExecutable: "agy", - option: "--conversation", - sessionId: sessionId - ) case .opencode: let original = commandParts(launchCommand: launchCommand, fallbackExecutable: "opencode") guard let preserved = AgentLaunchSanitizer.preservedArguments(kind: "opencode", args: original.tail) else { return nil } diff --git a/Sources/RestorableAgentTypes.swift b/Sources/RestorableAgentTypes.swift index 070f7c412cc3..d45dc561eb12 100644 --- a/Sources/RestorableAgentTypes.swift +++ b/Sources/RestorableAgentTypes.swift @@ -8,7 +8,6 @@ enum RestorableAgentKind: Codable, Hashable, Sendable { case amp case cursor case gemini - case antigravity case opencode case rovodev case hermesAgent @@ -21,13 +20,12 @@ enum RestorableAgentKind: Codable, Hashable, Sendable { static let allCases: [RestorableAgentKind] = [ .claude, .codex, - // Pi and Grok are registry-owned so the built-in Vault registrations can be - // overridden by project config while direct native values still encode. + .grok, + // Pi is registry-owned so the built-in Vault registration can be + // overridden by project config while direct .pi values still encode. .amp, .cursor, .gemini, - // Antigravity is registry-owned so the built-in Vault registration can be - // overridden by project config while direct .antigravity values still encode. .opencode, .rovodev, .hermesAgent, @@ -47,7 +45,6 @@ enum RestorableAgentKind: Codable, Hashable, Sendable { case "amp": self = .amp case "cursor": self = .cursor case "gemini": self = .gemini - case "antigravity": self = .antigravity case "opencode": self = .opencode case "rovodev": self = .rovodev case "hermes-agent": self = .hermesAgent @@ -70,7 +67,6 @@ enum RestorableAgentKind: Codable, Hashable, Sendable { case .amp: return "amp" case .cursor: return "cursor" case .gemini: return "gemini" - case .antigravity: return "antigravity" case .opencode: return "opencode" case .rovodev: return "rovodev" case .hermesAgent: return "hermes-agent" diff --git a/Sources/SessionAgentPresentation.swift b/Sources/SessionAgentPresentation.swift index 9a5747d2d9af..51d65f4ecbb2 100644 --- a/Sources/SessionAgentPresentation.swift +++ b/Sources/SessionAgentPresentation.swift @@ -19,7 +19,7 @@ extension SessionAgent { switch self { case .claude: return "AgentIcons/Claude" case .codex: return "AgentIcons/Codex" - case .grok: return "AgentIcons/Grok" + case .grok: return nil case .opencode: return "AgentIcons/OpenCode" case .rovodev: return "AgentIcons/RovoDev" case .registered(let agent): diff --git a/Sources/SessionIndexModels.swift b/Sources/SessionIndexModels.swift index baaddd5a897d..0372cb4bfc88 100644 --- a/Sources/SessionIndexModels.swift +++ b/Sources/SessionIndexModels.swift @@ -342,21 +342,21 @@ struct SessionEntry: Identifiable, Hashable { } return parts.joined(separator: " ") case let .grok(model, permissionMode, sandboxMode, grokHome): - var argv = ["grok", "-r", sessionId] + var parts = ["grok -r \(Self.shellQuote(sessionId))"] if let model, !model.isEmpty { - argv.append(contentsOf: ["-m", model]) + parts.append("-m \(Self.shellQuote(model))") } if let permissionMode, !permissionMode.isEmpty { - argv.append(contentsOf: ["--permission-mode", permissionMode]) + parts.append("--permission-mode \(Self.shellQuote(permissionMode))") } if let sandboxMode, !sandboxMode.isEmpty { - argv.append(contentsOf: ["--sandbox", sandboxMode]) + parts.append("--sandbox \(Self.shellQuote(sandboxMode))") } let environment = grokHome.flatMap { value -> [String: String]? in let trimmed = value.trimmingCharacters(in: .whitespacesAndNewlines) return trimmed.isEmpty ? nil : ["GROK_HOME": trimmed] } ?? [:] - return Self.singleQuotedShellCommand(environment: environment, argv: argv) + return Self.withShellEnvironment(environment, command: parts.joined(separator: " ")) case let .opencode(providerModel, agentName): var parts = ["opencode --session \(sessionId)"] if let providerModel, !providerModel.isEmpty { @@ -412,29 +412,6 @@ struct SessionEntry: Identifiable, Hashable { return "env \(assignments.joined(separator: " ")) \(command)" } - private static func singleQuotedShellCommand( - environment: [String: String], - argv: [String] - ) -> String { - var parts: [String] = [] - let assignments = environment - .filter { key, _ in - key.range(of: #"^[A-Za-z_][A-Za-z0-9_]*$"#, options: .regularExpression) != nil - } - .sorted { $0.key < $1.key } - .map { key, value in "\(key)=\(value)" } - if !assignments.isEmpty { - parts.append("env") - parts.append(contentsOf: assignments) - } - parts.append(contentsOf: argv) - return parts.map(Self.shellSingleQuote).joined(separator: " ") - } - - private static func shellSingleQuote(_ value: String) -> String { - "'\(value.replacingOccurrences(of: "'", with: #"'\''"#))'" - } - /// Single-quote a value for safe shell injection. Escapes embedded single quotes. static func shellQuote(_ value: String) -> String { if value.range(of: "[^A-Za-z0-9_./:=+-]", options: .regularExpression) == nil { diff --git a/Sources/SessionIndexRegisteredAgents.swift b/Sources/SessionIndexRegisteredAgents.swift index 1dbd6888dbd2..08e42c634a23 100644 --- a/Sources/SessionIndexRegisteredAgents.swift +++ b/Sources/SessionIndexRegisteredAgents.swift @@ -1,228 +1,5 @@ import Foundation -struct GrokSessionRoot: Sendable, Hashable { - let sessionsRoot: String - let grokHomeForResume: String? -} - -private struct GrokHookObservedSessionStoreFile: Decodable { - var sessions: [String: GrokHookObservedSessionRecord] - - private enum CodingKeys: String, CodingKey { - case sessions - } - - init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: CodingKeys.self) - sessions = try container.decodeIfPresent( - [String: GrokHookObservedSessionRecord].self, - forKey: .sessions - ) ?? [:] - } -} - -private struct GrokHookObservedSessionRecord: Decodable { - var launchCommand: GrokHookObservedLaunchCommand? -} - -private struct GrokHookObservedLaunchCommand: Decodable { - var environment: [String: String]? -} - -enum GrokSessionLocator { - static func defaultSessionsRoot(homeDirectory: String = NSHomeDirectory()) -> String { - let standardizedHome = expandTilde(homeDirectory, homeDirectory: homeDirectory) - return ((standardizedHome as NSString).appendingPathComponent(".grok") as NSString) - .appendingPathComponent("sessions") - } - - static func encodedSessionCWD(_ cwd: String) -> String { - var encoded = "" - for byte in cwd.utf8 { - let isUnreserved = (byte >= 0x41 && byte <= 0x5A) - || (byte >= 0x61 && byte <= 0x7A) - || (byte >= 0x30 && byte <= 0x39) - || byte == 0x2D - || byte == 0x2E - || byte == 0x5F - || byte == 0x7E - if isUnreserved { - encoded.append(Character(UnicodeScalar(byte))) - } else { - encoded.append(String(format: "%%%02X", byte)) - } - } - return encoded - } - - static func workingDirectory(fromProjectDirectoryName name: String) -> String? { - let decoded = name.removingPercentEncoding ?? name - return normalizedWorkingDirectory(decoded) - } - - static func normalizedWorkingDirectory(_ value: String?) -> String? { - let trimmed = normalized(value) - return trimmed.map { ($0 as NSString).standardizingPath } - } - - static func encodedSessionCWDs(for cwd: String) -> [String] { - guard let rawCwd = normalized(cwd) else { - return [] - } - var seen = Set() - return [rawCwd, (rawCwd as NSString).standardizingPath] - .map(encodedSessionCWD) - .filter { seen.insert($0).inserted } - } - - static func sessionRoot( - registration: CmuxVaultAgentRegistration, - environment: [String: String] = ProcessInfo.processInfo.environment, - homeDirectory: String = NSHomeDirectory() - ) -> GrokSessionRoot { - let rawRoot: String - let configuredRoot = normalized(registration.sessionDirectory) - let configuredIsDefault = configuredRoot.map { - expandTilde($0, homeDirectory: homeDirectory) - == (defaultSessionsRoot(homeDirectory: homeDirectory) as NSString).standardizingPath - } ?? false - if let grokHome = normalized(environment["GROK_HOME"]), - configuredRoot == nil || configuredIsDefault { - rawRoot = (grokHome as NSString).appendingPathComponent("sessions") - } else if let configured = configuredRoot { - rawRoot = configured - } else { - rawRoot = defaultSessionsRoot(homeDirectory: homeDirectory) - } - let sessionsRoot = expandTilde(rawRoot, homeDirectory: homeDirectory) - let grokHome = grokHomeForResume( - sessionsRoot: sessionsRoot, - defaultSessionsRoot: defaultSessionsRoot(homeDirectory: homeDirectory) - ) - return GrokSessionRoot(sessionsRoot: sessionsRoot, grokHomeForResume: grokHome) - } - - static func sessionRoots( - registration: CmuxVaultAgentRegistration, - cwdFilter: String?, - environment: [String: String] = ProcessInfo.processInfo.environment, - homeDirectory: String = NSHomeDirectory(), - observedGrokHomes: [String] = [] - ) -> [GrokSessionRoot] { - let root = sessionRoot( - registration: registration, - environment: environment, - homeDirectory: homeDirectory - ) - var roots = [root] - if registrationUsesDefaultGrokRoot(registration: registration, homeDirectory: homeDirectory) { - for grokHome in observedGrokHomes { - guard let candidate = sessionRoot( - grokHome: grokHome, - homeDirectory: homeDirectory - ) else { - continue - } - roots.append(candidate) - } - roots = deduplicatedSessionRoots(roots) - } - guard let cwdFilter = normalized(cwdFilter) else { - return roots - } - let scopedRoots = roots.flatMap { root in - encodedSessionCWDs(for: cwdFilter).map { encodedCwd in - let scopedRoot = (root.sessionsRoot as NSString).appendingPathComponent(encodedCwd) - return GrokSessionRoot(sessionsRoot: scopedRoot, grokHomeForResume: root.grokHomeForResume) - } - } - return deduplicatedSessionRoots(scopedRoots) - } - - static func observedGrokHomes( - homeDirectory: String = NSHomeDirectory(), - environment: [String: String] = ProcessInfo.processInfo.environment, - fileManager: FileManager = .default - ) -> [String] { - let storeURL = RestorableAgentKind.grok.hookStoreFileURL( - homeDirectory: homeDirectory, - environment: environment - ) - guard fileManager.fileExists(atPath: storeURL.path), - let data = try? Data(contentsOf: storeURL), - let state = try? JSONDecoder().decode(GrokHookObservedSessionStoreFile.self, from: data) else { - return [] - } - - var seen = Set() - var homes: [String] = [] - for record in state.sessions.values { - guard let rawHome = normalized(record.launchCommand?.environment?["GROK_HOME"]) else { - continue - } - let home = expandTilde(rawHome, homeDirectory: homeDirectory) - guard seen.insert(home).inserted else { continue } - homes.append(home) - } - return homes - } - - private static func grokHomeForResume(sessionsRoot: String, defaultSessionsRoot: String) -> String? { - let standardizedRoot = (sessionsRoot as NSString).standardizingPath - let standardizedDefault = (defaultSessionsRoot as NSString).standardizingPath - guard standardizedRoot != standardizedDefault else { return nil } - guard (standardizedRoot as NSString).lastPathComponent == "sessions" else { return nil } - return (standardizedRoot as NSString).deletingLastPathComponent - } - - private static func sessionRoot(grokHome: String, homeDirectory: String) -> GrokSessionRoot? { - guard let normalizedHome = normalized(grokHome) else { return nil } - let expandedHome = expandTilde(normalizedHome, homeDirectory: homeDirectory) - let sessionsRoot = (expandedHome as NSString).appendingPathComponent("sessions") - let grokHome = grokHomeForResume( - sessionsRoot: sessionsRoot, - defaultSessionsRoot: defaultSessionsRoot(homeDirectory: homeDirectory) - ) - return GrokSessionRoot(sessionsRoot: sessionsRoot, grokHomeForResume: grokHome) - } - - private static func registrationUsesDefaultGrokRoot( - registration: CmuxVaultAgentRegistration, - homeDirectory: String - ) -> Bool { - guard let configuredRoot = normalized(registration.sessionDirectory) else { - return true - } - let expandedConfigured = expandTilde(configuredRoot, homeDirectory: homeDirectory) - let expandedDefault = (defaultSessionsRoot(homeDirectory: homeDirectory) as NSString).standardizingPath - return expandedConfigured == expandedDefault - } - - private static func deduplicatedSessionRoots(_ roots: [GrokSessionRoot]) -> [GrokSessionRoot] { - var seen = Set() - return roots.filter { root in - seen.insert((root.sessionsRoot as NSString).standardizingPath).inserted - } - } - - private static func expandTilde(_ path: String, homeDirectory: String) -> String { - let home = ((homeDirectory as NSString).expandingTildeInPath as NSString).standardizingPath - if path == "~" { - return home - } - if path.hasPrefix("~/") { - let suffix = String(path.dropFirst(2)) - return ((home as NSString).appendingPathComponent(suffix) as NSString).standardizingPath - } - return ((path as NSString).expandingTildeInPath as NSString).standardizingPath - } - - private static func normalized(_ value: String?) -> String? { - let trimmed = value?.trimmingCharacters(in: .whitespacesAndNewlines) - return trimmed?.isEmpty == false ? trimmed : nil - } -} - extension SessionIndexStore { private struct RegisteredAgentJSONLMetadata { var title: String = "" @@ -231,141 +8,6 @@ extension SessionIndexStore { var sessionId: String? } - private struct AntigravityHistoryMetadata { - let sessionId: String - let title: String - let cwd: String? - let modified: Date - let fileURL: URL - } - - private struct GrokSessionMetadata { - var title: String = "" - var model: String? - var permissionMode: String? - var sandboxMode: String? - var branch: String? - } - - nonisolated static func loadGrokEntries( - registration: CmuxVaultAgentRegistration, - needle: String, - cwdFilter: String?, - offset: Int, - limit: Int, - agent: SessionAgent = .grok, - environment: [String: String] = ProcessInfo.processInfo.environment, - homeDirectory: String = NSHomeDirectory(), - fileManager: FileManager = .default - ) async -> [SessionEntry] { - let observedGrokHomes = GrokSessionLocator.observedGrokHomes( - homeDirectory: homeDirectory, - environment: environment, - fileManager: fileManager - ) - let roots = GrokSessionLocator.sessionRoots( - registration: registration, - cwdFilter: cwdFilter, - environment: environment, - homeDirectory: homeDirectory, - observedGrokHomes: observedGrokHomes - ) - guard !roots.isEmpty else { return [] } - let fm = fileManager - - var candidates: [(url: URL, modified: Date, prefilteredByRipgrep: Bool, root: GrokSessionRoot)] = [] - if !needle.isEmpty { - for root in roots { - guard let rgPaths = await ripgrepMatchingPaths( - needle: needle, - root: root.sessionsRoot, - fileGlob: "chat_history.jsonl" - ) else { - candidates.append( - contentsOf: enumerateGrokHistoryCandidates(root: root, fileManager: fileManager).map { - (url: $0.0, modified: $0.1, prefilteredByRipgrep: false, root: root) - } - ) - continue - } - for url in rgPaths where url.lastPathComponent == "chat_history.jsonl" { - guard let attrs = try? fm.attributesOfItem(atPath: url.path), - let modified = attrs[.modificationDate] as? Date else { - continue - } - candidates.append((url, modified, true, root)) - } - } - } else { - for root in roots { - candidates.append( - contentsOf: enumerateGrokHistoryCandidates(root: root, fileManager: fileManager).map { - (url: $0.0, modified: $0.1, prefilteredByRipgrep: false, root: root) - } - ) - } - } - - candidates.sort { $0.modified > $1.modified } - let target = offset + limit - var matches: [SessionEntry] = [] - var seenSessionIds = Set() - var scanned = 0 - for candidate in candidates { - if Task.isCancelled { break } - if matches.count >= target { break } - if scanned >= searchMaxFiles { break } - scanned += 1 - - if !needle.isEmpty && !candidate.prefilteredByRipgrep { - guard fileContains(candidate.url, needle: needle) else { continue } - } - - let sessionDirectory = candidate.url.deletingLastPathComponent() - let projectDirectory = sessionDirectory.deletingLastPathComponent().lastPathComponent - let cwd = GrokSessionLocator.workingDirectory(fromProjectDirectoryName: projectDirectory) - if let cwdFilter, - GrokSessionLocator.normalizedWorkingDirectory(cwd) - != GrokSessionLocator.normalizedWorkingDirectory(cwdFilter) { - continue - } - - let metadata = extractGrokSessionMetadata(url: candidate.url) - let sessionId = sessionDirectory.lastPathComponent - guard seenSessionIds.insert(sessionId).inserted else { continue } - let specifics: AgentSpecifics - switch agent { - case .grok: - specifics = .grok( - model: metadata.model, - permissionMode: metadata.permissionMode, - sandboxMode: metadata.sandboxMode, - grokHome: candidate.root.grokHomeForResume - ) - default: - specifics = .registered( - registrationWithGrokHomePrefix( - registration, - grokHome: candidate.root.grokHomeForResume - ) - ) - } - matches.append(SessionEntry( - id: "\(registration.id):\(sessionId)", - agent: agent, - sessionId: sessionId, - title: metadata.title, - cwd: cwd, - gitBranch: metadata.branch, - pullRequest: nil, - modified: candidate.modified, - fileURL: candidate.url, - specifics: specifics - )) - } - return Array(matches.dropFirst(offset).prefix(limit)) - } - nonisolated static func loadRegisteredAgentEntries( registration: CmuxVaultAgentRegistration, needle: String, @@ -373,26 +15,6 @@ extension SessionIndexStore { offset: Int, limit: Int ) async -> [SessionEntry] { - if registration.id == CmuxVaultAgentRegistration.builtInAntigravity.id { - return loadAntigravityHistoryEntries( - registration: registration, - needle: needle, - cwdFilter: cwdFilter, - offset: offset, - limit: limit - ) - } - - if case .grokSessionDirectory = registration.sessionIdSource { - return await loadGrokEntries( - registration: registration, - needle: needle, - cwdFilter: cwdFilter, - offset: offset, - limit: limit, - agent: .registered(RegisteredSessionAgent(registration: registration)) - ) - } let roots = registeredSessionRoots(registration: registration, cwdFilter: cwdFilter) guard !roots.isEmpty else { return [] } let fm = FileManager.default @@ -463,100 +85,10 @@ extension SessionIndexStore { return Array(matches.dropFirst(offset).prefix(limit)) } - nonisolated private static func loadAntigravityHistoryEntries( - registration: CmuxVaultAgentRegistration, - needle: String, - cwdFilter: String?, - offset: Int, - limit: Int - ) -> [SessionEntry] { - let roots = registeredSessionRoots(registration: registration, cwdFilter: cwdFilter) - guard !roots.isEmpty else { return [] } - - let fm = FileManager.default - var latestBySessionID: [String: AntigravityHistoryMetadata] = [:] - - for root in roots { - if Task.isCancelled { break } - let historyURL = URL(fileURLWithPath: root, isDirectory: true) - .appendingPathComponent("history.jsonl", isDirectory: false) - var isDirectory: ObjCBool = false - guard fm.fileExists(atPath: historyURL.path, isDirectory: &isDirectory), - !isDirectory.boolValue else { - continue - } - let fallbackModified = ((try? fm.attributesOfItem(atPath: historyURL.path))?[.modificationDate] as? Date) - ?? Date.distantPast - - forEachJSONLine(url: historyURL, maxBytes: Int.max) { object in - if Task.isCancelled { return true } - guard let sessionId = firstString(in: object, keys: antigravitySessionIDKeys()) else { - return false - } - let cwd = firstString(in: object, keys: registeredJSONLCWDKeys()) - if let cwdFilter, cwd != cwdFilter { return false } - - let title = antigravityHistoryTitle(in: object) ?? "" - guard antigravityHistoryMatchesNeedle( - needle: needle, - sessionId: sessionId, - title: title, - cwd: cwd - ) else { - return false - } - - let modified = antigravityHistoryModifiedDate(in: object, fallback: fallbackModified) - let metadata = AntigravityHistoryMetadata( - sessionId: sessionId, - title: title, - cwd: cwd, - modified: modified, - fileURL: historyURL - ) - if let existing = latestBySessionID[sessionId] { - if metadata.modified >= existing.modified { - latestBySessionID[sessionId] = metadata - } - } else { - latestBySessionID[sessionId] = metadata - } - return false - } - } - - let entries = latestBySessionID.values - .sorted { - if $0.modified == $1.modified { - return $0.sessionId < $1.sessionId - } - return $0.modified > $1.modified - } - .map { metadata in - SessionEntry( - id: "\(registration.id):\(metadata.sessionId)", - agent: .registered(RegisteredSessionAgent(registration: registration)), - sessionId: metadata.sessionId, - title: metadata.title, - cwd: metadata.cwd, - gitBranch: nil, - pullRequest: nil, - modified: metadata.modified, - fileURL: metadata.fileURL, - specifics: .registered(registration) - ) - } - return Array(entries.dropFirst(offset).prefix(limit)) - } - nonisolated private static func registeredSessionRoots( registration: CmuxVaultAgentRegistration, cwdFilter: String? ) -> [String] { - if case .grokSessionDirectory = registration.sessionIdSource { - return GrokSessionLocator.sessionRoots(registration: registration, cwdFilter: cwdFilter) - .map(\.sessionsRoot) - } guard let root = registration.sessionDirectory.map({ ($0 as NSString).expandingTildeInPath }) else { return [] } @@ -568,44 +100,6 @@ extension SessionIndexStore { return [root] } - nonisolated private static func registrationWithGrokHomePrefix( - _ registration: CmuxVaultAgentRegistration, - grokHome: String? - ) -> CmuxVaultAgentRegistration { - guard let grokHome = grokHome?.trimmingCharacters(in: .whitespacesAndNewlines), - !grokHome.isEmpty, - !registration.resumeCommand.contains("GROK_HOME") else { - return registration - } - var copy = registration - copy.resumeCommand = "env GROK_HOME=\(SessionEntry.shellQuote(grokHome)) \(registration.resumeCommand)" - return copy - } - - nonisolated private static func enumerateGrokHistoryCandidates( - root: GrokSessionRoot, - fileManager: FileManager - ) -> [(URL, Date)] { - let fm = fileManager - var isDirectory: ObjCBool = false - guard fm.fileExists(atPath: root.sessionsRoot, isDirectory: &isDirectory), - isDirectory.boolValue, - let enumerator = fm.enumerator( - at: URL(fileURLWithPath: root.sessionsRoot, isDirectory: true), - includingPropertiesForKeys: [.contentModificationDateKey, .isRegularFileKey], - options: [.skipsHiddenFiles] - ) else { - return [] - } - var candidates: [(URL, Date)] = [] - for case let url as URL in enumerator where url.lastPathComponent == "chat_history.jsonl" { - let values = try? url.resourceValues(forKeys: [.contentModificationDateKey, .isRegularFileKey]) - guard values?.isRegularFile == true, let modified = values?.contentModificationDate else { continue } - candidates.append((url, modified)) - } - return candidates - } - nonisolated private static func enumerateRegisteredJSONLCandidates(root: String) -> [(URL, Date)] { let fm = FileManager.default var isDirectory: ObjCBool = false @@ -627,50 +121,6 @@ extension SessionIndexStore { return candidates } - nonisolated private static func extractGrokSessionMetadata(url: URL) -> GrokSessionMetadata { - var metadata = GrokSessionMetadata() - var remainingBranchProbeLines: Int? - forEachJSONLine(url: url, maxBytes: 512 * 1024) { object in - if metadata.title.isEmpty { - metadata.title = grokTitle(in: object) ?? "" - } - if metadata.model == nil { - metadata.model = firstString(in: object, keys: ["model", "modelId", "modelID", "model_id"]) - ?? firstString( - in: object["message"] as? [String: Any] ?? [:], - keys: ["model", "modelId", "modelID", "model_id"] - ) - } - if metadata.permissionMode == nil { - metadata.permissionMode = firstString( - in: object, - keys: ["permissionMode", "permission_mode", "approvalPolicy", "approval_policy"] - ) - } - if metadata.sandboxMode == nil { - metadata.sandboxMode = firstString( - in: object, - keys: ["sandboxMode", "sandbox_mode", "sandbox"] - ) - } - if metadata.branch == nil, let git = object["git"] as? [String: Any] { - metadata.branch = firstString(in: git, keys: ["branch", "gitBranch"]) - } - if metadata.branch == nil { - metadata.branch = firstString(in: object, keys: ["gitBranch", "branch"]) - } - let hasStableMetadata = !metadata.title.isEmpty - && metadata.model != nil - && metadata.permissionMode != nil - && metadata.sandboxMode != nil - guard hasStableMetadata else { return false } - guard metadata.branch == nil else { return true } - remainingBranchProbeLines = (remainingBranchProbeLines ?? 32) - 1 - return (remainingBranchProbeLines ?? 0) <= 0 - } - return metadata - } - nonisolated private static func extractRegisteredJSONLMetadata( url: URL, registration: CmuxVaultAgentRegistration, @@ -681,15 +131,18 @@ extension SessionIndexStore { switch registration.sessionIdSource { case .argvOption: needsNativeSessionID = true - case .piSessionFile, .grokSessionDirectory: + case .piSessionFile: needsNativeSessionID = false } forEachJSONLine(url: url, maxBytes: 512 * 1024) { object in if metadata.sessionId == nil { - metadata.sessionId = firstString(in: object, keys: registeredJSONLSessionIDKeys()) + metadata.sessionId = firstString(in: object, keys: ["sessionId", "session_id", "id"]) } if metadata.cwd == nil { - metadata.cwd = firstString(in: object, keys: registeredJSONLCWDKeys()) + metadata.cwd = firstString( + in: object, + keys: ["cwd", "workingDirectory", "workspacePath", "projectPath", "directory"] + ) } if metadata.branch == nil, let git = object["git"] as? [String: Any] { metadata.branch = firstString(in: git, keys: ["branch", "gitBranch"]) @@ -723,57 +176,6 @@ extension SessionIndexStore { return metadata } - nonisolated private static func registeredJSONLCWDKeys() -> [String] { - ["cwd", "workingDirectory", "workspacePath", "workspace", "projectPath", "directory"] - } - - nonisolated private static func registeredJSONLSessionIDKeys() -> [String] { - ["sessionId", "session_id", "id"] - } - - nonisolated private static func antigravitySessionIDKeys() -> [String] { - ["conversationId", "conversation_id", "sessionId", "session_id", "id"] - } - - nonisolated private static func antigravityHistoryTitle(in object: [String: Any]) -> String? { - firstText(in: object, keys: ["title", "prompt", "display"]) - ?? firstTopLevelTitle(in: object) - } - - nonisolated private static func antigravityHistoryMatchesNeedle( - needle: String, - sessionId: String, - title: String, - cwd: String? - ) -> Bool { - guard !needle.isEmpty else { return true } - return [sessionId, title, cwd ?? ""].contains { value in - value.range(of: needle, options: [.caseInsensitive, .literal]) != nil - } - } - - nonisolated private static func antigravityHistoryModifiedDate( - in object: [String: Any], - fallback: Date - ) -> Date { - guard let timestamp = antigravityNumericTimestamp(object["timestamp"]) else { - return fallback - } - let seconds = timestamp > 10_000_000_000 ? timestamp / 1_000 : timestamp - guard seconds.isFinite, seconds > 0 else { return fallback } - return Date(timeIntervalSince1970: seconds) - } - - nonisolated private static func antigravityNumericTimestamp(_ value: Any?) -> Double? { - if let number = value as? NSNumber { - return number.doubleValue - } - if let string = value as? String { - return Double(string.trimmingCharacters(in: .whitespacesAndNewlines)) - } - return nil - } - nonisolated private static func fileContains(_ url: URL, needle: String) -> Bool { guard !needle.isEmpty, let handle = try? FileHandle(forReadingFrom: url) else { @@ -824,66 +226,6 @@ extension SessionIndexStore { return firstText(in: object, keys: ["text", "content"]) } - nonisolated private static func grokTitle(in object: [String: Any]) -> String? { - if shouldUseGrokObjectAsTitle(object) { - if let title = grokTitleText(firstText(in: object, keys: ["content", "text"])) { - return title - } - if let message = grokTitleText(firstString(in: object, keys: ["message"])) { - return message - } - } - if let message = object["message"] as? [String: Any], - shouldUseGrokObjectAsTitle(message) { - return grokTitleText(firstText(in: message, keys: ["content", "text"])) - } - if let messages = object["messages"] as? [[String: Any]] { - return messages.compactMap { message in - shouldUseGrokObjectAsTitle(message) - ? grokTitleText(firstText(in: message, keys: ["content", "text"])) - : nil - }.first - } - return nil - } - - nonisolated private static func grokTitleText(_ value: String?) -> String? { - guard let value else { return nil } - if let userQuery = grokTaggedContent(named: "user_query", in: value) { - return userQuery - } - let withoutMetadata = ["user_info", "git_status", "system-reminder"].reduce(value) { partial, tag in - removingGrokTaggedContent(named: tag, from: partial) - } - return trimmedNonEmpty(withoutMetadata) - } - - nonisolated private static func grokTaggedContent(named tag: String, in text: String) -> String? { - let openTag = "<\(tag)>" - let closeTag = "" - guard let openRange = text.range(of: openTag) else { return nil } - let bodyStart = openRange.upperBound - guard let closeRange = text[bodyStart...].range(of: closeTag) else { return nil } - return trimmedNonEmpty(String(text[bodyStart.. String { - let openTag = "<\(tag)>" - let closeTag = "" - var result = text - while let openRange = result.range(of: openTag) { - let bodyStart = openRange.upperBound - guard let closeRange = result[bodyStart...].range(of: closeTag) else { break } - result.removeSubrange(openRange.lowerBound.. Bool { - let role = firstString(in: object, keys: ["role", "type"]) - return role == nil || isUserRole(role) - } - nonisolated private static func firstTextValue(_ value: Any?) -> String? { if let string = value as? String { return trimmedNonEmpty(string) diff --git a/Sources/SessionIndexStore.swift b/Sources/SessionIndexStore.swift index 75e2f3ea8789..1f2ba649d36d 100644 --- a/Sources/SessionIndexStore.swift +++ b/Sources/SessionIndexStore.swift @@ -2,7 +2,6 @@ import AppKit import Bonsplit import CMUXAgentLaunch import Combine -import Darwin import Foundation import os import SQLite3 @@ -12,50 +11,6 @@ nonisolated private let sessionIndexLogger = Logger( category: "SessionIndexStore" ) -/// Locked cancellation state shared by synchronous `Process` callbacks. -/// `onCancel` cannot await an actor, so mutable state stays behind `lock`. -final class SessionIndexRipgrepCancellation: @unchecked Sendable { - private let lock = NSLock() - private let sendSignal: @Sendable (pid_t, Int32) -> Int32 - private var activeProcessIdentifier: pid_t? - private var finishedProcessIdentifier: pid_t? - - init(sendSignal: @escaping @Sendable (pid_t, Int32) -> Int32 = Darwin.kill) { - self.sendSignal = sendSignal - } - - func markStarted(processIdentifier: pid_t) { - lock.lock() - defer { lock.unlock() } - - if finishedProcessIdentifier == processIdentifier { - activeProcessIdentifier = nil - } else { - activeProcessIdentifier = processIdentifier - } - } - - func markFinished(processIdentifier: pid_t) { - lock.lock() - defer { lock.unlock() } - - finishedProcessIdentifier = processIdentifier - if activeProcessIdentifier == processIdentifier { - activeProcessIdentifier = nil - } - } - - func cancel() { - lock.lock() - let processIdentifier = activeProcessIdentifier - activeProcessIdentifier = nil - lock.unlock() - - guard let processIdentifier else { return } - _ = sendSignal(processIdentifier, SIGTERM) - } -} - // MARK: - Parsed metadata cache /// Process-wide cache for parsed Claude session metadata, keyed by file URL with @@ -1138,12 +1093,6 @@ final class SessionIndexStore: ObservableObject { let scopedCwd = currentDirectory?.trimmingCharacters(in: .whitespacesAndNewlines) cwdFilter = scopedCwd?.isEmpty == false ? scopedCwd : nil registry = await Self.vaultAgentRegistry(workingDirectory: cwdFilter) - } else if a == .grok { - let scopedCwd = currentDirectory?.trimmingCharacters(in: .whitespacesAndNewlines) - cwdFilter = scopedCwd?.isEmpty == false ? scopedCwd : nil - registry = await Self.vaultAgentRegistry( - workingDirectory: cwdFilter - ) } else { cwdFilter = nil registry = CmuxVaultAgentRegistry(registrations: []) @@ -1248,14 +1197,8 @@ final class SessionIndexStore: ObservableObject { switch agent { case .claude: return await loadClaudeEntries(needle: needle, cwdFilter: cwdFilter, offset: offset, limit: limit) case .codex: return await loadCodexEntries(needle: needle, cwdFilter: cwdFilter, offset: offset, limit: limit, errorBag: errorBag) - case .grok: - return await loadGrokEntries( - registration: registry.registration(id: "grok") ?? .builtInGrok, - needle: needle, - cwdFilter: cwdFilter, - offset: offset, - limit: limit - ) + // Grok sessions are restored from hook persistence, so searchAgent has no filesystem loader for this case. + case .grok: return [] case .opencode: return loadOpenCodeEntries(needle: needle, cwdFilter: cwdFilter, offset: offset, limit: limit, errorBag: errorBag) case .rovodev: return loadRovoDevEntries(needle: needle, cwdFilter: cwdFilter, offset: offset, limit: limit, errorBag: errorBag) case .hermesAgent: return loadHermesAgentEntries(needle: needle, cwdFilter: cwdFilter, offset: offset, limit: limit, errorBag: errorBag) @@ -1294,12 +1237,14 @@ final class SessionIndexStore: ObservableObject { /// URLs, or nil if rg isn't available or the run failed (caller falls back). /// /// Async by design so we can wire cancellation: when the awaiting Task is - /// cancelled (e.g. user types another key), `onCancel` signals the launched - /// rg process instead of letting it grind to completion. + /// cancelled (e.g. user types another key), `onCancel` calls + /// `process.terminate()`, killing the in-flight rg instead of letting it + /// grind to completion. Wait is also async (via `terminationHandler`) so we + /// don't tie up a cooperative-pool thread on `waitUntilExit`. nonisolated static func ripgrepMatchingPaths( - needle: String, root: String, fileGlob: String, ripgrepPath: String? = nil + needle: String, root: String, fileGlob: String ) async -> [URL]? { - guard let rg = ripgrepPath ?? resolvedRipgrepPath() else { return nil } + guard let rg = resolvedRipgrepPath() else { return nil } let process = Process() process.executableURL = URL(fileURLWithPath: rg) process.arguments = [ @@ -1320,23 +1265,9 @@ final class SessionIndexStore: ObservableObject { if let nullDev = FileHandle(forWritingAtPath: "/dev/null") { process.standardError = nullDev } - let cancellation = SessionIndexRipgrepCancellation() - process.terminationHandler = { process in - cancellation.markFinished(processIdentifier: process.processIdentifier) - } return await withTaskCancellationHandler { - guard !Task.isCancelled else { return [] } - do { - try process.run() - } catch { - if Task.isCancelled { return [] } - return nil as [URL]? - } - cancellation.markStarted(processIdentifier: process.processIdentifier) - if Task.isCancelled { - cancellation.cancel() - } + do { try process.run() } catch { return nil as [URL]? } // Drain stdout BEFORE waitUntilExit. With many matches rg writes // more than the ~64 KB pipe buffer; reading until EOF lets rg // make progress and EOF arrives when rg closes its stdout on exit. @@ -1347,8 +1278,6 @@ final class SessionIndexStore: ObservableObject { // late and never fires → deadlock.) let data = outPipe.fileHandleForReading.readDataToEndOfFile() process.waitUntilExit() - cancellation.markFinished(processIdentifier: process.processIdentifier) - if Task.isCancelled { return [] } // rg exit codes: 0 = matches, 1 = no matches, 2 = error/terminated. switch process.terminationStatus { case 0: @@ -1361,10 +1290,10 @@ final class SessionIndexStore: ObservableObject { return nil } } onCancel: { - // Fires synchronously when the awaiting Task is cancelled. SIGTERM - // closes stdout, lets readDataToEndOfFile return, and unblocks the - // body so this call can complete cleanly. - cancellation.cancel() + // Fires synchronously when the awaiting Task is cancelled. Sends + // SIGTERM to rg, which closes stdout, lets readDataToEndOfFile + // return, and unblocks the body so this call can complete cleanly. + process.terminate() } } diff --git a/Sources/SessionIndexView.swift b/Sources/SessionIndexView.swift index f87a6a567649..61cb04db01e7 100644 --- a/Sources/SessionIndexView.swift +++ b/Sources/SessionIndexView.swift @@ -1033,21 +1033,6 @@ private enum SessionTranscriptPreviewState: Equatable { case loaded([SessionTranscriptDisplayRow]) } -private extension SessionEntry { - var usesGrokTranscriptLayout: Bool { - if agent == .grok { - return true - } - guard case .registered(let registration) = specifics else { - return false - } - if case .grokSessionDirectory = registration.sessionIdSource { - return true - } - return false - } -} - private enum SessionTranscriptLoader { private static let streamChunkSize = 256 * 1024 private static let maxPreviewRecordBytes = 2 * 1024 * 1024 @@ -1079,58 +1064,6 @@ private enum SessionTranscriptLoader { Data(#""role":"#.utf8), Data(#""role": "#.utf8) ] - private static let grokAssistantRoleNeedles = [ - Data(#""role":"assistant""#.utf8), - Data(#""role": "assistant""#.utf8), - Data(#""type":"assistant""#.utf8), - Data(#""type": "assistant""#.utf8) - ] - private static let grokUserRoleNeedles = [ - Data(#""role":"user""#.utf8), - Data(#""role": "user""#.utf8), - Data(#""type":"user""#.utf8), - Data(#""type": "user""#.utf8) - ] - private static let grokSystemRoleNeedles = [ - Data(#""role":"system""#.utf8), - Data(#""role": "system""#.utf8), - Data(#""role":"developer""#.utf8), - Data(#""role": "developer""#.utf8), - Data(#""type":"system""#.utf8), - Data(#""type": "system""#.utf8), - Data(#""type":"developer""#.utf8), - Data(#""type": "developer""#.utf8) - ] - private static let grokToolRoleNeedles = [ - Data(#""role":"tool""#.utf8), - Data(#""role": "tool""#.utf8), - Data(#""role":"tool_use""#.utf8), - Data(#""role": "tool_use""#.utf8), - Data(#""role":"tool_result""#.utf8), - Data(#""role": "tool_result""#.utf8), - Data(#""role":"function_call""#.utf8), - Data(#""role": "function_call""#.utf8), - Data(#""role":"function_call_output""#.utf8), - Data(#""role": "function_call_output""#.utf8), - Data(#""type":"tool""#.utf8), - Data(#""type": "tool""#.utf8), - Data(#""type":"tool_use""#.utf8), - Data(#""type": "tool_use""#.utf8), - Data(#""type":"tool_result""#.utf8), - Data(#""type": "tool_result""#.utf8), - Data(#""type":"function_call""#.utf8), - Data(#""type": "function_call""#.utf8), - Data(#""type":"function_call_output""#.utf8), - Data(#""type": "function_call_output""#.utf8) - ] - private static let grokRoleNeedles = [ - Data(#""role":"#.utf8), - Data(#""role": "#.utf8) - ] - + grokAssistantRoleNeedles - + grokUserRoleNeedles - + grokSystemRoleNeedles - + grokToolRoleNeedles static func load(entry: SessionEntry) async throws -> [SessionTranscriptTurn] { if entry.agent == .opencode { @@ -1151,27 +1084,12 @@ private enum SessionTranscriptLoader { throw SessionTranscriptLoadError.missingFile } let agent = entry.agent - let sessionId = entry.sessionId - if agent.id == "antigravity" { - return try await Task.detached(priority: .userInitiated) { - try loadAntigravityHistorySynchronously(from: url, sessionId: sessionId) - }.value - } - let usesGrokTranscriptLayout = entry.usesGrokTranscriptLayout return try await Task.detached(priority: .userInitiated) { - try loadSynchronously( - from: url, - agent: agent, - usesGrokTranscriptLayout: usesGrokTranscriptLayout - ) + try loadSynchronously(from: url, agent: agent) }.value } - private static func loadSynchronously( - from url: URL, - agent: SessionAgent, - usesGrokTranscriptLayout: Bool - ) throws -> [SessionTranscriptTurn] { + private static func loadSynchronously(from url: URL, agent: SessionAgent) throws -> [SessionTranscriptTurn] { guard FileManager.default.fileExists(atPath: url.path) else { throw SessionTranscriptLoadError.missingFile } @@ -1212,12 +1130,7 @@ private enum SessionTranscriptLoader { didHitTurnLimit = turns.count >= maxPreviewTurns return } - guard let parsed = parseLineData( - lineData, - agent: agent, - usesGrokTranscriptLayout: usesGrokTranscriptLayout, - id: lineIndex - ) else { + guard let parsed = parseLineData(lineData, agent: agent, id: lineIndex) else { return } turns.append(parsed) @@ -1232,16 +1145,8 @@ private enum SessionTranscriptLoader { if remainingCapacity > 0 { lineData.append(contentsOf: segment.prefix(remainingCapacity)) } - if shouldParseRawLine( - lineData, - agent: agent, - usesGrokTranscriptLayout: usesGrokTranscriptLayout - ) { - oversizedPreviewRole = inferredRole( - from: lineData, - agent: agent, - usesGrokTranscriptLayout: usesGrokTranscriptLayout - ) ?? .event + if shouldParseRawLine(lineData, agent: agent) { + oversizedPreviewRole = inferredRole(from: lineData, agent: agent) ?? .event } lineData.removeAll(keepingCapacity: true) isSkippingOversizedLine = true @@ -1281,51 +1186,6 @@ private enum SessionTranscriptLoader { return coalesce(turns) } - private static func loadAntigravityHistorySynchronously( - from url: URL, - sessionId: String - ) throws -> [SessionTranscriptTurn] { - guard FileManager.default.fileExists(atPath: url.path) else { - throw SessionTranscriptLoadError.missingFile - } - - var turns: [SessionTranscriptTurn] = [] - var lineIndex = 0 - var didHitTurnLimit = false - let agent = SessionAgent.registered(RegisteredSessionAgent(id: "antigravity")) - - SessionIndexStore.forEachJSONLine(url: url, maxBytes: Int.max) { object in - defer { lineIndex += 1 } - if Task.isCancelled { return true } - guard turns.count < maxPreviewTurns else { - didHitTurnLimit = true - return true - } - guard antigravityHistorySessionID(in: object) == sessionId else { - return false - } - let content = object["display"] ?? object["prompt"] ?? object["text"] ?? object["message"] - guard let text = normalizedText(from: content, role: .user, agent: agent) else { - return false - } - turns.append(SessionTranscriptTurn(id: lineIndex, role: .user, text: text)) - return false - } - if didHitTurnLimit { - appendTurnLimitMarker(to: &turns, id: lineIndex) - } - return coalesce(turns) - } - - private static func antigravityHistorySessionID(in object: [String: Any]) -> String? { - for key in ["conversationId", "conversation_id", "sessionId", "session_id", "id"] { - guard let value = object[key] as? String else { continue } - let trimmed = value.trimmingCharacters(in: .whitespacesAndNewlines) - if !trimmed.isEmpty { return trimmed } - } - return nil - } - private static func loadOpenCodeSynchronously(sessionId: String) throws -> [SessionTranscriptTurn] { let snapshot: OpenCodeDatabaseSnapshot.Snapshot do { @@ -1448,26 +1308,19 @@ private enum SessionTranscriptLoader { private static func parseLineData( _ lineData: Data, agent: SessionAgent, - usesGrokTranscriptLayout: Bool, id: Int ) -> SessionTranscriptTurn? { guard !lineData.isEmpty, - shouldParseRawLine(lineData, agent: agent, usesGrokTranscriptLayout: usesGrokTranscriptLayout), + shouldParseRawLine(lineData, agent: agent), let object = try? JSONSerialization.jsonObject(with: lineData) as? [String: Any] else { return nil } - return parseLine( - object, - agent: agent, - usesGrokTranscriptLayout: usesGrokTranscriptLayout, - id: id - ) + return parseLine(object, agent: agent, id: id) } private static func parseLine( _ object: [String: Any], agent: SessionAgent, - usesGrokTranscriptLayout: Bool, id: Int ) -> SessionTranscriptTurn? { switch agent { @@ -1476,12 +1329,7 @@ private enum SessionTranscriptLoader { case .codex: return parseCodexLine(object, id: id) case .grok, .opencode, .rovodev, .registered: - return parseGenericLine( - object, - agent: agent, - usesGrokTranscriptLayout: usesGrokTranscriptLayout, - id: id - ) + return parseGenericLine(object, agent: agent, id: id) case .hermesAgent: return nil } @@ -1530,33 +1378,17 @@ private enum SessionTranscriptLoader { private static func parseGenericLine( _ object: [String: Any], agent: SessionAgent, - usesGrokTranscriptLayout: Bool, id: Int ) -> SessionTranscriptTurn? { - if let parsed = parseGenericMessage( - object, - agent: agent, - usesGrokTranscriptLayout: usesGrokTranscriptLayout, - id: id - ) { + if let parsed = parseGenericMessage(object, agent: agent, id: id) { return parsed } if let payload = object["payload"] as? [String: Any], - let parsed = parseGenericMessage( - payload, - agent: agent, - usesGrokTranscriptLayout: usesGrokTranscriptLayout, - id: id - ) { + let parsed = parseGenericMessage(payload, agent: agent, id: id) { return parsed } if let message = object["message"] as? [String: Any], - let parsed = parseGenericMessage( - message, - agent: agent, - usesGrokTranscriptLayout: usesGrokTranscriptLayout, - id: id - ) { + let parsed = parseGenericMessage(message, agent: agent, id: id) { return parsed } return nil @@ -1565,31 +1397,10 @@ private enum SessionTranscriptLoader { private static func parseGenericMessage( _ object: [String: Any], agent: SessionAgent, - usesGrokTranscriptLayout: Bool, id: Int ) -> SessionTranscriptTurn? { let fallbackRole: SessionTranscriptRole? = { if case .registered = agent { return .event }; return nil }() - let rawRole = object["role"] as? String - let parsedRole = transcriptRole(from: rawRole) - let roleFromRole = usesGrokTranscriptLayout - && parsedRole == .event - && rawRole?.caseInsensitiveCompare("event") != .orderedSame - ? nil - : parsedRole - let shouldUseGrokTypeRole = usesGrokTranscriptLayout - && roleFromRole == nil - let roleFromType: SessionTranscriptRole? = { - guard shouldUseGrokTypeRole else { return nil } - let rawType = object["type"] as? String - let parsedTypeRole = transcriptRole(from: rawType) - if parsedTypeRole == .event, - rawType?.caseInsensitiveCompare("event") != .orderedSame { - return nil - } - return parsedTypeRole - }() - let shouldUseFallbackRole = !usesGrokTranscriptLayout - guard let role = roleFromType ?? roleFromRole ?? (shouldUseFallbackRole ? fallbackRole : nil) else { + guard let role = transcriptRole(from: object["role"] as? String) ?? fallbackRole else { return nil } let content = object["content"] ?? object["text"] ?? object["message"] @@ -1793,23 +1604,14 @@ private enum SessionTranscriptLoader { } } - private static func shouldParseRawLine( - _ data: Data, - agent: SessionAgent, - usesGrokTranscriptLayout: Bool - ) -> Bool { - if usesGrokTranscriptLayout { - return containsAny(data, needles: grokRoleNeedles) - } + private static func shouldParseRawLine(_ data: Data, agent: SessionAgent) -> Bool { switch agent { case .claude: return containsAny(data, needles: claudeUserNeedles) case .codex: return containsAny(data, needles: codexResponseItemNeedles) && containsAny(data, needles: codexPreviewNeedles) - case .grok: - return containsAny(data, needles: grokRoleNeedles) - case .opencode, .rovodev: + case .grok, .opencode, .rovodev: return containsAny(data, needles: genericRoleNeedles) case .registered: return true @@ -1818,14 +1620,7 @@ private enum SessionTranscriptLoader { } } - private static func inferredRole( - from data: Data, - agent: SessionAgent, - usesGrokTranscriptLayout: Bool - ) -> SessionTranscriptRole? { - if usesGrokTranscriptLayout { - return inferredGrokRole(from: data) - } + private static func inferredRole(from data: Data, agent: SessionAgent) -> SessionTranscriptRole? { switch agent { case .claude: if containsAny(data, needles: [Data(#""type":"assistant""#.utf8), Data(#""type": "assistant""#.utf8)]) { @@ -1834,7 +1629,7 @@ private enum SessionTranscriptLoader { if containsAny(data, needles: [Data(#""type":"user""#.utf8), Data(#""type": "user""#.utf8)]) { return .user } - case .codex, .opencode, .rovodev, .registered: + case .codex, .grok, .opencode, .rovodev, .registered: if containsAny(data, needles: [Data(#""role":"assistant""#.utf8), Data(#""role": "assistant""#.utf8)]) { return .assistant } @@ -1844,30 +1639,12 @@ private enum SessionTranscriptLoader { if containsAny(data, needles: [Data(#""type":"function_call""#.utf8), Data(#""type": "function_call""#.utf8)]) { return .tool } - case .grok: - return inferredGrokRole(from: data) case .hermesAgent: return nil } return nil } - private static func inferredGrokRole(from data: Data) -> SessionTranscriptRole? { - if containsAny(data, needles: grokAssistantRoleNeedles) { - return .assistant - } - if containsAny(data, needles: grokUserRoleNeedles) { - return .user - } - if containsAny(data, needles: grokSystemRoleNeedles) { - return .system - } - if containsAny(data, needles: grokToolRoleNeedles) { - return .tool - } - return nil - } - private static func containsAny(_ data: Data, needles: [Data]) -> Bool { needles.contains { data.range(of: $0) != nil } } diff --git a/Sources/SessionPersistence.swift b/Sources/SessionPersistence.swift index 585a694d77ab..ab0a7350f278 100644 --- a/Sources/SessionPersistence.swift +++ b/Sources/SessionPersistence.swift @@ -1276,66 +1276,6 @@ struct SessionRightSidebarToolPanelSnapshot: Codable, Sendable { var mode: RightSidebarMode } -struct SessionNotificationSnapshot: Codable, Sendable { - var id: UUID - var title: String - var subtitle: String - var body: String - var createdAt: TimeInterval - var isRead: Bool - var paneFlash: Bool? - var clickAction: TerminalNotificationClickAction? - - init( - id: UUID, - title: String, - subtitle: String, - body: String, - createdAt: TimeInterval, - isRead: Bool, - paneFlash: Bool? = nil, - clickAction: TerminalNotificationClickAction? = nil - ) { - self.id = id - self.title = title - self.subtitle = subtitle - self.body = body - self.createdAt = createdAt - self.isRead = isRead - self.paneFlash = paneFlash - self.clickAction = clickAction - } - - init(notification: TerminalNotification) { - self.init( - id: notification.id, - title: notification.title, - subtitle: notification.subtitle, - body: notification.body, - createdAt: notification.createdAt.timeIntervalSince1970, - isRead: notification.isRead, - paneFlash: notification.paneFlash, - clickAction: notification.clickAction - ) - } - - func terminalNotification(tabId: UUID, surfaceId: UUID?, panelId: UUID?) -> TerminalNotification { - TerminalNotification( - id: id, - tabId: tabId, - surfaceId: surfaceId, - panelId: panelId, - title: title, - subtitle: subtitle, - body: body, - createdAt: Date(timeIntervalSince1970: createdAt), - isRead: isRead, - paneFlash: paneFlash ?? true, - clickAction: clickAction - ) - } -} - struct SessionPanelSnapshot: Codable, Sendable { var id: UUID var type: PanelType @@ -1345,7 +1285,6 @@ struct SessionPanelSnapshot: Codable, Sendable { var isPinned: Bool var isManuallyUnread: Bool var hasUnreadIndicator: Bool? = nil - var notifications: [SessionNotificationSnapshot]? = nil var gitBranch: SessionGitBranchSnapshot? var listeningPorts: [Int] var ttyName: String? @@ -1435,7 +1374,6 @@ struct SessionWorkspaceSnapshot: Codable, Sendable { var isPinned: Bool var isManuallyUnread: Bool? = nil var hasUnreadIndicator: Bool? = nil - var notifications: [SessionNotificationSnapshot]? = nil var terminalScrollBarHidden: Bool? var currentDirectory: String var focusedPanelId: UUID? diff --git a/Sources/Settings/ConfigSource.swift b/Sources/Settings/ConfigSource.swift index 94b8b12cf2cd..a275dd80690f 100644 --- a/Sources/Settings/ConfigSource.swift +++ b/Sources/Settings/ConfigSource.swift @@ -152,6 +152,145 @@ struct ConfigSourceEnvironment { } } +enum CmuxGhosttyConfigPathResolver { + static let releaseBundleIdentifier = "com.cmuxterm.app" + private static let releaseFallbackChannelSuffixes = ["debug", "nightly", "staging"] + + static func editableConfigURL( + currentBundleIdentifier: String?, + appSupportDirectory: URL + ) -> URL { + configDirectoryURL( + currentBundleIdentifier: currentBundleIdentifier, + appSupportDirectory: appSupportDirectory + ) + .appendingPathComponent("config.ghostty", isDirectory: false) + } + + static func activeOrEditableConfigURL( + currentBundleIdentifier: String?, + appSupportDirectory: URL, + fileManager: FileManager = .default + ) -> URL { + loadConfigURLs( + currentBundleIdentifier: currentBundleIdentifier, + appSupportDirectory: appSupportDirectory, + fileManager: fileManager + ) + .first + ?? editableConfigURL( + currentBundleIdentifier: currentBundleIdentifier, + appSupportDirectory: appSupportDirectory + ) + } + + static func loadConfigURLs( + currentBundleIdentifier: String?, + appSupportDirectory: URL, + fileManager: FileManager = .default + ) -> [URL] { + guard let currentBundleIdentifier, !currentBundleIdentifier.isEmpty else { + return preferredExistingConfigURLs( + for: releaseBundleIdentifier, + appSupportDirectory: appSupportDirectory, + fileManager: fileManager + ) + } + + let currentURLs = preferredExistingConfigURLs( + for: currentBundleIdentifier, + appSupportDirectory: appSupportDirectory, + fileManager: fileManager + ) + if !currentURLs.isEmpty { + return currentURLs + } + if allowsReleaseFallback(currentBundleIdentifier) { + let releaseURLs = preferredExistingConfigURLs( + for: releaseBundleIdentifier, + appSupportDirectory: appSupportDirectory, + fileManager: fileManager + ) + if !releaseURLs.isEmpty { + return releaseURLs + } + } + return [] + } + + static func configDirectoryURL( + currentBundleIdentifier: String?, + appSupportDirectory: URL + ) -> URL { + guard let currentBundleIdentifier, !currentBundleIdentifier.isEmpty else { + return appSupportDirectory.appendingPathComponent(releaseBundleIdentifier, isDirectory: true) + } + return appSupportDirectory.appendingPathComponent(currentBundleIdentifier, isDirectory: true) + } + + private static func preferredExistingConfigURLs( + for bundleIdentifier: String, + appSupportDirectory: URL, + fileManager: FileManager + ) -> [URL] { + let directory = appSupportDirectory.appendingPathComponent(bundleIdentifier, isDirectory: true) + let legacyConfig = directory.appendingPathComponent("config", isDirectory: false) + let configGhostty = directory.appendingPathComponent("config.ghostty", isDirectory: false) + if isNonEmptyConfigFile(configGhostty, fileManager: fileManager) { + // Do not layer legacy config under config.ghostty. Older builds wrote + // explicit dark colors there, which blocks appearance-driven themes. + return [configGhostty] + } + if isNonEmptyConfigFile(legacyConfig, fileManager: fileManager) { + return [legacyConfig] + } + return [] + } + + private static func isNonEmptyConfigFile(_ url: URL, fileManager: FileManager) -> Bool { + var isDirectory = ObjCBool(false) + guard fileManager.fileExists(atPath: url.path, isDirectory: &isDirectory), + !isDirectory.boolValue else { + return false + } + + if (try? url.resourceValues(forKeys: [.isSymbolicLinkKey]).isSymbolicLink) == true { + return isNonEmptySymlinkTarget(url, fileManager: fileManager) + } + + return isNonEmptyRegularFile(url, fileManager: fileManager) + } + + private static func isNonEmptySymlinkTarget(_ url: URL, fileManager: FileManager) -> Bool { + isNonEmptyRegularFile(url.resolvingSymlinksInPath(), fileManager: fileManager) + } + + private static func isNonEmptyRegularFile(_ url: URL, fileManager: FileManager) -> Bool { + guard let attrs = try? fileManager.attributesOfItem(atPath: url.path), + let type = attrs[.type] as? FileAttributeType, + type == .typeRegular, + let size = attrs[.size] as? NSNumber else { + return false + } + return size.intValue > 0 + } + + private static func allowsReleaseFallback(_ bundleIdentifier: String) -> Bool { + releaseFallbackChannelSuffixes.contains { channelSuffix in + matchesChannelBundleIdentifier(bundleIdentifier, channelSuffix: channelSuffix) + } + } + + private static func matchesChannelBundleIdentifier( + _ bundleIdentifier: String, + channelSuffix: String + ) -> Bool { + let channelBundleIdentifier = "\(releaseBundleIdentifier).\(channelSuffix)" + return bundleIdentifier == channelBundleIdentifier + || bundleIdentifier.hasPrefix("\(channelBundleIdentifier).") + } +} + struct ConfigSourceSnapshot { let source: ConfigSource let primaryURL: URL diff --git a/Sources/SettingsLazyLoadHelpers.swift b/Sources/SettingsLazyLoadHelpers.swift deleted file mode 100644 index 43806f6bacc6..000000000000 --- a/Sources/SettingsLazyLoadHelpers.swift +++ /dev/null @@ -1,40 +0,0 @@ -import SwiftUI - -enum SettingsScrollCoordinateSpace { - static let name = "SettingsScrollCoordinateSpace" -} - -enum SettingsLazyLoadTrigger: CaseIterable, Hashable { - case browserHistory - case browserImport -} - -struct SettingsLazyLoadFramePreferenceKey: PreferenceKey { - static var defaultValue: [SettingsLazyLoadTrigger: CGRect] = [:] - - static func reduce( - value: inout [SettingsLazyLoadTrigger: CGRect], - nextValue: () -> [SettingsLazyLoadTrigger: CGRect] - ) { - value.merge(nextValue()) { _, newValue in newValue } - } -} - -struct SettingsLazyLoadMarker: View { - let trigger: SettingsLazyLoadTrigger - - var body: some View { - GeometryReader { proxy in - Color.clear.preference( - key: SettingsLazyLoadFramePreferenceKey.self, - value: [trigger: proxy.frame(in: .named(SettingsScrollCoordinateSpace.name))] - ) - } - } -} - -extension View { - func settingsLazyLoadTrigger(_ trigger: SettingsLazyLoadTrigger) -> some View { - background(SettingsLazyLoadMarker(trigger: trigger)) - } -} diff --git a/Sources/SettingsNavigation.swift b/Sources/SettingsNavigation.swift index b1fe4148461f..e3ffb9e90cef 100644 --- a/Sources/SettingsNavigation.swift +++ b/Sources/SettingsNavigation.swift @@ -318,6 +318,7 @@ enum SettingsSearchIndex { setting(.app, "rename-selects-name", String(localized: "settings.app.renameSelectsName", defaultValue: "Rename Selects Existing Name"), "command palette rename text selection"), setting(.app, "palette-search-all", String(localized: "settings.app.commandPaletteSearchAllSurfaces", defaultValue: "Command Palette Searches All Surfaces"), "cmd p search terminal browser markdown"), setting(.terminal, "scrollbar", String(localized: "settings.terminal.scrollBar", defaultValue: "Show Terminal Scroll Bar"), "terminal shell scrollback"), + setting(.terminal, "timestamps", String(localized: "settings.terminal.timestamps", defaultValue: "Show Terminal Timestamps"), "terminal output time timestamp gutter"), setting(.terminal, "agent-auto-resume", String(localized: "settings.terminal.agentAutoResume", defaultValue: "Resume Agent Sessions on Reopen"), "terminal.autoResumeAgentSessions auto resume restore reopen relaunch quit sessions agents claude code codex opencode rovo dev rovodev toggle"), setting(.terminal, "resume-commands", String(localized: "settings.terminal.resumeCommands", defaultValue: "Resume Commands"), "surface resume command approvals prefixes auto restore prompt manual tmux hibernation"), setting(.sidebarAppearance, "match-terminal", String(localized: "settings.sidebarAppearance.matchTerminalBackground", defaultValue: "Match Terminal Background"), "sidebar material transparency"), @@ -327,7 +328,6 @@ enum SettingsSearchIndex { setting(.sidebarAppearance, "show-notification-message", String(localized: "settings.app.showNotificationMessage", defaultValue: "Show Notification Message in Sidebar"), "workspace latest notification"), setting(.sidebarAppearance, "show-branch-directory", String(localized: "settings.app.showBranchDirectory", defaultValue: "Show Branch + Directory in Sidebar"), "git cwd path"), setting(.sidebarAppearance, "show-pull-requests", String(localized: "settings.app.showPullRequests", defaultValue: "Show Pull Requests in Sidebar"), "review pr mr link"), - setting(.sidebarAppearance, "watch-git-status", String(localized: "settings.app.watchGitStatus", defaultValue: "Watch Git Status in Sidebar"), "git status branch watcher index lock"), setting(.sidebarAppearance, "make-pr-clickable", String(localized: "settings.app.makeSidebarPullRequestClickable", defaultValue: "Make Sidebar PR Clickable"), "pull requests pull request pr mr review clickable links select workspace row"), setting(.sidebarAppearance, "open-pr-links", String(localized: "settings.app.openSidebarPRLinks", defaultValue: "Open Sidebar PR Links in cmux Browser"), "pull request link browser"), setting(.sidebarAppearance, "open-port-links", String(localized: "settings.app.openSidebarPortLinks", defaultValue: "Open Sidebar Port Links in cmux Browser"), "port link browser"), @@ -342,7 +342,6 @@ enum SettingsSearchIndex { setting(.automation, "claude-code", String(localized: "settings.automation.claudeCode", defaultValue: "Claude Code Integration"), "agent hooks notifications"), setting(.automation, "claude-path", String(localized: "settings.automation.claudeCode.customPath", defaultValue: "Claude Binary Path"), "custom claude executable"), setting(.automation, "ripgrep-path", String(localized: "settings.automation.ripgrep.customPath", defaultValue: "Ripgrep Binary Path"), "custom ripgrep rg executable find search nix"), - setting(.automation, "subagent-notifications", String(localized: "settings.automation.suppressSubagentNotifications", defaultValue: "Suppress Subagent Notifications"), "nested child agent codex claude hooks notifications"), setting(.automation, "cursor", String(localized: "settings.automation.cursor", defaultValue: "Cursor Integration"), "agent hooks notifications"), setting(.automation, "gemini", String(localized: "settings.automation.gemini", defaultValue: "Gemini CLI Integration"), "agent hooks notifications"), setting(.automation, "port-base", String(localized: "settings.automation.portBase", defaultValue: "Port Base"), "CMUX_PORT start"), @@ -418,7 +417,6 @@ enum SettingsSearchIndex { "sidebar.showNotificationMessage": settingID(for: .sidebarAppearance, idSuffix: "show-notification-message"), "sidebar.showBranchDirectory": settingID(for: .sidebarAppearance, idSuffix: "show-branch-directory"), "sidebar.showPullRequests": settingID(for: .sidebarAppearance, idSuffix: "show-pull-requests"), - "sidebar.watchGitStatus": settingID(for: .sidebarAppearance, idSuffix: "watch-git-status"), "sidebar.makePullRequestsClickable": settingID(for: .sidebarAppearance, idSuffix: "make-pr-clickable"), "sidebar.openPullRequestLinksInCmuxBrowser": settingID(for: .sidebarAppearance, idSuffix: "open-pr-links"), "sidebar.openPortLinksInCmuxBrowser": settingID(for: .sidebarAppearance, idSuffix: "open-port-links"), @@ -428,6 +426,7 @@ enum SettingsSearchIndex { "sidebar.showProgress": settingID(for: .sidebarAppearance, idSuffix: "show-progress"), "sidebar.showCustomMetadata": settingID(for: .sidebarAppearance, idSuffix: "show-metadata"), "terminal.showScrollBar": settingID(for: .terminal, idSuffix: "scrollbar"), + "terminal.showTimestamps": settingID(for: .terminal, idSuffix: "timestamps"), "terminal.autoResumeAgentSessions": settingID(for: .terminal, idSuffix: "agent-auto-resume"), "workspaceColors.indicatorStyle": settingID(for: .workspaceColors, idSuffix: "indicator"), "workspaceColors.selectionColor": settingID(for: .workspaceColors, idSuffix: "selection"), @@ -438,7 +437,6 @@ enum SettingsSearchIndex { "automation.claudeCodeIntegration": settingID(for: .automation, idSuffix: "claude-code"), "automation.claudeBinaryPath": settingID(for: .automation, idSuffix: "claude-path"), "automation.ripgrepBinaryPath": settingID(for: .automation, idSuffix: "ripgrep-path"), - "automation.suppressSubagentNotifications": settingID(for: .automation, idSuffix: "subagent-notifications"), "automation.cursorIntegration": settingID(for: .automation, idSuffix: "cursor"), "automation.geminiIntegration": settingID(for: .automation, idSuffix: "gemini"), "automation.portBase": settingID(for: .automation, idSuffix: "port-base"), diff --git a/Sources/SettingsSearchAliases.swift b/Sources/SettingsSearchAliases.swift index 7df362cc4506..819720475ee3 100644 --- a/Sources/SettingsSearchAliases.swift +++ b/Sources/SettingsSearchAliases.swift @@ -76,7 +76,6 @@ enum SettingsSearchAliasIndex { "sidebarAppearance:show-notification-message": localized("settings.search.alias.setting.app.show-notification-message", defaultValue: "sidebar.showNotificationMessage latest message unread notification text sidebar"), "sidebarAppearance:show-branch-directory": localized("settings.search.alias.setting.app.show-branch-directory", defaultValue: "sidebar.showBranchDirectory git branch cwd path directory folder repo sidebar"), "sidebarAppearance:show-pull-requests": localized("settings.search.alias.setting.app.show-pull-requests", defaultValue: "sidebar.showPullRequests pr mr review github gitlab bitbucket pull request merge request"), - "sidebarAppearance:watch-git-status": localized("settings.search.alias.setting.app.watch-git-status", defaultValue: "sidebar.watchGitStatus git status branch watcher index lock"), "sidebarAppearance:make-pr-clickable": localized("settings.search.alias.setting.sidebarAppearance.make-pr-clickable", defaultValue: "sidebar.makePullRequestsClickable clickable pull requests pr mr reviews links select workspace row"), "sidebarAppearance:open-pr-links": localized("settings.search.alias.setting.app.open-pr-links", defaultValue: "sidebar.openPullRequestLinksInCmuxBrowser pr links github browser default external embedded"), "sidebarAppearance:open-port-links": localized("settings.search.alias.setting.app.open-port-links", defaultValue: "sidebar.openPortLinksInCmuxBrowser ports localhost links browser default external embedded"), @@ -91,7 +90,6 @@ enum SettingsSearchAliasIndex { "automation:claude-code": localized("settings.search.alias.setting.automation.claude-code", defaultValue: "automation.claudeCodeIntegration claude code hooks agent integration status notifications"), "automation:claude-path": localized("settings.search.alias.setting.automation.claude-path", defaultValue: "automation.claudeBinaryPath claude binary executable path cli command custom"), "automation:ripgrep-path": localized("settings.search.alias.setting.automation.ripgrep-path", defaultValue: "automation.ripgrepBinaryPath ripgrep rg binary executable path search find nix custom"), - "automation:subagent-notifications": localized("settings.search.alias.setting.automation.subagent-notifications", defaultValue: "automation.suppressSubagentNotifications subagent nested child agent codex claude hooks notifications"), "automation:cursor": localized("settings.search.alias.setting.automation.cursor", defaultValue: "automation.cursorIntegration cursor ide agent hooks notifications"), "automation:gemini": localized("settings.search.alias.setting.automation.gemini", defaultValue: "automation.geminiIntegration gemini cli google agent hooks notifications"), "automation:port-base": localized("settings.search.alias.setting.automation.port-base", defaultValue: "automation.portBase cmux_port start first base env environment variable"), @@ -116,6 +114,7 @@ enum SettingsSearchAliasIndex { "keyboardShortcuts:shortcut-chords": localized("settings.search.alias.setting.keyboardShortcuts.shortcut-chords", defaultValue: "tmux prefix ctrl-b control-b multi key sequence chord cmux json"), "keyboardShortcuts:reset-defaults": localized("settings.search.alias.setting.keyboardShortcuts.reset-defaults", defaultValue: "reset restore default defaults built in builtin shortcuts hotkeys keybindings commands"), "keyboardShortcuts:shortcuts": localized("settings.search.alias.setting.keyboardShortcuts.shortcuts", defaultValue: "hotkeys keybindings key bindings commands keyboard accelerators shortcuts cmux json"), + "terminal:timestamps": localized("settings.search.alias.setting.terminal.timestamps", defaultValue: "terminal.showTimestamps timestamps time gutter output lines long running agent hang debug"), "workspaceColors:indicator": localized("settings.search.alias.setting.workspaceColors.indicator", defaultValue: "workspaceColors.indicatorStyle tab indicator active workspace style color stripe dot"), "workspaceColors:selection": localized("settings.search.alias.setting.workspaceColors.selection", defaultValue: "workspaceColors.selectionColor selected workspace color highlight background active tab"), "workspaceColors:badge": localized("settings.search.alias.setting.workspaceColors.badge", defaultValue: "workspaceColors.notificationBadgeColor unread notification badge color dot count"), diff --git a/Sources/Sidebar/SidebarAppearanceSupport.swift b/Sources/Sidebar/SidebarAppearanceSupport.swift index 8503dcc62864..1cb7b0942e9f 100644 --- a/Sources/Sidebar/SidebarAppearanceSupport.swift +++ b/Sources/Sidebar/SidebarAppearanceSupport.swift @@ -40,16 +40,6 @@ func sidebarActiveForegroundNSColor( return baseColor.withAlphaComponent(clampedOpacity) } -func titlebarControlForegroundNSColor( - opacity: CGFloat, - appearance: WindowAppearanceSnapshot = .currentFromUserDefaults() -) -> NSColor { - cmuxReadableForegroundNSColor( - on: appearance.compositedTerminalBackgroundColor, - opacity: opacity - ) -} - func cmuxAccentNSColor(for colorScheme: ColorScheme) -> NSColor { switch colorScheme { case .dark: @@ -85,94 +75,6 @@ func cmuxAccentColor() -> Color { Color(nsColor: cmuxAccentNSColor()) } -func cmuxReadableColorScheme(for backgroundColor: NSColor) -> ColorScheme { - let backgroundLuminance = cmuxRelativeLuminance(backgroundColor) - let whiteContrast = cmuxContrastRatio(backgroundLuminance, 1.0) - let blackContrast = cmuxContrastRatio(backgroundLuminance, 0.0) - return whiteContrast >= blackContrast ? .dark : .light -} - -func cmuxReadableForegroundNSColor(on backgroundColor: NSColor, opacity: CGFloat) -> NSColor { - let clampedOpacity = max(0, min(opacity, 1)) - return cmuxReadableForegroundBaseColor(on: backgroundColor) - .withAlphaComponent(clampedOpacity) -} - -func cmuxReadableForegroundNSColor( - preferred preferredColor: NSColor, - on backgroundColor: NSColor, - minimumContrast: CGFloat = 4.5 -) -> NSColor { - let foregroundForComparison = preferredColor.alphaComponent < 1 - ? cmuxCompositedNSColor(preferredColor, over: backgroundColor) - : preferredColor - guard cmuxContrastRatio(foreground: foregroundForComparison, background: backgroundColor) < minimumContrast else { - return preferredColor - } - return cmuxReadableForegroundNSColor(on: backgroundColor, opacity: preferredColor.alphaComponent) -} - -func cmuxCompositedNSColor(_ foreground: NSColor, over background: NSColor) -> NSColor { - let fg = foreground.usingColorSpace(.sRGB) ?? foreground - let bg = background.usingColorSpace(.sRGB) ?? background - var foregroundRed: CGFloat = 0 - var foregroundGreen: CGFloat = 0 - var foregroundBlue: CGFloat = 0 - var foregroundAlpha: CGFloat = 0 - var backgroundRed: CGFloat = 0 - var backgroundGreen: CGFloat = 0 - var backgroundBlue: CGFloat = 0 - var backgroundAlpha: CGFloat = 0 - fg.getRed(&foregroundRed, green: &foregroundGreen, blue: &foregroundBlue, alpha: &foregroundAlpha) - bg.getRed(&backgroundRed, green: &backgroundGreen, blue: &backgroundBlue, alpha: &backgroundAlpha) - _ = backgroundAlpha - - let alpha = max(0, min(foregroundAlpha, 1)) - return NSColor( - srgbRed: foregroundRed * alpha + backgroundRed * (1 - alpha), - green: foregroundGreen * alpha + backgroundGreen * (1 - alpha), - blue: foregroundBlue * alpha + backgroundBlue * (1 - alpha), - alpha: 1 - ) -} - -func cmuxContrastRatio(foreground: NSColor, background: NSColor) -> CGFloat { - cmuxContrastRatio( - cmuxRelativeLuminance(foreground), - cmuxRelativeLuminance(background) - ) -} - -private func cmuxReadableForegroundBaseColor(on backgroundColor: NSColor) -> NSColor { - cmuxReadableColorScheme(for: backgroundColor) == .dark ? .white : .black -} - -private func cmuxRelativeLuminance(_ color: NSColor) -> CGFloat { - let srgb = color.usingColorSpace(.sRGB) ?? color - var red: CGFloat = 0 - var green: CGFloat = 0 - var blue: CGFloat = 0 - var alpha: CGFloat = 0 - srgb.getRed(&red, green: &green, blue: &blue, alpha: &alpha) - _ = alpha - - func linearized(_ component: CGFloat) -> CGFloat { - component <= 0.03928 - ? component / 12.92 - : CGFloat(pow(Double((component + 0.055) / 1.055), 2.4)) - } - - return 0.2126 * linearized(red) - + 0.7152 * linearized(green) - + 0.0722 * linearized(blue) -} - -private func cmuxContrastRatio(_ lhs: CGFloat, _ rhs: CGFloat) -> CGFloat { - let lighter = max(lhs, rhs) - let darker = min(lhs, rhs) - return (lighter + 0.05) / (darker + 0.05) -} - struct SidebarRemoteErrorCopyEntry: Equatable { let workspaceTitle: String let target: String @@ -222,22 +124,8 @@ func sidebarSelectedWorkspaceBackgroundNSColor( } func sidebarSelectedWorkspaceForegroundNSColor(opacity: CGFloat) -> NSColor { - sidebarSelectedWorkspaceForegroundNSColor( - on: sidebarSelectedWorkspaceBackgroundNSColor(for: .dark), - opacity: opacity - ) -} - -func sidebarSelectedWorkspaceForegroundNSColor( - on backgroundColor: NSColor, - opacity: CGFloat -) -> NSColor { let clampedOpacity = max(0, min(opacity, 1)) - let whiteContrast = cmuxContrastRatio(foreground: .white, background: backgroundColor) - guard whiteContrast < 2.75 else { - return NSColor.white.withAlphaComponent(clampedOpacity) - } - return cmuxReadableForegroundNSColor(on: backgroundColor, opacity: clampedOpacity) + return NSColor.white.withAlphaComponent(clampedOpacity) } struct SidebarWorkspaceRowBackgroundStyle { diff --git a/Sources/SocketControlSettings.swift b/Sources/SocketControlSettings.swift index b9f1d7361982..762bd6e649de 100644 --- a/Sources/SocketControlSettings.swift +++ b/Sources/SocketControlSettings.swift @@ -505,32 +505,12 @@ struct SocketControlSettings { if isTruthy(environment[allowSocketPathOverrideKey]) { return true } - if inheritedBundleIdentifierConflicts(environment: environment, bundleIdentifier: bundleIdentifier) { - return false - } if isDebugLikeBundleIdentifier(bundleIdentifier) || isStagingBundleIdentifier(bundleIdentifier) { return true } return isDebugBuild } - private static func inheritedBundleIdentifierConflicts( - environment: [String: String], - bundleIdentifier: String? - ) -> Bool { - guard let inheritedBundleIdentifier = normalizedBundleIdentifier(environment["CMUX_BUNDLE_ID"]), - let bundleIdentifier = normalizedBundleIdentifier(bundleIdentifier) else { - return false - } - return inheritedBundleIdentifier != bundleIdentifier - } - - private static func normalizedBundleIdentifier(_ value: String?) -> String? { - guard let value else { return nil } - let trimmed = value.trimmingCharacters(in: .whitespacesAndNewlines) - return trimmed.isEmpty ? nil : trimmed - } - static func isDebugLikeBundleIdentifier(_ bundleIdentifier: String?) -> Bool { guard let bundleIdentifier else { return false } return bundleIdentifier == "com.cmuxterm.app.debug" diff --git a/Sources/TabManager+EqualizeSplits.swift b/Sources/TabManager+EqualizeSplits.swift index 645d48440c80..1241afafa1fb 100644 --- a/Sources/TabManager+EqualizeSplits.swift +++ b/Sources/TabManager+EqualizeSplits.swift @@ -1,3 +1,5 @@ +import Bonsplit +import CoreGraphics import Foundation extension TabManager { @@ -14,12 +16,16 @@ extension TabManager { } @discardableResult - private func equalizeSplitsOnce(in tab: Workspace) -> TerminalController.EqualizeSplitsResult { - TerminalController.equalizeSplitsProportionally( + private func equalizeSplitsOnce(in tab: Workspace) -> EqualizeSplitsResult { + var foundSplit = false + var allSucceeded = true + equalizeSplits( in: tab.bonsplitController.treeSnapshot(), controller: tab.bonsplitController, - fromExternal: true + foundSplit: &foundSplit, + allSucceeded: &allSucceeded ) + return EqualizeSplitsResult(foundSplit: foundSplit, allSucceeded: allSucceeded) } private func scheduleEqualizeSplitsFollowUp(tabId: UUID) { @@ -38,4 +44,44 @@ extension TabManager { } } + private func equalizeSplits( + in node: ExternalTreeNode, + controller: BonsplitController, + foundSplit: inout Bool, + allSucceeded: inout Bool + ) { + switch node { + case .pane: + return + case .split(let splitNode): + foundSplit = true + if let splitId = UUID(uuidString: splitNode.id) { + if !controller.setDividerPosition(0.5, forSplit: splitId, fromExternal: true) { + allSucceeded = false + } + } else { + allSucceeded = false + } + + equalizeSplits( + in: splitNode.first, + controller: controller, + foundSplit: &foundSplit, + allSucceeded: &allSucceeded + ) + equalizeSplits( + in: splitNode.second, + controller: controller, + foundSplit: &foundSplit, + allSucceeded: &allSucceeded + ) + } + } + + private struct EqualizeSplitsResult { + let foundSplit: Bool + let allSucceeded: Bool + + var didFullyEqualize: Bool { foundSplit && allSucceeded } + } } diff --git a/Sources/TaskManagerSnapshot.swift b/Sources/TaskManagerSnapshot.swift index b85e302d0fff..28621e7b68f2 100644 --- a/Sources/TaskManagerSnapshot.swift +++ b/Sources/TaskManagerSnapshot.swift @@ -5,27 +5,21 @@ struct CmuxTaskManagerSnapshot { rows: [], agentRows: [], aggregateRows: [], - childMemoryRows: [], total: .zero, - sampledAt: nil, - memoryDiagnostic: nil + sampledAt: nil ) let rows: [CmuxTaskManagerRow] let agentRows: [CmuxTaskManagerRow] let aggregateRows: [CmuxTaskManagerRow] - let childMemoryRows: [CmuxTaskManagerRow] let total: CmuxTaskManagerResources let sampledAt: Date? - let memoryDiagnostic: CmuxTaskManagerMemoryDiagnostic? var hasLoadedResourceUsage: Bool { sampledAt != nil || !rows.isEmpty || !agentRows.isEmpty || !aggregateRows.isEmpty - || !childMemoryRows.isEmpty - || memoryDiagnostic != nil } var updatedText: String { @@ -39,35 +33,28 @@ struct CmuxTaskManagerSnapshot { rows: [CmuxTaskManagerRow], agentRows: [CmuxTaskManagerRow] = [], aggregateRows: [CmuxTaskManagerRow], - childMemoryRows: [CmuxTaskManagerRow] = [], total: CmuxTaskManagerResources, - sampledAt: Date?, - memoryDiagnostic: CmuxTaskManagerMemoryDiagnostic? = nil + sampledAt: Date? ) { self.rows = rows self.agentRows = agentRows self.aggregateRows = aggregateRows - self.childMemoryRows = childMemoryRows self.total = total self.sampledAt = sampledAt - self.memoryDiagnostic = memoryDiagnostic } init( rows: [CmuxTaskManagerRow], agentRows: [CmuxTaskManagerRow] = [], total: CmuxTaskManagerResources, - sampledAt: Date?, - memoryDiagnostic: CmuxTaskManagerMemoryDiagnostic? = nil + sampledAt: Date? ) { self.init( rows: rows, agentRows: agentRows, aggregateRows: Self.programAggregateRows(from: rows), - childMemoryRows: Self.childMemoryRows(from: memoryDiagnostic), total: total, - sampledAt: sampledAt, - memoryDiagnostic: memoryDiagnostic + sampledAt: sampledAt ) } @@ -91,74 +78,6 @@ struct CmuxTaskManagerSnapshot { self.aggregateRows = programTotalPayloads.isEmpty ? Self.programAggregateRows(from: self.rows) : Self.programAggregateRows(fromPayloads: programTotalPayloads) - let memoryDiagnostic = CmuxTaskManagerMemoryDiagnostic(payload["memory_diagnostic"] as? [String: Any]) - self.memoryDiagnostic = memoryDiagnostic - self.childMemoryRows = Self.childMemoryRows(from: memoryDiagnostic) - } - - private static func childMemoryRows(from diagnostic: CmuxTaskManagerMemoryDiagnostic?) -> [CmuxTaskManagerRow] { - guard let diagnostic else { return [] } - return diagnostic.groups.map { group in - let attribution = group.topAttribution - let workspaceId = attribution?.workspaceId - let surfaceId = attribution?.surfaceId - let surfaceType = attribution?.surfaceType?.lowercased() - let detailParts = [ - processCountDetail(group.processCount), - attributionDetail(attribution) - ].compactMap { $0 } - return CmuxTaskManagerRow( - id: "childMemoryAggregate:\(group.id)", - kind: .childMemoryAggregate, - level: 0, - title: group.name, - detail: detailParts.joined(separator: " / "), - resources: CmuxTaskManagerResources( - cpuPercent: 0, - residentBytes: group.rssBytes, - memoryBytes: group.rssBytes, - processCount: group.processCount, - processIds: group.processIds - ), - isDimmed: false, - workspaceId: workspaceId, - surfaceId: surfaceId, - terminalSurfaceId: surfaceType == "terminal" ? surfaceId : nil, - processId: nil, - rootProcessIds: group.processIds, - foregroundProcessGroupIds: [], - agentAssetName: agentAssetName(for: [group.name]) - ) - } - } - - private static func attributionDetail(_ attribution: CmuxTaskManagerMemoryAttribution?) -> String? { - guard let attribution else { - return String(localized: "taskManager.memory.unattributed", defaultValue: "Unattributed") - } - var parts: [String] = [] - if let workspace = attribution.workspaceRef ?? attribution.workspaceId?.uuidString { - parts.append(String(format: String( - localized: "taskManager.memory.workspace", - defaultValue: "Workspace %@" - ), workspace)) - } - if let pane = attribution.paneRef ?? attribution.paneId?.uuidString { - parts.append(String(format: String( - localized: "taskManager.memory.pane", - defaultValue: "Pane %@" - ), pane)) - } - if let surface = attribution.surfaceRef ?? attribution.surfaceId?.uuidString { - parts.append(String(format: String( - localized: "taskManager.memory.surface", - defaultValue: "Surface %@" - ), surface)) - } - if parts.isEmpty { - return String(localized: "taskManager.memory.unattributed", defaultValue: "Unattributed") - } - return parts.joined(separator: " / ") } private static func agentRows(from payloads: [[String: Any]]) -> [CmuxTaskManagerRow] { diff --git a/Sources/TaskManagerTypes.swift b/Sources/TaskManagerTypes.swift index c99a802d3285..598bbebdec63 100644 --- a/Sources/TaskManagerTypes.swift +++ b/Sources/TaskManagerTypes.swift @@ -14,7 +14,6 @@ struct CmuxTaskManagerRow: Identifiable, Equatable { case process case programAggregate case codingAgentAggregate - case childMemoryAggregate var systemImage: String { switch self { @@ -28,7 +27,6 @@ struct CmuxTaskManagerRow: Identifiable, Equatable { case .process: return "gearshape" case .programAggregate: return "gearshape.2" case .codingAgentAggregate: return "sparkles" - case .childMemoryAggregate: return "memorychip" } } @@ -44,7 +42,6 @@ struct CmuxTaskManagerRow: Identifiable, Equatable { case .process: return .secondary case .programAggregate: return .accentColor case .codingAgentAggregate: return .accentColor - case .childMemoryAggregate: return .pink } } } @@ -374,123 +371,6 @@ struct CmuxTaskManagerResources: Equatable { } } -struct CmuxTaskManagerMemoryDiagnostic: Sendable { - let summary: String - let appFootprintBytes: Int64 - let appResidentBytes: Int64 - let childRSSBytes: Int64 - let childProcessCount: Int - let groups: [CmuxTaskManagerMemoryGroup] - - init?(_ payload: [String: Any]?) { - guard let payload else { return nil } - let app = payload["app"] as? [String: Any] ?? [:] - let children = payload["children"] as? [String: Any] ?? [:] - self.summary = Self.string(payload["summary"]) ?? "" - self.appFootprintBytes = Self.int64(app["physical_footprint_bytes"]) - self.appResidentBytes = Self.int64(app["resident_bytes"]) - self.childRSSBytes = Self.int64(children["recursive_rss_bytes"]) - self.childProcessCount = Self.int(children["process_count"]) ?? 0 - self.groups = (children["groups"] as? [[String: Any]] ?? []) - .compactMap(CmuxTaskManagerMemoryGroup.init) - } - - static func string(_ raw: Any?) -> String? { - guard let value = raw as? String else { return nil } - let trimmed = value.trimmingCharacters(in: .whitespacesAndNewlines) - return trimmed.isEmpty ? nil : trimmed - } - - static func int64(_ raw: Any?) -> Int64 { - if let value = raw as? Int64 { return value } - if let value = raw as? Int { return Int64(value) } - if let value = raw as? NSNumber { return value.int64Value } - if let value = raw as? String, - let parsed = Int64(value.trimmingCharacters(in: .whitespacesAndNewlines)) { - return parsed - } - return 0 - } - - static func int(_ raw: Any?) -> Int? { - if let value = raw as? Int { return value } - if let value = raw as? NSNumber { return value.intValue } - if let value = raw as? String { - return Int(value.trimmingCharacters(in: .whitespacesAndNewlines)) - } - return nil - } - - static func intArray(_ raw: Any?) -> [Int] { - if let values = raw as? [Int] { return values } - guard let values = raw as? [Any] else { return [] } - return values.compactMap(int) - } -} - -struct CmuxTaskManagerMemoryGroup: Sendable { - let id: String - let name: String - let rssBytes: Int64 - let processCount: Int - let processIds: [Int] - let topAttribution: CmuxTaskManagerMemoryAttribution? - - init?(_ payload: [String: Any]) { - guard let name = CmuxTaskManagerMemoryDiagnostic.string(payload["name"]) else { - return nil - } - let processCount = CmuxTaskManagerMemoryDiagnostic.int(payload["process_count"]) ?? 0 - guard processCount > 0 else { return nil } - self.id = CmuxTaskManagerMemoryDiagnostic.string(payload["id"]) ?? name.lowercased() - self.name = name - self.rssBytes = CmuxTaskManagerMemoryDiagnostic.int64(payload["rss_bytes"]) - self.processCount = processCount - self.processIds = CmuxTaskManagerMemoryDiagnostic.intArray(payload["pids"]) - self.topAttribution = CmuxTaskManagerMemoryAttribution(payload["top_attribution"] as? [String: Any]) - } -} - -struct CmuxTaskManagerMemoryAttribution: Sendable { - let workspaceId: UUID? - let workspaceRef: String? - let paneId: UUID? - let paneRef: String? - let surfaceId: UUID? - let surfaceRef: String? - let surfaceType: String? - - init?(_ payload: [String: Any]?) { - guard let payload else { return nil } - self.workspaceId = Self.uuid(payload["workspace_id"]) - self.workspaceRef = CmuxTaskManagerMemoryDiagnostic.string(payload["workspace_ref"]) - self.paneId = Self.uuid(payload["pane_id"]) - self.paneRef = CmuxTaskManagerMemoryDiagnostic.string(payload["pane_ref"]) - self.surfaceId = Self.uuid(payload["surface_id"]) - self.surfaceRef = CmuxTaskManagerMemoryDiagnostic.string(payload["surface_ref"]) - self.surfaceType = CmuxTaskManagerMemoryDiagnostic.string(payload["surface_type"]) - if workspaceId == nil, - workspaceRef == nil, - paneId == nil, - paneRef == nil, - surfaceId == nil, - surfaceRef == nil, - surfaceType == nil { - return nil - } - } - - private static func uuid(_ raw: Any?) -> UUID? { - if let value = raw as? UUID { - return value - } - guard let value = CmuxTaskManagerMemoryDiagnostic.string(raw) else { - return nil - } - return UUID(uuidString: value) - } -} - enum CmuxTaskManagerFormat { private static let isoFormatter = ISO8601DateFormatter() private static let timeFormatter: DateFormatter = { @@ -611,14 +491,6 @@ struct CmuxTaskManagerCodingAgentDefinition: Equatable { directBasenames: ["gemini"], argumentNeedles: ["gemini"] ), - CmuxTaskManagerCodingAgentDefinition( - id: "antigravity", - displayName: "Antigravity", - assetName: "AgentIcons/Antigravity", - launchKinds: ["antigravity", "agy"], - directBasenames: ["agy", "antigravity"], - argumentNeedles: ["antigravity-cli", "antigravity"] - ), CmuxTaskManagerCodingAgentDefinition( id: "rovodev", displayName: "Rovo Dev", diff --git a/Sources/TaskManagerWindowController.swift b/Sources/TaskManagerWindowController.swift index 3553d729ebaf..9777e5b6546b 100644 --- a/Sources/TaskManagerWindowController.swift +++ b/Sources/TaskManagerWindowController.swift @@ -1,6 +1,6 @@ import AppKit +import Combine import Darwin -import Observation import SwiftUI @MainActor @@ -48,33 +48,31 @@ final class TaskManagerWindowController: NSWindowController, NSWindowDelegate { } @MainActor -@Observable -final class CmuxTaskManagerModel { - private(set) var snapshot = CmuxTaskManagerSnapshot.empty { +final class CmuxTaskManagerModel: ObservableObject { + @Published private(set) var snapshot = CmuxTaskManagerSnapshot.empty { didSet { updateSortedRows() } } - private(set) var isRefreshing = false - private(set) var errorMessage: String? - private(set) var sortOrder = CmuxTaskManagerSortOrder.defaultOrder { + @Published private(set) var isRefreshing = false + @Published private(set) var errorMessage: String? + @Published private(set) var sortOrder = CmuxTaskManagerSortOrder.defaultOrder { didSet { updateSortedRows() } } - var includesProcesses = false { + @Published var includesProcesses = false { didSet { guard oldValue != includesProcesses else { return } refresh(force: true) } } - @ObservationIgnored private var refreshTimer: Timer? - @ObservationIgnored private var refreshTask: Task? - @ObservationIgnored private var terminationTimers: [UUID: Timer] = [:] + private var refreshTimer: Timer? + private var refreshTask: Task? + private var terminationTimers: [UUID: Timer] = [:] private let refreshInterval: TimeInterval = 3.0 private let terminationGraceInterval: TimeInterval = 2.0 private(set) var sortedRows: [CmuxTaskManagerRow] = [] private(set) var sortedAgentRows: [CmuxTaskManagerRow] = [] private(set) var sortedAggregateRows: [CmuxTaskManagerRow] = [] - private(set) var sortedChildMemoryRows: [CmuxTaskManagerRow] = [] init() { updateSortedRows() @@ -128,7 +126,7 @@ final class CmuxTaskManagerModel { if shouldShowIndicator { isRefreshing = true } - refreshTask = Task { @MainActor [weak self] in + refreshTask = Task { [weak self] in do { let payload = try await TerminalController.shared.taskManagerTopPayload(includeProcesses: includeProcesses) guard !Task.isCancelled else { return } @@ -137,13 +135,7 @@ final class CmuxTaskManagerModel { self?.errorMessage = nil } catch { guard !Task.isCancelled else { return } - #if DEBUG - cmuxDebugLog("taskManager.refresh.error \(String(describing: error))") - #endif - self?.errorMessage = String( - localized: "taskManager.refresh.error", - defaultValue: "Unable to refresh Task Manager data." - ) + self?.errorMessage = String(describing: error) } if shouldShowIndicator { self?.isRefreshing = false @@ -167,12 +159,7 @@ final class CmuxTaskManagerModel { if let windowId = appDelegate.windowId(for: manager) { _ = appDelegate.focusMainWindow(windowId: windowId) } - manager.focusTab( - workspaceId, - surfaceId: row.surfaceId, - suppressFlash: true, - dismissRestoredUnreadOnResume: true - ) + manager.focusTab(workspaceId, surfaceId: row.surfaceId, suppressFlash: true) flashSelection(workspaceId: workspaceId, surfaceId: row.surfaceId) } @@ -184,12 +171,7 @@ final class CmuxTaskManagerModel { if let windowId = appDelegate.windowId(for: manager) { _ = appDelegate.focusMainWindow(windowId: windowId) } - manager.focusTab( - workspaceId, - surfaceId: terminalSurfaceId, - suppressFlash: true, - dismissRestoredUnreadOnResume: true - ) + manager.focusTab(workspaceId, surfaceId: terminalSurfaceId, suppressFlash: true) flashSelection(workspaceId: workspaceId, surfaceId: terminalSurfaceId) } @@ -278,7 +260,6 @@ final class CmuxTaskManagerModel { sortedRows = sortOrder.sortedRows(snapshot.rows) sortedAgentRows = sortOrder.sortedRows(snapshot.agentRows) sortedAggregateRows = sortOrder.sortedRows(snapshot.aggregateRows) - sortedChildMemoryRows = sortOrder.sortedRows(snapshot.childMemoryRows) } private func sendSignal(_ signal: Int32, toProcessId processId: Int) -> String? { diff --git a/Sources/TerminalController.swift b/Sources/TerminalController.swift index c9c4bf8b599f..696d07c5753d 100644 --- a/Sources/TerminalController.swift +++ b/Sources/TerminalController.swift @@ -1774,7 +1774,6 @@ class TerminalController { "browser.profiles.delete", "browser.import.cookies", "system.top", - "system.memory", ] private nonisolated static func executionPolicy(forV2Method method: String) -> SocketCommandExecutionPolicy { @@ -1884,8 +1883,6 @@ class TerminalController { } case "system.top": return v2Result(id: request.id, v2SystemTop(params: request.params)) - case "system.memory": - return v2Result(id: request.id, v2SystemMemory(params: request.params)) case let method where method.hasPrefix("vm."): return socketWorkerCloudVMResponse(method: method, id: request.id, params: request.params) default: @@ -3276,7 +3273,6 @@ class TerminalController { "system.identify", "system.tree", "system.top", - "system.memory", "events.stream", "auth.login", "auth.status", @@ -3595,113 +3591,31 @@ class TerminalController { ] } - private struct V2WindowRouting { - let includeAllWindows: Bool - let requestedWindowId: UUID? - let focused: [String: Any] - let caller: [String: Any] - let focusedWindowId: UUID? - } - - private func v2WindowSelectorDetails(params: [String: Any]) -> [String: Any]? { - guard let rawWindowId = params["window_id"] else { return nil } - if let string = rawWindowId as? String { - return ["window_id": string] - } - return ["window_id": String(describing: rawWindowId)] - } - - private func parseV2WindowRouting(params: [String: Any]) -> (routing: V2WindowRouting?, error: V2CallResult?) { - if params["all_windows"] != nil, v2Bool(params, "all_windows") == nil { - return ( - nil, - .err( - code: "invalid_params", - message: "Invalid all_windows. Pass true or false, or omit it. Use --window to target one window or --all-windows to target all windows.", - data: nil - ) - ) + private func v2SystemTree(params: [String: Any]) -> V2CallResult { + let workspaceFilter = v2UUID(params, "workspace_id") + if params["workspace_id"] != nil && workspaceFilter == nil { + return .err(code: "invalid_params", message: "Missing or invalid workspace_id", data: nil) } - let includeAllWindows = v2Bool(params, "all_windows") ?? false - let requestedWindowId = v2UUID(params, "window_id") - if params["window_id"] != nil && requestedWindowId == nil { - return ( - nil, - .err( - code: "invalid_params", - message: "Invalid window selector. Use --window to target one window, or run `cmux list-windows` to see available windows and retry.", - data: v2WindowSelectorDetails(params: params) - ) - ) - } - if includeAllWindows, requestedWindowId != nil { - return ( - nil, - .err( - code: "invalid_params", - message: "Choose either --window or --all-windows, not both. Run `cmux list-windows` to see available windows and retry.", - data: v2WindowSelectorDetails(params: params) - ) - ) - } var identifyParams: [String: Any] = [:] if let caller = params["caller"] as? [String: Any], !caller.isEmpty { identifyParams["caller"] = caller } - if let requestedWindowId { - identifyParams["window_id"] = requestedWindowId.uuidString - } let identifyPayload = v2Identify(params: identifyParams) let focused = identifyPayload["focused"] as? [String: Any] ?? [:] let caller = identifyPayload["caller"] as? [String: Any] ?? [:] let focusedWindowId = v2UUIDAny(focused["window_id"]) ?? v2UUIDAny(focused["window_ref"]) - return ( - V2WindowRouting( - includeAllWindows: includeAllWindows, - requestedWindowId: requestedWindowId, - focused: focused, - caller: caller, - focusedWindowId: focusedWindowId - ), - nil - ) - } - - private func v2WindowNotFoundResult(params: [String: Any], windowId: UUID) -> V2CallResult { - .err( - code: "not_found", - message: "Window not found. Run `cmux list-windows` to see available windows, then retry with --window .", - data: v2WindowSelectorDetails(params: params) ?? ["window_id": windowId.uuidString] - ) - } - - private func v2SystemTree(params: [String: Any]) -> V2CallResult { - let workspaceFilter = v2UUID(params, "workspace_id") - if params["workspace_id"] != nil && workspaceFilter == nil { - return .err(code: "invalid_params", message: "Missing or invalid workspace_id", data: nil) - } - let routingResult = parseV2WindowRouting(params: params) - if let error = routingResult.error { return error } - guard let routing = routingResult.routing else { - return .err(code: "internal_error", message: "Invalid window routing payload", data: nil) - } var windowNodes: [[String: Any]] = [] var workspaceFound = (workspaceFilter == nil) - var windowFound = (routing.requestedWindowId == nil) v2MainSync { guard let app = AppDelegate.shared else { return } let summaries = app.listMainWindowSummaries() - let defaultWindowId = routing.requestedWindowId ?? routing.focusedWindowId ?? summaries.first?.windowId + let defaultWindowId = focusedWindowId ?? summaries.first?.windowId for (windowIndex, summary) in summaries.enumerated() { - if let requestedWindowId = routing.requestedWindowId, summary.windowId != requestedWindowId { - continue - } - windowFound = true guard let manager = app.tabManagerFor(windowId: summary.windowId) else { continue } if let workspaceFilter { @@ -3725,7 +3639,7 @@ class TerminalController { break } - if !routing.includeAllWindows && summary.windowId != defaultWindowId { + if !includeAllWindows && summary.windowId != defaultWindowId { continue } @@ -3747,9 +3661,6 @@ class TerminalController { } } - if let requestedWindowId = routing.requestedWindowId, !windowFound { - return v2WindowNotFoundResult(params: params, windowId: requestedWindowId) - } if let workspaceFilter, !workspaceFound { return .err( code: "not_found", @@ -3762,8 +3673,8 @@ class TerminalController { } return .ok([ - "active": routing.focused.isEmpty ? (NSNull() as Any) : routing.focused, - "caller": routing.caller.isEmpty ? (NSNull() as Any) : routing.caller, + "active": focused.isEmpty ? (NSNull() as Any) : focused, + "caller": caller.isEmpty ? (NSNull() as Any) : caller, "windows": windowNodes ]) } @@ -3856,17 +3767,12 @@ class TerminalController { includeProcesses: includeProcesses ) let aggregates = processAggregates(from: processSnapshot, totalPIDs: totalPIDs) - let memoryDiagnostic = v2TopMemoryDiagnosticPayload( - processSnapshot: processSnapshot, - annotatedWindows: annotatedWindows - ) return [ "active": focused.isEmpty ? (NSNull() as Any) : focused, "caller": NSNull(), "sample": processSnapshot.samplePayload(), "totals": processSnapshot.summaryPayload(for: totalPIDs), - "memory_diagnostic": memoryDiagnostic, "program_totals": aggregates.programs, "coding_agents": aggregates.codingAgents, "windows": annotatedWindows @@ -3903,119 +3809,42 @@ class TerminalController { includeProcesses: includeProcesses ) let aggregates = processAggregates(from: processSnapshot, totalPIDs: totalPIDs) - let memoryDiagnostic = v2TopMemoryDiagnosticPayload( - processSnapshot: processSnapshot, - annotatedWindows: windowNodes - ) payload["sample"] = processSnapshot.samplePayload() payload["totals"] = processSnapshot.summaryPayload(for: totalPIDs) - payload["memory_diagnostic"] = memoryDiagnostic payload["program_totals"] = aggregates.programs payload["coding_agents"] = aggregates.codingAgents payload["windows"] = windowNodes return .ok(payload) } - private nonisolated func v2SystemMemory(params: [String: Any]) -> V2CallResult { - var baseParams = params - baseParams["include_processes"] = false - let base = v2MainSync { - self.v2RefreshKnownRefs() - return self.v2SystemTopBasePayload(params: baseParams) - } - guard case .ok(let value) = base else { return base } - guard var payload = value as? [String: Any], - var windowNodes = payload.removeValue(forKey: "windows") as? [[String: Any]] else { - return .err(code: "internal_error", message: "Invalid system.memory payload", data: nil) - } - func intParam(_ key: String) -> Int? { - if let i = params[key] as? Int { return i } - if let n = params[key] as? NSNumber { - guard CFGetTypeID(n) != CFBooleanGetTypeID() else { return nil } - let value = n.doubleValue - guard value.isFinite, - value.rounded(.towardZero) == value, - value >= Double(Int.min), - value <= Double(Int.max) else { - return nil - } - return n.intValue - } - if let s = params[key] as? String { - let trimmed = s.trimmingCharacters(in: .whitespacesAndNewlines) - guard !trimmed.isEmpty, - trimmed.range(of: #"^[+-]?\d+$"#, options: .regularExpression) != nil else { - return nil - } - return Int(trimmed) - } - return nil - } - var invalidLimitKey: String? - func groupLimitParam(_ key: String) -> Int? { - guard params[key] != nil else { return nil } - guard let value = intParam(key), (1...100).contains(value) else { - invalidLimitKey = key - return nil - } - return value - } - let topGroupLimitValue = groupLimitParam("top_group_limit") - if let invalidLimitKey { - return .err(code: "invalid_params", message: "\(invalidLimitKey) must be an integer from 1 to 100", data: nil) - } - let groupLimitValue = groupLimitParam("group_limit") - if let invalidLimitKey { - return .err(code: "invalid_params", message: "\(invalidLimitKey) must be an integer from 1 to 100", data: nil) - } - let topGroupLimit = topGroupLimitValue ?? groupLimitValue ?? 12 - let processSnapshot = CmuxTopProcessSnapshot.captureCached( - includeProcessDetails: true, - maximumAge: 2 - ) - let browserPIDOccurrences = v2TopBrowserPIDOccurrences(in: windowNodes) - _ = v2AnnotateTopWindows( - &windowNodes, - processSnapshot: processSnapshot, - browserPIDOccurrences: browserPIDOccurrences, - includeProcesses: false - ) - payload["sample"] = processSnapshot.samplePayload() - payload["memory_diagnostic"] = v2TopMemoryDiagnosticPayload( - processSnapshot: processSnapshot, - annotatedWindows: windowNodes, - topGroupLimit: topGroupLimit - ) - return .ok(payload) - } - private func v2SystemTopBasePayload(params: [String: Any]) -> V2CallResult { let workspaceFilter = v2UUID(params, "workspace_id") if params["workspace_id"] != nil && workspaceFilter == nil { return .err(code: "invalid_params", message: "Missing or invalid workspace_id", data: nil) } + if params["all_windows"] != nil, v2Bool(params, "all_windows") == nil { return .err(code: "invalid_params", message: "Missing or invalid all_windows", data: nil) } + let includeAllWindows = v2Bool(params, "all_windows") ?? false if params["include_processes"] != nil, v2Bool(params, "include_processes") == nil { return .err(code: "invalid_params", message: "Missing or invalid include_processes", data: nil) } let includeProcesses = v2Bool(params, "include_processes") ?? false - let routingResult = parseV2WindowRouting(params: params) - if let error = routingResult.error { return error } - guard let routing = routingResult.routing else { - return .err(code: "internal_error", message: "Invalid window routing payload", data: nil) + + var identifyParams: [String: Any] = [:] + if let caller = params["caller"] as? [String: Any], !caller.isEmpty { + identifyParams["caller"] = caller } + let identifyPayload = v2Identify(params: identifyParams) + let focused = identifyPayload["focused"] as? [String: Any] ?? [:] + let caller = identifyPayload["caller"] as? [String: Any] ?? [:] + let focusedWindowId = v2UUIDAny(focused["window_id"]) ?? v2UUIDAny(focused["window_ref"]) var windowNodes: [[String: Any]] = [] var workspaceFound = (workspaceFilter == nil) - var windowFound = (routing.requestedWindowId == nil) if let app = AppDelegate.shared { let summaries = app.listMainWindowSummaries() - let defaultWindowId = routing.requestedWindowId ?? routing.focusedWindowId ?? summaries.first?.windowId + let defaultWindowId = focusedWindowId ?? summaries.first?.windowId for (windowIndex, summary) in summaries.enumerated() { - if let requestedWindowId = routing.requestedWindowId, summary.windowId != requestedWindowId { - continue - } - windowFound = true guard let manager = app.tabManagerFor(windowId: summary.windowId) else { continue } if let workspaceFilter { @@ -4039,7 +3868,7 @@ class TerminalController { break } - if !routing.includeAllWindows && summary.windowId != defaultWindowId { + if !includeAllWindows && summary.windowId != defaultWindowId { continue } @@ -4063,9 +3892,6 @@ class TerminalController { v2AttachTopApplicationProcess(to: &windowNodes, workspaceFilter: workspaceFilter) - if let requestedWindowId = routing.requestedWindowId, !windowFound { - return v2WindowNotFoundResult(params: params, windowId: requestedWindowId) - } if let workspaceFilter, !workspaceFound { return .err( code: "not_found", @@ -4078,8 +3904,8 @@ class TerminalController { } return .ok([ - "active": routing.focused.isEmpty ? (NSNull() as Any) : routing.focused, - "caller": routing.caller.isEmpty ? (NSNull() as Any) : routing.caller, + "active": focused.isEmpty ? (NSNull() as Any) : focused, + "caller": caller.isEmpty ? (NSNull() as Any) : caller, "include_processes": includeProcesses, "windows": windowNodes ]) @@ -4685,8 +4511,7 @@ class TerminalController { func v2ResolveTabManager(params: [String: Any]) -> TabManager? { // Prefer explicit window_id routing. Fall back to global lookup by workspace_id/surface_id/tab_id, // and finally to the active window's TabManager. - if v2HasNonNullParam(params, "window_id") { - guard let windowId = v2UUID(params, "window_id") else { return nil } + if let windowId = v2UUID(params, "window_id") { return v2MainSync { AppDelegate.shared?.tabManagerFor(windowId: windowId) } } if let wsId = v2UUID(params, "workspace_id") { @@ -5497,68 +5322,54 @@ class TerminalController { v2MainSync { guard let ws = v2ResolveWorkspace(params: params, tabManager: tabManager) else { return } let tree = ws.bonsplitController.treeSnapshot() - let equalizeResult = Self.equalizeSplitsProportionally( - in: tree, - controller: ws.bonsplitController, - fromExternal: true, - orientationFilter: orientationFilter - ) + let success = v2ProportionalEqualize(node: tree, controller: ws.bonsplitController, orientationFilter: orientationFilter) result = .ok([ "workspace_id": ws.id.uuidString, "workspace_ref": v2Ref(kind: .workspace, uuid: ws.id), - "equalized": equalizeResult.foundSplit + "equalized": success ]) } return result } - struct EqualizeSplitsResult { - let foundSplit: Bool - let allSucceeded: Bool - - var didFullyEqualize: Bool { foundSplit && allSucceeded } + /// Count leaf panes in a tree node. + private func v2CountLeaves(_ node: ExternalTreeNode) -> Int { + switch node { + case .pane: + return 1 + case .split(let s): + return v2CountLeaves(s.first) + v2CountLeaves(s.second) + } } /// Proportionally equalize splits so each leaf pane gets equal space. - /// When an orientation filter is set, only matching splits are adjusted, while leaf counts still come from the full subtree. + /// For a split with N1 leaves on the left and N2 on the right, + /// the divider is set to N1/(N1+N2). + /// When orientationFilter is set (e.g. "vertical"), only splits matching + /// that orientation are equalized. This lets main-vertical layout equalize + /// the agent column without squishing the main pane. @discardableResult - static func equalizeSplitsProportionally( - in node: ExternalTreeNode, + private func v2ProportionalEqualize( + node: ExternalTreeNode, controller: BonsplitController, - fromExternal: Bool, orientationFilter: String? = nil - ) -> EqualizeSplitsResult { - var foundSplit = false - var allSucceeded = true - - @discardableResult - func equalize(_ node: ExternalTreeNode) -> Int { - switch node { - case .pane: - return 1 - case .split(let split): - let firstLeafCount = equalize(split.first) - let secondLeafCount = equalize(split.second) - let totalLeafCount = firstLeafCount + secondLeafCount - - if orientationFilter == nil || split.orientation == orientationFilter { - foundSplit = true - if let splitId = UUID(uuidString: split.id) { - let position = CGFloat(firstLeafCount) / CGFloat(totalLeafCount) - if !controller.setDividerPosition(position, forSplit: splitId, fromExternal: fromExternal) { - allSucceeded = false - } - } else { - allSucceeded = false - } - } + ) -> Bool { + guard case .split(let s) = node else { return false } + guard let splitId = UUID(uuidString: s.id) else { return false } - return totalLeafCount - } + var didEqualize = false + if orientationFilter == nil || s.orientation == orientationFilter { + let leftLeaves = v2CountLeaves(s.first) + let rightLeaves = v2CountLeaves(s.second) + let total = leftLeaves + rightLeaves + let position = CGFloat(leftLeaves) / CGFloat(total) + controller.setDividerPosition(position, forSplit: splitId, fromExternal: true) + didEqualize = true } - equalize(node) - return EqualizeSplitsResult(foundSplit: foundSplit, allSucceeded: allSucceeded) + let l = v2ProportionalEqualize(node: s.first, controller: controller, orientationFilter: orientationFilter) + let r = v2ProportionalEqualize(node: s.second, controller: controller, orientationFilter: orientationFilter) + return didEqualize || l || r } private func v2WorkspaceRemoteConfigure(params: [String: Any]) -> V2CallResult { @@ -6680,7 +6491,6 @@ class TerminalController { } if let paneId = v2UUID(params, "pane_id"), let located = v2LocatePane(paneId) { - guard located.tabManager === tabManager else { return nil } return located.workspace } guard let wsId = tabManager.selectedTabId else { return nil } @@ -7133,7 +6943,6 @@ class TerminalController { let workingDirectory = v2OptionalTrimmedRawString(params, "working_directory") let initialCommand = v2OptionalTrimmedRawString(params, "initial_command") let tmuxStartCommand = v2OptionalTrimmedRawString(params, "tmux_start_command") - let startupEnvironment = v2TrimmedStringMap(params, keys: ["startup_environment", "initial_env"]) let parsedInitialDivider = v2InitialDividerPosition(params) if let error = parsedInitialDivider.error { return error @@ -7191,7 +7000,6 @@ class TerminalController { workingDirectory: workingDirectory, initialCommand: initialCommand, tmuxStartCommand: tmuxStartCommand, - startupEnvironment: startupEnvironment, initialDividerPosition: initialDividerPosition.map { CGFloat($0) } ) } @@ -7227,7 +7035,6 @@ class TerminalController { let workingDirectory = v2OptionalTrimmedRawString(params, "working_directory") let initialCommand = v2OptionalTrimmedRawString(params, "initial_command") let tmuxStartCommand = v2OptionalTrimmedRawString(params, "tmux_start_command") - let startupEnvironment = v2TrimmedStringMap(params, keys: ["startup_environment", "initial_env"]) if panelType == .browser, BrowserAvailabilitySettings.isDisabled() { return v2BrowserDisabledExternalOpenResult(rawURL: urlStr, url: url, tabManager: tabManager) } @@ -7269,8 +7076,7 @@ class TerminalController { focus: focus, workingDirectory: workingDirectory, initialCommand: initialCommand, - tmuxStartCommand: tmuxStartCommand, - startupEnvironment: startupEnvironment + tmuxStartCommand: tmuxStartCommand )?.id } @@ -8543,7 +8349,6 @@ class TerminalController { let workingDirectory = v2OptionalTrimmedRawString(params, "working_directory") let initialCommand = v2OptionalTrimmedRawString(params, "initial_command") let tmuxStartCommand = v2OptionalTrimmedRawString(params, "tmux_start_command") - let startupEnvironment = v2TrimmedStringMap(params, keys: ["startup_environment", "initial_env"]) if panelType == .browser, BrowserAvailabilitySettings.isDisabled() { return v2BrowserDisabledExternalOpenResult(rawURL: urlStr, url: url, tabManager: tabManager) } @@ -8592,7 +8397,6 @@ class TerminalController { workingDirectory: workingDirectory, initialCommand: initialCommand, tmuxStartCommand: tmuxStartCommand, - startupEnvironment: startupEnvironment, initialDividerPosition: initialDividerPosition.map { CGFloat($0) } )?.id } @@ -14577,7 +14381,7 @@ class TerminalController { list_log [--limit=N] [--tab=X] - List log entries set_progress <0.0-1.0> [--label=X] [--tab=X] - Set progress bar clear_progress [--tab=X] - Clear progress bar - report_git_branch [--status=dirty|clean|unknown] [--tab=X] [--panel=Y] - Report git branch + report_git_branch [--status=dirty] [--tab=X] [--panel=Y] - Report git branch clear_git_branch [--tab=X] [--panel=Y] - Clear git branch report_pr [--label=PR] [--state=open|merged|closed] [--branch=] [--tab=X] [--panel=Y] - Report pull request / review item report_review [--label=MR] [--state=open|merged|closed] [--tab=X] [--panel=Y] - Alias for provider-specific review item @@ -18239,19 +18043,9 @@ class TerminalController { private func reportGitBranch(_ args: String) -> String { let parsed = parseOptions(args) guard let branch = parsed.positional.first else { - return "ERROR: Missing branch name — usage: report_git_branch [--status=dirty|clean|unknown] [--tab=X]" + return "ERROR: Missing branch name — usage: report_git_branch [--status=dirty] [--tab=X]" } - let status = parsed.options["status"]?.lowercased() - let isDirty: Bool? = { - switch status { - case "dirty": - return true - case "unknown": - return nil - default: - return false - } - }() + let isDirty = parsed.options["status"]?.lowercased() == "dirty" // Shell integration always includes explicit workspace/panel IDs. // Keep this telemetry path off-main so wake/main-thread stalls don't @@ -18265,10 +18059,6 @@ class TerminalController { let validSurfaceIds = Set(tab.panels.keys) tab.pruneSurfaceMetadata(validSurfaceIds: validSurfaceIds) guard validSurfaceIds.contains(scope.panelId) else { return } - guard SidebarWorkspaceDetailDefaults.watchGitStatusValue(defaults: .standard) else { - tabManager.clearSurfaceGitBranch(tabId: scope.workspaceId, surfaceId: scope.panelId) - return - } tabManager.updateSurfaceGitBranch( tabId: scope.workspaceId, surfaceId: scope.panelId, @@ -18285,16 +18075,7 @@ class TerminalController { result = parsed.options["tab"] != nil ? "ERROR: Tab not found" : "ERROR: No tab selected" return } - guard SidebarWorkspaceDetailDefaults.watchGitStatusValue(defaults: .standard) else { - tab.gitBranch = nil - return - } - let existingGitBranch = tab.gitBranch - let nextIsDirty = isDirty ?? (existingGitBranch?.branch == branch ? existingGitBranch?.isDirty ?? false : false) - tab.gitBranch = SidebarGitBranchState( - branch: branch, - isDirty: nextIsDirty - ) + tab.gitBranch = SidebarGitBranchState(branch: branch, isDirty: isDirty) } return result } @@ -18370,11 +18151,6 @@ class TerminalController { options: parsed.options, missingPanelUsage: "report_pr [--label=PR] [--state=open|merged|closed] [--branch=] [--tab=X] [--panel=Y]" ) { tab, surfaceId in - guard SidebarWorkspaceDetailDefaults.watchGitStatusValue(defaults: .standard) else { - tab.clearPanelPullRequest(panelId: surfaceId) - return - } - guard Self.shouldReplacePullRequest( current: tab.panelPullRequests[surfaceId], number: number, @@ -18607,11 +18383,6 @@ class TerminalController { options: parsed.options, missingPanelUsage: "report_pr_action [--target=X] [--tab=X] [--panel=Y]" ) { tab, surfaceId in - guard SidebarWorkspaceDetailDefaults.watchGitStatusValue(defaults: .standard) else { - tab.clearPanelPullRequest(panelId: surfaceId) - return - } - guard let tabManager = AppDelegate.shared?.tabManagerFor(tabId: tab.id) else { return } tabManager.handleWorkspacePullRequestCommandHint( tabId: tab.id, diff --git a/Sources/TerminalControllerTopSupport.swift b/Sources/TerminalControllerTopSupport.swift index 1b05d8b6ac90..76a034258590 100644 --- a/Sources/TerminalControllerTopSupport.swift +++ b/Sources/TerminalControllerTopSupport.swift @@ -37,18 +37,6 @@ extension TerminalController { return counts } - nonisolated func v2TopMemoryDiagnosticPayload( - processSnapshot: CmuxTopProcessSnapshot, - annotatedWindows: [[String: Any]], - topGroupLimit: Int = 12 - ) -> [String: Any] { - processSnapshot.memoryDiagnosticPayload( - appPID: Int(Darwin.getpid()), - topGroupLimit: topGroupLimit, - attributionByPID: v2TopMemoryAttributionByPID(in: annotatedWindows) - ) - } - nonisolated func v2AnnotateTopWindows( _ windows: inout [[String: Any]], processSnapshot: CmuxTopProcessSnapshot, @@ -287,12 +275,6 @@ extension TerminalController { return values.compactMap(v2TopInt) } - nonisolated func v2TopString(_ raw: Any?) -> String? { - guard let value = raw as? String else { return nil } - let trimmed = value.trimmingCharacters(in: .whitespacesAndNewlines) - return trimmed.isEmpty ? nil : trimmed - } - nonisolated func v2TopUUID(_ raw: Any?) -> UUID? { if let value = raw as? UUID { return value @@ -303,178 +285,6 @@ extension TerminalController { return nil } - private nonisolated func v2TopMemoryAttributionByPID(in windows: [[String: Any]]) -> [Int: CmuxTopProcessAttribution] { - var result: [Int: CmuxTopProcessAttribution] = [:] - var ambiguousSpecificityByPID: [Int: Int] = [:] - var commonOwnerSourceSpecificityByPID: [Int: Int] = [:] - for window in windows { - let workspaces = window["workspaces"] as? [[String: Any]] ?? [] - for workspace in workspaces { - let workspaceID = v2TopUUID(workspace["id"]) - let workspaceRef = v2TopString(workspace["ref"]) - - let tags = workspace["tags"] as? [[String: Any]] ?? [] - for tag in tags { - let attribution = CmuxTopProcessAttribution( - workspaceID: workspaceID, - workspaceRef: workspaceRef, - paneID: nil, - paneRef: nil, - surfaceID: nil, - surfaceRef: nil, - surfaceType: nil, - reason: "status-tag-process-tree" - ) - assignTopMemoryAttribution( - attribution, - from: tag, - to: &result, - ambiguousSpecificityByPID: &ambiguousSpecificityByPID, - commonOwnerSourceSpecificityByPID: &commonOwnerSourceSpecificityByPID - ) - } - - let panes = workspace["panes"] as? [[String: Any]] ?? [] - for pane in panes { - let paneID = v2TopUUID(pane["id"]) - let paneRef = v2TopString(pane["ref"]) - let surfaces = pane["surfaces"] as? [[String: Any]] ?? [] - for surface in surfaces { - let attribution = CmuxTopProcessAttribution( - workspaceID: workspaceID, - workspaceRef: workspaceRef, - paneID: paneID, - paneRef: paneRef, - surfaceID: v2TopUUID(surface["id"]), - surfaceRef: v2TopString(surface["ref"]), - surfaceType: v2TopString(surface["type"]), - reason: "surface-process-tree" - ) - assignTopMemoryAttribution( - attribution, - from: surface, - to: &result, - ambiguousSpecificityByPID: &ambiguousSpecificityByPID, - commonOwnerSourceSpecificityByPID: &commonOwnerSourceSpecificityByPID - ) - - let webviews = surface["webviews"] as? [[String: Any]] ?? [] - for webview in webviews { - assignTopMemoryAttribution( - attribution, - from: webview, - to: &result, - ambiguousSpecificityByPID: &ambiguousSpecificityByPID, - commonOwnerSourceSpecificityByPID: &commonOwnerSourceSpecificityByPID - ) - } - } - } - } - } - return result - } - - private nonisolated func assignTopMemoryAttribution( - _ attribution: CmuxTopProcessAttribution, - from node: [String: Any], - to result: inout [Int: CmuxTopProcessAttribution], - ambiguousSpecificityByPID: inout [Int: Int], - commonOwnerSourceSpecificityByPID: inout [Int: Int] - ) { - let resources = node["resources"] as? [String: Any] ?? [:] - let newSpecificity = v2TopMemoryAttributionSpecificity(attribution) - var seenPIDs = Set() - for pid in v2TopIntArray(resources["pids"]) where seenPIDs.insert(pid).inserted { - if let ambiguousSpecificity = ambiguousSpecificityByPID[pid] { - guard newSpecificity > ambiguousSpecificity else { continue } - ambiguousSpecificityByPID.removeValue(forKey: pid) - commonOwnerSourceSpecificityByPID.removeValue(forKey: pid) - } - guard let existing = result[pid] else { - result[pid] = attribution - continue - } - if existing == attribution { continue } - let existingSpecificity = v2TopMemoryAttributionSpecificity(existing) - let commonOwnerSourceSpecificity = commonOwnerSourceSpecificityByPID[pid] - let existingSourceSpecificity = commonOwnerSourceSpecificity ?? existingSpecificity - let mergedSourceSpecificity = max(existingSourceSpecificity, newSpecificity) - if let commonOwner = v2TopMemoryAttributionCommonOwner(existing, attribution), - commonOwnerSourceSpecificity != nil || newSpecificity == existingSourceSpecificity { - result[pid] = commonOwner - commonOwnerSourceSpecificityByPID[pid] = mergedSourceSpecificity - } else if newSpecificity > existingSourceSpecificity { - result[pid] = attribution - commonOwnerSourceSpecificityByPID.removeValue(forKey: pid) - } else if newSpecificity == existingSourceSpecificity { - result.removeValue(forKey: pid) - ambiguousSpecificityByPID[pid] = newSpecificity - commonOwnerSourceSpecificityByPID.removeValue(forKey: pid) - } else { - continue - } - } - } - - private nonisolated func v2TopMemoryAttributionCommonOwner( - _ lhs: CmuxTopProcessAttribution, - _ rhs: CmuxTopProcessAttribution - ) -> CmuxTopProcessAttribution? { - guard let workspaceID = lhs.workspaceID, workspaceID == rhs.workspaceID else { - return nil - } - let workspaceRef = lhs.workspaceRef ?? rhs.workspaceRef - if let paneID = lhs.paneID, paneID == rhs.paneID { - let paneRef = lhs.paneRef ?? rhs.paneRef - if let surfaceID = lhs.surfaceID, surfaceID == rhs.surfaceID { - return CmuxTopProcessAttribution( - workspaceID: workspaceID, - workspaceRef: workspaceRef, - paneID: paneID, - paneRef: paneRef, - surfaceID: surfaceID, - surfaceRef: lhs.surfaceRef ?? rhs.surfaceRef, - surfaceType: lhs.surfaceType ?? rhs.surfaceType, - reason: "shared-surface-process-tree" - ) - } - return CmuxTopProcessAttribution( - workspaceID: workspaceID, - workspaceRef: workspaceRef, - paneID: paneID, - paneRef: paneRef, - surfaceID: nil, - surfaceRef: nil, - surfaceType: nil, - reason: "shared-pane-process-tree" - ) - } - return CmuxTopProcessAttribution( - workspaceID: workspaceID, - workspaceRef: workspaceRef, - paneID: nil, - paneRef: nil, - surfaceID: nil, - surfaceRef: nil, - surfaceType: nil, - reason: "shared-workspace-process-tree" - ) - } - - private nonisolated func v2TopMemoryAttributionSpecificity(_ attribution: CmuxTopProcessAttribution) -> Int { - if attribution.surfaceID != nil { - return 3 - } - if attribution.paneID != nil { - return 2 - } - if attribution.workspaceID != nil { - return 1 - } - return 0 - } - nonisolated func v2AttachTopApplicationProcess( to windows: inout [[String: Any]], workspaceFilter: UUID? = nil diff --git a/Sources/TerminalControllerV2ParamParsingSupport.swift b/Sources/TerminalControllerV2ParamParsingSupport.swift index b6059e5a6b23..cb9f633928ee 100644 --- a/Sources/TerminalControllerV2ParamParsingSupport.swift +++ b/Sources/TerminalControllerV2ParamParsingSupport.swift @@ -44,18 +44,6 @@ extension TerminalController { return nil } - func v2TrimmedStringMap(_ params: [String: Any], keys: [String]) -> [String: String] { - for key in keys { - guard let raw = v2StringMap(params, key) else { continue } - return raw.reduce(into: [String: String]()) { result, pair in - let normalizedKey = pair.key.trimmingCharacters(in: .whitespacesAndNewlines) - guard !normalizedKey.isEmpty else { return } - result[normalizedKey] = pair.value - } - } - return [:] - } - func v2ActionKey(_ params: [String: Any], _ key: String = "action") -> String? { guard let action = v2String(params, key) else { return nil } return action.lowercased().replacingOccurrences(of: "-", with: "_") diff --git a/Sources/TerminalNotificationPolicy.swift b/Sources/TerminalNotificationPolicy.swift index 33516d4d15d1..5060494b7848 100644 --- a/Sources/TerminalNotificationPolicy.swift +++ b/Sources/TerminalNotificationPolicy.swift @@ -188,35 +188,12 @@ struct TerminalNotificationPolicyEnvelope: Codable, Sendable, Equatable { struct TerminalNotificationPolicyRequest: Sendable { let tabId: UUID let surfaceId: UUID? - let panelId: UUID? let title: String let subtitle: String let body: String let cwd: String? let isAppFocused: Bool let isFocusedPanel: Bool - - init( - tabId: UUID, - surfaceId: UUID?, - panelId: UUID? = nil, - title: String, - subtitle: String, - body: String, - cwd: String?, - isAppFocused: Bool, - isFocusedPanel: Bool - ) { - self.tabId = tabId - self.surfaceId = surfaceId - self.panelId = panelId - self.title = title - self.subtitle = subtitle - self.body = body - self.cwd = cwd - self.isAppFocused = isAppFocused - self.isFocusedPanel = isFocusedPanel - } } struct TerminalNotificationPolicyFailure: Error, Sendable, Hashable { diff --git a/Sources/TerminalNotificationStore.swift b/Sources/TerminalNotificationStore.swift index 1300123cbc38..8743e3dfac5a 100644 --- a/Sources/TerminalNotificationStore.swift +++ b/Sources/TerminalNotificationStore.swift @@ -661,7 +661,7 @@ enum NotificationAuthorizationState: Equatable { } } -enum TerminalNotificationClickAction: Codable, Hashable, Sendable { +enum TerminalNotificationClickAction: Hashable, Sendable { case revealInFinder(path: String) private static let kindUserInfoKey = "cmuxClickAction" @@ -695,7 +695,6 @@ struct TerminalNotification: Identifiable, Hashable { let id: UUID let tabId: UUID let surfaceId: UUID? - let panelId: UUID? let title: String let subtitle: String let body: String @@ -703,40 +702,6 @@ struct TerminalNotification: Identifiable, Hashable { var isRead: Bool var paneFlash: Bool = true var clickAction: TerminalNotificationClickAction? - - init( - id: UUID, - tabId: UUID, - surfaceId: UUID?, - panelId: UUID? = nil, - title: String, - subtitle: String, - body: String, - createdAt: Date, - isRead: Bool, - paneFlash: Bool = true, - clickAction: TerminalNotificationClickAction? = nil - ) { - self.id = id - self.tabId = tabId - self.surfaceId = surfaceId - self.panelId = panelId - self.title = title - self.subtitle = subtitle - self.body = body - self.createdAt = createdAt - self.isRead = isRead - self.paneFlash = paneFlash - self.clickAction = clickAction - } - - func matches(tabId targetTabId: UUID, surfaceId targetSurfaceId: UUID?) -> Bool { - guard tabId == targetTabId else { return false } - guard let targetSurfaceId else { - return surfaceId == nil && panelId == nil - } - return surfaceId == targetSurfaceId || panelId == targetSurfaceId - } } @MainActor @@ -937,22 +902,13 @@ final class TerminalNotificationStore: ObservableObject { } func openNotificationSettings() { - guard let url = Self.notificationSettingsURL(bundleIdentifier: Bundle.main.bundleIdentifier) else { return } + guard let url = URL(string: "x-apple.systempreferences:com.apple.preference.notifications") else { + return + } logAuthorization("open settings url=\(url.absoluteString)") notificationSettingsURLOpener(url) } - static func notificationSettingsURL(bundleIdentifier: String?) -> URL? { - if let bundleIdentifier = bundleIdentifier?.trimmingCharacters(in: .whitespacesAndNewlines), - !bundleIdentifier.isEmpty, - let encodedBundleIdentifier = bundleIdentifier.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) { - return URL( - string: "x-apple.systempreferences:com.apple.Notifications-Settings.extension?id=\(encodedBundleIdentifier)" - ) - } - return URL(string: "x-apple.systempreferences:com.apple.Notifications-Settings.extension") - } - func sendSettingsTestNotification() { logAuthorization("settings test tapped state=\(authorizationState.statusLabel)") ensureAuthorization(origin: .settingsTest) { [weak self] authorized in @@ -1125,7 +1081,8 @@ final class TerminalNotificationStore: ObservableObject { func hasUnreadNotificationRequiringPaneFlash(forTabId tabId: UUID, surfaceId: UUID?) -> Bool { notifications.contains { notification in - notification.matches(tabId: tabId, surfaceId: surfaceId) && + notification.tabId == tabId && + notification.surfaceId == surfaceId && !notification.isRead && notification.paneFlash } @@ -1140,10 +1097,6 @@ final class TerminalNotificationStore: ObservableObject { indexes.latestByTabId[tabId] } - func notifications(forTabId tabId: UUID, surfaceId: UUID?) -> [TerminalNotification] { - notifications.filter { $0.matches(tabId: tabId, surfaceId: surfaceId) } - } - func clearLatestNotification(forTabId tabId: UUID) { guard let latestNotification = indexes.latestByTabId[tabId] else { return } remove(id: latestNotification.id) @@ -1314,18 +1267,11 @@ final class TerminalNotificationStore: ObservableObject { let cwd = workspace?.surfaceTabBarDirectory ?? workspace?.currentDirectory ?? FileManager.default.homeDirectoryForCurrentUser.path - let panelId: UUID? = surfaceId.flatMap { surfaceId in - if workspace?.panels[surfaceId] != nil { - return surfaceId - } - return workspace?.panelIdFromSurfaceId(TabID(uuid: surfaceId)) - } return NotificationPolicyContext( request: TerminalNotificationPolicyRequest( tabId: tabId, surfaceId: surfaceId, - panelId: panelId, title: title, subtitle: subtitle, body: body, @@ -1350,7 +1296,6 @@ final class TerminalNotificationStore: ObservableObject { request: TerminalNotificationPolicyRequest( tabId: request.tabId, surfaceId: request.surfaceId, - panelId: request.panelId, title: payload.title, subtitle: payload.subtitle, body: payload.body, @@ -1380,7 +1325,6 @@ final class TerminalNotificationStore: ObservableObject { id: UUID(), tabId: request.tabId, surfaceId: request.surfaceId, - panelId: request.panelId, title: request.title, subtitle: request.subtitle, body: request.body, @@ -1589,7 +1533,8 @@ final class TerminalNotificationStore: ObservableObject { var updated = notifications var idsToClear: [String] = [] for index in updated.indices { - if updated[index].matches(tabId: tabId, surfaceId: surfaceId), + if updated[index].tabId == tabId, + updated[index].surfaceId == surfaceId, !updated[index].isRead { updated[index].isRead = true idsToClear.append(updated[index].id.uuidString) @@ -1634,7 +1579,7 @@ final class TerminalNotificationStore: ObservableObject { } private func latestNotificationIndex(forTabId tabId: UUID, surfaceId: UUID?, in notifications: [TerminalNotification]) -> Int? { - if let exactIndex = notifications.firstIndex(where: { $0.matches(tabId: tabId, surfaceId: surfaceId) }) { + if let exactIndex = notifications.firstIndex(where: { $0.tabId == tabId && $0.surfaceId == surfaceId }) { return exactIndex } if surfaceId != nil, @@ -1699,30 +1644,6 @@ final class TerminalNotificationStore: ObservableObject { center.removeDeliveredNotificationsOffMain(withIdentifiers: [id.uuidString]) } - func restoreSessionNotifications(_ restoredNotifications: [TerminalNotification], forTabId tabId: UUID) { - TerminalMutationBus.shared.discardPendingNotifications(forTabId: tabId) - - let removedIds = notifications - .filter { $0.tabId == tabId } - .map { $0.id.uuidString } - let restoredForTab = restoredNotifications - .filter { $0.tabId == tabId } - .sorted(by: Self.notificationSortPrecedes) - let keptNotifications = notifications.filter { $0.tabId != tabId } - let nextNotifications = (restoredForTab + keptNotifications).sorted(by: Self.notificationSortPrecedes) - - let didChangeNotifications = nextNotifications != notifications - if didChangeNotifications { - notifications = nextNotifications - } - clearFocusedReadIndicator(forTabId: tabId) - - if didChangeNotifications, !removedIds.isEmpty { - center.removeDeliveredNotificationsOffMain(withIdentifiers: removedIds) - center.removePendingNotificationRequestsOffMain(withIdentifiers: removedIds) - } - } - private func replaceNotificationsForClear(_ next: [TerminalNotification]) { suppressNotificationDiffPublishing = true; notifications = next; suppressNotificationDiffPublishing = false } func clearAll(discardQueuedNotifications: Bool = true) { @@ -1757,7 +1678,7 @@ final class TerminalNotificationStore: ObservableObject { updated.reserveCapacity(notifications.count) var idsToClear: [String] = [] for notification in notifications { - if notification.matches(tabId: tabId, surfaceId: surfaceId) { + if notification.tabId == tabId, notification.surfaceId == surfaceId { idsToClear.append(notification.id.uuidString) } else { updated.append(notification) @@ -1784,7 +1705,7 @@ final class TerminalNotificationStore: ObservableObject { var didMoveNotification = false let updated = notifications.map { notification -> TerminalNotification in - guard notification.matches(tabId: sourceTabId, surfaceId: surfaceId) else { + guard notification.tabId == sourceTabId, notification.surfaceId == surfaceId else { return notification } didMoveNotification = true @@ -1792,7 +1713,6 @@ final class TerminalNotificationStore: ObservableObject { id: notification.id, tabId: destinationTabId, surfaceId: notification.surfaceId, - panelId: notification.panelId, title: notification.title, subtitle: notification.subtitle, body: notification.body, @@ -2135,11 +2055,6 @@ final class TerminalNotificationStore: ObservableObject { indexes.unreadByTabSurface.insert( TabSurfaceKey(tabId: notification.tabId, surfaceId: notification.surfaceId) ) - if let panelId = notification.panelId, panelId != notification.surfaceId { - indexes.unreadByTabSurface.insert( - TabSurfaceKey(tabId: notification.tabId, surfaceId: panelId) - ) - } if indexes.latestUnreadByTabId[notification.tabId] == nil { indexes.latestUnreadByTabId[notification.tabId] = notification } @@ -2147,13 +2062,6 @@ final class TerminalNotificationStore: ObservableObject { return indexes } - private static func notificationSortPrecedes(_ lhs: TerminalNotification, _ rhs: TerminalNotification) -> Bool { - if lhs.createdAt != rhs.createdAt { - return lhs.createdAt > rhs.createdAt - } - return lhs.id.uuidString < rhs.id.uuidString - } - #if DEBUG func configureNotificationSettingsPromptHooksForTesting( windowProvider: @escaping () -> NSWindow?, @@ -2176,7 +2084,9 @@ final class TerminalNotificationStore: ObservableObject { block() } } - notificationSettingsURLOpener = { url in NSWorkspace.shared.open(url) } + notificationSettingsURLOpener = { url in + NSWorkspace.shared.open(url) + } hasPromptedForSettings = false } diff --git a/Sources/TerminalStartupEnvironment.swift b/Sources/TerminalStartupEnvironment.swift index 9fa3e845745e..d441de2c95cc 100644 --- a/Sources/TerminalStartupEnvironment.swift +++ b/Sources/TerminalStartupEnvironment.swift @@ -26,15 +26,6 @@ extension TerminalSurface { protectedKeys.insert("TERM_PROGRAM") } - static func applyManagedGitWatchEnvironment( - watchGitStatusEnabled: Bool, - to environment: inout [String: String], - protectedKeys: inout Set - ) { - environment["CMUX_NO_GIT_WATCH"] = watchGitStatusEnabled ? "" : "1" - protectedKeys.insert("CMUX_NO_GIT_WATCH") - } - static func mergedStartupEnvironment( base: [String: String], protectedKeys: Set, diff --git a/Sources/TerminalTimestampStore.swift b/Sources/TerminalTimestampStore.swift new file mode 100644 index 000000000000..9158a9991ba0 --- /dev/null +++ b/Sources/TerminalTimestampStore.swift @@ -0,0 +1,232 @@ +import CoreGraphics +import Foundation + +nonisolated struct TerminalTimestampScrollbarState: Equatable, Sendable { + let total: Int + let offset: Int + let len: Int + + init(total: Int, offset: Int, len: Int) { + self.total = max(0, total) + self.offset = max(0, offset) + self.len = max(0, len) + } + + init(_ scrollbar: GhosttyScrollbar) { + self.init( + total: Int(clamping: scrollbar.total), + offset: Int(clamping: scrollbar.offset), + len: Int(clamping: scrollbar.len) + ) + } + + static func visibleWindow( + total: Int, + fallbackLen: Int, + visibleTopRow: CGFloat, + viewportHeight: CGFloat, + cellHeight: CGFloat + ) -> Self { + let total = max(0, total) + guard total > 0 else { + return Self(total: 0, offset: 0, len: 0) + } + + let visibleOffset = min(total, max(0, Int(floor(visibleTopRow)))) + let viewportLen: Int + if cellHeight > 0, viewportHeight > 0 { + viewportLen = Int(ceil(viewportHeight / cellHeight)) + 1 + } else { + viewportLen = fallbackLen + } + let len = min(max(0, total - visibleOffset), max(fallbackLen, viewportLen, 0)) + return Self(total: total, offset: visibleOffset, len: len) + } +} + +nonisolated struct TerminalTimestampVisibleRow: Equatable, Sendable { + let row: Int + let timestamp: Date +} + +@MainActor +final class TerminalTimestampStore { + private let maxRetainedRows: Int + private var timestampsByRow: [Int: Date] = [:] + private var oldestTrackedRow: Int? + private var newestTrackedRow: Int? + private var pruneCursor = 0 + private var rowsBelowRetention: Set = [] + private var lastScrollbar: TerminalTimestampScrollbarState? + + init(maxRetainedRows: Int = 20_000) { + self.maxRetainedRows = max(1, maxRetainedRows) + } + + func record( + scrollbar: TerminalTimestampScrollbarState, + at date: Date, + markVisibleRows: Bool + ) { + let visibleRows = visibleRange(for: scrollbar) + if let previous = lastScrollbar { + if scrollbar.total < previous.total { + clearRows() + } else if scrollbar.total > previous.total { + let firstRetainedNewRow = max(previous.total, scrollbar.total - maxRetainedRows) + for row in firstRetainedNewRow.. [TerminalTimestampVisibleRow] { + visibleRange(for: scrollbar).compactMap { row in + guard let timestamp = timestampsByRow[row] else { return nil } + return TerminalTimestampVisibleRow(row: row, timestamp: timestamp) + } + } + + private func visibleRange(for scrollbar: TerminalTimestampScrollbarState) -> Range { + guard scrollbar.total > 0, scrollbar.len > 0 else { return 0..<0 } + let lower = min(scrollbar.offset, scrollbar.total) + let upper = min(scrollbar.total, lower + scrollbar.len) + return lower..) { + let minimumRow = max(0, totalRows - maxRetainedRows) + let previousNewestTrackedRow = newestTrackedRow + + guard !timestampsByRow.isEmpty else { + clearTrackedBounds() + pruneCursor = minimumRow + return + } + + var didChangeTrackedRows = false + for row in Array(rowsBelowRetention) { + guard row < minimumRow, timestampsByRow[row] != nil else { + rowsBelowRetention.remove(row) + continue + } + guard preservedRows.contains(row) else { + timestampsByRow.removeValue(forKey: row) + rowsBelowRetention.remove(row) + didChangeTrackedRows = true + continue + } + } + + let firstPossibleTrackedRow = min(oldestTrackedRow ?? minimumRow, minimumRow) + let scanStart = max(pruneCursor, firstPossibleTrackedRow) + if scanStart < minimumRow { + for row in scanStart..= minimumRow { + newestTrackedRow = previousNewestTrackedRow + } else { + newestTrackedRow = rowsBelowRetention.max() + } + return + } + + if let previousNewestTrackedRow, previousNewestTrackedRow >= minimumRow { + refreshOldestTrackedRow(startingAt: minimumRow) + } else { + refreshTrackedBounds() + } + } + + private func refreshOldestTrackedRow(startingAt row: Int) { + guard !timestampsByRow.isEmpty else { + clearTrackedBounds() + return + } + guard let newestTrackedRow else { + refreshTrackedBounds() + return + } + + var candidate = row + while candidate <= newestTrackedRow { + if timestampsByRow[candidate] != nil { + oldestTrackedRow = candidate + return + } + candidate += 1 + } + + refreshTrackedBounds() + } + + private func refreshTrackedBounds() { + guard !timestampsByRow.isEmpty else { + clearTrackedBounds() + return + } + + var oldest = Int.max + var newest = Int.min + for row in timestampsByRow.keys { + oldest = min(oldest, row) + newest = max(newest, row) + } + oldestTrackedRow = oldest + newestTrackedRow = newest + } + + private func clearTrackedBounds() { + oldestTrackedRow = nil + newestTrackedRow = nil + pruneCursor = 0 + rowsBelowRetention.removeAll(keepingCapacity: true) + } + + private func clearRows() { + timestampsByRow.removeAll(keepingCapacity: true) + clearTrackedBounds() + } +} diff --git a/Sources/TerminalWindowPortal.swift b/Sources/TerminalWindowPortal.swift index 3758a2e1652c..c6cbe71cedfb 100644 --- a/Sources/TerminalWindowPortal.swift +++ b/Sources/TerminalWindowPortal.swift @@ -218,9 +218,6 @@ final class WindowTerminalHostView: NSView { eventType: eventType ) else { return false } guard decision.result else { return false } - if decision.registryHit { - return true - } return hostedTerminalHitView(at: point) == nil } diff --git a/Sources/Update/UpdateTitlebarAccessory.swift b/Sources/Update/UpdateTitlebarAccessory.swift index 669a11de433d..c3f278b82646 100644 --- a/Sources/Update/UpdateTitlebarAccessory.swift +++ b/Sources/Update/UpdateTitlebarAccessory.swift @@ -349,7 +349,6 @@ func titlebarShortcutHintVerticalOffset(for config: TitlebarControlsStyleConfig) struct TitlebarControlButton: View { let config: TitlebarControlsStyleConfig - let foregroundColor: Color let accessibilityIdentifier: String let accessibilityLabel: String let action: () -> Void @@ -387,7 +386,7 @@ struct TitlebarControlButton: View { private var hoverBackground: some View { if config.hoverBackground && isHovering { RoundedRectangle(cornerRadius: config.buttonCornerRadius, style: .continuous) - .fill(foregroundColor.opacity(0.10)) + .fill(Color.primary.opacity(0.08)) } } } @@ -434,7 +433,6 @@ struct TitlebarControlsView: View { @ObservedObject private var popoverVisibilityState = NotificationsPopoverVisibilityState.shared @AppStorage("titlebarControlsStyle") private var styleRawValue = TitlebarControlsStyle.classic.rawValue @State private var shortcutRefreshTick = 0 - @State private var appearanceRefreshTick = 0 @State private var isHoveringControls = false @State private var hostWindowNumber: Int? @StateObject private var modifierKeyMonitor = TitlebarShortcutHintModifierMonitor() @@ -487,13 +485,9 @@ struct TitlebarControlsView: View { // Force the `.safeHelp(...)` tooltips to re-evaluate when shortcuts are changed in settings. // (The titlebar controls don't otherwise re-render on UserDefaults changes.) let _ = shortcutRefreshTick - let _ = appearanceRefreshTick let style = TitlebarControlsStyle(rawValue: styleRawValue) ?? .classic let config = style.config - let foregroundColor = Color(nsColor: titlebarControlForegroundNSColor(opacity: 0.78)) - controlsGroup(config: config, foregroundColor: foregroundColor) - .padding(.top, -1) - .padding(.bottom, 1) + controlsGroup(config: config) .padding(.leading, 4) .padding(.trailing, titlebarHintTrailingInset) .contentShape(Rectangle()) @@ -520,12 +514,6 @@ struct TitlebarControlsView: View { .onReceive(NotificationCenter.default.publisher(for: KeyboardShortcutSettings.didChangeNotification)) { _ in shortcutRefreshTick &+= 1 } - .onReceive(NotificationCenter.default.publisher(for: .ghosttyConfigDidReload)) { _ in - appearanceRefreshTick &+= 1 - } - .onReceive(NotificationCenter.default.publisher(for: .ghosttyDefaultBackgroundDidChange)) { _ in - appearanceRefreshTick &+= 1 - } .onAppear { modifierKeyMonitor.start() } @@ -545,12 +533,11 @@ struct TitlebarControlsView: View { } @ViewBuilder - private func controlsGroup(config: TitlebarControlsStyleConfig, foregroundColor: Color) -> some View { + private func controlsGroup(config: TitlebarControlsStyleConfig) -> some View { let hintLayoutItems = titlebarHintLayoutItems(config: config) let content = HStack(spacing: config.spacing) { TitlebarControlButton( config: config, - foregroundColor: foregroundColor, accessibilityIdentifier: "titlebarControl.toggleSidebar", accessibilityLabel: String(localized: "titlebar.sidebar.accessibilityLabel", defaultValue: "Toggle Sidebar"), action: { @@ -559,13 +546,12 @@ struct TitlebarControlsView: View { #endif onToggleSidebar() }) { - iconLabel(systemName: "sidebar.left", config: config, foregroundColor: foregroundColor) + iconLabel(systemName: "sidebar.left", config: config) } .safeHelp(KeyboardShortcutSettings.Action.toggleSidebar.tooltip(String(localized: "titlebar.sidebar.tooltip", defaultValue: "Show or hide the sidebar"))) TitlebarControlButton( config: config, - foregroundColor: foregroundColor, accessibilityIdentifier: "titlebarControl.showNotifications", accessibilityLabel: String(localized: "titlebar.notifications.accessibilityLabel", defaultValue: "Notifications"), action: { @@ -575,7 +561,7 @@ struct TitlebarControlsView: View { onToggleNotifications() }) { ZStack(alignment: .topTrailing) { - iconLabel(systemName: "bell", config: config, foregroundColor: foregroundColor) + iconLabel(systemName: "bell", config: config) if notificationStore.unreadCount > 0 { Text("\(min(notificationStore.unreadCount, 99))") @@ -595,7 +581,6 @@ struct TitlebarControlsView: View { TitlebarControlButton( config: config, - foregroundColor: foregroundColor, accessibilityIdentifier: "titlebarControl.newTab", accessibilityLabel: String(localized: "titlebar.newWorkspace.accessibilityLabel", defaultValue: "New Workspace"), action: { @@ -607,7 +592,7 @@ struct TitlebarControlsView: View { rightClickAction: { anchorView, event in _ = AppDelegate.shared?.showNewWorkspaceContextMenu(anchorView: anchorView, event: event) }) { - iconLabel(systemName: "plus", config: config, foregroundColor: foregroundColor) + iconLabel(systemName: "plus", config: config) } .safeHelp(KeyboardShortcutSettings.Action.newTab.tooltip(String(localized: "titlebar.newWorkspace.tooltip", defaultValue: "New workspace"))) @@ -726,10 +711,9 @@ struct TitlebarControlsView: View { } @ViewBuilder - private func iconLabel(systemName: String, config: TitlebarControlsStyleConfig, foregroundColor: Color) -> some View { + private func iconLabel(systemName: String, config: TitlebarControlsStyleConfig) -> some View { let icon = Image(systemName: systemName) .font(.system(size: config.iconSize, weight: .semibold)) - .foregroundColor(foregroundColor) .frame(width: config.buttonSize, height: config.buttonSize) if config.buttonBackground { @@ -1845,8 +1829,7 @@ final class UpdateTitlebarAccessoryController { queue: .main ) { [weak self] notification in guard let window = notification.object as? NSWindow else { return } - Task { @MainActor [weak self, weak window] in - guard let window else { return } + Task { @MainActor [weak self] in self?.attachIfNeeded(to: window) } }) @@ -1857,8 +1840,7 @@ final class UpdateTitlebarAccessoryController { queue: .main ) { [weak self] notification in guard let window = notification.object as? NSWindow else { return } - Task { @MainActor [weak self, weak window] in - guard let window else { return } + Task { @MainActor [weak self] in self?.attachIfNeeded(to: window) } }) @@ -1924,10 +1906,6 @@ final class UpdateTitlebarAccessoryController { } private func attachIfNeeded(to window: NSWindow) { - guard NSApp.windows.contains(where: { $0 === window }) else { - pendingAttachRetries.removeValue(forKey: ObjectIdentifier(window)) - return - } guard !isSettingsWindow(window) else { return } // Window identifiers are assigned by SwiftUI via WindowAccessor, which can run diff --git a/Sources/VaultAgentProcessScanner.swift b/Sources/VaultAgentProcessScanner.swift index 4539c67cfddf..d4411d8d85e7 100644 --- a/Sources/VaultAgentProcessScanner.swift +++ b/Sources/VaultAgentProcessScanner.swift @@ -48,22 +48,6 @@ extension RestorableAgentSessionIndex { fileManager: FileManager, processSnapshot: CmuxTopProcessSnapshot, capturedAt: TimeInterval - ) -> [PanelKey: (snapshot: SessionRestorableAgentSnapshot, updatedAt: TimeInterval)] { - return processDetectedSnapshots( - registry: registry, - fileManager: fileManager, - processSnapshot: processSnapshot, - capturedAt: capturedAt, - processArgumentsProvider: { CmuxTopProcessSnapshot.processArgumentsAndEnvironment(for: $0) } - ) - } - - static func processDetectedSnapshots( - registry: CmuxVaultAgentRegistry, - fileManager: FileManager, - processSnapshot: CmuxTopProcessSnapshot, - capturedAt: TimeInterval, - processArgumentsProvider: (Int) -> CmuxTopProcessArguments? ) -> [PanelKey: (snapshot: SessionRestorableAgentSnapshot, updatedAt: TimeInterval)] { var resolved = processDetectedOpenCodeSnapshots( processSnapshot: processSnapshot, @@ -91,7 +75,7 @@ extension RestorableAgentSessionIndex { for process in processSnapshot.cmuxScopedProcesses() { guard let workspaceId = process.cmuxWorkspaceID, let panelId = process.cmuxSurfaceID, - let processArguments = processArgumentsProvider(process.pid) else { + let processArguments = CmuxTopProcessSnapshot.processArgumentsAndEnvironment(for: process.pid) else { continue } let observed = VaultObservedAgentProcess( @@ -759,16 +743,12 @@ private struct VaultObservedAgentProcess: Sendable { private extension CmuxVaultAgentDetectRule { func matches(_ process: VaultObservedAgentProcess) -> Bool { - var expectedNames = processNames - if let processName { - expectedNames.append(processName) - } - guard !expectedNames.isEmpty || !argvContains.isEmpty else { return false } - let processNameMatch = expectedNames.isEmpty || expectedNames.contains { expected in + guard processName != nil || !argvContains.isEmpty else { return false } + let processNameMatch = processName.map { expected in process.executableBasenames.contains { candidate in candidate.compare(expected, options: [.caseInsensitive, .literal]) == .orderedSame } - } + } ?? true let argvContainsMatch = argvContains.isEmpty || argvContains.allSatisfy { needle in if needle.contains(" ") { let joinedArguments = process.arguments.joined(separator: " ") @@ -798,9 +778,9 @@ private extension CmuxVaultAgentSessionIDSource { ) -> String? { switch self { case .argvOption(let option): - return process.arguments.nonOptionValue(afterOption: option) + return process.arguments.value(afterOption: option) case .piSessionFile: - if let session = process.arguments.nonOptionValue(afterOption: "--session") { + if let session = process.arguments.value(afterOption: "--session") { return PiSessionLocator.resolvedSessionPath( session, for: process, @@ -809,11 +789,6 @@ private extension CmuxVaultAgentSessionIDSource { ) ?? session } return PiSessionLocator.latestSessionPath(for: process, registration: registration, fileManager: fileManager) - case .grokSessionDirectory: - if let session = process.arguments.grokResumeSessionID { - return session - } - return nil } } } @@ -850,38 +825,6 @@ private extension Array where Element == String { } return nil } - - func nonOptionValue(afterOption option: String) -> String? { - guard let value = value(afterOption: option), !value.hasPrefix("-") else { - return nil - } - return value - } - - var grokResumeSessionID: String? { - let options = ["-r", "--resume"] - for index in indices { - let argument = self[index] - if options.contains(argument) { - let nextIndex = self.index(after: index) - guard nextIndex < endIndex else { continue } - let value = self[nextIndex].trimmingCharacters(in: .whitespacesAndNewlines) - if !value.isEmpty, !value.hasPrefix("-") { - return value - } - continue - } - for option in options { - let prefix = option + "=" - guard argument.hasPrefix(prefix) else { continue } - let value = String(argument.dropFirst(prefix.count)).trimmingCharacters(in: .whitespacesAndNewlines) - if !value.isEmpty, !value.hasPrefix("-") { - return value - } - } - } - return nil - } } enum PiSessionLocator { diff --git a/Sources/VaultAgentRegistry.swift b/Sources/VaultAgentRegistry.swift index c093108b5b0d..45ad53a2be92 100644 --- a/Sources/VaultAgentRegistry.swift +++ b/Sources/VaultAgentRegistry.swift @@ -106,10 +106,6 @@ struct CmuxVaultAgentRegistration: Codable, Hashable, Sendable { !processName.isEmpty { return processName } - if let processName = detect.processNames.first?.trimmingCharacters(in: .whitespacesAndNewlines), - !processName.isEmpty { - return processName - } return id } @@ -125,48 +121,18 @@ struct CmuxVaultAgentRegistration: Codable, Hashable, Sendable { sessionDirectory: "~/.pi/agent/sessions" ) } - - static var builtInAntigravity: CmuxVaultAgentRegistration { - CmuxVaultAgentRegistration( - id: "antigravity", - name: "Antigravity", - iconAssetName: "AgentIcons/Antigravity", - detect: CmuxVaultAgentDetectRule(processNames: ["agy", "antigravity"]), - sessionIdSource: .argvOption("--conversation"), - resumeCommand: "{{executable}} --conversation {{sessionId}}", - cwd: .preserve, - sessionDirectory: "~/.gemini/antigravity-cli" - ) - } - - static var builtInGrok: CmuxVaultAgentRegistration { - CmuxVaultAgentRegistration( - id: "grok", - name: "Grok", - detect: CmuxVaultAgentDetectRule(processNames: ["grok", "grok-macos-aarch64", "grok-macos-aarch"]), - sessionIdSource: .grokSessionDirectory, - resumeCommand: "{{executable}} -r {{sessionId}}", - cwd: .preserve, - sessionDirectory: "~/.grok/sessions" - ) - } } struct CmuxVaultAgentDetectRule: Codable, Hashable, Sendable { var processName: String? - var processNames: [String] var argvContains: [String] private enum CodingKeys: String, CodingKey { - case processName, processNames, argvContains + case processName, argvContains } - init(processName: String? = nil, processNames: [String] = [], argvContains: [String] = []) { - let name = processName?.trimmingCharacters(in: .whitespacesAndNewlines) - self.processName = name?.isEmpty == true ? nil : name - self.processNames = processNames - .map { $0.trimmingCharacters(in: .whitespacesAndNewlines) } - .filter { !$0.isEmpty } + init(processName: String? = nil, argvContains: [String] = []) { + self.processName = processName?.trimmingCharacters(in: .whitespacesAndNewlines) self.argvContains = argvContains .map { $0.trimmingCharacters(in: .whitespacesAndNewlines) } .filter { !$0.isEmpty } @@ -177,7 +143,6 @@ struct CmuxVaultAgentDetectRule: Codable, Hashable, Sendable { let name = try container.decodeIfPresent(String.self, forKey: .processName)? .trimmingCharacters(in: .whitespacesAndNewlines) processName = name?.isEmpty == true ? nil : name - processNames = try Self.decodeOneOrManyStrings(forKey: .processNames, in: container) argvContains = try Self.decodeOneOrManyStrings(forKey: .argvContains, in: container) } @@ -200,7 +165,6 @@ struct CmuxVaultAgentDetectRule: Codable, Hashable, Sendable { enum CmuxVaultAgentSessionIDSource: Codable, Hashable, Sendable { case argvOption(String) case piSessionFile - case grokSessionDirectory private enum CodingKeys: String, CodingKey { case type, argvOption @@ -213,8 +177,6 @@ enum CmuxVaultAgentSessionIDSource: Codable, Hashable, Sendable { switch trimmed { case "piSessionFile", "pi-session-file": self = .piSessionFile - case "grokSessionDirectory", "grok-session-directory": - self = .grokSessionDirectory default: guard !trimmed.isEmpty else { throw DecodingError.dataCorrupted( @@ -240,17 +202,6 @@ enum CmuxVaultAgentSessionIDSource: Codable, Hashable, Sendable { ) } self = .piSessionFile - case "grokSessionDirectory", "grok-session-directory": - if let option = try container.decodeIfPresent(String.self, forKey: .argvOption)? - .trimmingCharacters(in: .whitespacesAndNewlines), - !option.isEmpty { - throw DecodingError.dataCorruptedError( - forKey: .argvOption, - in: container, - debugDescription: "grokSessionDirectory must not include argvOption" - ) - } - self = .grokSessionDirectory case "argvOption", "argv-option": let option = try container.decodeIfPresent(String.self, forKey: .argvOption)? .trimmingCharacters(in: .whitespacesAndNewlines) @@ -279,8 +230,6 @@ enum CmuxVaultAgentSessionIDSource: Codable, Hashable, Sendable { try container.encode(option, forKey: .argvOption) case .piSessionFile: try container.encode("piSessionFile", forKey: .type) - case .grokSessionDirectory: - try container.encode("grokSessionDirectory", forKey: .type) } } } @@ -352,11 +301,7 @@ struct CmuxVaultAgentRegistry: Sendable { environment: [String: String] = ProcessInfo.processInfo.environment, fileManager: FileManager = .default ) -> CmuxVaultAgentRegistry { - var registrations = [ - CmuxVaultAgentRegistration.builtInPi, - CmuxVaultAgentRegistration.builtInAntigravity, - CmuxVaultAgentRegistration.builtInGrok, - ] + var registrations = [CmuxVaultAgentRegistration.builtInPi] for path in configPaths(homeDirectory: homeDirectory, workingDirectory: workingDirectory, environment: environment, fileManager: fileManager) { guard let config = decodeConfig(at: path, fileManager: fileManager) else { continue } registrations.append(contentsOf: config.vault?.agents ?? []) diff --git a/Sources/WindowDecorationsController.swift b/Sources/WindowDecorationsController.swift index 463e8fa715d2..277fea8d1ab6 100644 --- a/Sources/WindowDecorationsController.swift +++ b/Sources/WindowDecorationsController.swift @@ -411,20 +411,17 @@ final class WindowDecorationsController { contentView.addSubview(target, positioned: .above, relativeTo: nil) } + let hostHeight = MinimalModeSidebarTitlebarControlsMetrics.hostHeight let contentBounds = contentView.bounds - let trafficLightFrameInContent = minimalModeTrafficLightFrameInContentCoordinates( - window: window, - contentView: contentView - ) - target.frame = minimalModeSidebarTitlebarControlsFrame( - contentBounds: contentBounds, - contentViewIsFlipped: contentView.isFlipped, - trafficLightFrameInContent: trafficLightFrameInContent, - visualDownwardAdjustment: trafficLightFrameInContent == nil - ? 0 - : MinimalModeSidebarTitlebarControlsMetrics.titlebarControlsOpticalYOffset( - backingScaleFactor: window.backingScaleFactor - ) + let topInset = MinimalModeSidebarTitlebarControlsMetrics.topInset + let targetY = contentView.isFlipped + ? contentBounds.minY + topInset + : max(0, contentBounds.maxY - hostHeight - topInset) + target.frame = NSRect( + x: MinimalModeSidebarTitlebarControlsMetrics.leadingInset, + y: targetY, + width: MinimalModeSidebarTitlebarControlsMetrics.hostWidth, + height: hostHeight ) #if DEBUG diff --git a/Sources/WindowDragHandleView.swift b/Sources/WindowDragHandleView.swift index 8d6b353da8ae..84a60b4a0a37 100644 --- a/Sources/WindowDragHandleView.swift +++ b/Sources/WindowDragHandleView.swift @@ -230,22 +230,8 @@ func handleTitlebarDoubleClick( private enum WindowDragHandleAssociatedObjectKeys { private static let suppressionDepthToken = NSObject() - private static let moveSuppressionSequenceToken = NSObject() static let suppressionDepth = UnsafeRawPointer(Unmanaged.passUnretained(suppressionDepthToken).toOpaque()) - static let moveSuppressionSequence = UnsafeRawPointer(Unmanaged.passUnretained(moveSuppressionSequenceToken).toOpaque()) -} - -// Stored as an NSWindow associated object and touched only from AppKit's -// main-thread mouse-event dispatch path. -private final class WindowMoveSuppressionSequenceState: @unchecked Sendable { - let reason: WindowMoveSuppressionReason - let previousMovableState: Bool - - init(reason: WindowMoveSuppressionReason, previousMovableState: Bool) { - self.reason = reason - self.previousMovableState = previousMovableState - } } func beginWindowDragSuppression(window: NSWindow?) -> Int? { @@ -296,74 +282,14 @@ func isWindowDragSuppressed(window: NSWindow?) -> Bool { windowDragSuppressionDepth(window: window) > 0 } -func activeWindowMoveSuppressionSequenceReason(window: NSWindow?) -> WindowMoveSuppressionReason? { - guard let window, - let state = objc_getAssociatedObject( - window, - WindowDragHandleAssociatedObjectKeys.moveSuppressionSequence - ) as? WindowMoveSuppressionSequenceState else { - return nil - } - return state.reason -} - @discardableResult -func beginWindowMoveSuppressionSequence( - window: NSWindow?, - reason: WindowMoveSuppressionReason -) -> WindowMoveSuppressionReason? { +func temporarilyDisableWindowDragging(window: NSWindow?) -> Bool? { guard let window else { return nil } - if let activeReason = activeWindowMoveSuppressionSequenceReason(window: window) { - ensureWindowMoveSuppressionSequenceIsImmovable(window: window) - return activeReason - } - let previousMovableState = window.isMovable - _ = beginWindowDragSuppression(window: window) - if window.isMovable { + if previousMovableState { window.isMovable = false } - let state = WindowMoveSuppressionSequenceState( - reason: reason, - previousMovableState: previousMovableState - ) - objc_setAssociatedObject( - window, - WindowDragHandleAssociatedObjectKeys.moveSuppressionSequence, - state, - .OBJC_ASSOCIATION_RETAIN_NONATOMIC - ) - return reason -} - -func ensureWindowMoveSuppressionSequenceIsImmovable(window: NSWindow?) { - guard let window, - activeWindowMoveSuppressionSequenceReason(window: window) != nil, - window.isMovable else { - return - } - window.isMovable = false -} - -@discardableResult -func finishWindowMoveSuppressionSequence(window: NSWindow?) -> WindowMoveSuppressionReason? { - guard let window, - let state = objc_getAssociatedObject( - window, - WindowDragHandleAssociatedObjectKeys.moveSuppressionSequence - ) as? WindowMoveSuppressionSequenceState else { - return nil - } - - objc_setAssociatedObject( - window, - WindowDragHandleAssociatedObjectKeys.moveSuppressionSequence, - nil, - .OBJC_ASSOCIATION_RETAIN_NONATOMIC - ) - _ = endWindowDragSuppression(window: window) - restoreWindowDragging(window: window, previousMovableState: state.previousMovableState) - return state.reason + return previousMovableState } func restoreWindowDragging(window: NSWindow?, previousMovableState: Bool?) { @@ -377,9 +303,6 @@ func restoreWindowDragging(window: NSWindow?, previousMovableState: Bool?) { @discardableResult func clearWindowDragSuppression(window: NSWindow?) -> Int { guard let window else { return 0 } - if activeWindowMoveSuppressionSequenceReason(window: window) != nil { - _ = finishWindowMoveSuppressionSequence(window: window) - } var depth = windowDragSuppressionDepth(window: window) while depth > 0 { depth = endWindowDragSuppression(window: window) @@ -633,103 +556,6 @@ enum MinimalModeSidebarTitlebarControlsMetrics { static let hostWidth: CGFloat = 124 static let hostHeight: CGFloat = 28 static let singleButtonHostWidth: CGFloat = hostHeight - - static func titlebarControlsOpticalYOffset(backingScaleFactor: CGFloat?) -> CGFloat { - let scale = max(1.0, backingScaleFactor ?? 1.0) - return 1.0 / scale - } - - @MainActor - static func titlebarControlsOpticalYOffset(in window: NSWindow?) -> CGFloat { - titlebarControlsOpticalYOffset( - backingScaleFactor: window?.backingScaleFactor ?? NSScreen.main?.backingScaleFactor - ) - } -} - -@MainActor -func minimalModeSidebarTitlebarControlsFrame( - in window: NSWindow, - defaults: UserDefaults = .standard -) -> NSRect { - let contentView = window.contentView - let contentBounds = contentView?.bounds ?? NSRect( - x: 0, - y: 0, - width: window.frame.width, - height: window.frame.height - ) - let trafficLightFrameInContent = minimalModeTrafficLightFrameInContentCoordinates(for: window) - return minimalModeSidebarTitlebarControlsFrame( - contentBounds: contentBounds, - contentViewIsFlipped: contentView?.isFlipped ?? false, - trafficLightFrameInContent: trafficLightFrameInContent, - visualDownwardAdjustment: trafficLightFrameInContent == nil - ? 0 - : MinimalModeSidebarTitlebarControlsMetrics.titlebarControlsOpticalYOffset(in: window), - defaults: defaults - ) -} - -@MainActor -func minimalModeSidebarTitlebarControlsTopInset( - in window: NSWindow, - defaults: UserDefaults = .standard -) -> CGFloat { - guard let contentView = window.contentView else { - return MinimalModeSidebarTitlebarControlsMetrics.topInset(defaults: defaults) - } - let controlsFrame = minimalModeSidebarTitlebarControlsFrame(in: window, defaults: defaults) - if contentView.isFlipped { - return controlsFrame.minY - contentView.bounds.minY - } - return contentView.bounds.maxY - controlsFrame.maxY -} - -func minimalModeSidebarTitlebarControlsFrame( - contentBounds: NSRect, - contentViewIsFlipped: Bool, - trafficLightFrameInContent: NSRect?, - visualDownwardAdjustment: CGFloat = 0, - defaults: UserDefaults = .standard -) -> NSRect { - let hostHeight = MinimalModeSidebarTitlebarControlsMetrics.hostHeight - let targetY: CGFloat - if let trafficLightFrameInContent { - let centeredY = trafficLightFrameInContent.midY - hostHeight / 2.0 - targetY = contentViewIsFlipped - ? centeredY + visualDownwardAdjustment - : centeredY - visualDownwardAdjustment - } else { - let topInset = MinimalModeSidebarTitlebarControlsMetrics.topInset(defaults: defaults) - targetY = contentViewIsFlipped - ? contentBounds.minY + topInset - : max(0, contentBounds.maxY - hostHeight - topInset) - } - return NSRect( - x: MinimalModeSidebarTitlebarControlsMetrics.leadingInset(defaults: defaults), - y: targetY, - width: MinimalModeSidebarTitlebarControlsMetrics.hostWidth, - height: hostHeight - ) -} - -func minimalModeTrafficLightFrameInContentCoordinates( - window: NSWindow, - contentView: NSView -) -> NSRect? { - dispatchPrecondition(condition: .onQueue(.main)) - guard let closeButton = window.standardWindowButton(.closeButton), - let closeButtonSuperview = closeButton.superview else { - return nil - } - return closeButtonSuperview.convert(closeButton.frame, to: contentView) -} - -@MainActor -private func minimalModeTrafficLightFrameInContentCoordinates(for window: NSWindow) -> NSRect? { - guard let contentView = window.contentView else { return nil } - return minimalModeTrafficLightFrameInContentCoordinates(window: window, contentView: contentView) } enum MinimalModeSidebarControlActionSlot: Int { @@ -999,19 +825,6 @@ func windowDragHandleShouldCaptureHit( ) -> Bool { let dragHandleWindow = dragHandleView.window - if let dragHandleWindow, - eventType == .leftMouseDown { - let windowPoint = dragHandleView.convert(point, to: nil) - if BonsplitTabItemHitRegionRegistry.containsWindowPoint(windowPoint, in: dragHandleWindow) { - #if DEBUG - cmuxDebugLog( - "titlebar.dragHandle.hitTest capture=false reason=bonsplitPaneTab point=\(windowDragHandleFormatPoint(point))" - ) - #endif - return false - } - } - // Suppression recovery runs first so stale depth is cleared even for // passive events — the associated-object reads/writes here are pure ObjC // runtime calls and cannot trigger Swift exclusive-access violations. diff --git a/Sources/Windowing/WindowAppearanceSnapshot.swift b/Sources/Windowing/WindowAppearanceSnapshot.swift index ca10347da1c3..2b809560fc92 100644 --- a/Sources/Windowing/WindowAppearanceSnapshot.swift +++ b/Sources/Windowing/WindowAppearanceSnapshot.swift @@ -275,15 +275,8 @@ struct WindowAppearanceSnapshot { CGFloat(max(0.0, min(1.0, opacity))) } - static func compositedTerminalColor( - backgroundColor: NSColor, - opacity: Double, - over baseColor: NSColor = .windowBackgroundColor - ) -> NSColor { - cmuxCompositedNSColor( - backgroundColor.withAlphaComponent(clampedOpacity(opacity)), - over: baseColor - ) + static func compositedTerminalColor(backgroundColor: NSColor, opacity: Double) -> NSColor { + backgroundColor.withAlphaComponent(clampedOpacity(opacity)) } static func terminalRenderingMode( @@ -293,43 +286,7 @@ struct WindowAppearanceSnapshot { } var compositedTerminalBackgroundColor: NSColor { - Self.compositedTerminalColor( - backgroundColor: terminalBackgroundColor, - opacity: terminalBackgroundOpacity - ) - } - - var chromeColorScheme: ColorScheme { - cmuxReadableColorScheme(for: compositedTerminalBackgroundColor) - } - - var sidebarContentColorScheme: ColorScheme { - unifySurfaceBackdrops ? chromeColorScheme : sidebarSettings.colorScheme - } - - func sidebarContrastOverlayColor(for role: WindowBackdropRole) -> NSColor? { - guard unifySurfaceBackdrops, - role == .leftSidebar || role == .rightSidebar else { - return nil - } - - let composited = compositedTerminalBackgroundColor - let srgb = composited.usingColorSpace(.sRGB) ?? composited - var red: CGFloat = 0 - var green: CGFloat = 0 - var blue: CGFloat = 0 - var alpha: CGFloat = 0 - srgb.getRed(&red, green: &green, blue: &blue, alpha: &alpha) - _ = alpha - - let isLight = cmuxReadableColorScheme(for: composited) == .light - let adjustment: CGFloat = isLight ? -0.05 : 0.07 - return NSColor( - srgbRed: min(1, max(0, red + adjustment)), - green: min(1, max(0, green + adjustment)), - blue: min(1, max(0, blue + adjustment)), - alpha: isLight ? 0.20 : 0.18 - ) + terminalBackgroundColor.withAlphaComponent(terminalBackgroundOpacity) } func policy(for role: WindowBackdropRole) -> WindowBackdropPolicy { diff --git a/Sources/Windowing/WindowBackdropController.swift b/Sources/Windowing/WindowBackdropController.swift index d4e3f9f46205..d9c8630f16a3 100644 --- a/Sources/Windowing/WindowBackdropController.swift +++ b/Sources/Windowing/WindowBackdropController.swift @@ -170,7 +170,7 @@ extension WindowAppearanceSnapshot { ) } - if terminalBackgroundOpacity < 0.999 { + if compositedTerminalBackgroundColor.alphaComponent < 0.999 { return WindowBackdropPlan( hostingPhase: .transparentRootBackdrop, windowBackgroundColor: cmuxTransparentWindowBaseColor(), @@ -184,7 +184,7 @@ extension WindowAppearanceSnapshot { return WindowBackdropPlan( hostingPhase: .opaqueWindowFill, windowBackgroundColor: compositedTerminalBackgroundColor, - windowIsOpaque: true, + windowIsOpaque: compositedTerminalBackgroundColor.alphaComponent >= 0.999, rootPolicy: rootPolicy, glass: nil, shouldApplyGhosttyCompositorBlur: false diff --git a/Sources/Workspace+PanelLifecycle.swift b/Sources/Workspace+PanelLifecycle.swift index 932a56f63058..fa650ca4753c 100644 --- a/Sources/Workspace+PanelLifecycle.swift +++ b/Sources/Workspace+PanelLifecycle.swift @@ -5,7 +5,6 @@ import Foundation extension Workspace { private static let structuredAgentHookStatusKeys: Set = [ "amp", - "antigravity", "claude_code", "codebuddy", "codex", @@ -20,8 +19,6 @@ extension Workspace { "qoder", "rovodev", ] - private static let managedSubagentEnvironmentKey = "CMUX_AGENT_MANAGED_SUBAGENT" - private static let truthyStartupEnvironmentValues: Set = ["1", "true", "yes", "on", "enabled"] func agentRuntimeState(forPanelId panelId: UUID) -> DetachedAgentRuntimeState? { let pidKeys = agentPIDKeysByPanelId[panelId] ?? [] @@ -127,28 +124,12 @@ extension Workspace { } func suppressesRawTerminalNotification(panelId: UUID?) -> Bool { - guard let panelId else { - return false - } - - if AgentSubagentNotificationSettings.suppressNotifications(), - terminalPanelHasManagedSubagentStartupEnvironment(panelId: panelId) { - return true + if let panelId { + let panelKeys = agentPIDKeysByPanelId[panelId] ?? [] + return panelKeys.contains { isStructuredAgentHookPIDKey($0) } } - let panelKeys = agentPIDKeysByPanelId[panelId] ?? [] - return panelKeys.contains { isStructuredAgentHookPIDKey($0) } - } - - private func terminalPanelHasManagedSubagentStartupEnvironment(panelId: UUID) -> Bool { - guard let rawValue = terminalPanel(for: panelId)? - .surface - .startupEnvironmentValue(Self.managedSubagentEnvironmentKey)? - .trimmingCharacters(in: .whitespacesAndNewlines) - .lowercased() else { - return false - } - return Self.truthyStartupEnvironmentValues.contains(rawValue) + return false } func sidebarStatusEntriesVisibleForDisplay() -> [SidebarStatusEntry] { diff --git a/Sources/Workspace.swift b/Sources/Workspace.swift index 0959bc7a89f1..ef1243bf8960 100644 --- a/Sources/Workspace.swift +++ b/Sources/Workspace.swift @@ -226,7 +226,6 @@ extension Workspace { let hasWorkspaceUnreadIndicator = (notificationStore?.hasUnreadNotification(forTabId: id, surfaceId: nil) ?? false) || (notificationStore?.hasRestoredUnreadIndicator(forTabId: id) ?? false) - let workspaceNotificationSnapshots = notificationSnapshots(surfaceId: nil) return SessionWorkspaceSnapshot( processTitle: processTitle, @@ -236,7 +235,6 @@ extension Workspace { isPinned: isPinned, isManuallyUnread: isWorkspaceManuallyUnread, hasUnreadIndicator: hasWorkspaceUnreadIndicator, - notifications: workspaceNotificationSnapshots.isEmpty ? nil : workspaceNotificationSnapshots, terminalScrollBarHidden: terminalScrollBarHidden ? true : nil, currentDirectory: currentDirectory, focusedPanelId: focusedPanelId, @@ -331,18 +329,11 @@ extension Workspace { } let isWorkspaceManuallyUnread = snapshot.isManuallyUnread == true restoreWorkspaceManualUnread(isWorkspaceManuallyUnread) - let restoredNotifications = restoredSessionNotifications( - from: snapshot, - oldToNewPanelIds: oldToNewPanelIds - ) - let hasUnreadWorkspaceNotification = snapshot.notifications?.contains { !$0.isRead } == true - if snapshot.hasUnreadIndicator == true, !hasUnreadWorkspaceNotification { + if snapshot.hasUnreadIndicator == true { AppDelegate.shared?.notificationStore?.restoreUnreadIndicator(forTabId: id) } else { AppDelegate.shared?.notificationStore?.clearRestoredUnreadIndicator(forTabId: id) } - AppDelegate.shared?.notificationStore?.restoreSessionNotifications(restoredNotifications, forTabId: id) - syncUnreadBadgeStateForAllPanels() } private func sessionLayoutSnapshot(from node: ExternalTreeNode) -> SessionWorkspaceLayoutSnapshot { @@ -447,7 +438,6 @@ extension Workspace { }() let isPinned = pinnedPanelIds.contains(panelId) let isManuallyUnread = manualUnreadPanelIds.contains(panelId) - let panelNotificationSnapshots = notificationSnapshots(surfaceId: panelId) let hasUnreadIndicator = restoredUnreadPanelIds.contains(panelId) || hasUnreadNotification(panelId: panelId) @@ -575,7 +565,6 @@ extension Workspace { isPinned: isPinned, isManuallyUnread: isManuallyUnread, hasUnreadIndicator: hasUnreadIndicator, - notifications: panelNotificationSnapshots.isEmpty ? nil : panelNotificationSnapshots, gitBranch: branchSnapshot, listeningPorts: listeningPorts, ttyName: ttyName, @@ -1072,8 +1061,7 @@ extension Workspace { } else { clearManualUnread(panelId: panelId) } - if snapshot.hasUnreadIndicator == true, - snapshot.notifications?.contains(where: { !$0.isRead }) != true { + if snapshot.hasUnreadIndicator == true { restorePanelUnreadIndicator(panelId) } else { clearRestoredUnreadIndicator(panelId: panelId) @@ -1126,36 +1114,6 @@ extension Workspace { syncUnreadBadgeStateForAllPanels() } - private func notificationSnapshots(surfaceId: UUID?) -> [SessionNotificationSnapshot] { - AppDelegate.shared?.notificationStore? - .notifications(forTabId: id, surfaceId: surfaceId) - .map(SessionNotificationSnapshot.init(notification:)) ?? [] - } - - private func restoredSessionNotifications( - from snapshot: SessionWorkspaceSnapshot, - oldToNewPanelIds: [UUID: UUID] - ) -> [TerminalNotification] { - var notifications = (snapshot.notifications ?? []).map { - $0.terminalNotification(tabId: id, surfaceId: nil, panelId: nil) - } - - for panelSnapshot in snapshot.panels { - guard let newPanelId = oldToNewPanelIds[panelSnapshot.id] else { continue } - notifications.append( - contentsOf: (panelSnapshot.notifications ?? []).map { - $0.terminalNotification( - tabId: id, - surfaceId: newPanelId, - panelId: newPanelId - ) - } - ) - } - - return notifications - } - private func applySessionDividerPositions( snapshotNode: SessionWorkspaceLayoutSnapshot, liveNode: ExternalTreeNode @@ -1214,9 +1172,7 @@ extension Workspace { case .split(let split): guard split.children.count == 2 else { - #if DEBUG NSLog("[CmuxConfig] split node requires exactly 2 children, got %d", split.children.count) - #endif leaves.append((paneId: paneId, surfaces: [])) return } @@ -1428,9 +1384,7 @@ extension Workspace { } self.removePendingTerminalInputObserver(registration, forPanelId: panelId) - #if DEBUG NSLog("[CmuxConfig] surface not ready after 3s, dropping command (%d chars)", text.count) - #endif } } } @@ -9210,21 +9164,6 @@ final class Workspace: Identifiable, ObservableObject { } } - func clearSidebarGitMetadata() { - if !panelGitBranches.isEmpty { - panelGitBranches.removeAll() - } - if !panelPullRequests.isEmpty { - panelPullRequests.removeAll() - } - if gitBranch != nil { - gitBranch = nil - } - if pullRequest != nil { - pullRequest = nil - } - } - func resetSidebarContext(reason: String = "unspecified") { statusEntries.removeAll() agentPIDs.removeAll() @@ -10430,7 +10369,6 @@ final class Workspace: Identifiable, ObservableObject { workingDirectory: String? = nil, initialCommand: String? = nil, tmuxStartCommand: String? = nil, - startupEnvironment: [String: String] = [:], initialDividerPosition: CGFloat? = nil ) -> TerminalPanel? { #if DEBUG @@ -10511,8 +10449,7 @@ final class Workspace: Identifiable, ObservableObject { workingDirectory: splitWorkingDirectory, portOrdinal: portOrdinal, initialCommand: startupCommand, - tmuxStartCommand: tmuxStartCommand, - additionalEnvironment: startupEnvironment + tmuxStartCommand: tmuxStartCommand ) configureTerminalPanel(newPanel) panels[newPanel.id] = newPanel @@ -12413,9 +12350,9 @@ final class Workspace: Identifiable, ObservableObject { requestAttentionFlash(panelId: panelId, reason: .notificationDismiss) } - func triggerUnreadIndicatorDismissFlash(panelId: UUID) { + func triggerManualUnreadDismissFlash(panelId: UUID) { guard terminalPanel(for: panelId) != nil else { return } - requestAttentionFlash(panelId: panelId, reason: .unreadIndicatorDismiss) + requestAttentionFlash(panelId: panelId, reason: .manualUnreadDismiss) } func triggerDebugFlash(panelId: UUID) { diff --git a/Sources/cmuxApp.swift b/Sources/cmuxApp.swift index 7fae9209ecd2..5a5067c13ea7 100644 --- a/Sources/cmuxApp.swift +++ b/Sources/cmuxApp.swift @@ -768,6 +768,10 @@ struct cmuxApp: App { targetWindow.toggleFullScreen(nil) } + splitCommandButton(title: String(localized: "menu.view.toggleTerminalTimestamps", defaultValue: "Toggle Terminal Timestamps"), shortcut: menuShortcut(for: .toggleTerminalTimestamps)) { + _ = TerminalTimestampsSettings.toggle() + } + Divider() splitCommandButton(title: String(localized: "menu.view.splitRight", defaultValue: "Split Right"), shortcut: menuShortcut(for: .splitRight)) { @@ -4694,19 +4698,6 @@ enum ClaudeCodeIntegrationSettings { } } -enum AgentSubagentNotificationSettings { - static let suppressNotificationsKey = "suppressSubagentNotifications" - static let defaultSuppressNotifications = true - static let environmentKey = "CMUX_SUPPRESS_SUBAGENT_NOTIFICATIONS" - - static func suppressNotifications(defaults: UserDefaults = .standard) -> Bool { - if defaults.object(forKey: suppressNotificationsKey) == nil { - return defaultSuppressNotifications - } - return defaults.bool(forKey: suppressNotificationsKey) - } -} - enum CursorIntegrationSettings { static let hooksEnabledKey = "cursorHooksEnabled" static let defaultHooksEnabled = true @@ -5040,8 +5031,6 @@ struct SettingsView: View { private var customClaudePath = "" @AppStorage(RipgrepIntegrationSettings.customRipgrepPathKey) private var customRipgrepPath = "" - @AppStorage(AgentSubagentNotificationSettings.suppressNotificationsKey) - private var suppressSubagentNotifications = AgentSubagentNotificationSettings.defaultSuppressNotifications @AppStorage(CursorIntegrationSettings.hooksEnabledKey) private var cursorHooksEnabled = CursorIntegrationSettings.defaultHooksEnabled @AppStorage(GeminiIntegrationSettings.hooksEnabledKey) @@ -5097,6 +5086,8 @@ struct SettingsView: View { private var paneFirstClickFocusEnabled = PaneFirstClickFocusSettings.defaultEnabled @AppStorage(TerminalScrollBarSettings.showScrollBarKey) private var showTerminalScrollBar = TerminalScrollBarSettings.defaultShowScrollBar + @AppStorage(TerminalTimestampsSettings.showTimestampsKey) + private var showTerminalTimestamps = TerminalTimestampsSettings.defaultShowTimestamps @AppStorage(FileDropBehaviorSettings.defaultBehaviorKey) private var fileDropDefaultBehavior = FileDropBehaviorSettings.defaultBehavior.rawValue @AppStorage(AgentSessionAutoResumeSettings.autoResumeAgentSessionsKey) @@ -5116,7 +5107,6 @@ struct SettingsView: View { @AppStorage("sidebarNotificationBadgeColorHex") private var sidebarNotificationBadgeColorHex: String? @AppStorage("sidebarShowBranchDirectory") private var sidebarShowBranchDirectory = SidebarWorkspaceDetailDefaults.showBranchDirectory @AppStorage("sidebarShowPullRequest") private var sidebarShowPullRequest = SidebarWorkspaceDetailDefaults.showPullRequests - @AppStorage(SidebarWorkspaceDetailDefaults.watchGitStatusKey) private var sidebarWatchGitStatus = SidebarWorkspaceDetailDefaults.watchGitStatus @AppStorage(SidebarPullRequestClickabilitySettings.key) private var sidebarMakePullRequestClickable = SidebarPullRequestClickabilitySettings.defaultClickable @AppStorage(BrowserLinkOpenSettings.openSidebarPullRequestLinksInCmuxBrowserKey) private var openSidebarPullRequestLinksInCmuxBrowser = BrowserLinkOpenSettings.defaultOpenSidebarPullRequestLinksInCmuxBrowser @@ -5143,11 +5133,7 @@ struct SettingsView: View { @State private var showOpenAccessConfirmation = false @State private var pendingOpenAccessMode: SocketControlMode? @State private var browserHistoryEntryCount: Int = 0 - @State private var didLoadBrowserHistoryForSettings = false @State private var detectedImportBrowsers: [InstalledBrowserCandidate] = [] - @State private var didRequestBrowserImportDetection = false - @State private var isDetectingImportBrowsers = false - @State private var browserImportDetectionGeneration = 0 @State private var browserInsecureHTTPAllowlistDraft = BrowserInsecureHTTPSettings.defaultAllowlistText @State private var socketPasswordDraft = "" @State private var socketPasswordStatusMessage: String? @@ -5243,6 +5229,17 @@ struct SettingsView: View { ) } + private var showTerminalTimestampsBinding: Binding { + Binding( + get: { showTerminalTimestamps }, + set: { newValue in + guard showTerminalTimestamps != newValue else { return } + showTerminalTimestamps = newValue + TerminalTimestampsSettings.notifyDidChange() + } + ) + } + private var selectedFileDropDefaultBehavior: FileDropDefaultBehavior { FileDropBehaviorSettings.behavior(for: fileDropDefaultBehavior) } @@ -5504,13 +5501,6 @@ struct SettingsView: View { } private var browserHistorySubtitle: String { - guard didLoadBrowserHistoryForSettings else { - return String( - localized: "settings.browser.history.subtitleLoading", - defaultValue: "Checking browsing history..." - ) - } - switch browserHistoryEntryCount { case 0: return String(localized: "settings.browser.history.subtitleEmpty", defaultValue: "No saved pages yet.") @@ -5522,13 +5512,7 @@ struct SettingsView: View { } private var browserImportSubtitle: String { - if isDetectingImportBrowsers || !didRequestBrowserImportDetection { - return String( - localized: "settings.browser.import.detecting", - defaultValue: "Checking installed browsers..." - ) - } - return InstalledBrowserDetector.summaryText(for: detectedImportBrowsers) + InstalledBrowserDetector.summaryText(for: detectedImportBrowsers) } private var browserImportHintSettingsNote: String { @@ -5703,7 +5687,6 @@ struct SettingsView: View { settingsNavigationGeneration += 1 let navigationGeneration = settingsNavigationGeneration let sectionID = SettingsSearchIndex.sectionID(for: destination.target) - prepareSettingsDestinationIfNeeded(destination) if destination.shouldHighlight { highlightedSearchAnchorID = destination.anchorID searchHighlightStartedAt = Date() @@ -5721,63 +5704,6 @@ struct SettingsView: View { } } - private func prepareSettingsDestinationIfNeeded(_ destination: SettingsNavigationDestination) { - if destination.anchorID == SettingsSearchIndex.settingID(for: .browser, idSuffix: "history") { - loadBrowserHistoryForSettingsIfNeeded() - } - - let browserImportAnchorIDs: Set = [ - SettingsSearchIndex.sectionID(for: .browserImport), - SettingsSearchIndex.settingID(for: .browserImport, idSuffix: "import-data"), - SettingsSearchIndex.settingID(for: .browserImport, idSuffix: "import-hint") - ] - if destination.target == .browserImport || browserImportAnchorIDs.contains(destination.anchorID) { - refreshDetectedImportBrowsersIfNeeded() - } - } - - private func handleSettingsLazyLoadFrames( - _ frames: [SettingsLazyLoadTrigger: CGRect], - viewportHeight: CGFloat - ) { - guard viewportHeight > 0 else { return } - - for trigger in SettingsLazyLoadTrigger.allCases { - guard let frame = frames[trigger], - Self.settingsLazyLoadFrameIsNearVisible(frame, viewportHeight: viewportHeight) else { - continue - } - switch trigger { - case .browserHistory: - loadBrowserHistoryForSettingsIfNeeded() - case .browserImport: - refreshDetectedImportBrowsersIfNeeded() - } - } - } - - private static func settingsLazyLoadFrameIsNearVisible( - _ frame: CGRect, - viewportHeight: CGFloat - ) -> Bool { - let preloadPadding: CGFloat = 160 - return frame.maxY >= -preloadPadding && frame.minY <= viewportHeight + preloadPadding - } - - private func loadBrowserHistoryForSettingsIfNeeded() { - guard !didLoadBrowserHistoryForSettings else { return } - BrowserHistoryStore.shared.loadIfNeeded() - didLoadBrowserHistoryForSettings = BrowserHistoryStore.shared.isLoaded - guard didLoadBrowserHistoryForSettings else { return } - browserHistoryEntryCount = BrowserHistoryStore.shared.entries.count - } - - private func refreshDetectedImportBrowsersIfNeeded() { - guard !didRequestBrowserImportDetection else { return } - didRequestBrowserImportDetection = true - refreshDetectedImportBrowsers() - } - private func chooseNotificationSoundFile() { let panel = NSOpenPanel() panel.canChooseFiles = true @@ -5857,10 +5783,9 @@ struct SettingsView: View { var body: some View { let _ = keyboardShortcutSettingsObserver.revision let _ = Self.validateBypassedSettingsConfigurationReviews() - GeometryReader { viewportProxy in - ScrollViewReader { proxy in - ScrollView { - VStack(alignment: .leading, spacing: 14) { + ScrollViewReader { proxy in + ScrollView { + VStack(alignment: .leading, spacing: 14) { SettingsSectionHeader(title: String(localized: "settings.section.account", defaultValue: "Account")) .settingsSearchAnchor(SettingsSearchIndex.sectionID(for: .account)) SettingsCard { @@ -6392,6 +6317,24 @@ struct SettingsView: View { SettingsCardDivider() + SettingsCardRow( + configurationReview: .json("terminal.showTimestamps"), + String(localized: "settings.terminal.timestamps", defaultValue: "Show Terminal Timestamps"), + subtitle: showTerminalTimestamps + ? String(localized: "settings.terminal.timestamps.subtitleOn", defaultValue: "Shows a left-side time gutter aligned with terminal output rows.") + : String(localized: "settings.terminal.timestamps.subtitleOff", defaultValue: "Hides the terminal timestamp gutter. Timestamps can also be toggled from the View menu or command palette.") + ) { + Toggle("", isOn: showTerminalTimestampsBinding) + .labelsHidden() + .controlSize(.small) + .accessibilityIdentifier("SettingsTerminalTimestampsToggle") + .accessibilityLabel( + String(localized: "settings.terminal.timestamps", defaultValue: "Show Terminal Timestamps") + ) + } + + SettingsCardDivider() + SettingsCardRow( configurationReview: .json("terminal.autoResumeAgentSessions"), String(localized: "settings.terminal.agentAutoResume", defaultValue: "Resume Agent Sessions on Reopen"), @@ -6507,17 +6450,6 @@ struct SettingsView: View { } .disabled(sidebarHideAllDetails) SettingsCardDivider() - SettingsCardRow( - configurationReview: .json("sidebar.watchGitStatus"), - String(localized: "settings.app.watchGitStatus", defaultValue: "Watch Git Status in Sidebar"), - subtitle: String(localized: "settings.app.watchGitStatus.subtitle", defaultValue: "Update sidebar branch and PR metadata from repository file changes without polling git.") - ) { - Toggle("", isOn: $sidebarWatchGitStatus) - .labelsHidden() - .controlSize(.small) - } - .disabled(sidebarHideAllDetails) - SettingsCardDivider() SettingsCardRow(configurationReview: .json("sidebar.makePullRequestsClickable"), String(localized: "settings.app.makeSidebarPullRequestClickable", defaultValue: "Make Sidebar PR Clickable"), subtitle: String(localized: "settings.app.makeSidebarPullRequestClickable.subtitle", defaultValue: "Review items stay visible as plain text, and clicks in that area select the workspace row.")) { Toggle("", isOn: $sidebarMakePullRequestClickable).labelsHidden().controlSize(.small).accessibilityIdentifier("SettingsSidebarPullRequestClickableToggle") } .disabled(sidebarHideAllDetails || !sidebarShowPullRequest) SettingsCardDivider() @@ -6726,25 +6658,6 @@ struct SettingsView: View { } } - SettingsCard { - SettingsCardRow( - configurationReview: .json("automation.suppressSubagentNotifications"), - String(localized: "settings.automation.suppressSubagentNotifications", defaultValue: "Suppress Subagent Notifications"), - subtitle: suppressSubagentNotifications - ? String(localized: "settings.automation.suppressSubagentNotifications.subtitleOn", defaultValue: "Child agent completions stay in Feed without notifications.") - : String(localized: "settings.automation.suppressSubagentNotifications.subtitleOff", defaultValue: "Child agent completions notify like top-level agents.") - ) { - Toggle("", isOn: $suppressSubagentNotifications) - .labelsHidden() - .controlSize(.small) - .accessibilityIdentifier("SettingsSuppressSubagentNotificationsToggle") - } - - SettingsCardDivider() - - SettingsCardNote(String(localized: "settings.automation.suppressSubagentNotifications.note", defaultValue: "Uses process ancestry from hook processes. Disable if nested Codex or Claude sessions should trigger completion notifications.")) - } - SettingsCard { SettingsCardRow( configurationReview: .json("automation.cursorIntegration"), @@ -7046,7 +6959,6 @@ struct SettingsView: View { .font(.caption) .foregroundStyle(.secondary) .fixedSize(horizontal: false, vertical: true) - .accessibilityIdentifier("SettingsBrowserImportSummary") Text(String(localized: "browser.import.hint.settingsFootnote", defaultValue: "You can always find this in Settings > Browser.")) .font(.system(size: 10.5)) @@ -7082,7 +6994,6 @@ struct SettingsView: View { } .buttonStyle(.bordered) .controlSize(.small) - .disabled(isDetectingImportBrowsers) } .accessibilityIdentifier("SettingsBrowserImportActions") @@ -7104,7 +7015,6 @@ struct SettingsView: View { SettingsSearchIndex.settingID(for: .browserImport, idSuffix: "import-data") ]) .accessibilityIdentifier("SettingsBrowserImportSection") - .settingsLazyLoadTrigger(.browserImport) .padding(.horizontal, 14) .padding(.vertical, 10) @@ -7135,9 +7045,8 @@ struct SettingsView: View { } .buttonStyle(.bordered) .controlSize(.small) - .disabled(!didLoadBrowserHistoryForSettings || browserHistoryEntryCount == 0) + .disabled(browserHistoryEntryCount == 0) } - .settingsLazyLoadTrigger(.browserHistory) } GlobalHotkeySection() @@ -7428,18 +7337,15 @@ struct SettingsView: View { SettingsSearchHighlightState(anchorID: highlightedSearchAnchorID, token: searchHighlightToken, startedAt: searchHighlightStartedAt) ) } - .coordinateSpace(name: SettingsScrollCoordinateSpace.name) - .onPreferenceChange(SettingsLazyLoadFramePreferenceKey.self) { frames in - handleSettingsLazyLoadFrames(frames, viewportHeight: viewportProxy.size.height) - } .toggleStyle(.switch) .onAppear { + BrowserHistoryStore.shared.loadIfNeeded() notificationStore.refreshAuthorizationStatus() browserThemeMode = BrowserThemeSettings.mode(defaults: .standard).rawValue browserImportHintVariantRaw = BrowserImportHintSettings.variant(for: browserImportHintVariantRaw).rawValue - didLoadBrowserHistoryForSettings = BrowserHistoryStore.shared.isLoaded - browserHistoryEntryCount = didLoadBrowserHistoryForSettings ? BrowserHistoryStore.shared.entries.count : 0 + browserHistoryEntryCount = BrowserHistoryStore.shared.entries.count browserInsecureHTTPAllowlistDraft = browserInsecureHTTPAllowlist + refreshDetectedImportBrowsers() reloadWorkspaceTabColorSettings() refreshNotificationCustomSoundStatus() let target = SettingsWindowPresenter.consumePendingContentNavigationTarget() @@ -7467,8 +7373,6 @@ struct SettingsView: View { } } .onReceive(BrowserHistoryStore.shared.$entries) { entries in - guard BrowserHistoryStore.shared.isLoaded else { return } - didLoadBrowserHistoryForSettings = true browserHistoryEntryCount = entries.count } .onReceive(NotificationCenter.default.publisher(for: UserDefaults.didChangeNotification)) { _ in @@ -7527,7 +7431,6 @@ struct SettingsView: View { Text(notificationCustomSoundErrorAlertMessage) } } - } } private static func validateBypassedSettingsConfigurationReviews() { @@ -7566,7 +7469,6 @@ struct SettingsView: View { claudeCodeHooksEnabled = ClaudeCodeIntegrationSettings.defaultHooksEnabled customClaudePath = "" customRipgrepPath = "" - suppressSubagentNotifications = AgentSubagentNotificationSettings.defaultSuppressNotifications cursorHooksEnabled = CursorIntegrationSettings.defaultHooksEnabled geminiHooksEnabled = GeminiIntegrationSettings.defaultHooksEnabled sendAnonymousTelemetry = TelemetrySettings.defaultSendAnonymousTelemetry @@ -7622,6 +7524,11 @@ struct SettingsView: View { if previousShowTerminalScrollBar != showTerminalScrollBar { TerminalScrollBarSettings.notifyDidChange() } + let previousShowTerminalTimestamps = showTerminalTimestamps + showTerminalTimestamps = TerminalTimestampsSettings.defaultShowTimestamps + if previousShowTerminalTimestamps != showTerminalTimestamps { + TerminalTimestampsSettings.notifyDidChange() + } fileDropDefaultBehavior = FileDropBehaviorSettings.defaultBehavior.rawValue let previousAutoResumeAgentSessions = autoResumeAgentSessions autoResumeAgentSessions = AgentSessionAutoResumeSettings.defaultAutoResumeAgentSessions @@ -7639,7 +7546,6 @@ struct SettingsView: View { sidebarNotificationBadgeColorHex = nil sidebarShowBranchDirectory = SidebarWorkspaceDetailDefaults.showBranchDirectory sidebarShowPullRequest = SidebarWorkspaceDetailDefaults.showPullRequests - sidebarWatchGitStatus = SidebarWorkspaceDetailDefaults.watchGitStatus sidebarMakePullRequestClickable = SidebarPullRequestClickabilitySettings.defaultClickable openSidebarPullRequestLinksInCmuxBrowser = BrowserLinkOpenSettings.defaultOpenSidebarPullRequestLinksInCmuxBrowser openSidebarPortLinksInCmuxBrowser = BrowserLinkOpenSettings.defaultOpenSidebarPortLinksInCmuxBrowser @@ -7714,23 +7620,7 @@ struct SettingsView: View { } private func refreshDetectedImportBrowsers() { - didRequestBrowserImportDetection = true - isDetectingImportBrowsers = true - browserImportDetectionGeneration += 1 - let generation = browserImportDetectionGeneration - let homeDirectoryURL = FileManager.default.homeDirectoryForCurrentUser - let bundleLookupSnapshot = InstalledBrowserDetector.applicationBundleLookupSnapshot() - Task.detached(priority: .userInitiated) { - let detectedBrowsers = InstalledBrowserDetector.detectInstalledBrowsers( - homeDirectoryURL: homeDirectoryURL, - bundleLookup: { bundleLookupSnapshot[$0] } - ) - await MainActor.run { - guard generation == browserImportDetectionGeneration else { return } - detectedImportBrowsers = detectedBrowsers - isDetectingImportBrowsers = false - } - } + detectedImportBrowsers = InstalledBrowserDetector.detectInstalledBrowsers() } } diff --git a/cmux.xcodeproj/project.pbxproj b/cmux.xcodeproj/project.pbxproj index fe7cac4b2187..575c5cabc0f4 100644 --- a/cmux.xcodeproj/project.pbxproj +++ b/cmux.xcodeproj/project.pbxproj @@ -38,7 +38,6 @@ 4378399A7C0245EF8186F306 /* OmnibarAndToolsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B09C007F42697761B5F1A2AB /* OmnibarAndToolsTests.swift */; }; 46F6AC15863EC84DCD3770A2 /* TerminalAndGhosttyTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02FC74F2C27127CC565B3E8C /* TerminalAndGhosttyTests.swift */; }; C35610000000000000000001 /* FinderFileDropRegressionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C35610000000000000000002 /* FinderFileDropRegressionTests.swift */; }; - C44550000000000000000001 /* PanelOwnedNativeViewSessionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C44550000000000000000002 /* PanelOwnedNativeViewSessionTests.swift */; }; 51D800000000000000000001 /* SidebarIdentifierFormattingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51D800000000000000000002 /* SidebarIdentifierFormattingTests.swift */; }; C0DE35530000000000000101 /* BundledCLILinkageTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C0DE35530000000000000102 /* BundledCLILinkageTests.swift */; }; C37800000000000000000001 /* VMSSHCommandTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C37800000000000000000002 /* VMSSHCommandTests.swift */; }; @@ -79,8 +78,6 @@ D0B10010A1B2C3D4E5F60001 /* BonsplitTabBarDebug.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0B10011A1B2C3D4E5F60001 /* BonsplitTabBarDebug.swift */; }; D0B10014A1B2C3D4E5F60001 /* DragOverlayRoutingPolicy.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0B10015A1B2C3D4E5F60001 /* DragOverlayRoutingPolicy.swift */; }; D0B1001AA1B2C3D4E5F60001 /* FileDropHintBadgeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0B1001BA1B2C3D4E5F60001 /* FileDropHintBadgeView.swift */; }; - 4472A0024472A0024472A002 /* BrowserScreenshotPipeline.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4472B0024472B0024472B002 /* BrowserScreenshotPipeline.swift */; }; - 4472A0034472A0034472A003 /* BrowserScreenshotSnapshotter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4472B0034472B0034472B003 /* BrowserScreenshotSnapshotter.swift */; }; D0B10020A1B2C3D4E5F60001 /* FileDropOverlayView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0B10021A1B2C3D4E5F60001 /* FileDropOverlayView.swift */; }; D0B10022A1B2C3D4E5F60001 /* FileDropOverlayViewHitTesting.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0B10023A1B2C3D4E5F60001 /* FileDropOverlayViewHitTesting.swift */; }; D0B1001CA1B2C3D4E5F60001 /* PaneDropRoutingSupport.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0B1001DA1B2C3D4E5F60001 /* PaneDropRoutingSupport.swift */; }; @@ -131,7 +128,6 @@ D35450010000000000000001 /* SidebarWorkspaceRowHoverTracker.swift in Sources */ = {isa = PBXBuildFile; fileRef = D35450020000000000000002 /* SidebarWorkspaceRowHoverTracker.swift */; }; A11EAB000000000000000000 /* AppearanceSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = A11EAB000000000000000001 /* AppearanceSettings.swift */; }; A5001001 /* cmuxApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5001011 /* cmuxApp.swift */; }; - D9CCF002D9CCF002D9CCF002 /* SettingsLazyLoadHelpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9CCF001D9CCF001D9CCF001 /* SettingsLazyLoadHelpers.swift */; }; C0DE34020000000000000001 /* CmuxHelpCommands.swift in Sources */ = {isa = PBXBuildFile; fileRef = C0DE34020000000000000003 /* CmuxHelpCommands.swift */; }; C0DE34020000000000000002 /* CmuxHelpResource.swift in Sources */ = {isa = PBXBuildFile; fileRef = C0DE34020000000000000004 /* CmuxHelpResource.swift */; }; A50019A0 /* SettingsNavigation.swift in Sources */ = {isa = PBXBuildFile; fileRef = A50019A1 /* SettingsNavigation.swift */; }; @@ -191,6 +187,7 @@ E30750000000000000000002 /* WorkspaceTabColorResolution.swift in Sources */ = {isa = PBXBuildFile; fileRef = E30750000000000000000001 /* WorkspaceTabColorResolution.swift */; }; A5001004 /* GhosttyConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5001014 /* GhosttyConfig.swift */; }; A5001005 /* GhosttyTerminalView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5001015 /* GhosttyTerminalView.swift */; }; + D3690A0023690A0023690A02 /* TerminalTimestampStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = D3690A0013690A0013690A01 /* TerminalTimestampStore.swift */; }; C13519000000000000000001 /* TerminalStartupEnvironment.swift in Sources */ = {isa = PBXBuildFile; fileRef = C13519000000000000000002 /* TerminalStartupEnvironment.swift */; }; C13519000000000000000005 /* RestorableAgentTypes.swift in Sources */ = {isa = PBXBuildFile; fileRef = C13519000000000000000006 /* RestorableAgentTypes.swift */; }; B3575000000000000000000C /* SessionIndexModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3575000000000000000000B /* SessionIndexModels.swift */; }; @@ -270,7 +267,6 @@ B42450030000000000000001 /* BrowserHiddenWebViewDiscardManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = B42450040000000000000001 /* BrowserHiddenWebViewDiscardManager.swift */; }; A5001402 /* BrowserPanel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5001412 /* BrowserPanel.swift */; }; B3770BA00000000000000001 /* BrowserAutomation.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3770BA00000000000000002 /* BrowserAutomation.swift */; }; - 4472A0014472A0014472A001 /* BrowserScreenshot.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4472B0014472B0014472B001 /* BrowserScreenshot.swift */; }; D7AB00000000000000000007 /* BrowserPanel+MoveTabToNewWorkspace.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7AB00000000000000000008 /* BrowserPanel+MoveTabToNewWorkspace.swift */; }; A5001403 /* TerminalPanelView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5001413 /* TerminalPanelView.swift */; }; A5001404 /* BrowserPanelView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5001414 /* BrowserPanelView.swift */; }; @@ -318,9 +314,6 @@ A5001534 /* BrowserWindowPortal.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5001533 /* BrowserWindowPortal.swift */; }; A5001540 /* PortScanner.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5001541 /* PortScanner.swift */; }; C7A501000000000000000002 /* CmuxTopSnapshot.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7A501000000000000000001 /* CmuxTopSnapshot.swift */; }; - C7A510000000000000000002 /* CmuxTopMemoryDiagnostics.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7A510000000000000000001 /* CmuxTopMemoryDiagnostics.swift */; }; - C7A511000000000000000002 /* CmuxTopProcessEnumeration.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7A511000000000000000001 /* CmuxTopProcessEnumeration.swift */; }; - C7A512000000000000000002 /* CmuxTopProcessSnapshotCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7A512000000000000000001 /* CmuxTopProcessSnapshotCache.swift */; }; B35750000000000000000004 /* CmuxTopProcessArguments.swift in Sources */ = {isa = PBXBuildFile; fileRef = B35750000000000000000003 /* CmuxTopProcessArguments.swift */; }; C7A508000000000000000002 /* CmuxTopSnapshotScopeCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7A508000000000000000001 /* CmuxTopSnapshotScopeCache.swift */; }; C7A50D000000000000000002 /* CmuxTopProcessCPUTracker.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7A50D000000000000000001 /* CmuxTopProcessCPUTracker.swift */; }; @@ -395,7 +388,6 @@ B9000061A1B2C3D4E5F60719 /* CMUXCLI+HermesAgentHooks.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9000060A1B2C3D4E5F60719 /* CMUXCLI+HermesAgentHooks.swift */; }; B9000063A1B2C3D4E5F60719 /* CMUXCLI+AgentHookDefinitions.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9000062A1B2C3D4E5F60719 /* CMUXCLI+AgentHookDefinitions.swift */; }; B9000068A1B2C3D4E5F60719 /* CMUXCLI+AmpExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9000069A1B2C3D4E5F60719 /* CMUXCLI+AmpExtension.swift */; }; - B9000071A1B2C3D4E5F60719 /* CMUXCLI+Memory.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9000070A1B2C3D4E5F60719 /* CMUXCLI+Memory.swift */; }; B900000BA1B2C3D4E5F60719 /* cmux in Copy CLI */ = {isa = PBXBuildFile; fileRef = B9000004A1B2C3D4E5F60719 /* cmux */; }; B900002EA1B2C3D4E5F60719 /* CMUXCLI+Themes.swift in Sources */ = {isa = PBXBuildFile; fileRef = B900002CA1B2C3D4E5F60719 /* CMUXCLI+Themes.swift */; }; B900002FA1B2C3D4E5F60719 /* CMUXCLI+ThemeSupport.swift in Sources */ = {isa = PBXBuildFile; fileRef = B900002DA1B2C3D4E5F60719 /* CMUXCLI+ThemeSupport.swift */; }; @@ -423,7 +415,6 @@ D3622000A1B2C3D4E5F60718 /* BrowserArrowKeyForwardingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D3622001A1B2C3D4E5F60718 /* BrowserArrowKeyForwardingTests.swift */; }; E30750000000000000000006 /* CmuxConfigNamedColorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E30750000000000000000005 /* CmuxConfigNamedColorTests.swift */; }; C1ADE00002A1B2C3D4E5F719 /* claude in Copy CLI */ = {isa = PBXBuildFile; fileRef = C1ADE00001A1B2C3D4E5F719 /* claude */; }; - C1ADE10002A1B2C3D4E5F719 /* grok in Copy CLI */ = {isa = PBXBuildFile; fileRef = C1ADE10001A1B2C3D4E5F719 /* grok */; }; C2577000A1B2C3D4E5F60718 /* TerminalCmdClickUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C2577001A1B2C3D4E5F60718 /* TerminalCmdClickUITests.swift */; }; CA39C0304FE351A21C372429 /* SidebarWidthPolicyTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE0171AF1F49F7547191CEE5 /* SidebarWidthPolicyTests.swift */; }; CB23911D7E131E8FBC9B82B6 /* SidebarOrderingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BC39DE4B96D1931C52AF7D68 /* SidebarOrderingTests.swift */; }; @@ -554,7 +545,6 @@ files = ( B900000BA1B2C3D4E5F60719 /* cmux in Copy CLI */, C1ADE00002A1B2C3D4E5F719 /* claude in Copy CLI */, - C1ADE10002A1B2C3D4E5F719 /* grok in Copy CLI */, D1BEF00002A1B2C3D4E5F719 /* open in Copy CLI */, ); name = "Copy CLI"; @@ -576,7 +566,6 @@ /* Begin PBXFileReference section */ 02FC74F2C27127CC565B3E8C /* TerminalAndGhosttyTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TerminalAndGhosttyTests.swift; sourceTree = ""; }; C35610000000000000000002 /* FinderFileDropRegressionTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FinderFileDropRegressionTests.swift; sourceTree = ""; }; - C44550000000000000000002 /* PanelOwnedNativeViewSessionTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PanelOwnedNativeViewSessionTests.swift; sourceTree = ""; }; D0B10009A1B2C3D4E5F60001 /* PortalTabDragRoutingTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PortalTabDragRoutingTests.swift; sourceTree = ""; }; D0B1000DA1B2C3D4E5F60001 /* CmuxWebViewDragRoutingTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CmuxWebViewDragRoutingTests.swift; sourceTree = ""; }; D0B1000FA1B2C3D4E5F60001 /* BrowserPaneDropRoutingTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BrowserPaneDropRoutingTests.swift; sourceTree = ""; }; @@ -662,7 +651,6 @@ A11EB0000000000000000001 /* GhosttyConfigPathResolverTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GhosttyConfigPathResolverTests.swift; sourceTree = ""; }; A5001000 /* cmux.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = cmux.app; sourceTree = BUILT_PRODUCTS_DIR; }; A5001011 /* cmuxApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = cmuxApp.swift; sourceTree = ""; }; - D9CCF001D9CCF001D9CCF001 /* SettingsLazyLoadHelpers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsLazyLoadHelpers.swift; sourceTree = ""; }; E3309A08 /* cmuxApp+EqualizeSplitsMenu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "cmuxApp+EqualizeSplitsMenu.swift"; sourceTree = ""; }; C0DE34020000000000000003 /* CmuxHelpCommands.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = App/CmuxHelpCommands.swift; sourceTree = ""; }; C0DE34020000000000000004 /* CmuxHelpResource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = App/CmuxHelpResource.swift; sourceTree = ""; }; @@ -726,6 +714,7 @@ A5001014 /* GhosttyConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GhosttyConfig.swift; sourceTree = ""; }; C4041001000000000000001A /* CommandClickFileOpenRouter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommandClickFileOpenRouter.swift; sourceTree = ""; }; A5001015 /* GhosttyTerminalView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GhosttyTerminalView.swift; sourceTree = ""; }; + D3690A0013690A0013690A01 /* TerminalTimestampStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TerminalTimestampStore.swift; sourceTree = ""; }; C13519000000000000000002 /* TerminalStartupEnvironment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TerminalStartupEnvironment.swift; sourceTree = ""; }; C13519000000000000000006 /* RestorableAgentTypes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RestorableAgentTypes.swift; sourceTree = ""; }; B3575000000000000000000B /* SessionIndexModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionIndexModels.swift; sourceTree = ""; }; @@ -758,9 +747,6 @@ C7A50A000000000000000001 /* TerminalControllerPaneResizeSupport.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TerminalControllerPaneResizeSupport.swift; sourceTree = ""; }; C7A50B000000000000000001 /* TerminalControllerV2ParamParsingSupport.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TerminalControllerV2ParamParsingSupport.swift; sourceTree = ""; }; C7A501000000000000000001 /* CmuxTopSnapshot.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CmuxTopSnapshot.swift; sourceTree = ""; }; - C7A510000000000000000001 /* CmuxTopMemoryDiagnostics.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CmuxTopMemoryDiagnostics.swift; sourceTree = ""; }; - C7A511000000000000000001 /* CmuxTopProcessEnumeration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CmuxTopProcessEnumeration.swift; sourceTree = ""; }; - C7A512000000000000000001 /* CmuxTopProcessSnapshotCache.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CmuxTopProcessSnapshotCache.swift; sourceTree = ""; }; B35750000000000000000003 /* CmuxTopProcessArguments.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CmuxTopProcessArguments.swift; sourceTree = ""; }; C7A508000000000000000001 /* CmuxTopSnapshotScopeCache.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CmuxTopSnapshotScopeCache.swift; sourceTree = ""; }; C7A50D000000000000000001 /* CmuxTopProcessCPUTracker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CmuxTopProcessCPUTracker.swift; sourceTree = ""; }; @@ -836,9 +822,6 @@ B42450040000000000000001 /* BrowserHiddenWebViewDiscardManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Panels/BrowserHiddenWebViewDiscardManager.swift; sourceTree = ""; }; A5001412 /* BrowserPanel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Panels/BrowserPanel.swift; sourceTree = ""; }; B3770BA00000000000000002 /* BrowserAutomation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Panels/BrowserAutomation.swift; sourceTree = ""; }; - 4472B0014472B0014472B001 /* BrowserScreenshot.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Panels/BrowserScreenshot.swift; sourceTree = ""; }; - 4472B0024472B0024472B002 /* BrowserScreenshotPipeline.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Panels/BrowserScreenshotPipeline.swift; sourceTree = ""; }; - 4472B0034472B0034472B003 /* BrowserScreenshotSnapshotter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Panels/BrowserScreenshotSnapshotter.swift; sourceTree = ""; }; D7AB00000000000000000008 /* BrowserPanel+MoveTabToNewWorkspace.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Panels/BrowserPanel+MoveTabToNewWorkspace.swift"; sourceTree = ""; }; A5001413 /* TerminalPanelView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Panels/TerminalPanelView.swift; sourceTree = ""; }; A5001414 /* BrowserPanelView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Panels/BrowserPanelView.swift; sourceTree = ""; }; @@ -948,7 +931,6 @@ B9000060A1B2C3D4E5F60719 /* CMUXCLI+HermesAgentHooks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CMUXCLI+HermesAgentHooks.swift"; sourceTree = ""; }; B9000062A1B2C3D4E5F60719 /* CMUXCLI+AgentHookDefinitions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CMUXCLI+AgentHookDefinitions.swift"; sourceTree = ""; }; B9000069A1B2C3D4E5F60719 /* CMUXCLI+AmpExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CMUXCLI+AmpExtension.swift"; sourceTree = ""; }; - B9000070A1B2C3D4E5F60719 /* CMUXCLI+Memory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CMUXCLI+Memory.swift"; sourceTree = ""; }; B9000004A1B2C3D4E5F60719 /* cmux */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = cmux; sourceTree = BUILT_PRODUCTS_DIR; }; B900002CA1B2C3D4E5F60719 /* CMUXCLI+Themes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CMUXCLI+Themes.swift"; sourceTree = ""; }; B900002DA1B2C3D4E5F60719 /* CMUXCLI+ThemeSupport.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CMUXCLI+ThemeSupport.swift"; sourceTree = ""; }; @@ -985,7 +967,6 @@ C1A2B3C4D5E6F70800000002 /* CmuxConfigTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CmuxConfigTests.swift; sourceTree = ""; }; E30750000000000000000005 /* CmuxConfigNamedColorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CmuxConfigNamedColorTests.swift; sourceTree = ""; }; C1ADE00001A1B2C3D4E5F719 /* claude */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = Resources/bin/claude; sourceTree = SOURCE_ROOT; }; - C1ADE10001A1B2C3D4E5F719 /* grok */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = Resources/bin/grok; sourceTree = SOURCE_ROOT; }; C2577001A1B2C3D4E5F60718 /* TerminalCmdClickUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TerminalCmdClickUITests.swift; sourceTree = ""; }; D0E0F0B1A1B2C3D4E5F60718 /* BrowserPaneNavigationKeybindUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BrowserPaneNavigationKeybindUITests.swift; sourceTree = ""; }; D0E0F0B5A1B2C3D4E5F60718 /* FindSelectionShortcutUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FindSelectionShortcutUITests.swift; sourceTree = ""; }; @@ -1119,7 +1100,6 @@ B2E7294509CC42FE9191870E /* xterm-ghostty */, A5002001 /* THIRD_PARTY_LICENSES.md */, C1ADE00001A1B2C3D4E5F719 /* claude */, - C1ADE10001A1B2C3D4E5F719 /* grok */, DA7A10CA710E000000000001 /* Localizable.xcstrings */, DA7A10CA710E000000000002 /* InfoPlist.xcstrings */, FEED0000000000000000F006 /* opencode-plugin.js */, @@ -1225,7 +1205,6 @@ A11EAC000000000000000001 /* GhosttyTerminalAppearance.swift */, A11EAD000000000000000001 /* WorkspaceAppearanceResolution.swift */, A5001011 /* cmuxApp.swift */, - D9CCF001D9CCF001D9CCF001 /* SettingsLazyLoadHelpers.swift */, E3309A08 /* cmuxApp+EqualizeSplitsMenu.swift */, C0DE34020000000000000003 /* CmuxHelpCommands.swift */, C0DE34020000000000000004 /* CmuxHelpResource.swift */, @@ -1319,6 +1298,7 @@ A5001014 /* GhosttyConfig.swift */, C4041001000000000000001A /* CommandClickFileOpenRouter.swift */, A5001015 /* GhosttyTerminalView.swift */, + D3690A0013690A0013690A01 /* TerminalTimestampStore.swift */, C13519000000000000000002 /* TerminalStartupEnvironment.swift */, C13519000000000000000006 /* RestorableAgentTypes.swift */, B3575000000000000000000B /* SessionIndexModels.swift */, @@ -1348,12 +1328,9 @@ C7A50A000000000000000001 /* TerminalControllerPaneResizeSupport.swift */, C7A50B000000000000000001 /* TerminalControllerV2ParamParsingSupport.swift */, C7A505000000000000000001 /* TerminalControllerTopSupport.swift */, - C7A501000000000000000001 /* CmuxTopSnapshot.swift */, - C7A510000000000000000001 /* CmuxTopMemoryDiagnostics.swift */, - C7A511000000000000000001 /* CmuxTopProcessEnumeration.swift */, - C7A512000000000000000001 /* CmuxTopProcessSnapshotCache.swift */, - B35750000000000000000003 /* CmuxTopProcessArguments.swift */, - C7A508000000000000000001 /* CmuxTopSnapshotScopeCache.swift */, + C7A501000000000000000001 /* CmuxTopSnapshot.swift */, + B35750000000000000000003 /* CmuxTopProcessArguments.swift */, + C7A508000000000000000001 /* CmuxTopSnapshotScopeCache.swift */, C7A50D000000000000000001 /* CmuxTopProcessCPUTracker.swift */, C7A50E000000000000000001 /* CmuxTopProcessDetails.swift */, C7A502000000000000000001 /* TaskManagerWindowController.swift */, @@ -1401,9 +1378,6 @@ B42450040000000000000001 /* BrowserHiddenWebViewDiscardManager.swift */, A5001412 /* BrowserPanel.swift */, B3770BA00000000000000002 /* BrowserAutomation.swift */, - 4472B0014472B0014472B001 /* BrowserScreenshot.swift */, - 4472B0024472B0024472B002 /* BrowserScreenshotPipeline.swift */, - 4472B0034472B0034472B003 /* BrowserScreenshotSnapshotter.swift */, D7AB00000000000000000008 /* BrowserPanel+MoveTabToNewWorkspace.swift */, A500RG00 /* ReactGrab.swift */, A5001413 /* TerminalPanelView.swift */, @@ -1529,7 +1503,6 @@ B9000060A1B2C3D4E5F60719 /* CMUXCLI+HermesAgentHooks.swift */, B9000062A1B2C3D4E5F60719 /* CMUXCLI+AgentHookDefinitions.swift */, B9000069A1B2C3D4E5F60719 /* CMUXCLI+AmpExtension.swift */, - B9000070A1B2C3D4E5F60719 /* CMUXCLI+Memory.swift */, B9000031A1B2C3D4E5F60719 /* CMUXCLI+DocsSettings.swift */, B900002DA1B2C3D4E5F60719 /* CMUXCLI+ThemeSupport.swift */, B900002CA1B2C3D4E5F60719 /* CMUXCLI+Themes.swift */, @@ -1599,7 +1572,6 @@ D0B1000FA1B2C3D4E5F60001 /* BrowserPaneDropRoutingTests.swift */, 02FC74F2C27127CC565B3E8C /* TerminalAndGhosttyTests.swift */, C35610000000000000000002 /* FinderFileDropRegressionTests.swift */, - C44550000000000000000002 /* PanelOwnedNativeViewSessionTests.swift */, 3069F1D10000000000000004 /* GhosttyPasteboardFidelityTests.swift */, D7AB34400000000000000004 /* GhosttyTerminalViewVisibilityPolicyTests.swift */, D7AB00000000000000000012 /* WorkspaceAdjacentPaneMoveTests.swift */, @@ -1974,7 +1946,6 @@ A11EAC000000000000000000 /* GhosttyTerminalAppearance.swift in Sources */, A11EAD000000000000000000 /* WorkspaceAppearanceResolution.swift in Sources */, A5001001 /* cmuxApp.swift in Sources */, - D9CCF002D9CCF002D9CCF002 /* SettingsLazyLoadHelpers.swift in Sources */, E3309A07 /* cmuxApp+EqualizeSplitsMenu.swift in Sources */, C0DE34020000000000000001 /* CmuxHelpCommands.swift in Sources */, C0DE34020000000000000002 /* CmuxHelpResource.swift in Sources */, @@ -2064,6 +2035,7 @@ A5001004 /* GhosttyConfig.swift in Sources */, C4041001000000000000001B /* CommandClickFileOpenRouter.swift in Sources */, A5001005 /* GhosttyTerminalView.swift in Sources */, + D3690A0023690A0023690A02 /* TerminalTimestampStore.swift in Sources */, C13519000000000000000001 /* TerminalStartupEnvironment.swift in Sources */, C13519000000000000000005 /* RestorableAgentTypes.swift in Sources */, B3575000000000000000000C /* SessionIndexModels.swift in Sources */, @@ -2097,12 +2069,9 @@ C7A50A000000000000000002 /* TerminalControllerPaneResizeSupport.swift in Sources */, C7A50B000000000000000002 /* TerminalControllerV2ParamParsingSupport.swift in Sources */, C7A505000000000000000002 /* TerminalControllerTopSupport.swift in Sources */, - C7A501000000000000000002 /* CmuxTopSnapshot.swift in Sources */, - C7A510000000000000000002 /* CmuxTopMemoryDiagnostics.swift in Sources */, - C7A511000000000000000002 /* CmuxTopProcessEnumeration.swift in Sources */, - C7A512000000000000000002 /* CmuxTopProcessSnapshotCache.swift in Sources */, - B35750000000000000000004 /* CmuxTopProcessArguments.swift in Sources */, - C7A508000000000000000002 /* CmuxTopSnapshotScopeCache.swift in Sources */, + C7A501000000000000000002 /* CmuxTopSnapshot.swift in Sources */, + B35750000000000000000004 /* CmuxTopProcessArguments.swift in Sources */, + C7A508000000000000000002 /* CmuxTopSnapshotScopeCache.swift in Sources */, C7A50D000000000000000002 /* CmuxTopProcessCPUTracker.swift in Sources */, C7A50E000000000000000002 /* CmuxTopProcessDetails.swift in Sources */, C7A502000000000000000002 /* TaskManagerWindowController.swift in Sources */, @@ -2150,9 +2119,6 @@ B42450030000000000000001 /* BrowserHiddenWebViewDiscardManager.swift in Sources */, A5001402 /* BrowserPanel.swift in Sources */, B3770BA00000000000000001 /* BrowserAutomation.swift in Sources */, - 4472A0014472A0014472A001 /* BrowserScreenshot.swift in Sources */, - 4472A0024472A0024472A002 /* BrowserScreenshotPipeline.swift in Sources */, - 4472A0034472A0034472A003 /* BrowserScreenshotSnapshotter.swift in Sources */, D7AB00000000000000000007 /* BrowserPanel+MoveTabToNewWorkspace.swift in Sources */, A500RG01 /* ReactGrab.swift in Sources */, A5001403 /* TerminalPanelView.swift in Sources */, @@ -2275,7 +2241,6 @@ B9000061A1B2C3D4E5F60719 /* CMUXCLI+HermesAgentHooks.swift in Sources */, B9000063A1B2C3D4E5F60719 /* CMUXCLI+AgentHookDefinitions.swift in Sources */, B9000068A1B2C3D4E5F60719 /* CMUXCLI+AmpExtension.swift in Sources */, - B9000071A1B2C3D4E5F60719 /* CMUXCLI+Memory.swift in Sources */, B9000035A1B2C3D4E5F60719 /* CMUXCLI+DocsSettings.swift in Sources */, B900002FA1B2C3D4E5F60719 /* CMUXCLI+ThemeSupport.swift in Sources */, B900002EA1B2C3D4E5F60719 /* CMUXCLI+Themes.swift in Sources */, @@ -2388,7 +2353,6 @@ D0B1000EA1B2C3D4E5F60001 /* BrowserPaneDropRoutingTests.swift in Sources */, 46F6AC15863EC84DCD3770A2 /* TerminalAndGhosttyTests.swift in Sources */, C35610000000000000000001 /* FinderFileDropRegressionTests.swift in Sources */, - C44550000000000000000001 /* PanelOwnedNativeViewSessionTests.swift in Sources */, 3069F1D10000000000000003 /* GhosttyPasteboardFidelityTests.swift in Sources */, D7AB34400000000000000003 /* GhosttyTerminalViewVisibilityPolicyTests.swift in Sources */, D7AB00000000000000000011 /* WorkspaceAdjacentPaneMoveTests.swift in Sources */, diff --git a/cmux.xcodeproj/xcshareddata/xcschemes/cmux-ci.xcscheme b/cmux.xcodeproj/xcshareddata/xcschemes/cmux-ci.xcscheme index cae26c54dc40..c47c0d492586 100644 --- a/cmux.xcodeproj/xcshareddata/xcschemes/cmux-ci.xcscheme +++ b/cmux.xcodeproj/xcshareddata/xcschemes/cmux-ci.xcscheme @@ -22,9 +22,6 @@ - - - diff --git a/cmux.xcodeproj/xcshareddata/xcschemes/cmux-unit.xcscheme b/cmux.xcodeproj/xcshareddata/xcschemes/cmux-unit.xcscheme index d471bb97e309..24ed0d3c54b3 100644 --- a/cmux.xcodeproj/xcshareddata/xcschemes/cmux-unit.xcscheme +++ b/cmux.xcodeproj/xcshareddata/xcschemes/cmux-unit.xcscheme @@ -19,9 +19,6 @@ - - - @@ -36,3 +33,4 @@ + diff --git a/cmux.xcodeproj/xcshareddata/xcschemes/cmux.xcscheme b/cmux.xcodeproj/xcshareddata/xcschemes/cmux.xcscheme index 09569727a4d0..8baf53212a44 100644 --- a/cmux.xcodeproj/xcshareddata/xcschemes/cmux.xcscheme +++ b/cmux.xcodeproj/xcshareddata/xcschemes/cmux.xcscheme @@ -16,9 +16,6 @@ - - - diff --git a/cmuxTests/AppDelegateEqualizeSplitsShortcutTests.swift b/cmuxTests/AppDelegateEqualizeSplitsShortcutTests.swift index 58623a5acd6b..302525c1da99 100644 --- a/cmuxTests/AppDelegateEqualizeSplitsShortcutTests.swift +++ b/cmuxTests/AppDelegateEqualizeSplitsShortcutTests.swift @@ -113,9 +113,6 @@ final class AppDelegateEqualizeSplitsShortcutTests: XCTestCase { XCTFail("Expected cached layout snapshot after seeding split geometry") return } - let expectedEqualizedPositions = shortcutRoutingExpectedEqualizedDividerPositions( - in: workspace.bonsplitController.treeSnapshot() - ) guard let event = makeKeyDownEvent(key: "=", modifiers: [.command, .control], keyCode: 24, windowNumber: window.windowNumber) else { XCTFail("Failed to construct Cmd+Ctrl+= event") @@ -133,11 +130,7 @@ final class AppDelegateEqualizeSplitsShortcutTests: XCTestCase { let equalizedSplits = shortcutRoutingSplitNodes(in: workspace.bonsplitController.treeSnapshot()) XCTAssertEqual(equalizedSplits.count, seededSplits.count) for split in equalizedSplits { - guard let expectedPosition = expectedEqualizedPositions[split.id] else { - XCTFail("Expected equalized split ID to remain present") - continue - } - XCTAssertEqual(split.dividerPosition, expectedPosition, accuracy: 0.000_1) + XCTAssertEqual(split.dividerPosition, 0.5, accuracy: 0.000_1) } let liveEqualizedLayout = workspace.bonsplitController.layoutSnapshot() @@ -161,27 +154,6 @@ final class AppDelegateEqualizeSplitsShortcutTests: XCTestCase { } } - private func shortcutRoutingExpectedEqualizedDividerPositions(in node: ExternalTreeNode) -> [String: Double] { - var positionsBySplitId: [String: Double] = [:] - - @discardableResult - func collectLeafCount(_ node: ExternalTreeNode) -> Int { - switch node { - case .pane: - return 1 - case .split(let split): - let firstLeafCount = collectLeafCount(split.first) - let secondLeafCount = collectLeafCount(split.second) - let totalLeafCount = firstLeafCount + secondLeafCount - positionsBySplitId[split.id] = Double(firstLeafCount) / Double(totalLeafCount) - return totalLeafCount - } - } - - collectLeafCount(node) - return positionsBySplitId - } - private func shortcutRoutingPaneFramesById(in snapshot: LayoutSnapshot) -> [String: PixelRect] { Dictionary(uniqueKeysWithValues: snapshot.panes.map { ($0.paneId, $0.frame) }) } diff --git a/cmuxTests/AppDelegateShortcutRoutingTests.swift b/cmuxTests/AppDelegateShortcutRoutingTests.swift index 5b74e7c3e703..206aa923a6be 100644 --- a/cmuxTests/AppDelegateShortcutRoutingTests.swift +++ b/cmuxTests/AppDelegateShortcutRoutingTests.swift @@ -105,10 +105,6 @@ final class AppDelegateShortcutRoutingTests: XCTestCase { super.setUp() // Prevent a single hanging test from consuming the entire CI timeout budget. executionTimeAllowance = 30 - #if DEBUG - KeyboardShortcutRecorderActivity.resetForTesting() - AppDelegate.shared?.debugResetShortcutRoutingStateForTesting() - #endif actionsWithPersistedShortcut = Set( KeyboardShortcutSettings.Action.allCases.filter { UserDefaults.standard.object(forKey: $0.defaultsKey) != nil @@ -121,15 +117,10 @@ final class AppDelegateShortcutRoutingTests: XCTestCase { ) originalSettingsFileStore = KeyboardShortcutSettings.installIsolatedTestFileStore(prefix: "cmux-shortcut-routing") KeyboardShortcutSettings.resetAll() - #if DEBUG - AppDelegate.shared?.debugResetShortcutRoutingStateForTesting() - #endif } override func tearDown() { #if DEBUG - KeyboardShortcutRecorderActivity.resetForTesting() - AppDelegate.shared?.debugResetShortcutRoutingStateForTesting() KeyboardShortcutSettings.shortcutLookupObserver = nil #endif KeyboardShortcutSettings.settingsFileStore = originalSettingsFileStore @@ -146,9 +137,6 @@ final class AppDelegateShortcutRoutingTests: XCTestCase { KeyboardShortcutSettings.resetShortcut(for: action) } } - #if DEBUG - AppDelegate.shared?.debugResetShortcutRoutingStateForTesting() - #endif super.tearDown() } @@ -179,18 +167,6 @@ final class AppDelegateShortcutRoutingTests: XCTestCase { #endif } - func testStopAllRecordingClearsStaleRecorderActivityCount() { - defer { KeyboardShortcutRecorderActivity.stopAllRecording() } - - KeyboardShortcutRecorderActivity.beginRecording() - KeyboardShortcutRecorderActivity.beginRecording() - XCTAssertTrue(KeyboardShortcutRecorderActivity.isAnyRecorderActive) - - KeyboardShortcutRecorderActivity.stopAllRecording() - - XCTAssertFalse(KeyboardShortcutRecorderActivity.isAnyRecorderActive) - } - func testCmdNUsesEventWindowContextWhenActiveManagerIsStale() { guard let appDelegate = AppDelegate.shared else { XCTFail("Expected AppDelegate.shared") @@ -344,9 +320,6 @@ final class AppDelegateShortcutRoutingTests: XCTestCase { fallbackPath: nil, startWatching: false ) - #if DEBUG - appDelegate.debugResetShortcutRoutingStateForTesting() - #endif window.makeKeyAndOrderFront(nil) RunLoop.main.run(until: Date(timeIntervalSinceNow: 0.05)) @@ -823,9 +796,7 @@ final class AppDelegateShortcutRoutingTests: XCTestCase { ) appDelegate.debugCreateMainWindowSourceIsNativeFullScreenOverride = nil - waitUntil(timeout: 1.0) { - !newWindow.collectionBehavior.contains(.fullScreenDisallowsTiling) - } + RunLoop.main.run(until: Date(timeIntervalSinceNow: 0.05)) XCTAssertFalse( newWindow.collectionBehavior.contains(.fullScreenDisallowsTiling), @@ -997,7 +968,7 @@ final class AppDelegateShortcutRoutingTests: XCTestCase { XCTAssertFalse(sidebarState.isVisible, "Cmd+B should toggle the Welcome window left sidebar") XCTAssertTrue(appDelegate.debugHandleCustomShortcut(event: rightSidebarEvent)) - _ = waitForCondition { fileExplorerState.isVisible } + RunLoop.main.run(until: Date(timeIntervalSinceNow: 0.05)) XCTAssertTrue(fileExplorerState.isVisible, "Cmd+Option+B should toggle the Welcome window right sidebar") #else XCTFail("debugHandleCustomShortcut is only available in DEBUG") @@ -1409,36 +1380,25 @@ final class AppDelegateShortcutRoutingTests: XCTestCase { return } - let firstWindowId = UUID() - let secondWindowId = UUID() - let firstWindow = makeRegisteredShortcutRoutingWindow(id: firstWindowId) - let secondWindow = makeRegisteredShortcutRoutingWindow(id: secondWindowId) - let firstManager = TabManager() - let secondManager = TabManager() - let firstSidebarState = SidebarState(isVisible: true) - let secondSidebarState = SidebarState(isVisible: true) + let firstWindowId = appDelegate.createMainWindow() + let secondWindowId = appDelegate.createMainWindow() - appDelegate.registerMainWindow( - firstWindow, - windowId: firstWindowId, - tabManager: firstManager, - sidebarState: firstSidebarState, - sidebarSelectionState: SidebarSelectionState() - ) - appDelegate.registerMainWindow( - secondWindow, - windowId: secondWindowId, - tabManager: secondManager, - sidebarState: secondSidebarState, - sidebarSelectionState: SidebarSelectionState() - ) defer { - closeRegisteredShortcutRoutingWindow(firstWindow, id: firstWindowId) - closeRegisteredShortcutRoutingWindow(secondWindow, id: secondWindowId) + closeWindow(withId: firstWindowId) + closeWindow(withId: secondWindowId) + } + + guard let firstManager = appDelegate.tabManagerFor(windowId: firstWindowId), + let secondManager = appDelegate.tabManagerFor(windowId: secondWindowId), + let secondWindow = window(withId: secondWindowId), + let firstWorkspace = firstManager.selectedWorkspace, + let secondWorkspace = secondManager.selectedWorkspace else { + XCTFail("Expected both window contexts to exist") + return } - let firstVisibleBefore = firstSidebarState.isVisible - let secondVisibleBefore = secondSidebarState.isVisible + let firstSurfaceCount = firstWorkspace.panels.count + let secondSurfaceCount = secondWorkspace.panels.count appDelegate.tabManager = firstManager XCTAssertTrue(appDelegate.tabManager === firstManager) @@ -1453,20 +1413,15 @@ final class AppDelegateShortcutRoutingTests: XCTestCase { return } - withTemporaryShortcut( - action: .toggleSidebar, - shortcut: StoredShortcut(key: "t", command: true, shift: false, option: false, control: false) - ) { #if DEBUG - XCTAssertTrue(appDelegate.debugHandleCustomShortcut(event: event)) + XCTAssertTrue(appDelegate.debugHandleCustomShortcut(event: event)) #else - XCTFail("debugHandleCustomShortcut is only available in DEBUG") + XCTFail("debugHandleCustomShortcut is only available in DEBUG") #endif - } RunLoop.main.run(until: Date(timeIntervalSinceNow: 0.05)) - XCTAssertEqual(appDelegate.sidebarVisibility(windowId: firstWindowId), firstVisibleBefore, "Cmd+T must not route to the stale active window") - XCTAssertEqual(appDelegate.sidebarVisibility(windowId: secondWindowId), !secondVisibleBefore, "Cmd+T should route to the event window") + XCTAssertEqual(firstWorkspace.panels.count, firstSurfaceCount, "Cmd+T must not create a surface in stale active window") + XCTAssertEqual(secondWorkspace.panels.count, secondSurfaceCount + 1, "Cmd+T should create a surface in the event window") XCTAssertTrue(appDelegate.tabManager === secondManager, "Shortcut routing should retarget active manager to event window") } @@ -1476,39 +1431,29 @@ final class AppDelegateShortcutRoutingTests: XCTestCase { return } - let firstWindowId = UUID() - let secondWindowId = UUID() - let firstWindow = makeRegisteredShortcutRoutingWindow(id: firstWindowId) - let secondWindow = makeRegisteredShortcutRoutingWindow(id: secondWindowId) - let firstManager = TabManager() - let secondManager = TabManager() - let firstSidebarState = SidebarState(isVisible: true) - let secondSidebarState = SidebarState(isVisible: true) + let firstWindowId = appDelegate.createMainWindow() + let secondWindowId = appDelegate.createMainWindow() - appDelegate.registerMainWindow( - firstWindow, - windowId: firstWindowId, - tabManager: firstManager, - sidebarState: firstSidebarState, - sidebarSelectionState: SidebarSelectionState() - ) - appDelegate.registerMainWindow( - secondWindow, - windowId: secondWindowId, - tabManager: secondManager, - sidebarState: secondSidebarState, - sidebarSelectionState: SidebarSelectionState() - ) defer { - closeRegisteredShortcutRoutingWindow(firstWindow, id: firstWindowId) - closeRegisteredShortcutRoutingWindow(secondWindow, id: secondWindowId) + closeWindow(withId: firstWindowId) + closeWindow(withId: secondWindowId) + } + + guard let firstManager = appDelegate.tabManagerFor(windowId: firstWindowId), + let secondManager = appDelegate.tabManagerFor(windowId: secondWindowId), + let firstWindow = window(withId: firstWindowId), + let secondWindow = window(withId: secondWindowId), + let firstWorkspace = firstManager.selectedWorkspace, + let secondWorkspace = secondManager.selectedWorkspace else { + XCTFail("Expected both window contexts to exist") + return } firstWindow.makeKeyAndOrderFront(nil) RunLoop.main.run(until: Date(timeIntervalSinceNow: 0.05)) - let firstVisibleBefore = firstSidebarState.isVisible - let secondVisibleBefore = secondSidebarState.isVisible + let firstSurfaceCount = firstWorkspace.panels.count + let secondSurfaceCount = secondWorkspace.panels.count appDelegate.tabManager = firstManager XCTAssertTrue(appDelegate.tabManager === firstManager) @@ -1523,21 +1468,16 @@ final class AppDelegateShortcutRoutingTests: XCTestCase { return } - withTemporaryShortcut( - action: .toggleSidebar, - shortcut: StoredShortcut(key: "d", command: true, shift: false, option: false, control: false) - ) { #if DEBUG - XCTAssertTrue(appDelegate.debugHandleCustomShortcut(event: event)) + XCTAssertTrue(appDelegate.debugHandleCustomShortcut(event: event)) #else - XCTFail("debugHandleCustomShortcut is only available in DEBUG") + XCTFail("debugHandleCustomShortcut is only available in DEBUG") #endif - } RunLoop.main.run(until: Date(timeIntervalSinceNow: 0.05)) - XCTAssertEqual(appDelegate.sidebarVisibility(windowId: firstWindowId), firstVisibleBefore, "Cmd+D must not route to the stale key window") - XCTAssertEqual(appDelegate.sidebarVisibility(windowId: secondWindowId), !secondVisibleBefore, "Cmd+D should route to the event window") - XCTAssertTrue(appDelegate.tabManager === secondManager, "Shortcut routing should keep the event window active") + XCTAssertEqual(firstWorkspace.panels.count, firstSurfaceCount, "Cmd+D must not create a split in the stale key window") + XCTAssertEqual(secondWorkspace.panels.count, secondSurfaceCount + 1, "Cmd+D should create a split in the event window") + XCTAssertTrue(appDelegate.tabManager === secondManager, "Split shortcut routing should keep the event window active") } func testCmdDPropagatesWhenSplitRightShortcutIsCleared() { @@ -1727,16 +1667,12 @@ final class AppDelegateShortcutRoutingTests: XCTestCase { } let windowId = appDelegate.createMainWindow() - defer { closeWindow(withId: windowId) } guard let targetWindow = window(withId: windowId) else { XCTFail("Expected test window") return } - targetWindow.makeKeyAndOrderFront(nil) - RunLoop.main.run(until: Date(timeIntervalSinceNow: 0.05)) appDelegate.debugCloseMainWindowConfirmationHandler = { _ in true } - defer { appDelegate.debugCloseMainWindowConfirmationHandler = nil } guard let event = makeKeyDownEvent( key: "w", @@ -1754,14 +1690,9 @@ final class AppDelegateShortcutRoutingTests: XCTestCase { XCTFail("debugHandleCustomShortcut is only available in DEBUG") #endif - waitUntil(timeout: 1.0) { - self.window(withId: windowId)?.isVisible != true - } + RunLoop.main.run(until: Date(timeIntervalSinceNow: 0.05)) - XCTAssertFalse( - self.window(withId: windowId)?.isVisible == true, - "Confirming Cmd+Ctrl+W should close the window" - ) + XCTAssertNil(self.window(withId: windowId), "Confirming Cmd+Ctrl+W should close the window") } // NOTE: This test is skipped in CI via -skip-testing in ci.yml because closing @@ -1884,16 +1815,6 @@ final class AppDelegateShortcutRoutingTests: XCTestCase { AppDelegate.installWindowResponderSwizzlesForTesting() - let windowId = appDelegate.createMainWindow() - defer { closeWindow(withId: windowId) } - - guard let mainWindow = window(withId: windowId) else { - XCTFail("Expected test main window") - return - } - mainWindow.makeKeyAndOrderFront(nil) - RunLoop.main.run(until: Date(timeIntervalSinceNow: 0.05)) - let previousMainMenu = NSApp.mainMenu let probeWindow = NSWindow( contentRect: NSRect(x: 0, y: 0, width: 320, height: 240), @@ -1901,7 +1822,6 @@ final class AppDelegateShortcutRoutingTests: XCTestCase { backing: .buffered, defer: false ) - probeWindow.isReleasedWhenClosed = false probeWindow.identifier = NSUserInterfaceItemIdentifier("cmux.browser-popup") let contentView = NSView(frame: probeWindow.contentRect(forFrameRect: probeWindow.frame)) let probeView = GhosttyCommandEquivalentProbeView(frame: NSRect(x: 0, y: 0, width: 200, height: 120)) @@ -1910,8 +1830,6 @@ final class AppDelegateShortcutRoutingTests: XCTestCase { defer { NSApp.mainMenu = previousMainMenu probeWindow.orderOut(nil) - probeWindow.close() - RunLoop.main.run(until: Date(timeIntervalSinceNow: 0.05)) } let staleMenu = NSMenu(title: "Test") @@ -3094,8 +3012,13 @@ final class AppDelegateShortcutRoutingTests: XCTestCase { return } - let window = makeCommandPaletteShortcutTestWindow() - defer { window.close() } + let windowId = appDelegate.createMainWindow() + defer { closeWindow(withId: windowId) } + + guard let window = window(withId: windowId) else { + XCTFail("Expected test window") + return + } appDelegate.setCommandPaletteVisible(true, for: window) defer { appDelegate.setCommandPaletteVisible(false, for: window) } @@ -3138,8 +3061,13 @@ final class AppDelegateShortcutRoutingTests: XCTestCase { return } - let window = makeCommandPaletteShortcutTestWindow() - defer { window.close() } + let windowId = appDelegate.createMainWindow() + defer { closeWindow(withId: windowId) } + + guard let window = window(withId: windowId) else { + XCTFail("Expected test window") + return + } appDelegate.setCommandPaletteVisible(true, for: window) defer { appDelegate.setCommandPaletteVisible(false, for: window) } @@ -3385,8 +3313,6 @@ final class AppDelegateShortcutRoutingTests: XCTestCase { XCTFail("Expected focused browser panel") return } - window.makeKeyAndOrderFront(nil) - RunLoop.main.run(until: Date(timeIntervalSinceNow: 0.05)) let field = OmnibarNativeTextField(frame: NSRect(x: 8, y: 8, width: 240, height: 24)) field.identifier = browserOmnibarTextFieldIdentifier @@ -3400,8 +3326,8 @@ final class AppDelegateShortcutRoutingTests: XCTestCase { field.removeFromSuperview() } - XCTAssertTrue(appDelegate.requestBrowserAddressBarFocus(panelId: browserPanelId)) - XCTAssertEqual(appDelegate.focusedBrowserAddressBarPanelId(), browserPanelId) + _ = browserPanel.requestAddressBarFocus() + NotificationCenter.default.post(name: .browserDidFocusAddressBar, object: browserPanelId) _ = window.makeFirstResponder(nil) XCTAssertTrue(window.firstResponder === window) @@ -3713,21 +3639,38 @@ final class AppDelegateShortcutRoutingTests: XCTestCase { return } + let windowId = appDelegate.createMainWindow() + defer { closeWindow(withId: windowId) } + + guard let window = window(withId: windowId) else { + XCTFail("Expected test window") + return + } + withTemporaryShortcut( action: .triggerFlash, shortcut: StoredShortcut(key: "/", command: true, shift: true, option: false, control: false) ) { - let event = makeKeyEvent( + guard let event = NSEvent.keyEvent( + with: .keyDown, + location: .zero, modifierFlags: [.command, .shift], + timestamp: ProcessInfo.processInfo.systemUptime, + windowNumber: window.windowNumber, + context: nil, characters: "?", charactersIgnoringModifiers: "?", + isARepeat: false, keyCode: 44 // kVK_ANSI_Slash - ) + ) else { + XCTFail("Failed to construct Cmd+Shift+/ event") + return + } #if DEBUG - XCTAssertTrue(appDelegate.debugMatchesConfiguredShortcut(event: event, action: .triggerFlash)) + XCTAssertTrue(appDelegate.debugHandleCustomShortcut(event: event)) #else - XCTFail("debugMatchesConfiguredShortcut is only available in DEBUG") + XCTFail("debugHandleCustomShortcut is only available in DEBUG") #endif } } @@ -3819,20 +3762,37 @@ final class AppDelegateShortcutRoutingTests: XCTestCase { return } + let windowId = appDelegate.createMainWindow() + defer { closeWindow(withId: windowId) } + + guard let window = window(withId: windowId) else { + XCTFail("Expected test window") + return + } + withTemporaryShortcut(action: .nextSurface) { // Non-US layouts can report "*" (or other symbols) for kVK_ANSI_RightBracket with Shift. // Shortcut matching should still allow Cmd+Shift+] via keyCode fallback. - let event = makeKeyEvent( + guard let event = NSEvent.keyEvent( + with: .keyDown, + location: .zero, modifierFlags: [.command, .shift], + timestamp: ProcessInfo.processInfo.systemUptime, + windowNumber: window.windowNumber, + context: nil, characters: "*", charactersIgnoringModifiers: "*", + isARepeat: false, keyCode: 30 // kVK_ANSI_RightBracket - ) + ) else { + XCTFail("Failed to construct non-US Cmd+Shift+] event") + return + } #if DEBUG - XCTAssertTrue(appDelegate.debugMatchesConfiguredShortcut(event: event, action: .nextSurface)) + XCTAssertTrue(appDelegate.debugHandleCustomShortcut(event: event)) #else - XCTFail("debugMatchesConfiguredShortcut is only available in DEBUG") + XCTFail("debugHandleCustomShortcut is only available in DEBUG") #endif } } @@ -4284,15 +4244,12 @@ final class AppDelegateShortcutRoutingTests: XCTestCase { XCTFail("Expected test window") return } - window.makeKeyAndOrderFront(nil) - RunLoop.main.run(until: Date(timeIntervalSinceNow: 0.05)) - let overlayHost = contentView.superview ?? contentView - let overlayContainer = NSView(frame: overlayHost.bounds) + let overlayContainer = NSView(frame: contentView.bounds) overlayContainer.identifier = commandPaletteOverlayContainerIdentifier overlayContainer.alphaValue = 1 overlayContainer.isHidden = false - overlayHost.addSubview(overlayContainer) + contentView.addSubview(overlayContainer) let fieldEditor = CommandPaletteMarkedTextFieldEditor(frame: NSRect(x: 0, y: 0, width: 200, height: 24)) fieldEditor.isFieldEditor = true @@ -4321,12 +4278,6 @@ final class AppDelegateShortcutRoutingTests: XCTestCase { } defer { NotificationCenter.default.removeObserver(moveToken) } - window.displayIfNeeded() - XCTAssertTrue( - window.makeFirstResponder(fieldEditor), - "Expected command palette field editor to own first responder" - ) - guard let downArrowEvent = makeKeyDownEvent( key: String(UnicodeScalar(NSDownArrowFunctionKey)!), modifiers: [], @@ -5383,6 +5334,18 @@ final class AppDelegateShortcutRoutingTests: XCTestCase { return } + let windowId = appDelegate.createMainWindow() + defer { closeWindow(withId: windowId) } + + guard let window = window(withId: windowId), + let manager = appDelegate.tabManagerFor(windowId: windowId), + let workspace = manager.selectedWorkspace else { + XCTFail("Expected test window context") + return + } + + let surfaceCountBefore = workspace.panels.count + // Simulate non-Latin layout where layout translation also fails (returns nil). // The ANSI keyCode fallback should still match the physical T key. appDelegate.shortcutLayoutCharacterProvider = { _, _ in nil } @@ -5390,21 +5353,30 @@ final class AppDelegateShortcutRoutingTests: XCTestCase { appDelegate.shortcutLayoutCharacterProvider = KeyboardLayout.character(forKeyCode:modifierFlags:) } - let event = makeKeyEvent( + guard let event = NSEvent.keyEvent( + with: .keyDown, + location: .zero, modifierFlags: [.command], + timestamp: ProcessInfo.processInfo.systemUptime, + windowNumber: window.windowNumber, + context: nil, characters: "", charactersIgnoringModifiers: "е", // Cyrillic е — non-ASCII + isARepeat: false, keyCode: 17 // kVK_ANSI_T - ) + ) else { + XCTFail("Failed to construct non-Latin Cmd+T event with failed layout translation") + return + } #if DEBUG - XCTAssertTrue( - appDelegate.debugMatchesConfiguredShortcut(event: event, action: .newSurface), - "Cmd+T should fall back to keyCode with non-Latin layout" - ) + XCTAssertTrue(appDelegate.debugHandleCustomShortcut(event: event), "Cmd+T should fall back to keyCode with non-Latin layout") #else - XCTFail("debugMatchesConfiguredShortcut is only available in DEBUG") + XCTFail("debugHandleCustomShortcut is only available in DEBUG") #endif + RunLoop.main.run(until: Date(timeIntervalSinceNow: 0.05)) + + XCTAssertEqual(workspace.panels.count, surfaceCountBefore + 1, "Cmd+T keyCode fallback should create a new surface") } func testWindowSendEventRepairsLostFirstResponderForFocusedTerminalTyping() { @@ -5684,144 +5656,6 @@ final class AppDelegateShortcutRoutingTests: XCTestCase { } } - func testCurrentNumberedDigitShortcutIsNotSuppressedAsStaleMenuShortcut() { - guard let appDelegate = AppDelegate.shared else { - XCTFail("Expected AppDelegate.shared") - return - } - - guard let event = makeKeyDownEvent( - key: "2", - modifiers: [.command], - keyCode: 19, - windowNumber: 0 - ) else { - XCTFail("Failed to construct Cmd+2 event") - return - } - - let remappedWorkspaceNumber = StoredShortcut( - key: "1", - command: false, - shift: false, - option: false, - control: true - ) - let currentSurfaceNumber = StoredShortcut( - key: "1", - command: true, - shift: false, - option: false, - control: false - ) - - withTemporaryShortcut(action: .selectWorkspaceByNumber, shortcut: remappedWorkspaceNumber) { - withTemporaryShortcut(action: .selectSurfaceByNumber, shortcut: currentSurfaceNumber) { - XCTAssertFalse( - appDelegate.shouldSuppressStaleCmuxMenuShortcut(event: event), - "A current numbered-digit shortcut must own Cmd+2 before stale menu suppression" - ) - } - } - } - - func testStaleCloseDefaultShortcutsSuppressMenuFallbackAfterReassignment() { - assertStaleCloseDefaultShortcutSuppressesMenuFallback( - staleAction: .closeTab, - replacementAction: .newTab, - replacementShortcut: StoredShortcut(key: "w", command: true, shift: false, option: false, control: false), - remappedStaleShortcut: StoredShortcut(key: "w", command: true, shift: false, option: true, control: false) - ) - - assertStaleCloseDefaultShortcutSuppressesMenuFallback( - staleAction: .closeWorkspace, - replacementAction: .newWindow, - replacementShortcut: StoredShortcut(key: "w", command: true, shift: true, option: false, control: false), - remappedStaleShortcut: StoredShortcut(key: "w", command: true, shift: true, option: true, control: false) - ) - - assertStaleCloseDefaultShortcutSuppressesMenuFallback( - staleAction: .closeWindow, - replacementAction: .toggleFullScreen, - replacementShortcut: StoredShortcut(key: "w", command: true, shift: false, option: false, control: true), - remappedStaleShortcut: StoredShortcut(key: "w", command: true, shift: false, option: true, control: true) - ) - } - - func testApplicationSendEventRoutesReassignedCmdWBeforeStaleCloseTabMenuEquivalent() { - guard let appDelegate = AppDelegate.shared else { - XCTFail("Expected AppDelegate.shared") - return - } - - AppDelegate.installWindowResponderSwizzlesForTesting() - - let windowId = appDelegate.createMainWindow() - guard let window = appDelegate.windowForMainWindowId(windowId), - let manager = appDelegate.tabManagerFor(windowId: windowId), - let initialSidebarVisible = appDelegate.sidebarVisibility(windowId: windowId) else { - closeWindow(withId: windowId) - XCTFail("Expected a main window context") - return - } - - let previousMainMenu = NSApp.mainMenu - let menuProbe = MenuActionProbe() - - defer { - NSApp.mainMenu = previousMainMenu - closeWindow(withId: windowId) - } - - let staleMenu = NSMenu(title: "Test") - let staleCloseItem = NSMenuItem( - title: "Close Tab", - action: #selector(MenuActionProbe.perform(_:)), - keyEquivalent: "w" - ) - staleCloseItem.keyEquivalentModifierMask = [.command] - staleCloseItem.target = menuProbe - staleMenu.addItem(staleCloseItem) - NSApp.mainMenu = staleMenu - - window.makeKeyAndOrderFront(nil) - window.displayIfNeeded() - - guard let event = makeKeyDownEvent( - key: "w", - modifiers: [.command], - keyCode: 13, - windowNumber: window.windowNumber - ) else { - XCTFail("Failed to construct Cmd+W event") - return - } - - let initialWorkspaceCount = manager.tabs.count - let remappedCloseTab = StoredShortcut(key: "w", command: true, shift: false, option: true, control: false) - let reassignedSidebarToggle = StoredShortcut(key: "w", command: true, shift: false, option: false, control: false) - - withTemporaryShortcut(action: .closeTab, shortcut: remappedCloseTab) { - withTemporaryShortcut(action: .toggleSidebar, shortcut: reassignedSidebarToggle) { - NSApp.sendEvent(event) - } - } - - RunLoop.main.run(until: Date(timeIntervalSinceNow: 0.05)) - - XCTAssertEqual(menuProbe.callCount, 0, "A stale Cmd+W Close Tab menu item must not run after Cmd+W is reassigned") - XCTAssertEqual( - manager.tabs.count, - initialWorkspaceCount, - "Plain Cmd+W must not close a tab after Close Tab is remapped away" - ) - XCTAssertEqual( - appDelegate.sidebarVisibility(windowId: windowId), - !initialSidebarVisible, - "The action currently assigned to Cmd+W should run before stale Close Tab menu fallback" - ) - } - func testApplicationSendEventSuppressesRemappedCmdDStaleMenuShortcut() { let previousMainMenu = NSApp.mainMenu let probeWindow = NSWindow( @@ -6137,19 +5971,6 @@ final class AppDelegateShortcutRoutingTests: XCTestCase { XCTFail("Expected focused terminal surface") return } - window.makeKeyAndOrderFront(nil) - window.displayIfNeeded() - terminalPanel.hostedView.setVisibleInUI(true) - terminalPanel.hostedView.setActive(true) - terminalPanel.hostedView.moveFocus() - waitUntil(timeout: 1.0) { - terminalPanel.hostedView.isSurfaceViewFirstResponder() - } - XCTAssertTrue( - terminalPanel.hostedView.isSurfaceViewFirstResponder(), - "Expected terminal surface to own first responder before Cmd+F" - ) - RunLoop.main.run(until: Date(timeIntervalSinceNow: 0.05)) appDelegate.noteTerminalKeyboardFocusIntent(workspaceId: workspace.id, panelId: terminalPanel.id, in: window) @@ -6169,9 +5990,6 @@ final class AppDelegateShortcutRoutingTests: XCTestCase { XCTFail("debugHandleCustomShortcut is only available in DEBUG") #endif - waitUntil(timeout: 1.0) { - terminalPanel.searchState != nil - } XCTAssertNotNil(terminalPanel.searchState, "Cmd+F from terminal focus should create terminal search state") } @@ -6317,38 +6135,6 @@ final class AppDelegateShortcutRoutingTests: XCTestCase { XCTAssertEqual(searchField.stringValue, "a", "Typing repair should preserve the first key in the search field") } - private func makeRegisteredShortcutRoutingWindow(id: UUID) -> NSWindow { - let window = NSWindow( - contentRect: NSRect(x: 0, y: 0, width: 320, height: 240), - styleMask: [.titled, .closable, .resizable], - backing: .buffered, - defer: false - ) - window.isReleasedWhenClosed = false - window.identifier = NSUserInterfaceItemIdentifier("cmux.main.\(id.uuidString)") - return window - } - - private func closeRegisteredShortcutRoutingWindow(_ window: NSWindow, id: UUID) { - AppDelegate.shared?.unregisterMainWindowContextForTesting(windowId: id) - window.orderOut(nil) - window.close() - RunLoop.main.run(until: Date(timeIntervalSinceNow: 0.05)) - } - - @discardableResult - private func waitForCondition( - timeout: TimeInterval = 1.0, - interval: TimeInterval = 0.01, - _ condition: () -> Bool - ) -> Bool { - let deadline = Date(timeIntervalSinceNow: timeout) - while !condition(), Date() < deadline { - RunLoop.main.run(until: Date(timeIntervalSinceNow: interval)) - } - return condition() - } - private func makeKeyDownEvent( key: String, modifiers: NSEvent.ModifierFlags, @@ -6418,60 +6204,11 @@ final class AppDelegateShortcutRoutingTests: XCTestCase { } else { KeyboardShortcutSettings.resetShortcut(for: action) } - #if DEBUG - AppDelegate.shared?.debugResetShortcutRoutingStateForTesting() - #endif } KeyboardShortcutSettings.setShortcut(shortcut ?? action.defaultShortcut, for: action) - #if DEBUG - AppDelegate.shared?.debugResetShortcutRoutingStateForTesting() - #endif body() } - private func makeCommandPaletteShortcutTestWindow() -> NSWindow { - let windowId = UUID() - let window = NSWindow( - contentRect: NSRect(x: 0, y: 0, width: 160, height: 120), - styleMask: [.titled], - backing: .buffered, - defer: false - ) - window.isReleasedWhenClosed = false - window.identifier = NSUserInterfaceItemIdentifier("cmux.main.\(windowId.uuidString)") - window.contentView = NSView(frame: NSRect(x: 0, y: 0, width: 160, height: 120)) - return window - } - - private func assertStaleCloseDefaultShortcutSuppressesMenuFallback( - staleAction: KeyboardShortcutSettings.Action, - replacementAction: KeyboardShortcutSettings.Action, - replacementShortcut: StoredShortcut, - remappedStaleShortcut: StoredShortcut, - file: StaticString = #filePath, - line: UInt = #line - ) { - guard let appDelegate = AppDelegate.shared else { - XCTFail("Expected AppDelegate.shared", file: file, line: line) - return - } - guard let event = makeKeyDownEvent(shortcut: replacementShortcut, windowNumber: 0) else { - XCTFail("Failed to construct reassigned close-default shortcut event", file: file, line: line) - return - } - - withTemporaryShortcut(action: staleAction, shortcut: remappedStaleShortcut) { - withTemporaryShortcut(action: replacementAction, shortcut: replacementShortcut) { - XCTAssertTrue( - appDelegate.shouldSuppressStaleCmuxMenuShortcut(event: event), - "\(staleAction.rawValue) should suppress its stale default menu fallback after that key is reassigned", - file: file, - line: line - ) - } - } - } - private func assertEscapeKeyUpIsConsumedAfterCommandPaletteOpenRequest( _ openRequest: (_ appDelegate: AppDelegate, _ window: NSWindow) -> Void, file: StaticString = #filePath, @@ -6584,21 +6321,10 @@ final class AppDelegateShortcutRoutingTests: XCTestCase { private func closeWindow(withId windowId: UUID) { guard let window = window(withId: windowId) else { return } - let appDelegate = AppDelegate.shared - let originalConfirmationHandler = appDelegate?.debugCloseMainWindowConfirmationHandler - appDelegate?.debugCloseMainWindowConfirmationHandler = { _ in true } - defer { appDelegate?.debugCloseMainWindowConfirmationHandler = originalConfirmationHandler } window.performClose(nil) RunLoop.main.run(until: Date(timeIntervalSinceNow: 0.05)) } - private func waitUntil(timeout: TimeInterval, condition: () -> Bool) { - let deadline = Date(timeIntervalSinceNow: timeout) - while !condition(), Date() < deadline { - RunLoop.main.run(until: Date(timeIntervalSinceNow: 0.01)) - } - } - private func restoreDefaultsValue(_ value: Any?, forKey key: String, defaults: UserDefaults) { if let value { defaults.set(value, forKey: key) diff --git a/cmuxTests/AppearanceSettingsTests.swift b/cmuxTests/AppearanceSettingsTests.swift index a9bc98ab29ad..ad88334dc68c 100644 --- a/cmuxTests/AppearanceSettingsTests.swift +++ b/cmuxTests/AppearanceSettingsTests.swift @@ -113,9 +113,6 @@ final class AppearanceSettingsTests: XCTestCase { XCTAssertTrue(soft) events.append("reload:\(source)") }, - applySurfaceColorScheme: { - events.append("color-scheme") - }, refreshHostBackground: { events.append("host-background") }, @@ -125,7 +122,6 @@ final class AppearanceSettingsTests: XCTestCase { ) XCTAssertEqual(events, [ - "color-scheme", "reload:appearanceSync:test", "host-background", "force-refresh:\(GhosttySurfaceConfigurationRefresh.forceRefreshReason)" @@ -141,9 +137,6 @@ final class AppearanceSettingsTests: XCTestCase { reloadSurfaceConfiguration: { _, _, _ in events.append("reload") }, - applySurfaceColorScheme: { - events.append("color-scheme") - }, refreshHostBackground: { events.append("host-background") }, @@ -158,65 +151,6 @@ final class AppearanceSettingsTests: XCTestCase { ]) } - func testAppConfigReloadRefreshAppliesSurfaceColorSchemeForPreviewReload() throws { - let fakeSurface = try XCTUnwrap(UnsafeMutableRawPointer(bitPattern: 0x3852)) - var events: [String] = [] - - GhosttySurfaceConfigurationRefresh.applyAfterAppConfigReload( - to: fakeSurface, - source: GhosttySurfaceConfigurationRefresh.cmuxThemeReloadPreviewSource, - reloadSurfaceConfiguration: { _, soft, source in - XCTAssertTrue(soft) - events.append("reload:\(source)") - }, - applySurfaceColorScheme: { - events.append("color-scheme") - }, - refreshHostBackground: { - events.append("host-background") - }, - forceRefresh: { reason in - events.append("force-refresh:\(reason)") - } - ) - - XCTAssertEqual(events, [ - "color-scheme", - "reload:\(GhosttySurfaceConfigurationRefresh.cmuxThemeReloadPreviewSource)", - "host-background", - "force-refresh:\(GhosttySurfaceConfigurationRefresh.forceRefreshReason)" - ]) - } - - func testCmuxThemeFinalReloadUsesFinalSource() { - XCTAssertEqual( - GhosttySurfaceConfigurationRefresh.cmuxThemeReloadSource(phase: "final"), - GhosttySurfaceConfigurationRefresh.cmuxThemeReloadFinalSource - ) - } - - func testCmuxThemePreviewReloadIsDebounced() { - XCTAssertEqual( - GhosttySurfaceConfigurationRefresh.cmuxThemeReloadSource(phase: "preview"), - GhosttySurfaceConfigurationRefresh.cmuxThemeReloadPreviewSource - ) - XCTAssertTrue( - GhosttySurfaceConfigurationRefresh.shouldDebounceCmuxThemeReload( - source: GhosttySurfaceConfigurationRefresh.cmuxThemeReloadPreviewSource - ) - ) - XCTAssertTrue( - GhosttySurfaceConfigurationRefresh.shouldDebounceCmuxThemeReload( - source: GhosttySurfaceConfigurationRefresh.cmuxThemeReloadLegacySource - ) - ) - XCTAssertFalse( - GhosttySurfaceConfigurationRefresh.shouldDebounceCmuxThemeReload( - source: GhosttySurfaceConfigurationRefresh.cmuxThemeReloadFinalSource - ) - ) - } - func testResolvedModeDefaultsToSystemWhenUnset() { let suiteName = "AppearanceSettingsTests.Default.\(UUID().uuidString)" guard let defaults = UserDefaults(suiteName: suiteName) else { @@ -375,70 +309,6 @@ final class AppearanceSettingsTests: XCTestCase { XCTAssertTrue(synchronizedAppearanceWasCleared) } - func testDefaultsObserverAppliesLiveAppearanceWhenStoredModeChanges() { - let suiteName = "AppearanceSettingsTests.DefaultsObserver.\(UUID().uuidString)" - guard let defaults = UserDefaults(suiteName: suiteName) else { - XCTFail("Failed to create isolated UserDefaults suite") - return - } - defer { defaults.removePersistentDomain(forName: suiteName) } - - let notificationCenter = NotificationCenter() - var appliedAppearanceName: NSAppearance.Name? - var synchronizedAppearanceName: NSAppearance.Name? - var synchronizedSource: String? - let liveEnvironment = AppearanceSettings.LiveApplyEnvironment( - setApplicationAppearance: { appearance in - appliedAppearanceName = appearance?.bestMatch(from: [.darkAqua, .aqua]) - }, - synchronizeTerminalThemeWithAppearance: { appearance, source in - synchronizedAppearanceName = appearance?.bestMatch(from: [.darkAqua, .aqua]) - synchronizedSource = source - }, - systemAppearance: { - XCTFail("Dark mode should not resolve system appearance") - return nil - } - ) - let observer = AppearanceSettingsUserDefaultsObserver( - environment: .init( - addDefaultsObserver: { handler in - notificationCenter.addObserver( - forName: UserDefaults.didChangeNotification, - object: nil, - queue: nil - ) { _ in - handler() - } - }, - removeObserver: { observer in - notificationCenter.removeObserver(observer) - }, - currentRawValue: { - defaults.string(forKey: AppearanceSettings.appearanceModeKey) - }, - applyStoredMode: { rawValue, source in - AppearanceSettings.applyStoredMode( - rawValue: rawValue, - defaults: defaults, - source: source, - environment: liveEnvironment - ) - } - ), - source: "test.defaultsObserver" - ) - - defaults.set(AppearanceMode.system.rawValue, forKey: AppearanceSettings.appearanceModeKey) - observer.startObserving() - defaults.set(AppearanceMode.dark.rawValue, forKey: AppearanceSettings.appearanceModeKey) - notificationCenter.post(name: UserDefaults.didChangeNotification, object: defaults) - - XCTAssertEqual(appliedAppearanceName, .darkAqua) - XCTAssertEqual(synchronizedAppearanceName, .darkAqua) - XCTAssertEqual(synchronizedSource, "test.defaultsObserver") - } - private func withTemporaryAppearanceDefaults( appearanceMode: String, appleInterfaceStyle: String?, diff --git a/cmuxTests/BrowserConfigTests.swift b/cmuxTests/BrowserConfigTests.swift index c00288a42c7b..c56968122e6a 100644 --- a/cmuxTests/BrowserConfigTests.swift +++ b/cmuxTests/BrowserConfigTests.swift @@ -7,7 +7,6 @@ import WebKit import ObjectiveC.runtime import Bonsplit import UserNotifications -import Network #if canImport(cmux_DEV) @testable import cmux_DEV @@ -2439,149 +2438,6 @@ final class BrowserJavaScriptDialogDelegateTests: XCTestCase { @MainActor final class BrowserSessionHistoryRestoreTests: XCTestCase { - private final class ProvisionalNavigationRaceServer { - enum ServerError: Error { - case listenerDidNotBecomeReady - case listenerPortUnavailable - } - - private static let queueKey = DispatchSpecificKey() - private let listener: NWListener - private let queue = DispatchQueue(label: "cmux.browser.provisional-navigation-race-server") - private let lock = NSLock() - private var heldBConnections: [NWConnection] = [] - private var receivedBRequest = false - private(set) var port: UInt16 = 0 - - init() throws { - let parameters = NWParameters.tcp - parameters.requiredLocalEndpoint = .hostPort( - host: NWEndpoint.Host("127.0.0.1"), - port: .any - ) - listener = try NWListener(using: parameters) - queue.setSpecific(key: Self.queueKey, value: ()) - - let ready = DispatchSemaphore(value: 0) - listener.stateUpdateHandler = { state in - if case .ready = state { - ready.signal() - } - } - listener.newConnectionHandler = { [weak self] connection in - self?.handle(connection) - } - listener.start(queue: queue) - - guard ready.wait(timeout: .now() + 2.0) == .success else { - throw ServerError.listenerDidNotBecomeReady - } - guard let port = listener.port?.rawValue else { - throw ServerError.listenerPortUnavailable - } - self.port = port - } - - var didReceiveBRequest: Bool { - lock.lock() - defer { lock.unlock() } - return receivedBRequest - } - - func url(path: String) -> URL { - URL(string: "http://127.0.0.1:\(port)\(path)")! - } - - func releaseHeldBResponses() -> Int { - if DispatchQueue.getSpecific(key: Self.queueKey) != nil { - return releaseHeldBResponsesOnQueue() - } - return queue.sync { - releaseHeldBResponsesOnQueue() - } - } - - private func releaseHeldBResponsesOnQueue() -> Int { - let connections: [NWConnection] - lock.lock() - connections = heldBConnections - heldBConnections.removeAll() - lock.unlock() - - for connection in connections { - sendPage("B", on: connection) - } - return connections.count - } - - func stop() { - listener.cancel() - _ = releaseHeldBResponses() - } - - private func handle(_ connection: NWConnection) { - connection.start(queue: queue) - receiveRequest(on: connection) - } - - private func receiveRequest(on connection: NWConnection, buffer: Data = Data()) { - connection.receive(minimumIncompleteLength: 1, maximumLength: 4096) { [weak self] data, _, _, error in - guard let self else { return } - if error != nil { - connection.cancel() - return - } - - var nextBuffer = buffer - if let data { - nextBuffer.append(data) - } - - guard let requestText = String(data: nextBuffer, encoding: .utf8), - requestText.contains("\r\n\r\n") else { - self.receiveRequest(on: connection, buffer: nextBuffer) - return - } - - let requestLine = requestText.split(separator: "\r\n", maxSplits: 1).first ?? "" - let path = requestLine.split(separator: " ").dropFirst().first.map(String.init) ?? "/" - if path == "/b" { - self.lock.lock() - self.receivedBRequest = true - self.heldBConnections.append(connection) - self.lock.unlock() - return - } - - self.sendPage("A", on: connection) - } - } - - private func sendPage(_ marker: String, on connection: NWConnection) { - let body = """ - - - Race \(marker) - - -
Race \(marker)
- - - """ - let response = """ - HTTP/1.1 200 OK\r - Content-Type: text/html; charset=utf-8\r - Content-Length: \(body.utf8.count)\r - Connection: close\r - \r - \(body) - """ - connection.send(content: Data(response.utf8), completion: .contentProcessed { _ in - connection.cancel() - }) - } - } - private func writeBrowserFixturePage( at url: URL, title: String, @@ -2603,29 +2459,6 @@ final class BrowserSessionHistoryRestoreTests: XCTestCase { } } - private func waitUntil( - _ description: String, - timeout: TimeInterval = 5.0, - file: StaticString = #filePath, - line: UInt = #line, - predicate: () -> Bool - ) throws { - let deadline = Date().addingTimeInterval(timeout) - while Date() < deadline { - if predicate() { - return - } - RunLoop.current.run(mode: .default, before: Date().addingTimeInterval(0.01)) - } - - XCTFail("Timed out waiting for \(description)", file: file, line: line) - throw BrowserTestTimeout(description: description) - } - - private struct BrowserTestTimeout: Error, CustomStringConvertible { - let description: String - } - private func waitForBrowserPanel( _ panel: BrowserPanel, url: URL, @@ -2752,46 +2585,6 @@ final class BrowserSessionHistoryRestoreTests: XCTestCase { waitForBrowserPanel(panel, url: pageA) } - func testBackDuringProvisionalNavigationDoesNotDesyncPublishedURLFromRenderedPage() throws { - let server = try ProvisionalNavigationRaceServer() - defer { server.stop() } - - let pageA = server.url(path: "/a") - let pageB = server.url(path: "/b") - let panel = BrowserPanel(workspaceId: UUID(), initialURL: pageA) - defer { panel.close() } - - waitForBrowserPanel(panel, url: pageA) - XCTAssertEqual(panel.pageTitle, "Race A") - - panel.navigate(to: pageB) - try waitUntil("server to receive provisional page B request") { - server.didReceiveBRequest - } - try waitUntil("browser back availability during provisional page B navigation") { - panel.canGoBack && panel.webView.isLoading - } - XCTAssertFalse(panel.canGoForward) - - panel.goBack() - try waitUntil("back action to expose page B as forward history before it can commit") { - panel.currentURL?.path == pageA.path && !panel.webView.isLoading - && panel.canGoForward - } - - let releasedBResponseCount = server.releaseHeldBResponses() - XCTAssertGreaterThan(releasedBResponseCount, 0) - try waitUntil("browser to remain on page A after held page B response is released") { - !panel.webView.isLoading && - panel.pageTitle == "Race A" && - panel.currentURL?.path == pageA.path - } - - let publishedURL = try XCTUnwrap(panel.currentURL) - XCTAssertEqual(publishedURL.path, pageA.path) - XCTAssertEqual(panel.pageTitle, "Race A") - } - func testWebViewReplacementAfterProcessTerminationUpdatesInstanceIdentity() { let panel = BrowserPanel( workspaceId: UUID(), @@ -3896,14 +3689,7 @@ final class BrowserDeveloperToolsVisibilityPersistenceTests: XCTestCase { backing: .buffered, defer: false ) - window.isReleasedWhenClosed = false - defer { - panel.closeDeveloperToolsForTeardown() - panel.webView.cmuxSetUnitTestInspector(nil) - panel.webView.removeFromSuperview() - window.close() - RunLoop.current.run(until: Date().addingTimeInterval(0.05)) - } + defer { window.orderOut(nil) } guard let contentView = window.contentView else { XCTFail("Expected content view") return @@ -3913,7 +3699,6 @@ final class BrowserDeveloperToolsVisibilityPersistenceTests: XCTestCase { visibleHosting.frame = contentView.bounds visibleHosting.autoresizingMask = [.width, .height] contentView.addSubview(visibleHosting) - defer { visibleHosting.removeFromSuperview() } window.makeKeyAndOrderFront(nil) window.displayIfNeeded() contentView.layoutSubtreeIfNeeded() @@ -3934,7 +3719,6 @@ final class BrowserDeveloperToolsVisibilityPersistenceTests: XCTestCase { ) inspectorView.autoresizingMask = [.width] visibleSlot.addSubview(inspectorView) - defer { inspectorView.removeFromSuperview() } panel.webView.frame = NSRect( x: 0, y: inspectorView.frame.maxY, @@ -3948,7 +3732,6 @@ final class BrowserDeveloperToolsVisibilityPersistenceTests: XCTestCase { offWindowHosting.frame = detachedRoot.bounds offWindowHosting.autoresizingMask = [.width, .height] detachedRoot.addSubview(offWindowHosting) - defer { offWindowHosting.removeFromSuperview() } detachedRoot.layoutSubtreeIfNeeded() offWindowHosting.layoutSubtreeIfNeeded() RunLoop.current.run(until: Date().addingTimeInterval(0.05)) diff --git a/cmuxTests/CJKIMEInputTests.swift b/cmuxTests/CJKIMEInputTests.swift index 478830fa3b66..13944e650f2c 100644 --- a/cmuxTests/CJKIMEInputTests.swift +++ b/cmuxTests/CJKIMEInputTests.swift @@ -2126,131 +2126,6 @@ final class GhosttyKeyEquivalentRegressionTests: XCTestCase { } } -@MainActor -final class DeadKeyCompositionRegressionTests: XCTestCase { - func testOptionTildeDeadKeyUsesOriginalEventBeforeAltTranslation() { - _ = NSApplication.shared - - let surface = TerminalSurface( - tabId: UUID(), - context: GHOSTTY_SURFACE_CONTEXT_SPLIT, - configTemplate: nil, - workingDirectory: nil - ) - let hostedView = surface.hostedView - - let window = NSWindow( - contentRect: NSRect(x: 0, y: 0, width: 360, height: 240), - styleMask: [.titled, .closable], - backing: .buffered, - defer: false - ) - let previousInterpretHook = cjkIMEInterpretKeyEventsHook - defer { - GhosttyNSView.debugGhosttySurfaceKeyEventObserver = nil - cjkIMEInterpretKeyEventsHook = previousInterpretHook - window.orderOut(nil) - } - - guard let contentView = window.contentView else { - XCTFail("Expected content view") - return - } - hostedView.frame = contentView.bounds - hostedView.autoresizingMask = [.width, .height] - contentView.addSubview(hostedView) - - window.makeKeyAndOrderFront(nil) - window.displayIfNeeded() - contentView.layoutSubtreeIfNeeded() - hostedView.setVisibleInUI(true) - hostedView.setActive(true) - RunLoop.current.run(until: Date().addingTimeInterval(0.05)) - - guard let view = findGhosttyNSView(in: hostedView) else { - XCTFail("Expected hosted GhosttyNSView") - return - } - - var deadKeyPrimed = false - installCJKIMEInterpretKeyEventsSwizzle() - cjkIMEInterpretKeyEventsHook = { candidateView, events in - guard candidateView === view, - let event = events.first else { return false } - - let flags = event.modifierFlags.intersection(.deviceIndependentFlagsMask) - if event.keyCode == 45, - flags.contains(.option), - !flags.contains(.command), - !flags.contains(.control), - (event.characters ?? "").isEmpty { - deadKeyPrimed = true - candidateView.setMarkedText( - "~", - selectedRange: NSRange(location: 1, length: 0), - replacementRange: NSRange(location: NSNotFound, length: 0) - ) - return true - } - - if event.keyCode == 0, deadKeyPrimed, candidateView.hasMarkedText() { - candidateView.insertText("ã", replacementRange: NSRange(location: NSNotFound, length: 0)) - return true - } - - return false - } - - var pressedText: [String] = [] - var pressedKeycodes: [UInt32] = [] - GhosttyNSView.debugGhosttySurfaceKeyEventObserver = { keyEvent in - guard keyEvent.action == GHOSTTY_ACTION_PRESS else { return } - if let text = keyEvent.text { - pressedText.append(String(cString: text)) - } else { - pressedKeycodes.append(keyEvent.keycode) - } - } - - guard let optionN = NSEvent.keyEvent( - with: .keyDown, - location: .zero, - modifierFlags: [.option], - timestamp: ProcessInfo.processInfo.systemUptime, - windowNumber: window.windowNumber, - context: nil, - characters: "", - charactersIgnoringModifiers: "n", - isARepeat: false, - keyCode: 45 - ), let aKey = NSEvent.keyEvent( - with: .keyDown, - location: .zero, - modifierFlags: [], - timestamp: ProcessInfo.processInfo.systemUptime + 0.01, - windowNumber: window.windowNumber, - context: nil, - characters: "a", - charactersIgnoringModifiers: "a", - isARepeat: false, - keyCode: 0 - ) else { - XCTFail("Failed to create dead-key events") - return - } - - window.makeFirstResponder(view) - withExtendedLifetime(surface) { - view.keyDown(with: optionN) - view.keyDown(with: aKey) - } - - XCTAssertEqual(pressedText, ["ã"]) - XCTAssertEqual(pressedKeycodes, [], "Dead-key composition should not leak raw Alt-N key events") - XCTAssertFalse(view.hasMarkedText(), "Composition should clear after the composed character commits") - } -} - @MainActor final class GhosttyOptionDeleteRegressionTests: XCTestCase { func testOptionDeletePreservesAltAsModifierForWordDelete() { diff --git a/cmuxTests/CLIGenericHookPersistenceTests.swift b/cmuxTests/CLIGenericHookPersistenceTests.swift index bd072b235d1b..8d4a095e5c71 100644 --- a/cmuxTests/CLIGenericHookPersistenceTests.swift +++ b/cmuxTests/CLIGenericHookPersistenceTests.swift @@ -71,34 +71,6 @@ extension CLINotifyProcessIntegrationRegressionTests { ], expectedEnvironment: ["GEMINI_CLI_HOME": "/tmp/gemini home"] ), - GenericHookPersistenceScenario( - agent: "antigravity", - subcommand: "session-start", - sessionId: "antigravity-conversation-123", - executable: "/Users/example/.local/bin/agy", - launchArguments: [ - "/Users/example/.local/bin/agy", - "--conversation", - "old-conversation", - "--sandbox", - "danger-full-access", - "--add-dir", - "/tmp/extra repo", - "initial prompt should not persist" - ], - extraEnvironment: [ - "GEMINI_CLI_HOME": "/tmp/gemini home", - "GEMINI_API_KEY": "secret" - ], - expectedArguments: [ - "/Users/example/.local/bin/agy", - "--sandbox", - "danger-full-access", - "--add-dir", - "/tmp/extra repo" - ], - expectedEnvironment: ["GEMINI_CLI_HOME": "/tmp/gemini home"] - ), GenericHookPersistenceScenario( agent: "grok", subcommand: "session-start", @@ -256,446 +228,6 @@ extension CLINotifyProcessIntegrationRegressionTests { } } - func testAntigravityStopAndNotificationsUseGenericNotificationPath() throws { - let cliPath = try bundledCLIPath() - let socketPath = makeSocketPath("antigravity-notification") - let listenerFD = try bindUnixSocket(at: socketPath) - let state = MockSocketServerState() - let root = FileManager.default.temporaryDirectory - .appendingPathComponent("cmux-antigravity-notification-\(UUID().uuidString)", isDirectory: true) - let workspaceId = "11111111-1111-1111-1111-111111111111" - let surfaceId = "22222222-2222-2222-2222-222222222222" - let sessionId = "antigravity-conversation-123" - - try FileManager.default.createDirectory(at: root, withIntermediateDirectories: true) - defer { - Darwin.close(listenerFD) - unlink(socketPath) - try? FileManager.default.removeItem(at: root) - } - - let environment: [String: String] = [ - "HOME": root.path, - "PATH": "/usr/bin:/bin:/usr/sbin:/sbin", - "PWD": root.path, - "CMUX_SOCKET_PATH": socketPath, - "CMUX_WORKSPACE_ID": workspaceId, - "CMUX_SURFACE_ID": surfaceId, - "CMUX_AGENT_HOOK_STATE_DIR": root.path, - "CMUX_CLI_SENTRY_DISABLED": "1", - ] - - func runAntigravityHook(_ subcommand: String, input: String) -> ProcessRunResult { - let serverHandled = startMockServer(listenerFD: listenerFD, state: state) { line in - guard let payload = self.jsonObject(line) else { - return "OK" - } - guard let id = payload["id"] as? String, let method = payload["method"] as? String else { - return self.malformedRequestResponse(id: payload["id"] as? String, raw: line) - } - switch method { - case "surface.list": - return self.surfaceListResponse(id: id, surfaceId: surfaceId) - case "feed.push": - return self.v2Response(id: id, ok: true, result: [:]) - default: - return self.v2Response(id: id, ok: false, error: ["code": "unrecognized_method", "message": "unexpected method: \(method)"]) - } - } - let result = runProcess( - executablePath: cliPath, - arguments: ["hooks", "antigravity", subcommand], - environment: environment, - standardInput: input, - timeout: 5 - ) - wait(for: [serverHandled], timeout: 5) - return result - } - - let start = runAntigravityHook( - "session-start", - input: #"{"session_id":"\#(sessionId)","cwd":"\#(root.path)","hook_event_name":"SessionStart"}"# - ) - XCTAssertFalse(start.timedOut, start.stderr) - XCTAssertEqual(start.status, 0, start.stderr) - XCTAssertEqual(start.stdout, "{}\n") - - let backgroundMessage = "Antigravity is waiting on background work" - let backgroundStopCommandStart = state.commands.count - let backgroundStop = runAntigravityHook( - "stop", - input: #"{"session_id":"\#(sessionId)","cwd":"\#(root.path)","hook_event_name":"Stop","last_assistant_message":"\#(backgroundMessage)","fullyIdle":false}"# - ) - XCTAssertFalse(backgroundStop.timedOut, backgroundStop.stderr) - XCTAssertEqual(backgroundStop.status, 0, backgroundStop.stderr) - XCTAssertEqual(backgroundStop.stdout, "{}\n") - - let backgroundStopCommands = Array(state.commands.dropFirst(backgroundStopCommandStart)) - XCTAssertFalse( - backgroundStopCommands.contains { $0.hasPrefix("notify_target_async ") }, - "Antigravity Stop with active background work must not publish idle notifications, saw \(backgroundStopCommands)" - ) - XCTAssertTrue( - backgroundStopCommands.contains { $0.contains("set_status antigravity Running") }, - "Antigravity Stop with active background work should keep the session running, saw \(backgroundStopCommands)" - ) - XCTAssertFalse( - backgroundStopCommands.contains { $0.contains("set_status antigravity Idle") }, - "Antigravity Stop with active background work must not mark idle, saw \(backgroundStopCommands)" - ) - - let backgroundDuplicateCommandStart = state.commands.count - let backgroundDuplicate = runAntigravityHook( - "notification", - input: #"{"session_id":"\#(sessionId)","cwd":"\#(root.path)","hook_event_name":"Notification","message":"Turn complete in 1.0s.","fullyIdle":false}"# - ) - XCTAssertFalse(backgroundDuplicate.timedOut, backgroundDuplicate.stderr) - XCTAssertEqual(backgroundDuplicate.status, 0, backgroundDuplicate.stderr) - XCTAssertEqual(backgroundDuplicate.stdout, "{}\n") - - let backgroundDuplicateCommands = Array(state.commands.dropFirst(backgroundDuplicateCommandStart)) - XCTAssertFalse( - backgroundDuplicateCommands.contains { $0.hasPrefix("notify_target_async ") }, - "Idle-classified Antigravity notifications must not double-notify while background work is active, saw \(backgroundDuplicateCommands)" - ) - XCTAssertFalse( - backgroundDuplicateCommands.contains { $0.contains("set_status antigravity Idle") }, - "Idle-classified Antigravity notifications must not override the running status while background work is active, saw \(backgroundDuplicateCommands)" - ) - - let missingFullyIdleSessionId = "\(sessionId)-missing-fully-idle" - let missingFullyIdleStart = runAntigravityHook( - "session-start", - input: #"{"session_id":"\#(missingFullyIdleSessionId)","cwd":"\#(root.path)","hook_event_name":"SessionStart"}"# - ) - XCTAssertFalse(missingFullyIdleStart.timedOut, missingFullyIdleStart.stderr) - XCTAssertEqual(missingFullyIdleStart.status, 0, missingFullyIdleStart.stderr) - XCTAssertEqual(missingFullyIdleStart.stdout, "{}\n") - - let missingFullyIdleBackgroundStop = runAntigravityHook( - "stop", - input: #"{"session_id":"\#(missingFullyIdleSessionId)","cwd":"\#(root.path)","hook_event_name":"Stop","last_assistant_message":"Background work still running","fullyIdle":false}"# - ) - XCTAssertFalse(missingFullyIdleBackgroundStop.timedOut, missingFullyIdleBackgroundStop.stderr) - XCTAssertEqual(missingFullyIdleBackgroundStop.status, 0, missingFullyIdleBackgroundStop.stderr) - XCTAssertEqual(missingFullyIdleBackgroundStop.stdout, "{}\n") - - let missingFullyIdleNotificationCommandStart = state.commands.count - let missingFullyIdleNotification = runAntigravityHook( - "notification", - input: #"{"session_id":"\#(missingFullyIdleSessionId)","cwd":"\#(root.path)","hook_event_name":"Notification","message":"Turn complete in 2.0s."}"# - ) - XCTAssertFalse(missingFullyIdleNotification.timedOut, missingFullyIdleNotification.stderr) - XCTAssertEqual(missingFullyIdleNotification.status, 0, missingFullyIdleNotification.stderr) - XCTAssertEqual(missingFullyIdleNotification.stdout, "{}\n") - - let missingFullyIdleNotificationCommands = Array(state.commands.dropFirst(missingFullyIdleNotificationCommandStart)) - XCTAssertTrue( - missingFullyIdleNotificationCommands.contains { $0.hasPrefix("notify_target_async ") }, - "Antigravity idle notifications without fullyIdle must publish instead of staying suppressed, saw \(missingFullyIdleNotificationCommands)" - ) - XCTAssertTrue( - missingFullyIdleNotificationCommands.contains { $0.contains("set_status antigravity Idle") }, - "Antigravity idle notifications without fullyIdle should mark idle, saw \(missingFullyIdleNotificationCommands)" - ) - - let stopMessage = "Antigravity finished updating docs" - let stopCommandStart = state.commands.count - let stop = runAntigravityHook( - "stop", - input: #"{"session_id":"\#(sessionId)","cwd":"\#(root.path)","hook_event_name":"AfterAgent","last_assistant_message":"\#(stopMessage)"}"# - ) - XCTAssertFalse(stop.timedOut, stop.stderr) - XCTAssertEqual(stop.status, 0, stop.stderr) - XCTAssertEqual(stop.stdout, "{}\n") - - let stopCommands = Array(state.commands.dropFirst(stopCommandStart)) - XCTAssertTrue( - stopCommands.contains { - $0.contains("notify_target_async \(workspaceId) \(surfaceId) Antigravity|Completed in ") - && $0.contains(stopMessage) - }, - "Expected Antigravity stop to publish a turn-completion notification, saw \(stopCommands)" - ) - XCTAssertTrue( - stopCommands.contains { $0.contains("set_status antigravity Idle") }, - "Expected Antigravity stop to leave the session idle, saw \(stopCommands)" - ) - - let sessionEndCommandStart = state.commands.count - let sessionEnd = runAntigravityHook( - "session-end", - input: #"{"session_id":"\#(sessionId)","cwd":"\#(root.path)","hook_event_name":"SessionEnd"}"# - ) - XCTAssertFalse(sessionEnd.timedOut, sessionEnd.stderr) - XCTAssertEqual(sessionEnd.status, 0, sessionEnd.stderr) - XCTAssertEqual(sessionEnd.stdout, "{}\n") - - let sessionEndCommands = Array(state.commands.dropFirst(sessionEndCommandStart)) - XCTAssertTrue( - sessionEndCommands.contains { $0.contains("feed.push") }, - "Expected Antigravity SessionEnd to emit feed telemetry, saw \(sessionEndCommands)" - ) - XCTAssertFalse( - sessionEndCommands.contains { $0.hasPrefix("clear_agent_pid antigravity.") }, - "Antigravity SessionEnd is a turn boundary and must not clear saved routing, saw \(sessionEndCommands)" - ) - - let duplicateCompletionCommandStart = state.commands.count - let duplicateCompletion = runAntigravityHook( - "notification", - input: #"{"session_id":"\#(sessionId)","cwd":"\#(root.path)","hook_event_name":"Notification","message":"Turn complete in 2.0s."}"# - ) - XCTAssertFalse(duplicateCompletion.timedOut, duplicateCompletion.stderr) - XCTAssertEqual(duplicateCompletion.status, 0, duplicateCompletion.stderr) - XCTAssertEqual(duplicateCompletion.stdout, "{}\n") - - let duplicateCompletionCommands = Array(state.commands.dropFirst(duplicateCompletionCommandStart)) - XCTAssertFalse( - duplicateCompletionCommands.contains { $0.hasPrefix("notify_target_async ") }, - "Antigravity turn-completion notification must not double-notify after stop already did, saw \(duplicateCompletionCommands)" - ) - - let permissionMessage = "Allow shell command?" - let permissionCommandStart = state.commands.count - let permission = runAntigravityHook( - "notification", - input: #"{"session_id":"\#(sessionId)","cwd":"\#(root.path)","hook_event_name":"Notification","reason":"permission_prompt","message":"\#(permissionMessage)"}"# - ) - XCTAssertFalse(permission.timedOut, permission.stderr) - XCTAssertEqual(permission.status, 0, permission.stderr) - XCTAssertEqual(permission.stdout, "{}\n") - - let permissionCommands = Array(state.commands.dropFirst(permissionCommandStart)) - XCTAssertTrue( - permissionCommands.contains { - $0.contains("notify_target_async \(workspaceId) \(surfaceId) Antigravity|Permission|\(permissionMessage)") - }, - "Expected Antigravity permission notifications to publish through cmux, saw \(permissionCommands)" - ) - XCTAssertTrue( - permissionCommands.contains { $0.contains("set_status antigravity Antigravity needs input") }, - "Expected Antigravity permission notifications to mark needs-input, saw \(permissionCommands)" - ) - - let stopErrorMessage = "Tool crashed" - let stopErrorCommandStart = state.commands.count - let stopError = runAntigravityHook( - "stop", - input: #"{"conversationId":"\#(sessionId)","workspacePaths":["\#(root.path)"],"hook_event_name":"Stop","terminationReason":"error","error":"\#(stopErrorMessage)","fullyIdle":true}"# - ) - XCTAssertFalse(stopError.timedOut, stopError.stderr) - XCTAssertEqual(stopError.status, 0, stopError.stderr) - XCTAssertEqual(stopError.stdout, "{}\n") - - let stopErrorCommands = Array(state.commands.dropFirst(stopErrorCommandStart)) - XCTAssertTrue( - stopErrorCommands.contains { - $0.contains("notify_target_async \(workspaceId) \(surfaceId) Antigravity|Error|\(stopErrorMessage)") - }, - "Expected Antigravity Stop errors to publish through cmux, saw \(stopErrorCommands)" - ) - XCTAssertTrue( - stopErrorCommands.contains { $0.contains("set_status antigravity Antigravity error") }, - "Expected Antigravity Stop errors to mark error status, saw \(stopErrorCommands)" - ) - - let errorMessage = "Execution failed" - let errorCommandStart = state.commands.count - let error = runAntigravityHook( - "notification", - input: #"{"session_id":"\#(sessionId)","cwd":"\#(root.path)","hook_event_name":"Notification","message":"\#(errorMessage)"}"# - ) - XCTAssertFalse(error.timedOut, error.stderr) - XCTAssertEqual(error.status, 0, error.stderr) - XCTAssertEqual(error.stdout, "{}\n") - - let errorCommands = Array(state.commands.dropFirst(errorCommandStart)) - XCTAssertTrue( - errorCommands.contains { - $0.contains("notify_target_async \(workspaceId) \(surfaceId) Antigravity|Error|\(errorMessage)") - }, - "Expected Antigravity error notifications to publish through cmux, saw \(errorCommands)" - ) - XCTAssertTrue( - errorCommands.contains { $0.contains("set_status antigravity Antigravity error") }, - "Expected Antigravity error notifications to mark error status, saw \(errorCommands)" - ) - } - - func testAntigravityHookInstallUsesNativeHooksJSONShape() throws { - let cliPath = try bundledCLIPath() - let root = FileManager.default.temporaryDirectory - .appendingPathComponent("cmux-antigravity-hook-install-\(UUID().uuidString)", isDirectory: true) - try FileManager.default.createDirectory(at: root, withIntermediateDirectories: true) - defer { try? FileManager.default.removeItem(at: root) } - - let result = runProcess( - executablePath: cliPath, - arguments: ["hooks", "agy", "install", "--yes"], - environment: [ - "HOME": root.path, - "PATH": "/usr/bin:/bin:/usr/sbin:/sbin", - "CMUX_BUNDLED_CLI_PATH": root.path, - "CMUX_CLI_SENTRY_DISABLED": "1", - ], - timeout: 5 - ) - - XCTAssertFalse(result.timedOut, result.stderr) - XCTAssertEqual(result.status, 0, result.stderr) - - let hookURL = root - .appendingPathComponent(".gemini", isDirectory: true) - .appendingPathComponent("config", isDirectory: true) - .appendingPathComponent("hooks.json", isDirectory: false) - let json = try XCTUnwrap(JSONSerialization.jsonObject(with: Data(contentsOf: hookURL)) as? [String: Any]) - XCTAssertNil(json["hooks"]) - - let cmuxGroup = try XCTUnwrap(json["cmux"] as? [String: Any]) - let allCommands = cmuxGroup.values - .compactMap { $0 as? [[String: Any]] } - .flatMap { entries in - entries.flatMap { entry -> [String] in - var commands: [String] = [] - if let command = entry["command"] as? String { - commands.append(command) - } - if let hooks = entry["hooks"] as? [[String: Any]] { - commands += hooks.compactMap { $0["command"] as? String } - } - return commands - } - } - XCTAssertFalse(allCommands.isEmpty) - XCTAssertTrue( - allCommands.allSatisfy { $0.contains("cmux-antigravity-hook-v2") }, - "Expected Antigravity hooks to use the pinned dispatch path, saw \(allCommands)" - ) - XCTAssertFalse( - allCommands.contains { $0.contains("'\(root.path)'") || $0.contains("\"\(root.path)\"") }, - "Directory-valued CMUX_BUNDLED_CLI_PATH must not be embedded as a hook executable, saw \(allCommands)" - ) - XCTAssertFalse( - allCommands.contains { $0.contains(#"[ -n "$CMUX_SURFACE_ID" ]"#) }, - "Antigravity hooks must still dispatch when agy does not preserve CMUX_SURFACE_ID, saw \(allCommands)" - ) - - let preToolUse = try XCTUnwrap(cmuxGroup["PreToolUse"] as? [[String: Any]]) - let preToolCommands = preToolUse - .compactMap { $0["hooks"] as? [[String: Any]] } - .flatMap { $0 } - XCTAssertTrue( - preToolCommands.contains { - ($0["command"] as? String)?.contains("hooks feed --source antigravity --event PreToolUse") == true - && ($0["timeout"] as? Int) == 120 - }, - "Expected Antigravity PreToolUse feed hook with second-based timeout, saw \(preToolCommands)" - ) - - let stop = try XCTUnwrap(cmuxGroup["Stop"] as? [[String: Any]]) - XCTAssertTrue( - stop.contains { - ($0["command"] as? String)?.contains("hooks antigravity stop") == true - && ($0["timeout"] as? Int) == 10 - }, - "Expected Antigravity Stop hook to be a direct command handler, saw \(stop)" - ) - XCTAssertNotNil(cmuxGroup["SessionStart"]) - XCTAssertNotNil(cmuxGroup["SessionEnd"]) - XCTAssertNotNil(cmuxGroup["turn-completion"]) - XCTAssertNotNil(cmuxGroup["Notification"]) - XCTAssertNotNil(cmuxGroup["PostToolUse"]) - } - - func testAntigravityFeedHookMissingSessionIdUsesStableFallback() throws { - let cliPath = try bundledCLIPath() - let socketPath = makeSocketPath("antigravity-feed-stable-session") - let listenerFD = try bindUnixSocket(at: socketPath) - let state = MockSocketServerState() - let root = FileManager.default.temporaryDirectory - .appendingPathComponent("cmux-antigravity-feed-stable-session-\(UUID().uuidString)", isDirectory: true) - let workspaceId = "33333333-3333-3333-3333-333333333333" - let surfaceId = "44444444-4444-4444-4444-444444444444" - - try FileManager.default.createDirectory(at: root, withIntermediateDirectories: true) - defer { - Darwin.close(listenerFD) - unlink(socketPath) - try? FileManager.default.removeItem(at: root) - } - - let environment: [String: String] = [ - "HOME": root.path, - "PATH": "/usr/bin:/bin:/usr/sbin:/sbin", - "PWD": root.path, - "CMUX_SOCKET_PATH": socketPath, - "CMUX_WORKSPACE_ID": workspaceId, - "CMUX_SURFACE_ID": surfaceId, - "CMUX_ANTIGRAVITY_PID": "424242", - "CMUX_CLI_SENTRY_DISABLED": "1", - ] - - func runFeedHook(input: String) -> ProcessRunResult { - let serverHandled = startMockServer(listenerFD: listenerFD, state: state) { line in - guard let payload = self.jsonObject(line) else { - return self.malformedRequestResponse(raw: line) - } - guard let id = payload["id"] as? String, let method = payload["method"] as? String else { - return self.malformedRequestResponse(id: payload["id"] as? String, raw: line) - } - XCTAssertEqual(method, "feed.push") - return self.v2Response(id: id, ok: true, result: ["status": "acknowledged"]) - } - let result = runProcess( - executablePath: cliPath, - arguments: ["hooks", "feed", "--source", "antigravity", "--event", "PreToolUse"], - environment: environment, - standardInput: input, - timeout: 5 - ) - wait(for: [serverHandled], timeout: 5) - return result - } - - let input = #"{"hook_event_name":"PreToolUse","workspacePaths":["\#(root.path)"],"notification":{"transcript_path":"\#(root.appendingPathComponent("transcript-a.jsonl").path)"},"toolCall":{"name":"read_file","args":{"path":"README.md"}}}"# - let first = runFeedHook(input: input) - XCTAssertFalse(first.timedOut, first.stderr) - XCTAssertEqual(first.status, 0, first.stderr) - XCTAssertEqual(first.stdout, "{}\n") - - let second = runFeedHook(input: input) - XCTAssertFalse(second.timedOut, second.stderr) - XCTAssertEqual(second.status, 0, second.stderr) - XCTAssertEqual(second.stdout, "{}\n") - - let differentTranscriptInput = #"{"hook_event_name":"PreToolUse","workspacePaths":["\#(root.path)"],"notification":{"transcript_path":"\#(root.appendingPathComponent("transcript-b.jsonl").path)"},"toolCall":{"name":"read_file","args":{"path":"README.md"}}}"# - let third = runFeedHook(input: differentTranscriptInput) - XCTAssertFalse(third.timedOut, third.stderr) - XCTAssertEqual(third.status, 0, third.stderr) - XCTAssertEqual(third.stdout, "{}\n") - - let events = state.commands.compactMap { command -> [String: Any]? in - guard let payload = self.jsonObject(command), - payload["method"] as? String == "feed.push", - let params = payload["params"] as? [String: Any], - let event = params["event"] as? [String: Any] else { - return nil - } - return event - } - let sessionIds = events.compactMap { $0["session_id"] as? String } - XCTAssertEqual(sessionIds.count, 3, "Expected three feed events, saw \(state.commands)") - XCTAssertEqual(sessionIds[0], sessionIds[1]) - XCTAssertNotEqual(sessionIds[1], sessionIds[2]) - XCTAssertTrue( - sessionIds[0].hasPrefix("antigravity-fallback-"), - "Expected deterministic Antigravity fallback session id, saw \(sessionIds[0])" - ) - XCTAssertEqual(events.compactMap { $0["_ppid"] as? Int }, [424242, 424242, 424242]) - } - func testGrokNotificationHookUsesPayloadMessageAndStopDoesNotSendGenericNotification() throws { let cliPath = try bundledCLIPath() let socketPath = makeSocketPath("grok-notification") diff --git a/cmuxTests/CMUXCLIErrorOutputRegressionTests.swift b/cmuxTests/CMUXCLIErrorOutputRegressionTests.swift index 83bf7a932617..567ac8df9895 100644 --- a/cmuxTests/CMUXCLIErrorOutputRegressionTests.swift +++ b/cmuxTests/CMUXCLIErrorOutputRegressionTests.swift @@ -1,13 +1,6 @@ import Darwin -import Foundation import XCTest -#if canImport(cmux_DEV) -@testable import cmux_DEV -#elseif canImport(cmux) -@testable import cmux -#endif - final class CMUXCLIErrorOutputRegressionTests: XCTestCase { private struct ProcessRunResult { let status: Int32 @@ -134,380 +127,6 @@ final class CMUXCLIErrorOutputRegressionTests: XCTestCase { ) } - func testThemesSetReloadsRunningAppAfterEveryThemeWrite() throws { - let cliPath = try bundledCLIPath() - let fileManager = FileManager.default - let root = fileManager.temporaryDirectory - .appendingPathComponent("cmux-themes-socket-\(UUID().uuidString)", isDirectory: true) - try fileManager.createDirectory(at: root, withIntermediateDirectories: true) - defer { try? fileManager.removeItem(at: root) } - - let resourcesURL = root.appendingPathComponent("resources", isDirectory: true) - let themesURL = resourcesURL.appendingPathComponent("themes", isDirectory: true) - try fileManager.createDirectory(at: themesURL, withIntermediateDirectories: true) - try writeTheme(named: "Theme A", background: "#101010", to: themesURL) - try writeTheme(named: "Theme B", background: "#f8f8f8", to: themesURL) - try writeTheme(named: "Theme C", background: "#003b49", to: themesURL) - - let socketPath = "/tmp/cmux-theme-\(UUID().uuidString.prefix(8)).sock" - let responder = try UnixSocketResponder(path: socketPath, response: "OK") - defer { responder.stop() } - let bundleIdentifier = "com.cmuxterm.app.debug.issue-4355-test" - let reloadExpectation = expectation(description: "cmux themes set posts final reload notifications") - reloadExpectation.expectedFulfillmentCount = 3 - let notificationQueue = OperationQueue() - notificationQueue.maxConcurrentOperationCount = 1 - let notificationLock = NSLock() - var observedReloads: [(bundleIdentifier: String?, phase: String?)] = [] - let observer = DistributedNotificationCenter.default().addObserver( - forName: Notification.Name("com.cmuxterm.themes.reload-config"), - object: nil, - queue: notificationQueue - ) { notification in - let observedBundleIdentifier = notification.userInfo?["bundleIdentifier"] as? String - guard observedBundleIdentifier == bundleIdentifier else { return } - let observedPhase = notification.userInfo?["phase"] as? String - notificationLock.lock() - observedReloads.append((bundleIdentifier: observedBundleIdentifier, phase: observedPhase)) - notificationLock.unlock() - reloadExpectation.fulfill() - } - defer { - DistributedNotificationCenter.default().removeObserver(observer) - } - - var environment = ProcessInfo.processInfo.environment - for key in Array(environment.keys) where key.hasPrefix("CMUX_") { - environment.removeValue(forKey: key) - } - environment["CFFIXED_USER_HOME"] = root.path - environment["HOME"] = root.path - environment["GHOSTTY_RESOURCES_DIR"] = resourcesURL.path - environment["CMUX_SOCKET_PATH"] = socketPath - environment["CMUX_BUNDLE_ID"] = bundleIdentifier - environment["CMUX_CLI_SENTRY_DISABLED"] = "1" - - let configURL = root - .appendingPathComponent("Library", isDirectory: true) - .appendingPathComponent("Application Support", isDirectory: true) - .appendingPathComponent(bundleIdentifier, isDirectory: true) - .appendingPathComponent("config.ghostty", isDirectory: false) - - var observedThemeValues: [String] = [] - for themeName in ["Theme A", "Theme B", "Theme C"] { - let result = runProcess( - executablePath: cliPath, - arguments: ["themes", "set", themeName], - environment: environment, - timeout: 5 - ) - - XCTAssertFalse(result.timedOut, result.stdout) - XCTAssertEqual(result.status, 0, result.stdout) - observedThemeValues.append(try managedThemeValue(in: configURL)) - } - wait(for: [reloadExpectation], timeout: 5) - - XCTAssertEqual(observedThemeValues, [ - "light:Theme A,dark:Theme A", - "light:Theme B,dark:Theme B", - "light:Theme C,dark:Theme C", - ]) - notificationLock.lock() - let reloads = observedReloads - notificationLock.unlock() - XCTAssertEqual(reloads.map { $0.bundleIdentifier }, Array(repeating: bundleIdentifier, count: 3)) - XCTAssertEqual(reloads.map { $0.phase }, Array(repeating: "final", count: 3)) - XCTAssertEqual(responder.receivedRequests, []) - } - - func testThemesSetTargetsResolvedTaggedSocketWhenBundleEnvironmentIsStale() throws { - let cliPath = try bundledCLIPath() - let fileManager = FileManager.default - let root = fileManager.temporaryDirectory - .appendingPathComponent("cmux-themes-stale-bundle-\(UUID().uuidString)", isDirectory: true) - try fileManager.createDirectory(at: root, withIntermediateDirectories: true) - defer { try? fileManager.removeItem(at: root) } - - let resourcesURL = root.appendingPathComponent("resources", isDirectory: true) - let themesURL = resourcesURL.appendingPathComponent("themes", isDirectory: true) - try fileManager.createDirectory(at: themesURL, withIntermediateDirectories: true) - try writeTheme(named: "Theme A", background: "#101010", to: themesURL) - - let socketPath = "/tmp/cmux-debug-active-theme.sock" - let staleBundleIdentifier = "com.cmuxterm.app.debug.stale.theme" - let targetBundleIdentifier = "com.cmuxterm.app.debug.active.theme" - let reloadExpectation = expectation(description: "cmux themes set targets the resolved socket bundle") - let notificationQueue = OperationQueue() - notificationQueue.maxConcurrentOperationCount = 1 - let notificationLock = NSLock() - var observedReloads: [(bundleIdentifier: String?, phase: String?, socketPath: String?)] = [] - let observer = DistributedNotificationCenter.default().addObserver( - forName: Notification.Name("com.cmuxterm.themes.reload-config"), - object: nil, - queue: notificationQueue - ) { notification in - let observedBundleIdentifier = notification.userInfo?["bundleIdentifier"] as? String - guard observedBundleIdentifier == targetBundleIdentifier else { return } - let observedPhase = notification.userInfo?["phase"] as? String - let observedSocketPath = notification.userInfo?["socketPath"] as? String - notificationLock.lock() - observedReloads.append(( - bundleIdentifier: observedBundleIdentifier, - phase: observedPhase, - socketPath: observedSocketPath - )) - notificationLock.unlock() - reloadExpectation.fulfill() - } - defer { - DistributedNotificationCenter.default().removeObserver(observer) - } - - var environment = ProcessInfo.processInfo.environment - for key in Array(environment.keys) where key.hasPrefix("CMUX_") { - environment.removeValue(forKey: key) - } - environment["CFFIXED_USER_HOME"] = root.path - environment["HOME"] = root.path - environment["GHOSTTY_RESOURCES_DIR"] = resourcesURL.path - environment["CMUX_SOCKET_PATH"] = socketPath - environment["CMUX_BUNDLE_ID"] = staleBundleIdentifier - environment["CMUX_CLI_SENTRY_DISABLED"] = "1" - - let result = runProcess( - executablePath: cliPath, - arguments: ["--json", "themes", "set", "Theme A"], - environment: environment, - timeout: 5 - ) - - XCTAssertFalse(result.timedOut, result.stdout) - XCTAssertEqual(result.status, 0, result.stdout) - wait(for: [reloadExpectation], timeout: 5) - - notificationLock.lock() - let reloads = observedReloads - notificationLock.unlock() - XCTAssertEqual(reloads.map { $0.bundleIdentifier }, [targetBundleIdentifier]) - XCTAssertEqual(reloads.map { $0.phase }, ["final"]) - XCTAssertEqual(reloads.map { $0.socketPath }, [socketPath]) - XCTAssertFalse(result.stdout.contains(staleBundleIdentifier), result.stdout) - XCTAssertTrue(result.stdout.contains(targetBundleIdentifier), result.stdout) - } - - func testThemesSetNightlyOverridePathIsReadableByNightlyAppConfigResolution() throws { - let cliPath = try bundledCLIPath() - let fileManager = FileManager.default - let root = fileManager.temporaryDirectory - .appendingPathComponent("cmux-themes-nightly-path-\(UUID().uuidString)", isDirectory: true) - try fileManager.createDirectory(at: root, withIntermediateDirectories: true) - defer { try? fileManager.removeItem(at: root) } - - let resourcesURL = root.appendingPathComponent("resources", isDirectory: true) - let themesURL = resourcesURL.appendingPathComponent("themes", isDirectory: true) - try fileManager.createDirectory(at: themesURL, withIntermediateDirectories: true) - try writeTheme(named: "Theme A", background: "#101010", to: themesURL) - - let bundleIdentifier = "com.cmuxterm.app.nightly" - var environment = ProcessInfo.processInfo.environment - for key in Array(environment.keys) where key.hasPrefix("CMUX_") { - environment.removeValue(forKey: key) - } - environment["CFFIXED_USER_HOME"] = root.path - environment["HOME"] = root.path - environment["GHOSTTY_RESOURCES_DIR"] = resourcesURL.path - environment["CMUX_SOCKET_PATH"] = "/tmp/cmux-nightly.sock" - environment["CMUX_BUNDLE_ID"] = bundleIdentifier - environment["CMUX_CLI_SENTRY_DISABLED"] = "1" - - let result = runProcess( - executablePath: cliPath, - arguments: ["--json", "themes", "set", "Theme A"], - environment: environment, - timeout: 5 - ) - - XCTAssertFalse(result.timedOut, result.stdout) - XCTAssertEqual(result.status, 0, result.stdout) - - let payload = try XCTUnwrap( - JSONSerialization.jsonObject(with: Data(result.stdout.utf8)) as? [String: Any], - result.stdout - ) - let configPath = try XCTUnwrap(payload["config_path"] as? String, result.stdout) - XCTAssertEqual(payload["reload_target_bundle_id"] as? String, bundleIdentifier) - - let appSupportDirectory = root - .appendingPathComponent("Library", isDirectory: true) - .appendingPathComponent("Application Support", isDirectory: true) - let expectedConfigURL = appSupportDirectory - .appendingPathComponent(bundleIdentifier, isDirectory: true) - .appendingPathComponent("config.ghostty", isDirectory: false) - XCTAssertEqual(configPath, expectedConfigURL.path) - - let appReadablePaths = GhosttyApp.cmuxAppSupportConfigURLs( - currentBundleIdentifier: bundleIdentifier, - appSupportDirectory: appSupportDirectory - ).map(\.path) - XCTAssertEqual(appReadablePaths, [expectedConfigURL.path]) - } - - func testBareInteractiveThemesReloadsRunningAppAfterPickerExits() throws { - let cliPath = try bundledCLIPath() - let fileManager = FileManager.default - let root = fileManager.temporaryDirectory - .appendingPathComponent("cmux-themes-picker-socket-\(UUID().uuidString)", isDirectory: true) - try fileManager.createDirectory(at: root, withIntermediateDirectories: true) - defer { try? fileManager.removeItem(at: root) } - - let fakeCLIPath = try fakeTaggedBundledCLIPath( - sourceCLIPath: cliPath, - tagSlug: "theme-picker-\(UUID().uuidString.lowercased())" - ) - let fakeGhosttyHelperURL = URL(fileURLWithPath: fakeCLIPath) - .deletingLastPathComponent() - .appendingPathComponent("ghostty", isDirectory: false) - try """ - #!/usr/bin/env python3 - import os - import sys - import time - - deadline = time.time() + 2.0 - last_error = "" - while time.time() < deadline: - try: - if os.isatty(0) and os.tcgetpgrp(0) == os.getpgrp(): - sys.exit(0) - last_error = f"pgrp={os.getpgrp()} tpgid={os.tcgetpgrp(0)}" - except OSError as error: - last_error = str(error) - time.sleep(0.02) - - sys.stderr.write(f"theme picker was not foregrounded: {last_error}\\n") - sys.exit(42) - """.write(to: fakeGhosttyHelperURL, atomically: true, encoding: .utf8) - try fileManager.setAttributes( - [.posixPermissions: 0o755], - ofItemAtPath: fakeGhosttyHelperURL.path - ) - - let socketPath = "/tmp/cmux-theme-picker-\(UUID().uuidString.prefix(8)).sock" - let responder = try UnixSocketResponder(path: socketPath, response: "OK") - defer { responder.stop() } - let bundleIdentifier = "com.cmuxterm.app.debug.theme-picker.\(UUID().uuidString.lowercased())" - let reloadExpectation = expectation(description: "bare cmux themes posts final reload notification") - let notificationQueue = OperationQueue() - notificationQueue.maxConcurrentOperationCount = 1 - let notificationLock = NSLock() - var observedReloads: [(bundleIdentifier: String?, phase: String?)] = [] - let observer = DistributedNotificationCenter.default().addObserver( - forName: Notification.Name("com.cmuxterm.themes.reload-config"), - object: nil, - queue: notificationQueue - ) { notification in - let observedBundleIdentifier = notification.userInfo?["bundleIdentifier"] as? String - guard observedBundleIdentifier == bundleIdentifier else { return } - let observedPhase = notification.userInfo?["phase"] as? String - notificationLock.lock() - observedReloads.append((bundleIdentifier: observedBundleIdentifier, phase: observedPhase)) - notificationLock.unlock() - reloadExpectation.fulfill() - } - defer { - DistributedNotificationCenter.default().removeObserver(observer) - } - - let command = [ - "env", - "-i", - "HOME=\(shellSingleQuote(root.path))", - "CFFIXED_USER_HOME=\(shellSingleQuote(root.path))", - "CMUX_SOCKET_PATH=\(shellSingleQuote(socketPath))", - "CMUX_BUNDLE_ID=\(shellSingleQuote(bundleIdentifier))", - "CMUX_CLI_SENTRY_DISABLED=1", - "PATH=/usr/bin:/bin", - "/usr/bin/script", - "-q", - "/dev/null", - shellSingleQuote(fakeCLIPath), - "themes", - ].joined(separator: " ") - let result = runShell(command, timeout: 5) - - XCTAssertFalse(result.timedOut, result.stdout) - XCTAssertEqual(result.status, 0, result.stdout) - wait(for: [reloadExpectation], timeout: 5) - notificationLock.lock() - let reloads = observedReloads - notificationLock.unlock() - XCTAssertEqual(reloads.map { $0.bundleIdentifier }, [bundleIdentifier]) - XCTAssertEqual(reloads.map { $0.phase }, ["final"]) - XCTAssertEqual(responder.receivedRequests, []) - } - - func testBareInteractiveThemesTreatsSigintAsSilentCancel() throws { - let cliPath = try bundledCLIPath() - let fileManager = FileManager.default - let root = fileManager.temporaryDirectory - .appendingPathComponent("cmux-themes-picker-cancel-\(UUID().uuidString)", isDirectory: true) - try fileManager.createDirectory(at: root, withIntermediateDirectories: true) - defer { try? fileManager.removeItem(at: root) } - - let fakeCLIPath = try fakeTaggedBundledCLIPath( - sourceCLIPath: cliPath, - tagSlug: "theme-picker-cancel-\(UUID().uuidString.lowercased())" - ) - let fakeGhosttyHelperURL = URL(fileURLWithPath: fakeCLIPath) - .deletingLastPathComponent() - .appendingPathComponent("ghostty", isDirectory: false) - try """ - #!/usr/bin/env python3 - import os - import signal - import sys - import time - - deadline = time.time() + 2.0 - while time.time() < deadline: - if os.isatty(0) and os.tcgetpgrp(0) == os.getpgrp(): - signal.signal(signal.SIGINT, signal.SIG_DFL) - os.kill(os.getpid(), signal.SIGINT) - time.sleep(0.02) - sys.exit(42) - """.write(to: fakeGhosttyHelperURL, atomically: true, encoding: .utf8) - try fileManager.setAttributes( - [.posixPermissions: 0o755], - ofItemAtPath: fakeGhosttyHelperURL.path - ) - - let socketPath = "/tmp/cmux-theme-picker-cancel-\(UUID().uuidString.prefix(8)).sock" - let responder = try UnixSocketResponder(path: socketPath, response: "OK") - defer { responder.stop() } - - let command = [ - "env", - "-i", - "HOME=\(shellSingleQuote(root.path))", - "CFFIXED_USER_HOME=\(shellSingleQuote(root.path))", - "CMUX_SOCKET_PATH=\(shellSingleQuote(socketPath))", - "CMUX_CLI_SENTRY_DISABLED=1", - "PATH=/usr/bin:/bin", - "/usr/bin/script", - "-q", - "/dev/null", - shellSingleQuote(fakeCLIPath), - "themes", - ].joined(separator: " ") - let result = runShell(command, timeout: 5) - - XCTAssertFalse(result.timedOut, result.stdout) - XCTAssertEqual(result.status, 0, result.stdout) - XCTAssertFalse(result.stdout.contains("Interactive theme picker exited"), result.stdout) - XCTAssertEqual(responder.receivedRequests, []) - } - func testBrowserDownloadWaitUsesRequestedTimeoutForSocketResponse() throws { let cliPath = try bundledCLIPath() let socketPath = "/tmp/cmux-dw-\(UUID().uuidString.prefix(8)).sock" @@ -603,36 +222,6 @@ final class CMUXCLIErrorOutputRegressionTests: XCTestCase { return directory.appendingPathComponent("cmux.sock", isDirectory: false) } - private func writeTheme(named name: String, background: String, to directory: URL) throws { - try """ - background = \(background) - foreground = #eeeeee - cursor-color = #ff00ff - cursor-text = #000000 - """.write( - to: directory.appendingPathComponent(name, isDirectory: false), - atomically: true, - encoding: .utf8 - ) - } - - private func managedThemeValue(in configURL: URL) throws -> String { - let contents = try String(contentsOf: configURL, encoding: .utf8) - let values = contents.components(separatedBy: .newlines).compactMap { line -> String? in - let trimmed = line.trimmingCharacters(in: .whitespacesAndNewlines) - guard !trimmed.isEmpty, !trimmed.hasPrefix("#") else { return nil } - let parts = trimmed.split(separator: "=", maxSplits: 1).map(String.init) - guard parts.count == 2, - parts[0].trimmingCharacters(in: .whitespacesAndNewlines) == "theme" else { - return nil - } - return parts[1] - .trimmingCharacters(in: .whitespacesAndNewlines) - .trimmingCharacters(in: CharacterSet(charactersIn: "\"")) - } - return try XCTUnwrap(values.last) - } - private func fakeTaggedBundledCLIPath( sourceCLIPath: String, tagSlug: String, @@ -713,11 +302,7 @@ final class CMUXCLIErrorOutputRegressionTests: XCTestCase { let timedOut = exitSignal.wait(timeout: .now() + timeout) == .timedOut if timedOut { process.terminate() - if exitSignal.wait(timeout: .now() + 1) == .timedOut, - process.isRunning { - kill(process.processIdentifier, SIGKILL) - _ = exitSignal.wait(timeout: .now() + 1) - } + _ = exitSignal.wait(timeout: .now() + 1) } return ProcessRunResult( @@ -757,11 +342,7 @@ final class CMUXCLIErrorOutputRegressionTests: XCTestCase { let timedOut = exitSignal.wait(timeout: .now() + timeout) == .timedOut if timedOut { process.terminate() - if exitSignal.wait(timeout: .now() + 1) == .timedOut, - process.isRunning { - kill(process.processIdentifier, SIGKILL) - _ = exitSignal.wait(timeout: .now() + 1) - } + _ = exitSignal.wait(timeout: .now() + 1) } return ProcessRunResult( @@ -779,7 +360,6 @@ private final class UnixSocketResponder { private let queue = DispatchQueue(label: "com.cmux.tests.unix-socket-responder") private let lock = NSLock() private var stopped = false - private var requests: [String] = [] private var listenerFD: Int32 = -1 init(path: String, response: String, responseDelay: TimeInterval = 0) throws { @@ -838,12 +418,6 @@ private final class UnixSocketResponder { stop() } - var receivedRequests: [String] { - lock.lock() - defer { lock.unlock() } - return requests - } - func stop() { lock.lock() guard !stopped else { @@ -897,12 +471,6 @@ private final class UnixSocketResponder { guard !request.isEmpty else { return } - if let line = String(data: request, encoding: .utf8)? - .trimmingCharacters(in: .whitespacesAndNewlines) { - lock.lock() - requests.append(line) - lock.unlock() - } if responseDelay > 0 { Thread.sleep(forTimeInterval: responseDelay) } diff --git a/cmuxTests/CMUXOpenCommandTests.swift b/cmuxTests/CMUXOpenCommandTests.swift index 5950e478256d..4d80be116dc4 100644 --- a/cmuxTests/CMUXOpenCommandTests.swift +++ b/cmuxTests/CMUXOpenCommandTests.swift @@ -205,41 +205,6 @@ final class CMUXOpenCommandTests: XCTestCase { XCTAssertTrue(lines[3].contains("workspace workspace:low"), result.stdout) } - func testTopCommandForwardsWindowFlag() throws { - let cliPath = try bundledCLIPath() - let socketPath = makeSocketPath("top-window") - let listenerFD = try bindUnixSocket(at: socketPath) - let windowId = "11111111-1111-1111-1111-111111111111" - defer { - Darwin.close(listenerFD) - unlink(socketPath) - } - - let payload: [String: Any] = [ - "windows": [ - topNode(ref: "window:2", cpu: 2, rss: 2_000, processCount: 2, extra: [ - "id": windowId, - "workspaces": [], - ]), - ], - ] - let serverHandled = startTopMockServer(listenerFD: listenerFD, payload: payload) { params in - XCTAssertEqual(params["window_id"] as? String, windowId) - XCTAssertEqual(params["all_windows"] as? Bool, false) - } - - let result = runCLI( - cliPath: cliPath, - socketPath: socketPath, - arguments: ["top", "--window", windowId] - ) - - wait(for: [serverHandled], timeout: 5) - XCTAssertFalse(result.timedOut, result.stderr) - XCTAssertEqual(result.status, 0, result.stderr) - XCTAssertTrue(result.stdout.contains("window window:2"), result.stdout) - } - func testTopCommandSortsMixedWorkspaceChildrenByMemoryAlias() throws { let cliPath = try bundledCLIPath() let socketPath = makeSocketPath("top-mem") @@ -685,18 +650,13 @@ final class CMUXOpenCommandTests: XCTestCase { return handled } - private func startTopMockServer( - listenerFD: Int32, - payload: [String: Any], - assertParams: (([String: Any]) -> Void)? = nil - ) -> XCTestExpectation { + private func startTopMockServer(listenerFD: Int32, payload: [String: Any]) -> XCTestExpectation { startMockServer(listenerFD: listenerFD, state: MockSocketServerState()) { line in guard let request = Self.v2Payload(from: line), let id = request["id"] as? String, request["method"] as? String == "system.top" else { return Self.v2Response(id: "unknown", ok: false, error: ["code": "unexpected"]) } - assertParams?(request["params"] as? [String: Any] ?? [:]) return Self.v2Response(id: id, ok: true, result: payload) } } diff --git a/cmuxTests/CmuxWebViewDragRoutingTests.swift b/cmuxTests/CmuxWebViewDragRoutingTests.swift index ef4515c972de..5b1c17bfb7a9 100644 --- a/cmuxTests/CmuxWebViewDragRoutingTests.swift +++ b/cmuxTests/CmuxWebViewDragRoutingTests.swift @@ -254,197 +254,3 @@ final class CmuxWebViewDragRoutingTests: XCTestCase { XCTAssertEqual(cmuxUnitTestWKWebViewDragLifecycleEvents, []) } } - -@MainActor -final class BrowserScreenshotPipelineTests: XCTestCase { - private func makeTestImage(width: Int, height: Int) throws -> NSImage { - let rep = try XCTUnwrap( - NSBitmapImageRep( - bitmapDataPlanes: nil, - pixelsWide: width, - pixelsHigh: height, - bitsPerSample: 8, - samplesPerPixel: 4, - hasAlpha: true, - isPlanar: false, - colorSpaceName: .deviceRGB, - bytesPerRow: 0, - bitsPerPixel: 0 - ) - ) - - for y in 0..( - makeView: { view }, - closeView: { - XCTAssertTrue($0 === view) - closeCount += 1 - }, - dismantleView: { - XCTAssertTrue($0 === view) - dismantleCount += 1 - } - ) - - XCTAssertTrue(session.view(configure: { _ in }) === view) - session.close() - XCTAssertEqual(closeCount, 1) - XCTAssertEqual(dismantleCount, 0) - - XCTAssertFalse(session.dismantle(view)) - XCTAssertEqual(dismantleCount, 1) - - XCTAssertFalse(session.dismantle(view)) - XCTAssertEqual(dismantleCount, 1) - } - func testTextLoaderRejectsOversizedTextFiles() throws { let url = FileManager.default.temporaryDirectory .appendingPathComponent(UUID().uuidString) @@ -253,14 +153,6 @@ final class FilePreviewReviewFeedbackTests: XCTestCase { return url } - private func temporaryBinaryFile() throws -> URL { - let url = FileManager.default.temporaryDirectory - .appendingPathComponent(UUID().uuidString) - .appendingPathExtension("bin") - try Data([0, 1, 2, 3, 0, 4]).write(to: url, options: .atomic) - return url - } - private func keyEvent(key: String, keyCode: UInt16) -> NSEvent? { NSEvent.keyEvent( with: .keyDown, diff --git a/cmuxTests/GhosttyConfigTests.swift b/cmuxTests/GhosttyConfigTests.swift index c3527229da1b..fe689d90e58c 100644 --- a/cmuxTests/GhosttyConfigTests.swift +++ b/cmuxTests/GhosttyConfigTests.swift @@ -589,90 +589,6 @@ final class GhosttyConfigTests: XCTestCase { } } - func testTerminalRuntimeColorSchemeFollowsResolvedThemeBackground() { - XCTAssertEqual( - GhosttyApp.terminalRuntimeColorSchemePreference( - forBackgroundColor: NSColor(hex: "#F7F7F7")! - ), - .light - ) - XCTAssertEqual( - GhosttyApp.terminalRuntimeColorSchemePreference( - forBackgroundColor: NSColor(hex: "#090300")! - ), - .dark - ) - } - - func testRuntimeColorSchemeSynchronizationDecisionOnlySkipsReentrantCalls() { - XCTAssertEqual( - GhosttyApp.runtimeColorSchemeSynchronizationDecision( - applied: nil, - requested: GHOSTTY_COLOR_SCHEME_DARK, - isSynchronizing: false - ), - .apply - ) - XCTAssertEqual( - GhosttyApp.runtimeColorSchemeSynchronizationDecision( - applied: GHOSTTY_COLOR_SCHEME_DARK, - requested: GHOSTTY_COLOR_SCHEME_DARK, - isSynchronizing: false - ), - .apply - ) - XCTAssertEqual( - GhosttyApp.runtimeColorSchemeSynchronizationDecision( - applied: GHOSTTY_COLOR_SCHEME_LIGHT, - requested: GHOSTTY_COLOR_SCHEME_DARK, - isSynchronizing: true - ), - .skipReentrant - ) - } - - func testRuntimeColorSchemeForCmuxSingleThemeReloadKeepsResolvedSchemeDuringConfigLoad() { - XCTAssertEqual( - GhosttyApp.runtimeColorSchemeForConfigLoad( - source: GhosttySurfaceConfigurationRefresh.cmuxThemeReloadFinalSource, - requestedColorScheme: .dark, - effectiveTerminalColorScheme: .light, - cmuxThemeValue: "light:3024 Day,dark:3024 Day" - ), - .light - ) - XCTAssertEqual( - GhosttyApp.runtimeColorSchemeForConfigLoad( - source: GhosttySurfaceConfigurationRefresh.cmuxThemeReloadPreviewSource, - requestedColorScheme: .dark, - effectiveTerminalColorScheme: .light, - cmuxThemeValue: "3024 Day" - ), - .light - ) - } - - func testRuntimeColorSchemeForPairedThemeReloadUsesAppearanceDuringConfigLoad() { - XCTAssertEqual( - GhosttyApp.runtimeColorSchemeForConfigLoad( - source: GhosttySurfaceConfigurationRefresh.cmuxThemeReloadFinalSource, - requestedColorScheme: .dark, - effectiveTerminalColorScheme: .light, - cmuxThemeValue: "light:3024 Day,dark:3024 Night" - ), - .dark - ) - XCTAssertEqual( - GhosttyApp.runtimeColorSchemeForConfigLoad( - source: "socket.reload_config", - requestedColorScheme: .dark, - effectiveTerminalColorScheme: .light, - cmuxThemeValue: "light:3024 Day,dark:3024 Day" - ), - .dark - ) - } - func testScrollLagCaptureRequiresSustainedLag() { let cases: [(samples: Int, averageMs: Double, maxMs: Double, expected: Bool)] = [ (4, 18, 85, false), @@ -751,37 +667,6 @@ final class GhosttyConfigTests: XCTestCase { XCTAssertFalse(ClaudeCodeIntegrationSettings.hooksEnabled(defaults: defaults)) } - func testSubagentNotificationSuppressionDefaultsToEnabledWhenUnset() { - let suiteName = "cmux.tests.subagent-notifications.\(UUID().uuidString)" - guard let defaults = UserDefaults(suiteName: suiteName) else { - XCTFail("Failed to create isolated user defaults suite") - return - } - defer { - defaults.removePersistentDomain(forName: suiteName) - } - - defaults.removeObject(forKey: AgentSubagentNotificationSettings.suppressNotificationsKey) - XCTAssertTrue(AgentSubagentNotificationSettings.suppressNotifications(defaults: defaults)) - } - - func testSubagentNotificationSuppressionRespectsStoredPreference() { - let suiteName = "cmux.tests.subagent-notifications.\(UUID().uuidString)" - guard let defaults = UserDefaults(suiteName: suiteName) else { - XCTFail("Failed to create isolated user defaults suite") - return - } - defer { - defaults.removePersistentDomain(forName: suiteName) - } - - defaults.set(true, forKey: AgentSubagentNotificationSettings.suppressNotificationsKey) - XCTAssertTrue(AgentSubagentNotificationSettings.suppressNotifications(defaults: defaults)) - - defaults.set(false, forKey: AgentSubagentNotificationSettings.suppressNotificationsKey) - XCTAssertFalse(AgentSubagentNotificationSettings.suppressNotifications(defaults: defaults)) - } - func testTelemetryDefaultsToEnabledWhenUnset() { let suiteName = "cmux.tests.telemetry.\(UUID().uuidString)" guard let defaults = UserDefaults(suiteName: suiteName) else { @@ -2502,19 +2387,6 @@ final class SocketControlSettingsTests: XCTestCase { XCTAssertEqual(path, "/tmp/cmux-debug-my-tag.sock") } - func testTaggedDebugBundleIgnoresSocketOverrideInheritedFromDifferentCmuxBundle() { - let path = SocketControlSettings.socketPath( - environment: [ - "CMUX_BUNDLE_ID": "com.cmuxterm.app.nightly", - "CMUX_SOCKET_PATH": "/tmp/cmux-nightly.sock", - ], - bundleIdentifier: "com.cmuxterm.app.debug.issue.4355.cmux.themes.set.state.dependent", - isDebugBuild: true - ) - - XCTAssertEqual(path, "/tmp/cmux-debug-issue-4355-cmux-themes-set-state-dependent.sock") - } - func testTaggedDebugBundleIgnoresMismatchedInheritedSocketOverride() { let path = SocketControlSettings.socketPath( environment: [ @@ -4277,129 +4149,6 @@ final class ZshShellIntegrationHandoffTests: XCTestCase { ) } - func testBashNoGitWatchSkipsHeadTrackingAndPRClear() throws { - let fileManager = FileManager.default - let root = fileManager.temporaryDirectory - .appendingPathComponent("cmux-bash-no-git-watch-\(UUID().uuidString)") - let repoA = root.appendingPathComponent("repo-a", isDirectory: true) - let repoB = root.appendingPathComponent("repo-b", isDirectory: true) - let logPath = root.appendingPathComponent("send.log", isDirectory: false) - let socketPath = root.appendingPathComponent("cmux-test.sock", isDirectory: false) - - try fileManager.createDirectory(at: root, withIntermediateDirectories: true) - let socketFD = try bindUnixSocket(at: socketPath.path) - defer { - Darwin.close(socketFD) - unlink(socketPath.path) - try? fileManager.removeItem(at: root) - } - - let result = try runInteractiveBash( - cmuxLoadShellIntegration: true, - command: """ - mkdir -p "\(repoA.path)/.git" "\(repoB.path)/.git" - printf '%s\\n' 'ref: refs/heads/main' > "\(repoA.path)/.git/HEAD" - printf '%s\\n' 'ref: refs/heads/feature' > "\(repoB.path)/.git/HEAD" - : > "\(logPath.path)" - _cmux_send() { printf '%s\\n' "$1" >> "\(logPath.path)"; } - cd "\(repoA.path)" - _CMUX_TTY_REPORTED=1 - _CMUX_PORTS_LAST_RUN=$(_cmux_now) - _CMUX_PWD_LAST_PWD="$PWD" - _CMUX_GIT_HEAD_LAST_PWD="$PWD" - _CMUX_GIT_HEAD_PATH="$PWD/.git/HEAD" - _CMUX_GIT_HEAD_SIGNATURE="$(_cmux_git_head_signature "$_CMUX_GIT_HEAD_PATH")" - printf '%s\\n' 'ref: refs/heads/old-cleared' > "$_CMUX_GIT_HEAD_PATH" - cd "\(repoB.path)" - _CMUX_PWD_LAST_PWD="$PWD" - _CMUX_LAST_PR_ACTION="checkout" - _CMUX_LAST_PR_TARGET="feature" - _cmux_prompt_command - printf 'HEAD_PATH=%s\\n' "$_CMUX_GIT_HEAD_PATH" - printf 'HEAD_LAST_PWD=%s\\n' "$_CMUX_GIT_HEAD_LAST_PWD" - printf 'LAST_PR_ACTION=%s\\n' "$_CMUX_LAST_PR_ACTION" - printf 'LOG< "\(repoA.path)/.git/HEAD" - printf '%s\\n' 'ref: refs/heads/feature' > "\(repoB.path)/.git/HEAD" - : > "\(logPath.path)" - _cmux_send() { printf '%s\\n' "$1" >> "\(logPath.path)"; } - cd "\(repoA.path)" - _CMUX_TTY_REPORTED=1 - _CMUX_PORTS_LAST_RUN=$(_cmux_now) - _CMUX_PWD_LAST_PWD="$PWD" - _CMUX_GIT_HEAD_LAST_PWD="$PWD" - _CMUX_GIT_HEAD_PATH="$PWD/.git/HEAD" - _CMUX_GIT_HEAD_SIGNATURE="$(_cmux_git_head_signature "$_CMUX_GIT_HEAD_PATH")" - printf '%s\\n' 'ref: refs/heads/old-cleared' > "$_CMUX_GIT_HEAD_PATH" - cd "\(repoB.path)" - _CMUX_PWD_LAST_PWD="$PWD" - _CMUX_LAST_PR_ACTION="checkout" - _CMUX_LAST_PR_TARGET="feature" - _cmux_precmd - printf 'HEAD_PATH=%s\\n' "$_CMUX_GIT_HEAD_PATH" - printf 'HEAD_LAST_PWD=%s\\n' "$_CMUX_GIT_HEAD_LAST_PWD" - printf 'LAST_PR_ACTION=%s\\n' "$_CMUX_LAST_PR_ACTION" - printf 'LOG< = [] - - TerminalSurface.applyManagedGitWatchEnvironment( - watchGitStatusEnabled: false, - to: &environment, - protectedKeys: &protectedKeys - ) - - XCTAssertEqual(environment["CMUX_NO_GIT_WATCH"], "1") - XCTAssertTrue(protectedKeys.contains("CMUX_NO_GIT_WATCH")) - } - - func testApplyManagedGitWatchEnvironmentClearsInheritedOptOutWhenEnabled() { - var environment = [ - "CMUX_NO_GIT_WATCH": "1" - ] - var protectedKeys: Set = [] - - TerminalSurface.applyManagedGitWatchEnvironment( - watchGitStatusEnabled: true, - to: &environment, - protectedKeys: &protectedKeys - ) - let merged = TerminalSurface.mergedStartupEnvironment( - base: environment, - protectedKeys: protectedKeys, - additionalEnvironment: [ - "CMUX_NO_GIT_WATCH": "1" - ], - initialEnvironmentOverrides: [ - "CMUX_NO_GIT_WATCH": "1" - ] - ) - - XCTAssertEqual(merged["CMUX_NO_GIT_WATCH"], "") - } - func testMergedStartupEnvironmentAllowsSessionReplayAndInitialEnvCMUXKeys() { let replayPath = "/tmp/cmux-replay-\(UUID().uuidString)" let merged = TerminalSurface.mergedStartupEnvironment( diff --git a/cmuxTests/GhosttyTerminalViewVisibilityPolicyTests.swift b/cmuxTests/GhosttyTerminalViewVisibilityPolicyTests.swift index 5c239d824cf8..fa521110dcc5 100644 --- a/cmuxTests/GhosttyTerminalViewVisibilityPolicyTests.swift +++ b/cmuxTests/GhosttyTerminalViewVisibilityPolicyTests.swift @@ -64,4 +64,277 @@ final class GhosttyTerminalViewVisibilityPolicyTests: XCTestCase { break } } + + @MainActor + func testTerminalTimestampStoreAssignsNewRowsFromScrollbarGrowth() { + let store = TerminalTimestampStore() + let first = Date(timeIntervalSince1970: 100) + let second = Date(timeIntervalSince1970: 140) + + store.record( + scrollbar: TerminalTimestampScrollbarState(total: 3, offset: 0, len: 3), + at: first, + markVisibleRows: true + ) + store.record( + scrollbar: TerminalTimestampScrollbarState(total: 5, offset: 2, len: 3), + at: second, + markVisibleRows: true + ) + + XCTAssertEqual( + store.visibleRows(for: TerminalTimestampScrollbarState(total: 5, offset: 2, len: 3)), + [ + TerminalTimestampVisibleRow(row: 2, timestamp: first), + TerminalTimestampVisibleRow(row: 3, timestamp: second), + TerminalTimestampVisibleRow(row: 4, timestamp: second), + ] + ) + } + + func testTerminalTimestampVisibleWindowTracksCurrentScrollPosition() { + let state = TerminalTimestampScrollbarState.visibleWindow( + total: 100, + fallbackLen: 3, + visibleTopRow: 42.25, + viewportHeight: 25, + cellHeight: 10 + ) + + XCTAssertEqual(state, TerminalTimestampScrollbarState(total: 100, offset: 42, len: 4)) + } + + @MainActor + func testTerminalTimestampStoreDoesNotInventOldRowsDuringUserScroll() { + let store = TerminalTimestampStore() + let first = Date(timeIntervalSince1970: 100) + let userScroll = Date(timeIntervalSince1970: 200) + + store.record( + scrollbar: TerminalTimestampScrollbarState(total: 8, offset: 5, len: 3), + at: first, + markVisibleRows: true + ) + store.record( + scrollbar: TerminalTimestampScrollbarState(total: 8, offset: 0, len: 3), + at: userScroll, + markVisibleRows: false + ) + + XCTAssertEqual( + store.visibleRows(for: TerminalTimestampScrollbarState(total: 8, offset: 0, len: 3)), + [] + ) + XCTAssertEqual( + store.visibleRows(for: TerminalTimestampScrollbarState(total: 8, offset: 5, len: 3)), + [ + TerminalTimestampVisibleRow(row: 5, timestamp: first), + TerminalTimestampVisibleRow(row: 6, timestamp: first), + TerminalTimestampVisibleRow(row: 7, timestamp: first), + ] + ) + } + + @MainActor + func testTerminalTimestampStoreMarksNewRowsWithoutBackfillingVisibleScrollback() { + let store = TerminalTimestampStore() + let first = Date(timeIntervalSince1970: 100) + let laterOutput = Date(timeIntervalSince1970: 200) + + store.record( + scrollbar: TerminalTimestampScrollbarState(total: 8, offset: 5, len: 3), + at: first, + markVisibleRows: true + ) + store.record( + scrollbar: TerminalTimestampScrollbarState(total: 10, offset: 0, len: 3), + at: laterOutput, + markVisibleRows: false + ) + + XCTAssertEqual( + store.visibleRows(for: TerminalTimestampScrollbarState(total: 10, offset: 0, len: 3)), + [] + ) + XCTAssertEqual( + store.visibleRows(for: TerminalTimestampScrollbarState(total: 10, offset: 8, len: 2)), + [ + TerminalTimestampVisibleRow(row: 8, timestamp: laterOutput), + TerminalTimestampVisibleRow(row: 9, timestamp: laterOutput), + ] + ) + } + + @MainActor + func testTerminalTimestampStorePrunesRowsOutsideRetentionWindow() { + let store = TerminalTimestampStore(maxRetainedRows: 3) + let timestamp = Date(timeIntervalSince1970: 100) + + store.record( + scrollbar: TerminalTimestampScrollbarState(total: 0, offset: 0, len: 0), + at: timestamp, + markVisibleRows: false + ) + store.record( + scrollbar: TerminalTimestampScrollbarState(total: 5, offset: 0, len: 5), + at: timestamp, + markVisibleRows: false + ) + + XCTAssertEqual( + store.visibleRows(for: TerminalTimestampScrollbarState(total: 5, offset: 0, len: 5)), + [ + TerminalTimestampVisibleRow(row: 2, timestamp: timestamp), + TerminalTimestampVisibleRow(row: 3, timestamp: timestamp), + TerminalTimestampVisibleRow(row: 4, timestamp: timestamp), + ] + ) + } + + @MainActor + func testTerminalTimestampStoreClearsRebasedRowsAfterScrollbackShrink() { + let store = TerminalTimestampStore() + let oldTimestamp = Date(timeIntervalSince1970: 100) + let reboundTimestamp = Date(timeIntervalSince1970: 200) + + store.record( + scrollbar: TerminalTimestampScrollbarState(total: 8, offset: 0, len: 8), + at: oldTimestamp, + markVisibleRows: true + ) + store.record( + scrollbar: TerminalTimestampScrollbarState(total: 5, offset: 0, len: 5), + at: reboundTimestamp, + markVisibleRows: true + ) + + XCTAssertEqual( + store.visibleRows(for: TerminalTimestampScrollbarState(total: 5, offset: 0, len: 5)), + [ + TerminalTimestampVisibleRow(row: 0, timestamp: reboundTimestamp), + TerminalTimestampVisibleRow(row: 1, timestamp: reboundTimestamp), + TerminalTimestampVisibleRow(row: 2, timestamp: reboundTimestamp), + TerminalTimestampVisibleRow(row: 3, timestamp: reboundTimestamp), + TerminalTimestampVisibleRow(row: 4, timestamp: reboundTimestamp), + ] + ) + } + + @MainActor + func testTerminalTimestampStoreKeepsVisibleRowsMarkedOutsideRetentionWindow() { + let store = TerminalTimestampStore(maxRetainedRows: 3) + let tailTimestamp = Date(timeIntervalSince1970: 100) + let visibleTimestamp = Date(timeIntervalSince1970: 200) + + store.record( + scrollbar: TerminalTimestampScrollbarState(total: 5, offset: 2, len: 3), + at: tailTimestamp, + markVisibleRows: true + ) + store.record( + scrollbar: TerminalTimestampScrollbarState(total: 5, offset: 0, len: 2), + at: visibleTimestamp, + markVisibleRows: true + ) + + XCTAssertEqual( + store.visibleRows(for: TerminalTimestampScrollbarState(total: 5, offset: 0, len: 2)), + [ + TerminalTimestampVisibleRow(row: 0, timestamp: visibleTimestamp), + TerminalTimestampVisibleRow(row: 1, timestamp: visibleTimestamp), + ] + ) + } + + @MainActor + func testTerminalTimestampStorePreservesMarkedVisibleRowsAcrossScrollUpdates() { + let store = TerminalTimestampStore(maxRetainedRows: 3) + let tailTimestamp = Date(timeIntervalSince1970: 100) + let visibleTimestamp = Date(timeIntervalSince1970: 200) + let scrollTimestamp = Date(timeIntervalSince1970: 300) + + store.record( + scrollbar: TerminalTimestampScrollbarState(total: 5, offset: 2, len: 3), + at: tailTimestamp, + markVisibleRows: true + ) + store.record( + scrollbar: TerminalTimestampScrollbarState(total: 5, offset: 0, len: 2), + at: visibleTimestamp, + markVisibleRows: true + ) + store.record( + scrollbar: TerminalTimestampScrollbarState(total: 5, offset: 0, len: 2), + at: scrollTimestamp, + markVisibleRows: false + ) + + XCTAssertEqual( + store.visibleRows(for: TerminalTimestampScrollbarState(total: 5, offset: 0, len: 2)), + [ + TerminalTimestampVisibleRow(row: 0, timestamp: visibleTimestamp), + TerminalTimestampVisibleRow(row: 1, timestamp: visibleTimestamp), + ] + ) + + store.record( + scrollbar: TerminalTimestampScrollbarState(total: 5, offset: 2, len: 3), + at: scrollTimestamp, + markVisibleRows: false + ) + + XCTAssertEqual( + store.visibleRows(for: TerminalTimestampScrollbarState(total: 5, offset: 0, len: 2)), + [] + ) + } + + @MainActor + func testTerminalTimestampStoreRetainsVisibleRowsAcrossAdvancingPruneCursor() { + let store = TerminalTimestampStore(maxRetainedRows: 3) + let tailTimestamp = Date(timeIntervalSince1970: 100) + let visibleTimestamp = Date(timeIntervalSince1970: 200) + let outputTimestamp = Date(timeIntervalSince1970: 300) + let scrollTimestamp = Date(timeIntervalSince1970: 400) + + store.record( + scrollbar: TerminalTimestampScrollbarState(total: 5, offset: 2, len: 3), + at: tailTimestamp, + markVisibleRows: true + ) + store.record( + scrollbar: TerminalTimestampScrollbarState(total: 5, offset: 0, len: 2), + at: visibleTimestamp, + markVisibleRows: true + ) + store.record( + scrollbar: TerminalTimestampScrollbarState(total: 7, offset: 0, len: 2), + at: outputTimestamp, + markVisibleRows: false + ) + store.record( + scrollbar: TerminalTimestampScrollbarState(total: 8, offset: 0, len: 2), + at: outputTimestamp, + markVisibleRows: false + ) + + XCTAssertEqual( + store.visibleRows(for: TerminalTimestampScrollbarState(total: 8, offset: 0, len: 2)), + [ + TerminalTimestampVisibleRow(row: 0, timestamp: visibleTimestamp), + TerminalTimestampVisibleRow(row: 1, timestamp: visibleTimestamp), + ] + ) + + store.record( + scrollbar: TerminalTimestampScrollbarState(total: 8, offset: 5, len: 3), + at: scrollTimestamp, + markVisibleRows: false + ) + + XCTAssertEqual( + store.visibleRows(for: TerminalTimestampScrollbarState(total: 8, offset: 0, len: 2)), + [] + ) + } } diff --git a/cmuxTests/KeyboardShortcutSettingsFileStoreStartupTests.swift b/cmuxTests/KeyboardShortcutSettingsFileStoreStartupTests.swift index 5d75ddfb9c87..0d7c8ce51aee 100644 --- a/cmuxTests/KeyboardShortcutSettingsFileStoreStartupTests.swift +++ b/cmuxTests/KeyboardShortcutSettingsFileStoreStartupTests.swift @@ -201,7 +201,7 @@ final class KeyboardShortcutSettingsFileStoreStartupTests: XCTestCase { XCTAssertEqual(dockTileNotificationCount, 0) } - func testManagedAppearanceReplayUpdatesDefaultWithoutLiveAppearanceApplication() throws { + func testManagedAppearanceInitialLoadDoesNotSynchronizeTerminalThemeUntilReload() throws { let defaults = UserDefaults.standard let key = AppearanceSettings.appearanceModeKey @@ -227,37 +227,31 @@ final class KeyboardShortcutSettingsFileStoreStartupTests: XCTestCase { var appliedAppearanceNames: [NSAppearance.Name?] = [] var synchronizedAppearanceNames: [(appearance: NSAppearance.Name?, source: String)] = [] - AppearanceSettings.setLiveEnvironmentProviderForTesting { - AppearanceSettings.LiveApplyEnvironment( - setApplicationAppearance: { appearance in - appliedAppearanceNames.append(appearance?.bestMatch(from: [.darkAqua, .aqua])) - }, - synchronizeTerminalThemeWithAppearance: { appearance, source in - synchronizedAppearanceNames.append(( - appearance: appearance?.bestMatch(from: [.darkAqua, .aqua]), - source: source - )) - }, - systemAppearance: { - NSAppearance(named: .aqua) - } - ) - } + let environment = AppearanceSettings.LiveApplyEnvironment( + setApplicationAppearance: { appearance in + appliedAppearanceNames.append(appearance?.bestMatch(from: [.darkAqua, .aqua])) + }, + synchronizeTerminalThemeWithAppearance: { appearance, source in + synchronizedAppearanceNames.append(( + appearance: appearance?.bestMatch(from: [.darkAqua, .aqua]), + source: source + )) + }, + systemAppearance: { + NSAppearance(named: .aqua) + } + ) let store = KeyboardShortcutSettingsFileStore( primaryPath: settingsFileURL.path, fallbackPath: nil, additionalFallbackPaths: [], + appearanceEnvironment: environment, startWatching: false ) XCTAssertEqual(defaults.string(forKey: key), AppearanceMode.dark.rawValue) - XCTAssertTrue(appliedAppearanceNames.isEmpty) - XCTAssertTrue(synchronizedAppearanceNames.isEmpty) - - store.applyDeferredManagedDefaultSideEffects() - - XCTAssertTrue(appliedAppearanceNames.isEmpty) + XCTAssertEqual(appliedAppearanceNames, [.darkAqua]) XCTAssertTrue(synchronizedAppearanceNames.isEmpty) try withExtendedLifetime(store) { @@ -275,81 +269,10 @@ final class KeyboardShortcutSettingsFileStoreStartupTests: XCTestCase { } XCTAssertEqual(defaults.string(forKey: key), AppearanceMode.light.rawValue) - XCTAssertTrue(appliedAppearanceNames.isEmpty) - XCTAssertTrue(synchronizedAppearanceNames.isEmpty) - } - } - - func testSettingsFileStoreDoesNotReachTerminalReloadThroughManagedAppearanceReplay() throws { - let defaults = UserDefaults.standard - let key = AppearanceSettings.appearanceModeKey - - try preservingDefaults(keys: [key, settingsFileBackupsDefaultsKey, importedManagedDefaultsKey]) { - defaults.removeObject(forKey: key) - defaults.removeObject(forKey: settingsFileBackupsDefaultsKey) - defaults.removeObject(forKey: importedManagedDefaultsKey) - - let directoryURL = try makeTemporaryDirectory() - defer { try? FileManager.default.removeItem(at: directoryURL) } - - let settingsFileURL = directoryURL.appendingPathComponent("cmux.json", isDirectory: false) - try writeSettingsFile( - """ - { - "app": { - "appearance": "dark" - } - } - """, - to: settingsFileURL - ) - - var storeInitInProgress = true - var reachedTerminalReloadDuringInit = false - var terminalReloadSources: [String] = [] - AppearanceSettings.setLiveEnvironmentProviderForTesting { - AppearanceSettings.LiveApplyEnvironment( - setApplicationAppearance: { _ in }, - synchronizeTerminalThemeWithAppearance: { _, source in - if storeInitInProgress { - reachedTerminalReloadDuringInit = true - } - terminalReloadSources.append(source) - }, - systemAppearance: { - NSAppearance(named: .aqua) - } - ) - } - - let store = KeyboardShortcutSettingsFileStore( - primaryPath: settingsFileURL.path, - fallbackPath: nil, - additionalFallbackPaths: [], - startWatching: false - ) - storeInitInProgress = false - - XCTAssertFalse(reachedTerminalReloadDuringInit) - XCTAssertTrue(terminalReloadSources.isEmpty) - - try writeSettingsFile( - """ - { - "app": { - "appearance": "light" - } - } - """, - to: settingsFileURL - ) - store.reload() - - XCTAssertEqual(defaults.string(forKey: key), AppearanceMode.light.rawValue) - XCTAssertTrue( - terminalReloadSources.isEmpty, - "CmuxSettingsFileStore must not synchronously route managed appearance replay into Ghostty reloadConfiguration" - ) + XCTAssertEqual(appliedAppearanceNames, [.darkAqua, .aqua]) + XCTAssertEqual(synchronizedAppearanceNames.count, 1) + XCTAssertEqual(synchronizedAppearanceNames.first?.appearance, .aqua) + XCTAssertEqual(synchronizedAppearanceNames.first?.source, "cmuxConfig.applyManagedDefault") } } @@ -499,7 +422,7 @@ final class KeyboardShortcutSettingsFileStoreStartupTests: XCTestCase { } @MainActor - func testSettingsFileStoreInitialAppearanceImportDoesNotApplyLiveAppearance() throws { + func testSettingsFileStoreInitialAppearanceReplayDoesNotSynchronizeTerminalTheme() throws { let defaults = UserDefaults.standard let key = AppearanceSettings.appearanceModeKey @@ -555,7 +478,7 @@ final class KeyboardShortcutSettingsFileStoreStartupTests: XCTestCase { store.applyDeferredManagedDefaultSideEffects() - XCTAssertNil(appliedAppearanceName) + XCTAssertEqual(appliedAppearanceName, .darkAqua) XCTAssertNil(synchronizedAppearanceName) XCTAssertTrue(synchronizedSources.isEmpty) @@ -572,9 +495,9 @@ final class KeyboardShortcutSettingsFileStoreStartupTests: XCTestCase { store.reload() XCTAssertEqual(defaults.string(forKey: key), AppearanceMode.light.rawValue) - XCTAssertNil(appliedAppearanceName) - XCTAssertNil(synchronizedAppearanceName) - XCTAssertTrue(synchronizedSources.isEmpty) + XCTAssertEqual(appliedAppearanceName, .aqua) + XCTAssertEqual(synchronizedAppearanceName, .aqua) + XCTAssertEqual(synchronizedSources, ["cmuxConfig.applyManagedDefault"]) } } @@ -769,6 +692,41 @@ final class KeyboardShortcutSettingsFileStoreStartupTests: XCTestCase { XCTAssertEqual(defaults.object(forKey: key) as? Bool, false) } + func testSettingsFileStoreAppliesTerminalTimestampSetting() throws { + let defaults = UserDefaults.standard + let key = TerminalTimestampsSettings.showTimestampsKey + + try preservingDefaults(keys: [key, settingsFileBackupsDefaultsKey, importedManagedDefaultsKey]) { + defaults.removeObject(forKey: key) + defaults.removeObject(forKey: settingsFileBackupsDefaultsKey) + defaults.removeObject(forKey: importedManagedDefaultsKey) + + let directoryURL = try makeTemporaryDirectory() + defer { try? FileManager.default.removeItem(at: directoryURL) } + + let settingsFileURL = directoryURL.appendingPathComponent("cmux.json", isDirectory: false) + try writeSettingsFile( + """ + { + "terminal": { + "showTimestamps": true + } + } + """, + to: settingsFileURL + ) + + _ = KeyboardShortcutSettingsFileStore( + primaryPath: settingsFileURL.path, + fallbackPath: nil, + additionalFallbackPaths: [], + startWatching: false + ) + + XCTAssertEqual(defaults.object(forKey: key) as? Bool, true) + } + } + func testSettingsFileStoreAppliesAutomationRipgrepBinaryPath() throws { let defaults = UserDefaults.standard let key = "ripgrepCustomBinaryPath" diff --git a/cmuxTests/KeyboardShortcutSpaceKeyTests.swift b/cmuxTests/KeyboardShortcutSpaceKeyTests.swift index 7ffd4363b10c..31d6a9eb594e 100644 --- a/cmuxTests/KeyboardShortcutSpaceKeyTests.swift +++ b/cmuxTests/KeyboardShortcutSpaceKeyTests.swift @@ -45,9 +45,6 @@ final class KeyboardShortcutSpaceKeyTests: XCTestCase { XCTAssertEqual(StoredShortcut.parseConfig("cmd+shift+spacebar")?.configIdentifier, "cmd+shift+space") XCTAssertEqual(StoredShortcut.parseConfig("cmd+shift+ ")?.configIdentifier, "cmd+shift+space") XCTAssertEqual(StoredShortcut.parseConfig(" ")?.configIdentifier, "space") - XCTAssertEqual(StoredShortcut.parseConfig(" "), .unbound) - XCTAssertEqual(StoredShortcut.parseConfig("\t"), .unbound) - XCTAssertNil(StoredShortcut.parseConfig("cmd+shift+ ")) } func testSettingsFileStoreParsesSpaceShortcutBinding() throws { diff --git a/cmuxTests/MarkdownPanelTests.swift b/cmuxTests/MarkdownPanelTests.swift index 7aea595d2189..e77dfb552924 100644 --- a/cmuxTests/MarkdownPanelTests.swift +++ b/cmuxTests/MarkdownPanelTests.swift @@ -526,23 +526,38 @@ final class MarkdownPanelTests: XCTestCase { components.queryItems = [URLQueryItem(name: "url", value: imageURL.absoluteString)] let localImageURL = try XCTUnwrap(components.url) + let frame = NSRect(x: 0, y: 0, width: 320, height: 240) + let configuration = WKWebViewConfiguration() let coordinator = MarkdownWebRenderer.Coordinator() - defer { coordinator.cancelImageLoads() } - - let finished = expectation(description: "local image request finished") - let task = MarkdownURLSchemeTaskSpy( - request: URLRequest(url: localImageURL), - finishedExpectation: finished - ) - coordinator.webView(WKWebView(frame: .zero), start: task) - - await fulfillment(of: [finished], timeout: 2) - let snapshot = task.snapshot() - XCTAssertEqual(snapshot.responses.count, 1) - XCTAssertEqual(snapshot.responses.first?.mimeType, "image/png") - XCTAssertEqual(snapshot.data, Data()) - XCTAssertTrue(snapshot.didFinish) - XCTAssertNil(snapshot.error) + configuration.setURLSchemeHandler(coordinator, forURLScheme: MarkdownWebRenderer.localImageURLScheme) + let webView = MarkdownWebView(frame: frame, configuration: configuration) + coordinator.webView = webView + let window = NSWindow(contentRect: frame, styleMask: [.borderless], backing: .buffered, defer: false) + window.contentView = webView + window.orderFrontRegardless() + defer { + webView.navigationDelegate = nil + coordinator.webView = nil + coordinator.cancelImageLoads() + window.close() + } + + let loaded = expectation(description: "markdown image shell loaded") + let loadDelegate = MarkdownShellLoadDelegate(expectation: loaded) + webView.navigationDelegate = loadDelegate + webView.loadHTMLString( + "\"outside\"", + baseURL: nil + ) + await fulfillment(of: [loaded], timeout: 5) + if let error = loadDelegate.error { + throw error + } + + let image = try await waitForMarkdownImage(in: webView) + XCTAssertEqual(image["complete"] as? Bool, true) + XCTAssertEqual(image["naturalWidth"] as? Int, 0) + XCTAssertEqual(image["naturalHeight"] as? Int, 0) } func testMarkdownRenderLoadsSafeDataImage() async throws { @@ -1334,65 +1349,6 @@ private final class MarkdownShellLoadDelegate: NSObject, WKNavigationDelegate { } } -private final class MarkdownURLSchemeTaskSpy: NSObject, WKURLSchemeTask { - struct Snapshot { - let responses: [URLResponse] - let data: Data - let didFinish: Bool - let error: Error? - } - - let request: URLRequest - private let finishedExpectation: XCTestExpectation - private let lock = NSLock() - private var responses: [URLResponse] = [] - private var receivedData = Data() - private var finished = false - private var receivedError: Error? - - init(request: URLRequest, finishedExpectation: XCTestExpectation) { - self.request = request - self.finishedExpectation = finishedExpectation - } - - func didReceive(_ response: URLResponse) { - lock.lock() - responses.append(response) - lock.unlock() - } - - func didReceive(_ data: Data) { - lock.lock() - receivedData.append(data) - lock.unlock() - } - - func didFinish() { - lock.lock() - finished = true - lock.unlock() - finishedExpectation.fulfill() - } - - func didFailWithError(_ error: Error) { - lock.lock() - receivedError = error - lock.unlock() - finishedExpectation.fulfill() - } - - func snapshot() -> Snapshot { - lock.lock() - defer { lock.unlock() } - return Snapshot( - responses: responses, - data: receivedData, - didFinish: finished, - error: receivedError - ) - } -} - private final class MarkdownRemoteImageHoldingSchemeHandler: NSObject, WKURLSchemeHandler { private var tasks: [ObjectIdentifier: WKURLSchemeTask] = [:] diff --git a/cmuxTests/NotificationAndMenuBarTests.swift b/cmuxTests/NotificationAndMenuBarTests.swift index 86e2aff3fe16..abfd1f29ddb8 100644 --- a/cmuxTests/NotificationAndMenuBarTests.swift +++ b/cmuxTests/NotificationAndMenuBarTests.swift @@ -1332,9 +1332,6 @@ final class NotificationDockBadgeTests: XCTestCase { scheduler: { _, block in block() }, urlOpener: { openedURL = $0 } ) - addTeardownBlock { - store.resetNotificationSettingsPromptHooksForTesting() - } store.promptToEnableNotificationsForTesting() let drained = expectation(description: "main queue drained") @@ -1343,14 +1340,9 @@ final class NotificationDockBadgeTests: XCTestCase { XCTAssertEqual(alertSpy.beginSheetModalCallCount, 1) XCTAssertEqual(alertSpy.runModalCallCount, 0) - guard let encodedBundleIdentifier = Bundle.main.bundleIdentifier? - .addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) else { - XCTFail("Expected test bundle identifier to be URL-encodable") - return - } XCTAssertEqual( openedURL?.absoluteString, - "x-apple.systempreferences:com.apple.Notifications-Settings.extension?id=\(encodedBundleIdentifier)" + "x-apple.systempreferences:com.apple.preference.notifications" ) } @@ -1365,13 +1357,8 @@ final class NotificationDockBadgeTests: XCTestCase { windowProvider: { promptWindow }, alertFactory: { alertSpy }, scheduler: { _, block in queuedRetryBlocks.append(block) }, - urlOpener: { _ in - XCTFail("Should not open settings for Not Now response") - } + urlOpener: { _ in XCTFail("Should not open settings for Not Now response") } ) - addTeardownBlock { - store.resetNotificationSettingsPromptHooksForTesting() - } store.promptToEnableNotificationsForTesting() let drained = expectation(description: "main queue drained") diff --git a/cmuxTests/PanelOwnedNativeViewSessionTests.swift b/cmuxTests/PanelOwnedNativeViewSessionTests.swift deleted file mode 100644 index b793bd8e23ea..000000000000 --- a/cmuxTests/PanelOwnedNativeViewSessionTests.swift +++ /dev/null @@ -1,90 +0,0 @@ -import AppKit -import XCTest - -#if canImport(cmux_DEV) -@testable import cmux_DEV -#elseif canImport(cmux) -@testable import cmux -#endif - -@MainActor -final class PanelOwnedNativeViewSessionTests: XCTestCase { - private final class ProbeView: NSView { - var isClosed = false - var configureCount = 0 - } - - func testUpdateAfterCloseDoesNotReAdoptClosedNativeView() { - var makeCount = 0 - let session = PanelOwnedNativeViewSession( - makeView: { - makeCount += 1 - return ProbeView(frame: .zero) - }, - closeView: { view in - view.isClosed = true - view.removeFromSuperview() - } - ) - - let initialView = session.view { view in - XCTAssertFalse(view.isClosed) - view.configureCount += 1 - } - - XCTAssertEqual(makeCount, 1) - XCTAssertEqual(initialView.configureCount, 1) - - session.close() - - XCTAssertTrue(initialView.isClosed) - - session.update(initialView) { view in - XCTFail("Closed native views must not be re-adopted or configured after the panel session closes") - view.configureCount += 1 - } - - XCTAssertEqual(initialView.configureCount, 1) - - let replacementView = session.view { view in - XCTAssertFalse(view.isClosed) - view.configureCount += 1 - } - - XCTAssertFalse(replacementView === initialView) - XCTAssertEqual(replacementView.configureCount, 1) - XCTAssertEqual(makeCount, 2) - } - - func testQuickLookSessionCreatesFreshViewForEachRepresentableMount() throws { - let fileURL = URL(fileURLWithPath: NSTemporaryDirectory()) - .appendingPathComponent("cmux-4455-quicklook-\(UUID().uuidString).bin") - try Data([0, 1, 2, 3]).write(to: fileURL) - defer { try? FileManager.default.removeItem(at: fileURL) } - - let panel = FilePreviewPanel(workspaceId: UUID(), filePath: fileURL.path) - let session = FilePreviewQuickLookSession() - - let firstView = session.view( - panel: panel, - isVisibleInUI: true, - backgroundColor: .clear, - drawsBackground: false - ) - let remountedView = session.view( - panel: panel, - isVisibleInUI: true, - backgroundColor: .clear, - drawsBackground: false - ) - - XCTAssertFalse( - firstView === remountedView, - "QuickLook views must be owned by the SwiftUI representable mount, because AppKit can deactivate a QLPreviewView when that mount is removed" - ) - - session.dismantle(firstView) - session.dismantle(remountedView) - panel.close() - } -} diff --git a/cmuxTests/PiVaultAgentPersistenceTests.swift b/cmuxTests/PiVaultAgentPersistenceTests.swift index 3672003751ba..d0468f525a5f 100644 --- a/cmuxTests/PiVaultAgentPersistenceTests.swift +++ b/cmuxTests/PiVaultAgentPersistenceTests.swift @@ -68,206 +68,6 @@ final class PiVaultAgentPersistenceTests: XCTestCase { XCTAssertEqual(SessionAgent.registered(agent).assetName, "AgentIcons/Pi") } - func testBuiltInAntigravityRegistrationUsesBrandedIconAsset() { - let agent = RegisteredSessionAgent(registration: CmuxVaultAgentRegistration.builtInAntigravity) - - XCTAssertEqual(agent.iconAssetName, "AgentIcons/Antigravity") - XCTAssertEqual(SessionAgent.registered(agent).assetName, "AgentIcons/Antigravity") - XCTAssertEqual(CmuxVaultAgentRegistration.builtInAntigravity.detect.processNames, ["agy", "antigravity"]) - } - - func testBuiltInAntigravityRegistrationLoadsHistoryDisplayAndWorkspace() async throws { - let tempDir = FileManager.default.temporaryDirectory - .appendingPathComponent("cmux-antigravity-vault-history-\(UUID().uuidString)", isDirectory: true) - try FileManager.default.createDirectory(at: tempDir, withIntermediateDirectories: true) - defer { try? FileManager.default.removeItem(at: tempDir) } - - let historyURL = tempDir.appendingPathComponent("history.jsonl", isDirectory: false) - try """ - {"conversationId":"antigravity-conversation-123","display":"Implement Antigravity notifications","timestamp":1779231774516,"workspace":"/tmp/antigravity repo"} - """.write(to: historyURL, atomically: true, encoding: .utf8) - - var registration = CmuxVaultAgentRegistration.builtInAntigravity - registration.sessionDirectory = tempDir.path - let entries = await SessionIndexStore.loadRegisteredAgentEntries( - registration: registration, - needle: "", - cwdFilter: nil, - offset: 0, - limit: 10 - ) - - let entry = try XCTUnwrap(entries.first) - XCTAssertEqual(entry.agent, .registered(RegisteredSessionAgent(registration: registration))) - XCTAssertEqual(entry.sessionId, "antigravity-conversation-123") - XCTAssertEqual(entry.title, "Implement Antigravity notifications") - XCTAssertEqual(entry.cwd, "/tmp/antigravity repo") - XCTAssertEqual( - entry.resumeCommand, - "cd '/tmp/antigravity repo' && 'agy' '--conversation' 'antigravity-conversation-123'" - ) - } - - func testBuiltInAntigravityRegistrationIndexesEachHistoryConversation() async throws { - let tempDir = FileManager.default.temporaryDirectory - .appendingPathComponent("cmux-antigravity-vault-conversations-\(UUID().uuidString)", isDirectory: true) - try FileManager.default.createDirectory(at: tempDir, withIntermediateDirectories: true) - defer { try? FileManager.default.removeItem(at: tempDir) } - - let historyURL = tempDir.appendingPathComponent("history.jsonl", isDirectory: false) - try """ - {"display":"first prompt","timestamp":1779262970000,"workspace":"/tmp/antigravity repo","conversationId":"conversation-a"} - {"display":"newer prompt","timestamp":1779262980000,"workspace":"/tmp/antigravity repo","conversationId":"conversation-b"} - {"display":"unresumable prompt","timestamp":1779262990000,"workspace":"/tmp/antigravity repo"} - {"display":"latest prompt","timestamp":1779263000000,"workspace":"/tmp/antigravity repo","conversationId":"conversation-a"} - """.write(to: historyURL, atomically: true, encoding: .utf8) - - var registration = CmuxVaultAgentRegistration.builtInAntigravity - registration.sessionDirectory = tempDir.path - let entries = await SessionIndexStore.loadRegisteredAgentEntries( - registration: registration, - needle: "", - cwdFilter: nil, - offset: 0, - limit: 10 - ) - - XCTAssertEqual(entries.map(\.sessionId), ["conversation-a", "conversation-b"]) - XCTAssertEqual(entries.map(\.title), ["latest prompt", "newer prompt"]) - XCTAssertEqual(entries.map(\.cwd), ["/tmp/antigravity repo", "/tmp/antigravity repo"]) - - let filtered = await SessionIndexStore.loadRegisteredAgentEntries( - registration: registration, - needle: "newer", - cwdFilter: nil, - offset: 0, - limit: 10 - ) - XCTAssertEqual(filtered.map(\.sessionId), ["conversation-b"]) - XCTAssertEqual( - filtered.first?.resumeCommand, - "cd '/tmp/antigravity repo' && 'agy' '--conversation' 'conversation-b'" - ) - } - - func testRegisteredAgentJSONLWorkspaceKeyIsSharedCWDMetadata() async throws { - let tempDir = FileManager.default.temporaryDirectory - .appendingPathComponent("cmux-registered-workspace-cwd-\(UUID().uuidString)", isDirectory: true) - try FileManager.default.createDirectory(at: tempDir, withIntermediateDirectories: true) - defer { try? FileManager.default.removeItem(at: tempDir) } - - let sessionFile = tempDir.appendingPathComponent("metadata.jsonl") - try """ - {"sessionId":"native-session-123","workspace":"/tmp/acme-workspace","title":"Resume Acme"} - """.write(to: sessionFile, atomically: true, encoding: .utf8) - - let registration = CmuxVaultAgentRegistration( - id: "acme-agent", - name: "Acme Agent", - detect: CmuxVaultAgentDetectRule(processName: "acme-agent"), - sessionIdSource: .argvOption("--session"), - resumeCommand: "acme-agent --session {{sessionId}}", - cwd: .preserve, - sessionDirectory: tempDir.path - ) - - let entries = await SessionIndexStore.loadRegisteredAgentEntries( - registration: registration, - needle: "", - cwdFilter: nil, - offset: 0, - limit: 10 - ) - - let entry = try XCTUnwrap(entries.first) - XCTAssertEqual(entry.sessionId, "native-session-123") - XCTAssertEqual(entry.title, "Resume Acme") - XCTAssertEqual(entry.cwd, "/tmp/acme-workspace") - } - - func testRegisteredAgentJSONLDisplayFieldIsNotSharedTitleMetadata() async throws { - let tempDir = FileManager.default.temporaryDirectory - .appendingPathComponent("cmux-registered-display-title-\(UUID().uuidString)", isDirectory: true) - try FileManager.default.createDirectory(at: tempDir, withIntermediateDirectories: true) - defer { try? FileManager.default.removeItem(at: tempDir) } - - let sessionFile = tempDir.appendingPathComponent("metadata.jsonl") - try """ - {"sessionId":"native-session-123","cwd":"/tmp/acme","display":"Antigravity-only prompt"} - """.write(to: sessionFile, atomically: true, encoding: .utf8) - - let registration = CmuxVaultAgentRegistration( - id: "acme-agent", - name: "Acme Agent", - detect: CmuxVaultAgentDetectRule(processName: "acme-agent"), - sessionIdSource: .argvOption("--session"), - resumeCommand: "acme-agent --session {{sessionId}}", - cwd: .preserve, - sessionDirectory: tempDir.path - ) - - let entries = await SessionIndexStore.loadRegisteredAgentEntries( - registration: registration, - needle: "", - cwdFilter: nil, - offset: 0, - limit: 10 - ) - - let entry = try XCTUnwrap(entries.first) - XCTAssertEqual(entry.sessionId, "native-session-123") - XCTAssertEqual(entry.title, "") - XCTAssertEqual( - entry.displayTitle, - String(localized: "sessionIndex.untitled", defaultValue: "Untitled chat") - ) - } - - func testRegisteredAgentJSONLSessionIDDoesNotUseAntigravityConversationID() async throws { - let tempDir = FileManager.default.temporaryDirectory - .appendingPathComponent("cmux-registered-session-id-\(UUID().uuidString)", isDirectory: true) - try FileManager.default.createDirectory(at: tempDir, withIntermediateDirectories: true) - defer { try? FileManager.default.removeItem(at: tempDir) } - - let sessionFile = tempDir.appendingPathComponent("metadata.jsonl") - try """ - {"conversationId":"foreign-conversation","sessionId":"native-session-123","cwd":"/tmp/acme","title":"Resume Acme"} - """.write(to: sessionFile, atomically: true, encoding: .utf8) - - let registration = CmuxVaultAgentRegistration( - id: "acme-agent", - name: "Acme Agent", - detect: CmuxVaultAgentDetectRule(processName: "acme-agent"), - sessionIdSource: .argvOption("--session"), - resumeCommand: "acme-agent --session {{sessionId}}", - cwd: .preserve, - sessionDirectory: tempDir.path - ) - - let entries = await SessionIndexStore.loadRegisteredAgentEntries( - registration: registration, - needle: "", - cwdFilter: nil, - offset: 0, - limit: 10 - ) - - let entry = try XCTUnwrap(entries.first) - XCTAssertEqual(entry.sessionId, "native-session-123") - XCTAssertEqual(entry.resumeCommand, "cd '/tmp/acme' && 'acme-agent' '--session' 'native-session-123'") - } - - func testBuiltInGrokRegistrationUsesNativeSessionDirectory() { - let registration = CmuxVaultAgentRegistration.builtInGrok - - XCTAssertEqual(registration.id, "grok") - XCTAssertEqual(registration.sessionIdSource, .grokSessionDirectory) - XCTAssertEqual(registration.sessionDirectory, "~/.grok/sessions") - XCTAssertEqual(registration.detect.processNames, ["grok", "grok-macos-aarch64", "grok-macos-aarch"]) - XCTAssertTrue(registration.detect.argvContains.isEmpty) - XCTAssertEqual(SessionAgent.grok.assetName, "AgentIcons/Grok") - } - func testRegisteredAgentTemplateFailsClosedWhenPlaceholderIsUnavailable() { let registration = CmuxVaultAgentRegistration( id: "acme-agent", @@ -606,403 +406,6 @@ final class PiVaultAgentPersistenceTests: XCTestCase { XCTAssertEqual(entry.cwd, cwd) } - func testGrokVaultLoadsNativeChatHistoryFromEncodedDirectory() async throws { - let tempDir = FileManager.default.temporaryDirectory - .appendingPathComponent("cmux-grok-vault-\(UUID().uuidString)", isDirectory: true) - try FileManager.default.createDirectory(at: tempDir, withIntermediateDirectories: true) - defer { try? FileManager.default.removeItem(at: tempDir) } - - let cwd = "/tmp/grok repo" - let sessionId = "grok-session-123" - let grokHome = tempDir.appendingPathComponent("grok-home", isDirectory: true) - let sessionsRoot = grokHome.appendingPathComponent("sessions", isDirectory: true) - let historyURL = sessionsRoot - .appendingPathComponent(GrokSessionLocator.encodedSessionCWD(cwd), isDirectory: true) - .appendingPathComponent(sessionId, isDirectory: true) - .appendingPathComponent("chat_history.jsonl", isDirectory: false) - try FileManager.default.createDirectory( - at: historyURL.deletingLastPathComponent(), - withIntermediateDirectories: true - ) - try """ - {"type":"assistant","content":"assistant preface"} - {"type":"user","content":"Implement Grok Vault","model":"grok-4","permissionMode":"auto","sandboxMode":"danger-full-access","git":{"branch":"issue-4394-grok-vault-resume"}} - {"type":"assistant","content":"done"} - """.write(to: historyURL, atomically: true, encoding: .utf8) - - var registration = CmuxVaultAgentRegistration.builtInGrok - registration.sessionDirectory = sessionsRoot.path - let entries = await SessionIndexStore.loadGrokEntries( - registration: registration, - needle: "", - cwdFilter: nil, - offset: 0, - limit: 10 - ) - - let entry = try XCTUnwrap(entries.first) - XCTAssertEqual(entry.agent, .grok) - XCTAssertEqual(entry.sessionId, sessionId) - XCTAssertEqual(entry.title, "Implement Grok Vault") - XCTAssertEqual(entry.cwd, cwd) - XCTAssertEqual(entry.gitBranch, "issue-4394-grok-vault-resume") - XCTAssertEqual(entry.fileURL, historyURL) - XCTAssertEqual( - entry.resumeCommand, - "cd '/tmp/grok repo' && 'env' 'GROK_HOME=\(grokHome.path)' 'grok' '-r' 'grok-session-123' '-m' 'grok-4' '--permission-mode' 'auto' '--sandbox' 'danger-full-access'" - ) - } - - func testGrokVaultTitlePrefersUserQueryOverInjectedMetadata() async throws { - let tempDir = FileManager.default.temporaryDirectory - .appendingPathComponent("cmux-grok-vault-metadata-title-\(UUID().uuidString)", isDirectory: true) - try FileManager.default.createDirectory(at: tempDir, withIntermediateDirectories: true) - defer { try? FileManager.default.removeItem(at: tempDir) } - - let cwd = "/tmp/grok metadata repo" - let sessionId = "grok-metadata-session" - let sessionsRoot = tempDir.appendingPathComponent("sessions", isDirectory: true) - let historyURL = sessionsRoot - .appendingPathComponent(GrokSessionLocator.encodedSessionCWD(cwd), isDirectory: true) - .appendingPathComponent(sessionId, isDirectory: true) - .appendingPathComponent("chat_history.jsonl", isDirectory: false) - try FileManager.default.createDirectory( - at: historyURL.deletingLastPathComponent(), - withIntermediateDirectories: true - ) - - let userContent = """ - - OS Version: macos 26.4 - - - Current branch: issue-4394-grok-vault-resume - - - Implement native Vault metadata - - """ - let records: [[String: Any]] = [ - ["type": "system", "content": "You are Grok"], - ["type": "user", "content": userContent, "model": "grok-4"], - ] - let jsonLines = try records.map { record in - let data = try JSONSerialization.data(withJSONObject: record, options: [.sortedKeys]) - return String(decoding: data, as: UTF8.self) - }.joined(separator: "\n") - try (jsonLines + "\n").write(to: historyURL, atomically: true, encoding: .utf8) - - var registration = CmuxVaultAgentRegistration.builtInGrok - registration.sessionDirectory = sessionsRoot.path - let entries = await SessionIndexStore.loadGrokEntries( - registration: registration, - needle: "", - cwdFilter: nil, - offset: 0, - limit: 10 - ) - - let entry = try XCTUnwrap(entries.first) - XCTAssertEqual(entry.title, "Implement native Vault metadata") - } - - func testGrokVaultFindsBranchAfterStableMetadata() async throws { - let tempDir = FileManager.default.temporaryDirectory - .appendingPathComponent("cmux-grok-vault-late-branch-\(UUID().uuidString)", isDirectory: true) - try FileManager.default.createDirectory(at: tempDir, withIntermediateDirectories: true) - defer { try? FileManager.default.removeItem(at: tempDir) } - - let cwd = "/tmp/grok late branch" - let sessionId = "grok-late-branch-session" - let sessionsRoot = tempDir.appendingPathComponent("sessions", isDirectory: true) - let historyURL = sessionsRoot - .appendingPathComponent(GrokSessionLocator.encodedSessionCWD(cwd), isDirectory: true) - .appendingPathComponent(sessionId, isDirectory: true) - .appendingPathComponent("chat_history.jsonl", isDirectory: false) - try FileManager.default.createDirectory( - at: historyURL.deletingLastPathComponent(), - withIntermediateDirectories: true - ) - try """ - {"type":"user","content":"Find late branch","model":"grok-4","permissionMode":"auto","sandboxMode":"danger-full-access"} - {"type":"assistant","content":"Working","git":{"branch":"late-branch"}} - """.write(to: historyURL, atomically: true, encoding: .utf8) - - var registration = CmuxVaultAgentRegistration.builtInGrok - registration.sessionDirectory = sessionsRoot.path - let entries = await SessionIndexStore.loadGrokEntries( - registration: registration, - needle: "", - cwdFilter: nil, - offset: 0, - limit: 10 - ) - - let entry = try XCTUnwrap(entries.first) - XCTAssertEqual(entry.gitBranch, "late-branch") - } - - func testGrokVaultLoadsHookObservedShellGrokHome() async throws { - let tempDir = FileManager.default.temporaryDirectory - .appendingPathComponent("cmux-grok-vault-observed-home-\(UUID().uuidString)", isDirectory: true) - try FileManager.default.createDirectory(at: tempDir, withIntermediateDirectories: true) - defer { try? FileManager.default.removeItem(at: tempDir) } - - let homeDirectory = tempDir.appendingPathComponent("home", isDirectory: true) - let hookStore = homeDirectory - .appendingPathComponent(".cmuxterm", isDirectory: true) - .appendingPathComponent("grok-hook-sessions.json", isDirectory: false) - try FileManager.default.createDirectory(at: hookStore.deletingLastPathComponent(), withIntermediateDirectories: true) - - let cwd = "/tmp/grok observed home" - let sessionId = "grok-observed-home-session" - let grokHome = tempDir.appendingPathComponent("shell-grok-home", isDirectory: true) - let historyURL = grokHome - .appendingPathComponent("sessions", isDirectory: true) - .appendingPathComponent(GrokSessionLocator.encodedSessionCWD(cwd), isDirectory: true) - .appendingPathComponent(sessionId, isDirectory: true) - .appendingPathComponent("chat_history.jsonl", isDirectory: false) - try FileManager.default.createDirectory( - at: historyURL.deletingLastPathComponent(), - withIntermediateDirectories: true - ) - try """ - {"type":"user","content":"Find sessions under shell GROK_HOME","model":"grok-4","permissionMode":"auto","sandboxMode":"danger-full-access"} - """.write(to: historyURL, atomically: true, encoding: .utf8) - - try """ - { - "version": 1, - "sessions": { - "\(sessionId)": { - "launchCommand": { - "environment": { - "GROK_HOME": "\(grokHome.path)" - } - } - } - } - } - """.write(to: hookStore, atomically: true, encoding: .utf8) - - let entries = await SessionIndexStore.loadGrokEntries( - registration: .builtInGrok, - needle: "", - cwdFilter: nil, - offset: 0, - limit: 10, - environment: [:], - homeDirectory: homeDirectory.path - ) - - let entry = try XCTUnwrap(entries.first) - XCTAssertEqual(entry.sessionId, sessionId) - XCTAssertEqual(entry.title, "Find sessions under shell GROK_HOME") - XCTAssertEqual(entry.cwd, cwd) - XCTAssertEqual( - entry.resumeCommand, - "cd '/tmp/grok observed home' && 'env' 'GROK_HOME=\(grokHome.path)' 'grok' '-r' '\(sessionId)' '-m' 'grok-4' '--permission-mode' 'auto' '--sandbox' 'danger-full-access'" - ) - } - - func testGrokVaultLoadsHookObservedShellGrokHomeFromCustomStateDir() async throws { - let tempDir = FileManager.default.temporaryDirectory - .appendingPathComponent("cmux-grok-vault-custom-state-\(UUID().uuidString)", isDirectory: true) - try FileManager.default.createDirectory(at: tempDir, withIntermediateDirectories: true) - defer { try? FileManager.default.removeItem(at: tempDir) } - - let homeDirectory = tempDir.appendingPathComponent("home", isDirectory: true) - let hookStateDir = tempDir.appendingPathComponent("hook-state", isDirectory: true) - let hookStore = hookStateDir.appendingPathComponent("grok-hook-sessions.json", isDirectory: false) - try FileManager.default.createDirectory(at: hookStateDir, withIntermediateDirectories: true) - - let cwd = "/tmp/grok custom state" - let sessionId = "grok-custom-state-session" - let grokHome = tempDir.appendingPathComponent("custom-state-grok-home", isDirectory: true) - let historyURL = grokHome - .appendingPathComponent("sessions", isDirectory: true) - .appendingPathComponent(GrokSessionLocator.encodedSessionCWD(cwd), isDirectory: true) - .appendingPathComponent(sessionId, isDirectory: true) - .appendingPathComponent("chat_history.jsonl", isDirectory: false) - try FileManager.default.createDirectory( - at: historyURL.deletingLastPathComponent(), - withIntermediateDirectories: true - ) - try """ - {"type":"user","content":"Find sessions under custom hook state","model":"grok-4"} - """.write(to: historyURL, atomically: true, encoding: .utf8) - - try """ - { - "version": 1, - "sessions": { - "\(sessionId)": { - "launchCommand": { - "environment": { - "GROK_HOME": "\(grokHome.path)" - } - } - } - } - } - """.write(to: hookStore, atomically: true, encoding: .utf8) - - let entries = await SessionIndexStore.loadGrokEntries( - registration: .builtInGrok, - needle: "", - cwdFilter: nil, - offset: 0, - limit: 10, - environment: ["CMUX_AGENT_HOOK_STATE_DIR": hookStateDir.path], - homeDirectory: homeDirectory.path - ) - - let entry = try XCTUnwrap(entries.first) - XCTAssertEqual(entry.sessionId, sessionId) - XCTAssertEqual(entry.title, "Find sessions under custom hook state") - XCTAssertEqual( - entry.resumeCommand, - "cd '/tmp/grok custom state' && 'env' 'GROK_HOME=\(grokHome.path)' 'grok' '-r' '\(sessionId)' '-m' 'grok-4'" - ) - } - - func testRegisteredGrokSessionDirectoryUsesNativeDirectoryLayout() async throws { - let tempDir = FileManager.default.temporaryDirectory - .appendingPathComponent("cmux-registered-grok-vault-\(UUID().uuidString)", isDirectory: true) - try FileManager.default.createDirectory(at: tempDir, withIntermediateDirectories: true) - defer { try? FileManager.default.removeItem(at: tempDir) } - - let cwd = "/tmp/custom grok repo" - let sessionId = "custom-grok-session-123" - let sessionsRoot = tempDir.appendingPathComponent("sessions", isDirectory: true) - let historyURL = sessionsRoot - .appendingPathComponent(GrokSessionLocator.encodedSessionCWD(cwd), isDirectory: true) - .appendingPathComponent(sessionId, isDirectory: true) - .appendingPathComponent("chat_history.jsonl", isDirectory: false) - try FileManager.default.createDirectory( - at: historyURL.deletingLastPathComponent(), - withIntermediateDirectories: true - ) - try """ - {"type":"user","content":"Resume a custom Grok-compatible agent","git":{"branch":"issue-4394-grok-vault-resume"}} - """.write(to: historyURL, atomically: true, encoding: .utf8) - - let registration = CmuxVaultAgentRegistration( - id: "custom-grok", - name: "Custom Grok", - detect: CmuxVaultAgentDetectRule(processName: "custom-grok"), - sessionIdSource: .grokSessionDirectory, - resumeCommand: "custom-grok -r {{sessionId}}", - cwd: .preserve, - sessionDirectory: sessionsRoot.path - ) - let entries = await SessionIndexStore.loadRegisteredAgentEntries( - registration: registration, - needle: "", - cwdFilter: nil, - offset: 0, - limit: 10 - ) - - let entry = try XCTUnwrap(entries.first) - XCTAssertEqual(entry.id, "custom-grok:\(sessionId)") - XCTAssertEqual(entry.agent, .registered(RegisteredSessionAgent(registration: registration))) - XCTAssertEqual(entry.sessionId, sessionId) - XCTAssertEqual(entry.title, "Resume a custom Grok-compatible agent") - XCTAssertEqual(entry.cwd, cwd) - XCTAssertEqual(entry.gitBranch, "issue-4394-grok-vault-resume") - XCTAssertEqual( - entry.resumeCommand, - "cd '/tmp/custom grok repo' && 'env' 'GROK_HOME=\(tempDir.path)' 'custom-grok' '-r' '\(sessionId)'" - ) - } - - func testGrokVaultCWDFilterUsesEncodedProjectDirectory() async throws { - let tempDir = FileManager.default.temporaryDirectory - .appendingPathComponent("cmux-grok-vault-filter-\(UUID().uuidString)", isDirectory: true) - try FileManager.default.createDirectory(at: tempDir, withIntermediateDirectories: true) - defer { try? FileManager.default.removeItem(at: tempDir) } - - let sessionsRoot = tempDir.appendingPathComponent("sessions", isDirectory: true) - func writeHistory(cwd: String, sessionId: String, prompt: String) throws { - let historyURL = sessionsRoot - .appendingPathComponent(GrokSessionLocator.encodedSessionCWD(cwd), isDirectory: true) - .appendingPathComponent(sessionId, isDirectory: true) - .appendingPathComponent("chat_history.jsonl", isDirectory: false) - try FileManager.default.createDirectory( - at: historyURL.deletingLastPathComponent(), - withIntermediateDirectories: true - ) - try #"{"type":"user","content":"\#(prompt)"}"# - .write(to: historyURL, atomically: true, encoding: .utf8) - } - - try writeHistory(cwd: "/tmp/current grok repo", sessionId: "current-session", prompt: "current") - try writeHistory(cwd: "/tmp/current grok repo/../current grok repo", sessionId: "current-session", prompt: "duplicate") - try writeHistory(cwd: "/tmp/other grok repo", sessionId: "other-session", prompt: "other") - - var registration = CmuxVaultAgentRegistration.builtInGrok - registration.sessionDirectory = sessionsRoot.path - let entries = await SessionIndexStore.loadGrokEntries( - registration: registration, - needle: "", - cwdFilter: "/tmp/current grok repo/../current grok repo", - offset: 0, - limit: 10 - ) - - XCTAssertEqual(entries.map(\.sessionId), ["current-session"]) - XCTAssertEqual(entries.first?.cwd, "/tmp/current grok repo") - } - - @MainActor - func testGrokAgentSearchScopeUsesCurrentDirectoryCWDFilter() async throws { - let tempDir = FileManager.default.temporaryDirectory - .appendingPathComponent("cmux-grok-agent-scope-filter-\(UUID().uuidString)", isDirectory: true) - try FileManager.default.createDirectory(at: tempDir, withIntermediateDirectories: true) - defer { try? FileManager.default.removeItem(at: tempDir) } - - let previousGrokHome = getenv("GROK_HOME").map { String(cString: $0) } - let grokHome = tempDir.appendingPathComponent("grok-home", isDirectory: true) - setenv("GROK_HOME", grokHome.path, 1) - defer { - if let previousGrokHome { - setenv("GROK_HOME", previousGrokHome, 1) - } else { - unsetenv("GROK_HOME") - } - } - - let sessionsRoot = grokHome.appendingPathComponent("sessions", isDirectory: true) - func writeHistory(cwd: String, sessionId: String, prompt: String) throws { - let historyURL = sessionsRoot - .appendingPathComponent(GrokSessionLocator.encodedSessionCWD(cwd), isDirectory: true) - .appendingPathComponent(sessionId, isDirectory: true) - .appendingPathComponent("chat_history.jsonl", isDirectory: false) - try FileManager.default.createDirectory( - at: historyURL.deletingLastPathComponent(), - withIntermediateDirectories: true - ) - try #"{"type":"user","content":"\#(prompt)","model":"grok-4"}"# - .write(to: historyURL, atomically: true, encoding: .utf8) - } - - try writeHistory(cwd: "/tmp/current grok search", sessionId: "current-session", prompt: "current") - try writeHistory(cwd: "/tmp/other grok search", sessionId: "other-session", prompt: "other") - - let store = SessionIndexStore() - store.setCurrentDirectoryIfChanged("/tmp/current grok search") - let outcome = await store.searchSessions( - query: "", - scope: .agent(.grok), - offset: 0, - limit: 10 - ) - - XCTAssertEqual(outcome.entries.map(\.sessionId), ["current-session"]) - XCTAssertEqual(outcome.entries.first?.cwd, "/tmp/current grok search") - } - func testPiVaultAgentSnapshotRoundTripBuildsTargetedSessionCommand() throws { let tempDir = FileManager.default.temporaryDirectory .appendingPathComponent("cmux-pi-vault-agent-\(UUID().uuidString)", isDirectory: true) diff --git a/cmuxTests/PortScannerTests.swift b/cmuxTests/PortScannerTests.swift index 85c6f81a02d2..51a8aa93608d 100644 --- a/cmuxTests/PortScannerTests.swift +++ b/cmuxTests/PortScannerTests.swift @@ -36,34 +36,3 @@ final class PortScannerProcessCaptureTests: XCTestCase { XCTAssertLessThanOrEqual(finalCount - baseline, 8) } } - -final class ProcessTerminationGateTests: XCTestCase { - func testPrelaunchTerminationRequestIsDeferredUntilLaunch() { - let gate = ProcessTerminationGate() - - XCTAssertFalse( - gate.requestTermination(), - "A cancellation that arrives before Process.run() succeeds must not touch the Process." - ) - XCTAssertTrue( - gate.markLaunched(), - "Once launch succeeds, the deferred termination request should be applied to the running Process." - ) - gate.markFinished() - XCTAssertFalse( - gate.requestTermination(), - "Late cancellation after completion must not touch Process termination state." - ) - } - - func testFinishedPrelaunchProcessIgnoresDeferredTermination() { - let gate = ProcessTerminationGate() - - XCTAssertFalse(gate.requestTermination()) - gate.markFinished() - XCTAssertFalse( - gate.markLaunched(), - "If launch fails and the run is already finished, no deferred termination should be applied." - ) - } -} diff --git a/cmuxTests/PortalTabDragRoutingTests.swift b/cmuxTests/PortalTabDragRoutingTests.swift index 3ae13c40c612..68e62d20ee0e 100644 --- a/cmuxTests/PortalTabDragRoutingTests.swift +++ b/cmuxTests/PortalTabDragRoutingTests.swift @@ -1,7 +1,6 @@ import XCTest import AppKit -import SwiftUI -@testable import Bonsplit +import Bonsplit #if canImport(cmux_DEV) @testable import cmux_DEV @@ -23,139 +22,6 @@ final class PortalTabDragRoutingTests: XCTestCase { } } - func testCompactPaneTabChromeStaysBelowDragHitMinimum() throws { - let appearance = BonsplitConfiguration.Appearance( - tabMinWidth: 140, - tabMaxWidth: 220, - splitButtons: [] - ) - let measuredWidth = try XCTUnwrap( - renderedSelectedPaneTabIndicatorWidth( - title: "~", - icon: "terminal.fill", - appearance: appearance - ) - ) - - XCTAssertGreaterThan( - measuredWidth, - 40, - "The regression measurement must prove the selected tab indicator actually rendered" - ) - XCTAssertLessThanOrEqual( - measuredWidth, - 80, - "Short pane-tab visible chrome should stay compact; drag affordance must come from hit testing, not a wider rendered tab" - ) - } - - private func makeHostedTerminalView(frame: NSRect) -> GhosttySurfaceScrollView { - let surfaceView = GhosttyNSView(frame: frame) - let hostedView = GhosttySurfaceScrollView(surfaceView: surfaceView) - hostedView.frame = frame - hostedView.autoresizingMask = [.width, .height] - return hostedView - } - - private func renderedSelectedPaneTabIndicatorWidth( - title: String, - icon: String?, - appearance: BonsplitConfiguration.Appearance - ) -> CGFloat? { - let controller = BonsplitController(configuration: BonsplitConfiguration(appearance: appearance)) - guard let pane = controller.internalController.rootNode.allPanes.first else { return nil } - let tab = TabItem(title: title, icon: icon) - pane.tabs = [tab] - pane.selectedTabId = tab.id - - let size = NSSize(width: 180, height: appearance.tabBarHeight) - let hostingView = NSHostingView( - rootView: TabBarView(pane: pane, isFocused: true, showSplitButtons: false) - .environment(controller) - .environment(controller.internalController) - ) - let window = NSWindow( - contentRect: NSRect(origin: .zero, size: size), - styleMask: [.titled, .closable], - backing: .buffered, - defer: false - ) - window.isOpaque = false - window.backgroundColor = .clear - defer { window.orderOut(nil) } - guard let contentView = window.contentView else { return nil } - - contentView.wantsLayer = true - contentView.layer?.backgroundColor = NSColor.clear.cgColor - hostingView.frame = NSRect(origin: .zero, size: size) - hostingView.autoresizingMask = [.width, .height] - contentView.addSubview(hostingView) - - window.makeKeyAndOrderFront(nil) - let sampleRect = NSRect(x: 0, y: 0, width: size.width, height: 4) - return waitForHighSaturationWidth( - in: hostingView, - sampleRect: sampleRect - ) - } - - private func waitForHighSaturationWidth( - in view: NSView, - sampleRect: NSRect, - timeout: TimeInterval = 1.0 - ) -> CGFloat? { - let deadline = Date().addingTimeInterval(timeout) - repeat { - view.layoutSubtreeIfNeeded() - view.displayIfNeeded() - if let width = highSaturationWidth(in: view, sampleRect: sampleRect) { - return width - } - _ = RunLoop.current.run(mode: .default, before: Date().addingTimeInterval(0.01)) - } while Date() < deadline - return highSaturationWidth(in: view, sampleRect: sampleRect) - } - - private func highSaturationWidth(in view: NSView, sampleRect: NSRect) -> CGFloat? { - let integralBounds = view.bounds.integral - guard let bitmap = view.bitmapImageRepForCachingDisplay(in: integralBounds) else { return nil } - bitmap.size = integralBounds.size - view.cacheDisplay(in: integralBounds, to: bitmap) - - let scaleX = CGFloat(bitmap.pixelsWide) / max(1, integralBounds.width) - let scaleY = CGFloat(bitmap.pixelsHigh) / max(1, integralBounds.height) - let minX = max(0, Int(floor(sampleRect.minX * scaleX))) - let maxX = min(bitmap.pixelsWide, Int(ceil(sampleRect.maxX * scaleX))) - let minY = max(0, Int(floor(sampleRect.minY * scaleY))) - let maxY = min(bitmap.pixelsHigh, Int(ceil(sampleRect.maxY * scaleY))) - - var activeColumnCount = 0 - for x in minX.. 0.05 else { continue } - let alpha = min(max(rgb.alphaComponent, 0), 1) - let red = rgb.redComponent * alpha - let green = rgb.greenComponent * alpha - let blue = rgb.blueComponent * alpha - let high = max(red, green, blue) - guard high > 0.01 else { continue } - let low = min(red, green, blue) - if (high - low) / high > 0.4 { - hasIndicatorPixel = true - break - } - } - if hasIndicatorPixel { - activeColumnCount += 1 - } - } - guard activeColumnCount > 0 else { return nil } - return CGFloat(activeColumnCount) / scaleX - } - private struct TabStripPassThroughFixture { let host: WindowTerminalHostView let pointInHost: NSPoint @@ -245,56 +111,6 @@ final class PortalTabDragRoutingTests: XCTestCase { ) } - func testHostViewTrustsRegisteredTabStripRegionAboveHostedTerminal() { - let window = NSWindow( - contentRect: NSRect(x: 0, y: 0, width: 420, height: 260), - styleMask: [.titled, .closable], - backing: .buffered, - defer: false - ) - defer { window.orderOut(nil) } - guard let contentView = window.contentView, - let container = contentView.superview else { - XCTFail("Expected window content container") - return - } - - let tabStripHeight: CGFloat = 44 - let tabStrip = NSView( - frame: NSRect( - x: 0, - y: contentView.bounds.maxY - tabStripHeight, - width: contentView.bounds.width, - height: tabStripHeight - ) - ) - tabStrip.autoresizingMask = [.width, .minYMargin] - contentView.addSubview(tabStrip) - BonsplitTabBarHitRegionRegistry.register(tabStrip) - defer { BonsplitTabBarHitRegionRegistry.unregister(tabStrip) } - - let hostFrame = container.convert(contentView.bounds, from: contentView) - let host = WindowTerminalHostView(frame: hostFrame) - host.autoresizingMask = [.width, .height] - let hostedTerminal = makeHostedTerminalView(frame: host.bounds) - host.addSubview(hostedTerminal) - container.addSubview(host, positioned: .above, relativeTo: contentView) - - let titlebarBandHeight = max(28, min(72, window.frame.height - window.contentLayoutRect.height)) - let pointInContent = NSPoint( - x: contentView.bounds.midX, - y: contentView.bounds.maxY - titlebarBandHeight - 8 - ) - let pointInWindow = contentView.convert(pointInContent, to: nil) - let pointInHost = host.convert(pointInWindow, from: nil) - let event = makeMouseEvent(type: .leftMouseDown, at: pointInWindow, window: window) - - XCTAssertNil( - host.performHitTest(at: pointInHost, currentEvent: event), - "Terminal portal should defer to the registered minimal tab strip even when a hosted terminal view overlaps it" - ) - } - func testHostViewPassesThroughUnderlyingTabStripWithoutCurrentEvent() { let window = NSWindow( contentRect: NSRect(x: 0, y: 0, width: 420, height: 260), diff --git a/cmuxTests/RestorableAgentHookProviderResumeTests.swift b/cmuxTests/RestorableAgentHookProviderResumeTests.swift index 164d347aa0a9..a8552273a4f2 100644 --- a/cmuxTests/RestorableAgentHookProviderResumeTests.swift +++ b/cmuxTests/RestorableAgentHookProviderResumeTests.swift @@ -44,40 +44,6 @@ extension SocketListenerAcceptPolicyTests { ) } - func testAntigravityResumeCommandUsesConversationAndDropsStartupSelectors() { - let snapshot = SessionRestorableAgentSnapshot( - kind: .antigravity, - sessionId: "antigravity-conversation-123", - workingDirectory: "/tmp/antigravity repo", - launchCommand: AgentLaunchCommandSnapshot( - launcher: "antigravity", - executablePath: "/Users/example/.local/bin/agy", - arguments: [ - "/Users/example/.local/bin/agy", - "--conversation", - "old-conversation", - "--sandbox", - "danger-full-access", - "--add-dir", - "/tmp/extra repo", - "initial prompt should not replay" - ], - workingDirectory: "/tmp/antigravity repo", - environment: [ - "GEMINI_CLI_HOME": "/tmp/gemini home", - "GEMINI_API_KEY": "secret" - ], - capturedAt: 123, - source: "process" - ) - ) - - XCTAssertEqual( - snapshot.resumeCommand, - "cd '/tmp/antigravity repo' && 'env' 'GEMINI_CLI_HOME=/tmp/gemini home' '/Users/example/.local/bin/agy' '--conversation' 'antigravity-conversation-123' '--sandbox' 'danger-full-access' '--add-dir' '/tmp/extra repo'" - ) - } - func testRovoDevResumeCommandUsesRestoreAndPreservesYolo() { let snapshot = SessionRestorableAgentSnapshot( kind: .rovodev, diff --git a/cmuxTests/RovoDevSessionIndexTests.swift b/cmuxTests/RovoDevSessionIndexTests.swift index 3da201a1d712..3d447853c072 100644 --- a/cmuxTests/RovoDevSessionIndexTests.swift +++ b/cmuxTests/RovoDevSessionIndexTests.swift @@ -1,4 +1,3 @@ -import Darwin import XCTest #if canImport(cmux_DEV) @@ -8,80 +7,6 @@ import XCTest #endif final class RovoDevSessionIndexTests: XCTestCase { - func testRipgrepCancellationDoesNotSignalBeforeProcessStarts() { - var sentSignals: [(pid_t, Int32)] = [] - let cancellation = SessionIndexRipgrepCancellation { processIdentifier, signal in - sentSignals.append((processIdentifier, signal)) - return 0 - } - - cancellation.cancel() - - XCTAssertTrue(sentSignals.isEmpty) - } - - func testRipgrepCancellationSignalsActiveProcess() { - var sentSignals: [(pid_t, Int32)] = [] - let cancellation = SessionIndexRipgrepCancellation { processIdentifier, signal in - sentSignals.append((processIdentifier, signal)) - return 0 - } - - cancellation.markStarted(processIdentifier: 12345) - cancellation.cancel() - cancellation.cancel() - cancellation.markFinished(processIdentifier: 12345) - cancellation.cancel() - - XCTAssertEqual(sentSignals.count, 1) - XCTAssertEqual(sentSignals.first?.0, 12345) - XCTAssertEqual(sentSignals.first?.1, SIGTERM) - } - - func testRipgrepCancellationDoesNotResurrectFinishedProcess() { - var sentSignals: [(pid_t, Int32)] = [] - let cancellation = SessionIndexRipgrepCancellation { processIdentifier, signal in - sentSignals.append((processIdentifier, signal)) - return 0 - } - - cancellation.markFinished(processIdentifier: 12345) - cancellation.markStarted(processIdentifier: 12345) - cancellation.cancel() - - XCTAssertTrue(sentSignals.isEmpty) - } - - func testRipgrepMatchingPathsCancellationDoesNotReportFailure() async throws { - let fixture = try makeFixture() - defer { try? FileManager.default.removeItem(at: fixture.tempDir) } - - let fakeRipgrep = fixture.tempDir.appendingPathComponent("rg") - try """ - #!/bin/sh - exec /bin/sleep 10 - """.write(to: fakeRipgrep, atomically: true, encoding: .utf8) - try FileManager.default.setAttributes( - [.posixPermissions: 0o755], - ofItemAtPath: fakeRipgrep.path - ) - - let task = Task { - await SessionIndexStore.ripgrepMatchingPaths( - needle: "needle", - root: fixture.tempDir.path, - fileGlob: "*.jsonl", - ripgrepPath: fakeRipgrep.path - ) - } - try await Task.sleep(for: .milliseconds(50)) - task.cancel() - - let matches = await task.value - - XCTAssertEqual(matches, []) - } - func testRovoDevSessionIndexReadsMetadataAndResumeCommand() throws { let fixture = try makeFixture() defer { try? FileManager.default.removeItem(at: fixture.tempDir) } diff --git a/cmuxTests/SessionIndexViewTests.swift b/cmuxTests/SessionIndexViewTests.swift index 0db2b2d09e53..dc42b8334ea0 100644 --- a/cmuxTests/SessionIndexViewTests.swift +++ b/cmuxTests/SessionIndexViewTests.swift @@ -133,7 +133,7 @@ final class SessionIndexViewTests: XCTestCase { XCTAssertEqual( entry.resumeCommand, - "'env' 'GROK_HOME=/tmp/grok home' 'grok' '-r' 'grok-session-123' '-m' 'grok-4' '--permission-mode' 'auto' '--sandbox' 'danger-full-access'" + "env GROK_HOME='/tmp/grok home' grok -r grok-session-123 -m grok-4 --permission-mode auto --sandbox danger-full-access" ) } diff --git a/cmuxTests/SessionPersistenceTests.swift b/cmuxTests/SessionPersistenceTests.swift index 880f7b48301b..0be92e2d5303 100644 --- a/cmuxTests/SessionPersistenceTests.swift +++ b/cmuxTests/SessionPersistenceTests.swift @@ -73,59 +73,6 @@ final class SessionPersistenceTests: XCTestCase { XCTAssertTrue(panelSnapshot.listeningPorts.isEmpty) } - @MainActor - func testWorkspaceSessionSnapshotRestoresPaneNotificationsIntoStore() throws { - let store = TerminalNotificationStore.shared - let appDelegate = AppDelegate.shared ?? AppDelegate() - let originalNotificationStore = appDelegate.notificationStore - appDelegate.notificationStore = store - store.replaceNotificationsForTesting([]) - defer { - store.replaceNotificationsForTesting([]) - appDelegate.notificationStore = originalNotificationStore - } - - let workspace = Workspace() - let panelId = try XCTUnwrap(workspace.focusedPanelId) - let liveSurfaceId = UUID() - let notification = TerminalNotification( - id: UUID(), - tabId: workspace.id, - surfaceId: liveSurfaceId, - panelId: panelId, - title: "Agent finished", - subtitle: "codex", - body: "Tests passed", - createdAt: Date(timeIntervalSince1970: 1_700_000_000), - isRead: false, - paneFlash: true - ) - store.replaceNotificationsForTesting([notification]) - - let snapshot = workspace.sessionSnapshot(includeScrollback: false) - let panelSnapshot = try XCTUnwrap(snapshot.panels.first { $0.id == panelId }) - XCTAssertEqual(panelSnapshot.notifications?.first?.body, "Tests passed") - - store.replaceNotificationsForTesting([]) - let restored = Workspace() - restored.restoreSessionSnapshot(snapshot) - - let restoredPanelId = try XCTUnwrap(restored.focusedPanelId) - let restoredNotification = try XCTUnwrap(store.latestNotification(forTabId: restored.id)) - XCTAssertEqual(restoredNotification.surfaceId, restoredPanelId) - XCTAssertEqual(restoredNotification.panelId, restoredPanelId) - XCTAssertEqual(restoredNotification.title, "Agent finished") - XCTAssertEqual(restoredNotification.body, "Tests passed") - XCTAssertFalse(restoredNotification.isRead) - XCTAssertTrue(store.hasUnreadNotification(forTabId: restored.id, surfaceId: restoredPanelId)) - let restoredSurfaceId = try XCTUnwrap(restored.surfaceIdFromPanelId(restoredPanelId)) - XCTAssertEqual(restored.bonsplitController.tab(restoredSurfaceId)?.showsNotificationBadge, true) - XCTAssertEqual(store.unreadCount(forTabId: restored.id), 1) - XCTAssertFalse(restored.hasRestoredUnreadIndicator(panelId: restoredPanelId)) - XCTAssertTrue(store.notificationMenuSnapshot.hasNotifications) - XCTAssertTrue(store.notificationMenuSnapshot.hasUnreadNotifications) - } - func testSaveAndLoadRoundTripWithCustomSnapshotPath() throws { let tempDir = FileManager.default.temporaryDirectory .appendingPathComponent("cmux-session-tests-\(UUID().uuidString)", isDirectory: true) @@ -1136,46 +1083,6 @@ final class SessionPersistenceTests: XCTestCase { XCTAssertNil(exitedAgentSnapshot.panels.first?.terminal?.agent) } - @MainActor - func testRestoredAntigravityAgentAutoResumeUsesConversationCommand() throws { - let source = Workspace() - let sourcePanelId = try XCTUnwrap(source.focusedPanelId) - let sourceIndex = try makeRestorableAgentIndex( - kind: .antigravity, - workspaceId: source.id, - panelId: sourcePanelId, - sessionId: "antigravity-conversation-123", - arguments: [ - "/usr/local/bin/agy", - "--conversation", - "old-conversation", - "--sandbox", - "danger-full-access", - "startup prompt should not replay", - ], - environment: [:] - ) - let snapshot = source.sessionSnapshot( - includeScrollback: false, - restorableAgentIndex: sourceIndex - ) - - let restored = Workspace() - restored.restoreSessionSnapshot(snapshot) - let restoredPanelId = try XCTUnwrap(restored.focusedPanelId) - restored.updatePanelShellActivityState(panelId: restoredPanelId, state: .commandRunning) - - let agent = try XCTUnwrap( - restored.sessionSnapshot(includeScrollback: false).panels.first?.terminal?.agent - ) - XCTAssertEqual(agent.kind, .custom("antigravity")) - XCTAssertEqual(agent.sessionId, "antigravity-conversation-123") - XCTAssertEqual( - agent.resumeCommand, - "cd '/tmp/repo' && '/usr/local/bin/agy' '--conversation' 'antigravity-conversation-123' '--sandbox' 'danger-full-access'" - ) - } - @MainActor func testRestoredAgentWithoutResumeCommandInvalidatesOnFirstCommand() throws { let source = Workspace() @@ -1540,8 +1447,6 @@ final class SessionPersistenceTests: XCTestCase { resolvedEnvironment = [:] case .gemini: resolvedEnvironment = ["GEMINI_CLI_HOME": "/tmp/gemini"] - case .antigravity: - resolvedEnvironment = ["GEMINI_CLI_HOME": "/tmp/gemini"] case .opencode: resolvedEnvironment = ["OPENCODE_CONFIG_DIR": "/tmp/opencode"] case .hermesAgent: @@ -3560,66 +3465,6 @@ final class SocketListenerAcceptPolicyTests: XCTestCase { XCTAssertEqual(snapshot.launchCommand?.source, "process") } - func testAntigravityProcessDetectionDoesNotTreatTrailingFlagAsConversationID() throws { - let workspaceId = UUID() - let panelId = UUID() - let processId = 1_739_392_001 - let panelKey = RestorableAgentSessionIndex.PanelKey(workspaceId: workspaceId, panelId: panelId) - let processSnapshot = CmuxTopProcessSnapshot( - processes: [ - CmuxTopProcessInfo( - pid: processId, - parentPID: 1, - name: "agy", - path: "/usr/local/bin/agy", - ttyDevice: nil, - cmuxWorkspaceID: workspaceId, - cmuxSurfaceID: panelId, - cmuxAttributionReason: "cmux-test", - processGroupID: nil, - terminalProcessGroupID: nil, - cpuPercent: 0, - residentBytes: 0, - virtualBytes: 0, - threadCount: 1 - ) - ], - sampledAt: Date(timeIntervalSince1970: 0), - includesProcessDetails: true - ) - let registry = CmuxVaultAgentRegistry(registrations: [.builtInAntigravity]) - - func detectedSnapshot(arguments: [String]) -> SessionRestorableAgentSnapshot? { - RestorableAgentSessionIndex.processDetectedSnapshots( - registry: registry, - fileManager: FileManager.default, - processSnapshot: processSnapshot, - capturedAt: 42, - processArgumentsProvider: { requestedProcessId in - guard requestedProcessId == processId else { return nil } - return CmuxTopProcessArguments( - arguments: arguments, - environment: ["PWD": "/tmp/antigravity repo"] - ) - } - )[panelKey]?.snapshot - } - - XCTAssertNil( - detectedSnapshot(arguments: ["/usr/local/bin/agy", "--conversation", "--sandbox", "danger-full-access"]) - ) - XCTAssertNil( - detectedSnapshot(arguments: ["/usr/local/bin/agy", "--conversation=--sandbox"]) - ) - - let validSnapshot = try XCTUnwrap( - detectedSnapshot(arguments: ["/usr/local/bin/agy", "--conversation", "conversation-123", "--sandbox", "danger-full-access"]) - ) - XCTAssertEqual(validSnapshot.sessionId, "conversation-123") - XCTAssertEqual(validSnapshot.workingDirectory, "/tmp/antigravity repo") - XCTAssertEqual(validSnapshot.launchCommand?.launcher, "antigravity") - } - } final class SidebarDragFailsafePolicyTests: XCTestCase { diff --git a/cmuxTests/SidebarWidthPolicyTests.swift b/cmuxTests/SidebarWidthPolicyTests.swift index 7cfd2c96f619..92c62ffc781f 100644 --- a/cmuxTests/SidebarWidthPolicyTests.swift +++ b/cmuxTests/SidebarWidthPolicyTests.swift @@ -128,62 +128,6 @@ final class SidebarWorkspaceSelectionColorTests: XCTestCase { assertColor(coloredSelected.color, equals: NSColor(hex: selectionHex)) } - func testDefaultSelectedForegroundFallsBackForPaleSelectionBackground() throws { - let background = try XCTUnwrap(NSColor(hex: "#F7F7F7")) - let foreground = sidebarSelectedWorkspaceForegroundNSColor( - on: background, - opacity: 1.0 - ) - - assertColor(foreground, equals: .black) - XCTAssertGreaterThanOrEqual( - cmuxContrastRatio(foreground: foreground, background: background), - 4.5 - ) - } - - func testSelectedForegroundPrefersWhiteForSaturatedSelectionBackground() throws { - let background = try XCTUnwrap(NSColor(hex: "#0088FF")) - let foreground = sidebarSelectedWorkspaceForegroundNSColor( - on: background, - opacity: 1.0 - ) - - assertColor(foreground, equals: .white) - XCTAssertGreaterThanOrEqual( - cmuxContrastRatio(foreground: foreground, background: background), - 3.0 - ) - } - - func testSelectedForegroundKeepsWhiteForStandardInactiveSelectionBlue() throws { - let background = try XCTUnwrap(NSColor(hex: "#6795F5")) - let foreground = sidebarSelectedWorkspaceForegroundNSColor( - on: background, - opacity: 0.75 - ) - - assertColor(foreground, equals: NSColor.white.withAlphaComponent(0.75)) - } - - func testTitlebarControlForegroundContrastsWithLightTerminalBackground() throws { - let background = try XCTUnwrap(NSColor(hex: "#F7F7F7")) - let snapshot = makeWindowAppearanceSnapshot(background: background) - let foreground = titlebarControlForegroundNSColor( - opacity: 1.0, - appearance: snapshot - ) - - assertColor(foreground, equals: .black) - XCTAssertGreaterThanOrEqual( - cmuxContrastRatio( - foreground: foreground, - background: snapshot.compositedTerminalBackgroundColor - ), - 4.5 - ) - } - private func assertColor( _ actual: NSColor?, equals expected: NSColor?, @@ -204,36 +148,6 @@ final class SidebarWorkspaceSelectionColorTests: XCTestCase { ) } - private func makeWindowAppearanceSnapshot(background: NSColor) -> WindowAppearanceSnapshot { - WindowAppearanceSnapshot( - terminalBackgroundColor: background, - terminalBackgroundOpacity: 1.0, - terminalBackgroundBlur: .disabled, - terminalRenderingMode: .windowHostBackdrop, - unifySurfaceBackdrops: true, - sidebarSettings: SidebarBackdropSettingsSnapshot( - materialRawValue: SidebarMaterialOption.sidebar.rawValue, - blendModeRawValue: SidebarBlendModeOption.withinWindow.rawValue, - stateRawValue: SidebarStateOption.followWindow.rawValue, - tintHex: SidebarTintDefaults.hex, - tintHexLight: nil, - tintHexDark: nil, - tintOpacity: SidebarTintDefaults.opacity, - cornerRadius: 0, - blurOpacity: 1, - colorScheme: .light - ), - windowGlassSettings: WindowGlassSettingsSnapshot( - sidebarBlendModeRawValue: SidebarBlendModeOption.withinWindow.rawValue, - isEnabled: false, - tintHex: "#000000", - tintOpacity: 0, - terminalBackgroundBlur: .disabled, - terminalGlassTintColor: background - ) - ) - } - private func colorsAreEqual(_ lhs: NSColor?, _ rhs: NSColor?) -> Bool { guard let lhs, let rhs else { return lhs == nil && rhs == nil diff --git a/cmuxTests/TabManagerUnitTests.swift b/cmuxTests/TabManagerUnitTests.swift index a11d91caf2a3..f20c466f6f21 100644 --- a/cmuxTests/TabManagerUnitTests.swift +++ b/cmuxTests/TabManagerUnitTests.swift @@ -351,183 +351,6 @@ final class TabManagerPullRequestProbeTests: XCTestCase { ) } - func testGitHubRepositorySlugsFromGitConfigIgnoreInlineComments() { - let config = """ - [remote "origin"] ; user's main fork - url = git@github.com:austinwang/cmux.git # main origin - fetch = +refs/heads/*:refs/remotes/origin/* - [remote "upstream"] # canonical repo - url = https://github.com/manaflow-ai/cmux.git ; upstream source - fetch = +refs/heads/*:refs/remotes/upstream/* - """ - - XCTAssertEqual( - TabManager.githubRepositorySlugs(fromGitConfigForTesting: config), - ["manaflow-ai/cmux", "austinwang/cmux"] - ) - } - - func testGitHubRepositorySlugsFromGitConfigUnquotesUrlValues() { - let config = """ - [remote "origin"] ; user's main fork - url = "git@github.com:austinwang/cmux.git" # main origin - fetch = +refs/heads/*:refs/remotes/origin/* - [remote "upstream"] # canonical repo - url = "https://github.com/manaflow-ai/cmux.git" ; upstream source - fetch = +refs/heads/*:refs/remotes/upstream/* - """ - - XCTAssertEqual( - TabManager.githubRepositorySlugs(fromGitConfigForTesting: config), - ["manaflow-ai/cmux", "austinwang/cmux"] - ) - } - - func testGitHubRepositorySlugsFromGitConfigUsesLastRemoteURLValue() { - let config = """ - [remote "origin"] - url = https://github.com/old-owner/old-repo.git - url = https://github.com/manaflow-ai/cmux.git - """ - - XCTAssertEqual( - TabManager.githubRepositorySlugs(fromGitConfigForTesting: config), - ["manaflow-ai/cmux"] - ) - } - - func testGitHubRepositorySlugsFromGitConfigReadsIncludedConfigFiles() throws { - let repoURL = FileManager.default.temporaryDirectory.appendingPathComponent( - "cmux-git-config-includes-\(UUID().uuidString)", - isDirectory: true - ) - let gitURL = repoURL.appendingPathComponent(".git", isDirectory: true) - try FileManager.default.createDirectory(at: gitURL, withIntermediateDirectories: true) - defer { - try? FileManager.default.removeItem(at: repoURL) - } - - try "ref: refs/heads/main\n".write( - to: gitURL.appendingPathComponent("HEAD"), - atomically: true, - encoding: .utf8 - ) - try """ - [include] - path = remotes.inc - [includeIf "gitdir:\(gitURL.path)/**"] - path = conditional-remotes.inc - """.write( - to: gitURL.appendingPathComponent("config"), - atomically: true, - encoding: .utf8 - ) - try """ - [remote "origin"] - url = "git@github.com:austinwang/cmux.git" # user's main fork - """.write( - to: gitURL.appendingPathComponent("remotes.inc"), - atomically: true, - encoding: .utf8 - ) - try """ - [remote "upstream"] - url = https://github.com/manaflow-ai/cmux.git ; canonical repo - """.write( - to: gitURL.appendingPathComponent("conditional-remotes.inc"), - atomically: true, - encoding: .utf8 - ) - - XCTAssertEqual( - TabManager.githubRepositorySlugs(directoryForTesting: repoURL.path), - ["manaflow-ai/cmux", "austinwang/cmux"] - ) - } - - func testGitHubRepositorySlugsFromGitConfigAppliesIncludesInPlace() throws { - let repoURL = FileManager.default.temporaryDirectory.appendingPathComponent( - "cmux-git-config-include-order-\(UUID().uuidString)", - isDirectory: true - ) - let gitURL = repoURL.appendingPathComponent(".git", isDirectory: true) - try FileManager.default.createDirectory(at: gitURL, withIntermediateDirectories: true) - defer { - try? FileManager.default.removeItem(at: repoURL) - } - - try "ref: refs/heads/main\n".write( - to: gitURL.appendingPathComponent("HEAD"), - atomically: true, - encoding: .utf8 - ) - try """ - [include] - path = remotes.inc - [remote "origin"] - url = https://github.com/manaflow-ai/cmux.git - """.write( - to: gitURL.appendingPathComponent("config"), - atomically: true, - encoding: .utf8 - ) - try """ - [remote "origin"] - url = https://github.com/old-owner/old-repo.git - """.write( - to: gitURL.appendingPathComponent("remotes.inc"), - atomically: true, - encoding: .utf8 - ) - - XCTAssertEqual( - TabManager.githubRepositorySlugs(directoryForTesting: repoURL.path), - ["manaflow-ai/cmux"] - ) - } - - func testGitHubRepositorySlugsFromGitConfigTreatsTrailingSlashGitdirAsRecursive() throws { - let parentURL = FileManager.default.temporaryDirectory.appendingPathComponent( - "cmux-git-config-recursive-include-\(UUID().uuidString)", - isDirectory: true - ) - let repoURL = parentURL - .appendingPathComponent("teams", isDirectory: true) - .appendingPathComponent("cmux", isDirectory: true) - let gitURL = repoURL.appendingPathComponent(".git", isDirectory: true) - try FileManager.default.createDirectory(at: gitURL, withIntermediateDirectories: true) - defer { - try? FileManager.default.removeItem(at: parentURL) - } - - try "ref: refs/heads/main\n".write( - to: gitURL.appendingPathComponent("HEAD"), - atomically: true, - encoding: .utf8 - ) - try """ - [includeIf "gitdir:\(parentURL.path)/"] - path = recursive-remotes.inc - """.write( - to: gitURL.appendingPathComponent("config"), - atomically: true, - encoding: .utf8 - ) - try """ - [remote "upstream"] - url = https://github.com/manaflow-ai/cmux.git - """.write( - to: gitURL.appendingPathComponent("recursive-remotes.inc"), - atomically: true, - encoding: .utf8 - ) - - XCTAssertEqual( - TabManager.githubRepositorySlugs(directoryForTesting: repoURL.path), - ["manaflow-ai/cmux"] - ) - } - func testPreferredPullRequestPrefersOpenOverMergedAndClosed() { let candidates = [ TabManager.GitHubPullRequestProbeItem( diff --git a/cmuxTests/TaskManagerResourcesTests.swift b/cmuxTests/TaskManagerResourcesTests.swift index bdc7708438f3..2c2b3876bc00 100644 --- a/cmuxTests/TaskManagerResourcesTests.swift +++ b/cmuxTests/TaskManagerResourcesTests.swift @@ -31,18 +31,6 @@ final class TaskManagerResourcesTests: XCTestCase { XCTAssertEqual(definition.id, "grok") } - func testAntigravityCodingAgentDefinitionUsesBrandedIconAsset() throws { - let definition = try XCTUnwrap(CmuxTaskManagerCodingAgentDefinition.matchingDefinition( - processName: "agy", - processPath: "/Users/example/.local/bin/agy", - arguments: ["/Users/example/.local/bin/agy", "--conversation", "conversation-123"], - environment: [:] - )) - - XCTAssertEqual(definition.id, "antigravity") - XCTAssertEqual(definition.assetName, "AgentIcons/Antigravity") - } - func testAttributedPayloadProratesSharedResourceMeasurements() { let summary = resourceSummary() @@ -559,8 +547,6 @@ final class TaskManagerResourcesTests: XCTestCase { ("amp", "amp"), ("cursor-agent", "cursor"), ("gemini", "gemini"), - ("agy", "antigravity"), - ("antigravity", "antigravity"), ("hermes", "hermes-agent"), ("hermes-agent", "hermes-agent"), ("copilot", "copilot"), diff --git a/cmuxTests/TerminalAndGhosttyTests.swift b/cmuxTests/TerminalAndGhosttyTests.swift index 6aeb9f00e756..d7503fd7eb0c 100644 --- a/cmuxTests/TerminalAndGhosttyTests.swift +++ b/cmuxTests/TerminalAndGhosttyTests.swift @@ -1613,6 +1613,25 @@ final class TerminalKeyboardCopyModeResolveTests: XCTestCase { XCTAssertEqual(resolve(45, chars: "n", hasSelection: false, state: &searchState), .perform(.searchNext, count: 2)) } + func testOnlyViewportScrollMotionsTagScrollbarUpdatesAsKeyboardInitiated() { + XCTAssertTrue(TerminalKeyboardCopyModeAction.scrollLines(1).shouldTreatScrollbarUpdatesAsKeyboardInitiated) + XCTAssertTrue(TerminalKeyboardCopyModeAction.scrollPage(-1).shouldTreatScrollbarUpdatesAsKeyboardInitiated) + XCTAssertTrue(TerminalKeyboardCopyModeAction.scrollHalfPage(1).shouldTreatScrollbarUpdatesAsKeyboardInitiated) + XCTAssertTrue(TerminalKeyboardCopyModeAction.scrollToTop.shouldTreatScrollbarUpdatesAsKeyboardInitiated) + XCTAssertTrue(TerminalKeyboardCopyModeAction.scrollToBottom.shouldTreatScrollbarUpdatesAsKeyboardInitiated) + XCTAssertTrue(TerminalKeyboardCopyModeAction.jumpToPrompt(1).shouldTreatScrollbarUpdatesAsKeyboardInitiated) + + XCTAssertFalse(TerminalKeyboardCopyModeAction.searchNext.shouldTreatScrollbarUpdatesAsKeyboardInitiated) + XCTAssertFalse(TerminalKeyboardCopyModeAction.searchPrevious.shouldTreatScrollbarUpdatesAsKeyboardInitiated) + XCTAssertTrue(TerminalKeyboardCopyModeAction.searchNext.scrollbarUpdateIntent.contains(.explicitSync)) + XCTAssertTrue(TerminalKeyboardCopyModeAction.searchPrevious.scrollbarUpdateIntent.contains(.explicitSync)) + XCTAssertFalse( + TerminalKeyboardCopyModeAction + .adjustSelection(.down) + .shouldTreatScrollbarUpdatesAsKeyboardInitiated + ) + } + func testInvalidKeyClearsPendingState() { var state = TerminalKeyboardCopyModeInputState() XCTAssertEqual(resolve(18, chars: "2", hasSelection: false, state: &state), .consume) @@ -1843,28 +1862,6 @@ final class PanelAppearanceBackgroundTests: XCTestCase { XCTAssertEqual(appearance.contentBackgroundColor.alphaComponent, 1.0, accuracy: 0.0001) } - func testLowContrastPanelForegroundFallsBackToReadableColor() { - var config = GhosttyConfig() - config.backgroundColor = NSColor(hex: "#FFFFFF")! - config.backgroundOpacity = 1.0 - config.foregroundColor = NSColor(hex: "#FFFFFF")! - - let appearance = PanelAppearance.fromConfig(config, usesTransparentWindow: false) - - XCTAssertEqual(appearance.foregroundColor.hexString(), "#000000") - } - - func testReadablePanelForegroundPreservesThemeColor() { - var config = GhosttyConfig() - config.backgroundColor = NSColor(hex: "#000000")! - config.backgroundOpacity = 1.0 - config.foregroundColor = NSColor(hex: "#FDF6E3")! - - let appearance = PanelAppearance.fromConfig(config, usesTransparentWindow: false) - - XCTAssertEqual(appearance.foregroundColor.hexString(), "#FDF6E3") - } - func testGhosttyGlassBackgroundUsesClearContentBackground() { var config = GhosttyConfig() config.backgroundOpacity = 1.0 @@ -3103,6 +3100,154 @@ final class GhosttySurfaceOverlayTests: XCTestCase { ) } + func testKeyboardInitiatedScrollbarUpdateSyncsWithoutTimestampBackfill() { + let window = NSWindow( + contentRect: NSRect(x: 0, y: 0, width: 360, height: 240), + styleMask: [.titled, .closable], + backing: .buffered, + defer: false + ) + defer { window.orderOut(nil) } + + guard let contentView = window.contentView else { + XCTFail("Expected content view") + return + } + + let surfaceView = GhosttyNSView(frame: NSRect(x: 0, y: 0, width: 160, height: 120)) + surfaceView.cellSize = CGSize(width: 10, height: 10) + let hostedView = GhosttySurfaceScrollView(surfaceView: surfaceView) + hostedView.frame = contentView.bounds + hostedView.autoresizingMask = [.width, .height] + contentView.addSubview(hostedView) + + window.makeKeyAndOrderFront(nil) + window.displayIfNeeded() + contentView.layoutSubtreeIfNeeded() + hostedView.layoutSubtreeIfNeeded() + RunLoop.current.run(until: Date().addingTimeInterval(0.05)) + + guard let scrollView = hostedView.subviews.first(where: { $0 is NSScrollView }) as? NSScrollView else { + XCTFail("Expected hosted terminal scroll view") + return + } + + NotificationCenter.default.post( + name: .ghosttyDidUpdateScrollbar, + object: surfaceView, + userInfo: [GhosttyNotificationKey.scrollbar: makeScrollbar(total: 100, offset: 90, len: 10)] + ) + RunLoop.current.run(until: Date().addingTimeInterval(0.01)) + XCTAssertEqual(scrollView.contentView.bounds.origin.y, 0, accuracy: 0.01) + XCTAssertEqual( + hostedView + .debugTimestampVisibleRows(for: makeScrollbar(total: 100, offset: 90, len: 10)) + .map(\.row), + Array(90 ..< 100) + ) + + surfaceView.debugEnqueueScrollbarUpdateAfterKeyboardScrollIntent( + makeScrollbar(total: 100, offset: 40, len: 10) + ) + surfaceView.enqueueScrollbarUpdate( + makeScrollbar(total: 100, offset: 40, len: 10), + wasKeyboardInitiated: false + ) + RunLoop.current.run(until: Date().addingTimeInterval(0.01)) + XCTAssertEqual(scrollView.contentView.bounds.origin.y, 500, accuracy: 0.01) + XCTAssertEqual( + hostedView + .debugTimestampVisibleRows(for: makeScrollbar(total: 100, offset: 40, len: 10)) + .map(\.row), + [], + "Keyboard backscroll should not stamp rows the user manually revealed" + ) + + surfaceView.debugEnqueueScrollbarUpdateAfterKeyboardScrollIntent( + makeScrollbar(total: 100, offset: 30, len: 10) + ) + RunLoop.current.run(until: Date().addingTimeInterval(0.01)) + XCTAssertEqual( + scrollView.contentView.bounds.origin.y, + 600, + accuracy: 0.01, + "Keyboard scroll commands should keep syncing while the viewport is already in scrollback" + ) + XCTAssertEqual( + hostedView + .debugTimestampVisibleRows(for: makeScrollbar(total: 100, offset: 30, len: 10)) + .map(\.row), + [] + ) + } + + func testSearchScrollbarUpdateSyncsAfterKeyboardBackscroll() { + let window = NSWindow( + contentRect: NSRect(x: 0, y: 0, width: 360, height: 240), + styleMask: [.titled, .closable], + backing: .buffered, + defer: false + ) + defer { window.orderOut(nil) } + + guard let contentView = window.contentView else { + XCTFail("Expected content view") + return + } + + let surfaceView = GhosttyNSView(frame: NSRect(x: 0, y: 0, width: 160, height: 120)) + surfaceView.cellSize = CGSize(width: 10, height: 10) + let hostedView = GhosttySurfaceScrollView(surfaceView: surfaceView) + hostedView.frame = contentView.bounds + hostedView.autoresizingMask = [.width, .height] + contentView.addSubview(hostedView) + + window.makeKeyAndOrderFront(nil) + window.displayIfNeeded() + contentView.layoutSubtreeIfNeeded() + hostedView.layoutSubtreeIfNeeded() + RunLoop.current.run(until: Date().addingTimeInterval(0.05)) + + guard let scrollView = hostedView.subviews.first(where: { $0 is NSScrollView }) as? NSScrollView else { + XCTFail("Expected hosted terminal scroll view") + return + } + + NotificationCenter.default.post( + name: .ghosttyDidUpdateScrollbar, + object: surfaceView, + userInfo: [GhosttyNotificationKey.scrollbar: makeScrollbar(total: 100, offset: 90, len: 10)] + ) + RunLoop.current.run(until: Date().addingTimeInterval(0.01)) + XCTAssertEqual(scrollView.contentView.bounds.origin.y, 0, accuracy: 0.01) + + surfaceView.debugEnqueueScrollbarUpdateAfterKeyboardScrollIntent( + makeScrollbar(total: 100, offset: 40, len: 10) + ) + RunLoop.current.run(until: Date().addingTimeInterval(0.01)) + XCTAssertEqual(scrollView.contentView.bounds.origin.y, 500, accuracy: 0.01) + + surfaceView.enqueueScrollbarUpdate( + makeScrollbar(total: 100, offset: 20, len: 10), + intent: [.explicitSync] + ) + RunLoop.current.run(until: Date().addingTimeInterval(0.01)) + + XCTAssertEqual( + scrollView.contentView.bounds.origin.y, + 700, + accuracy: 0.01, + "Search navigation should sync the wrapper viewport even after keyboard backscroll disabled passive auto-scroll" + ) + XCTAssertEqual( + hostedView + .debugTimestampVisibleRows(for: makeScrollbar(total: 100, offset: 20, len: 10)) + .map(\.row), + [], + "Search-driven scrollback navigation should not backfill timestamps for manually revealed rows" + ) + } + func testInactiveOverlayVisibilityTracksRequestedState() { let hostedView = GhosttySurfaceScrollView( surfaceView: GhosttyNSView(frame: NSRect(x: 0, y: 0, width: 80, height: 50)) diff --git a/cmuxTests/TerminalControllerSocketSecurityTests.swift b/cmuxTests/TerminalControllerSocketSecurityTests.swift index f5d00e6fa7fd..5cc13af5265b 100644 --- a/cmuxTests/TerminalControllerSocketSecurityTests.swift +++ b/cmuxTests/TerminalControllerSocketSecurityTests.swift @@ -519,59 +519,6 @@ final class TerminalControllerSocketSecurityTests: XCTestCase { XCTAssertFalse(store.hasUnreadNotification(forTabId: workspace.id, surfaceId: focusedPanelId)) } - func testPaneCreateStartupEnvironmentMarksManagedSubagentForRawNotificationSuppression() async throws { - let socketPath = makeSocketPath("pane-env") - let manager = TabManager() - let workspace = manager.addWorkspace(select: true) - let defaults = UserDefaults.standard - let previousSuppressionDefault = defaults.object(forKey: AgentSubagentNotificationSettings.suppressNotificationsKey) - - defaults.set(true, forKey: AgentSubagentNotificationSettings.suppressNotificationsKey) - defer { - if manager.tabs.contains(where: { $0.id == workspace.id }) { - manager.closeWorkspace(workspace) - } - if let previousSuppressionDefault { - defaults.set(previousSuppressionDefault, forKey: AgentSubagentNotificationSettings.suppressNotificationsKey) - } else { - defaults.removeObject(forKey: AgentSubagentNotificationSettings.suppressNotificationsKey) - } - } - - let sourcePanelId = try XCTUnwrap(workspace.focusedPanelId) - XCTAssertFalse(workspace.suppressesRawTerminalNotification(panelId: sourcePanelId)) - - TerminalController.shared.start( - tabManager: manager, - socketPath: socketPath, - accessMode: .allowAll - ) - try waitForSocket(at: socketPath) - - let response = try await sendV2RequestAsync( - method: "pane.create", - params: [ - "workspace_id": workspace.id.uuidString, - "surface_id": sourcePanelId.uuidString, - "direction": "right", - "startup_environment": [ - "CMUX_AGENT_MANAGED_SUBAGENT": "1" - ] - ], - to: socketPath - ) - - XCTAssertEqual(response["ok"] as? Bool, true, "Unexpected JSON-RPC response: \(response)") - let result = try XCTUnwrap(response["result"] as? [String: Any], "Unexpected JSON-RPC response: \(response)") - let newSurfaceIDString = try XCTUnwrap(result["surface_id"] as? String) - let newSurfaceID = try XCTUnwrap(UUID(uuidString: newSurfaceIDString)) - let newPanel = try XCTUnwrap(workspace.panels[newSurfaceID] as? TerminalPanel) - - XCTAssertEqual(newPanel.surface.startupEnvironmentValue("CMUX_AGENT_MANAGED_SUBAGENT"), "1") - XCTAssertTrue(workspace.suppressesRawTerminalNotification(panelId: newSurfaceID)) - XCTAssertFalse(workspace.suppressesRawTerminalNotification(panelId: sourcePanelId)) - } - func testSurfaceRelayRPCsReturnResolvedFocusedSurfaceWhenSurfaceIDOmitted() async throws { let socketPath = makeSocketPath("relay-fallback") let manager = TabManager() diff --git a/cmuxTests/TerminalNotificationClearAllTests.swift b/cmuxTests/TerminalNotificationClearAllTests.swift index bd6af331a325..1f33585b2f39 100644 --- a/cmuxTests/TerminalNotificationClearAllTests.swift +++ b/cmuxTests/TerminalNotificationClearAllTests.swift @@ -313,7 +313,7 @@ final class TerminalNotificationClearAllTests: XCTestCase { workspace.newTerminalSplit(from: firstPanelId, orientation: .horizontal) ) - workspace.recordAgentPID(key: "codex.codex-session-123", pid: pid_t(12345), panelId: firstPanelId) + workspace.recordAgentPID(key: "grok.grok-session-123", pid: pid_t(12345), panelId: firstPanelId) XCTAssertTrue(workspace.suppressesRawTerminalNotification(panelId: firstPanelId)) XCTAssertFalse(workspace.suppressesRawTerminalNotification(panelId: secondPanel.id)) @@ -322,17 +322,6 @@ final class TerminalNotificationClearAllTests: XCTestCase { workspace.recordAgentPID(key: "custom-tool.session", pid: pid_t(12346), panelId: secondPanel.id) XCTAssertFalse(workspace.suppressesRawTerminalNotification(panelId: secondPanel.id)) - - let managedSubagentPanel = try XCTUnwrap( - workspace.newTerminalSplit( - from: secondPanel.id, - orientation: .horizontal, - startupEnvironment: ["CMUX_AGENT_MANAGED_SUBAGENT": "1"] - ) - ) - - XCTAssertTrue(workspace.suppressesRawTerminalNotification(panelId: managedSubagentPanel.id)) - XCTAssertFalse(workspace.suppressesRawTerminalNotification(panelId: secondPanel.id)) } func testSidebarStatusOnlyShowsStructuredAgentStatusBackedByLivePanelRuntime() throws { diff --git a/cmuxTests/VMSSHCommandTests.swift b/cmuxTests/VMSSHCommandTests.swift index b4991cf87844..5bd70ecb782c 100644 --- a/cmuxTests/VMSSHCommandTests.swift +++ b/cmuxTests/VMSSHCommandTests.swift @@ -44,8 +44,6 @@ extension CLINotifyProcessIntegrationRegressionTests { ] ) case "workspace.create": - let params = payload["params"] as? [String: Any] ?? [:] - XCTAssertEqual(params["window_id"] as? String, windowID) return self.v2Response( id: id, ok: true, @@ -87,7 +85,7 @@ extension CLINotifyProcessIntegrationRegressionTests { let result = runProcess( executablePath: cliPath, - arguments: ["vm", "ssh", vmID, "--window", windowID], + arguments: ["vm", "ssh", vmID], environment: environment, timeout: 5 ) @@ -121,104 +119,6 @@ extension CLINotifyProcessIntegrationRegressionTests { XCTAssertNotNil(configureParams["relay_port"] as? Int) } - func testSSHCommandGlobalWindowOverridesCallerEnvironment() throws { - let cliPath = try bundledCLIPath() - let socketPath = makeSocketPath("ssh-global-window") - let listenerFD = try bindUnixSocket(at: socketPath) - let state = MockSocketServerState() - let workspaceID = "11111111-1111-1111-1111-111111111111" - let workspaceRef = "workspace:8" - let windowID = "22222222-2222-2222-2222-222222222222" - let callerWorkspaceID = "33333333-3333-3333-3333-333333333333" - let callerSurfaceID = "44444444-4444-4444-4444-444444444444" - - defer { - Darwin.close(listenerFD) - unlink(socketPath) - } - - let serverHandled = startMockServer(listenerFD: listenerFD, state: state) { line in - guard let payload = self.jsonObject(line), - let id = payload["id"] as? String, - let method = payload["method"] as? String else { - return self.malformedRequestResponse(raw: line) - } - - switch method { - case "window.focus": - let params = payload["params"] as? [String: Any] ?? [:] - XCTAssertEqual(params["window_id"] as? String, windowID) - return self.v2Response(id: id, ok: true, result: ["window_id": windowID]) - case "workspace.create": - let params = payload["params"] as? [String: Any] ?? [:] - XCTAssertEqual(params["window_id"] as? String, windowID) - XCTAssertNil(params["workspace_id"]) - XCTAssertNil(params["surface_id"]) - return self.v2Response( - id: id, - ok: true, - result: [ - "workspace_id": workspaceID, - "window_id": windowID, - ] - ) - case "workspace.remote.configure": - return self.v2Response( - id: id, - ok: true, - result: [ - "workspace_id": workspaceID, - "workspace_ref": workspaceRef, - "remote": [ - "enabled": true, - "state": "connecting", - ], - ] - ) - default: - return self.v2Response( - id: id, - ok: false, - error: ["code": "unexpected", "message": "Unexpected method \(method)"] - ) - } - } - - var environment = ProcessInfo.processInfo.environment - environment["CMUX_SOCKET_PATH"] = socketPath - environment["CMUX_WORKSPACE_ID"] = callerWorkspaceID - environment["CMUX_SURFACE_ID"] = callerSurfaceID - environment["CMUX_CLI_SENTRY_DISABLED"] = "1" - environment["CMUX_CLAUDE_HOOK_SENTRY_DISABLED"] = "1" - - let result = runProcess( - executablePath: cliPath, - arguments: [ - "--window", windowID, - "ssh", - "--no-focus", - "cmux-macmini", - ], - environment: environment, - timeout: 5 - ) - - wait(for: [serverHandled], timeout: 5) - XCTAssertFalse(result.timedOut, result.stderr) - XCTAssertEqual(result.status, 0, result.stderr) - XCTAssertEqual(result.stdout, "OK workspace=\(workspaceRef) target=cmux-macmini state=connecting\n") - XCTAssertTrue(result.stderr.isEmpty, result.stderr) - - let requests = try state.commands.map { line -> [String: Any] in - let data = try XCTUnwrap(line.data(using: .utf8)) - return try XCTUnwrap(JSONSerialization.jsonObject(with: data, options: []) as? [String: Any]) - } - XCTAssertEqual( - requests.compactMap { $0["method"] as? String }, - ["window.focus", "workspace.create", "workspace.remote.configure"] - ) - } - func testVMSSHInfoRemainsPrintOnly() throws { let cliPath = try bundledCLIPath() let socketPath = makeSocketPath("vm-info") diff --git a/cmuxTests/WindowAndDragTests.swift b/cmuxTests/WindowAndDragTests.swift index be0cc85871e1..adacb591fcf5 100644 --- a/cmuxTests/WindowAndDragTests.swift +++ b/cmuxTests/WindowAndDragTests.swift @@ -7,7 +7,7 @@ import SwiftUI import UniformTypeIdentifiers import WebKit import ObjectiveC.runtime -@testable import Bonsplit +import Bonsplit import UserNotifications #if canImport(cmux_DEV) @@ -16,20 +16,6 @@ import UserNotifications @testable import cmux #endif -private final class FakeBonsplitTabItemRegionView: NSView, BonsplitTabItemHitRegionProviding { - nonisolated(unsafe) var tabFrames: [CGRect] = [] - - deinit {} - - nonisolated func containsBonsplitTabItemHit(localPoint: NSPoint) -> Bool { - tabFrames.contains { $0.contains(localPoint) } - } - - override func hitTest(_ point: NSPoint) -> NSView? { - nil - } -} - @MainActor final class WindowGlassEffectTests: XCTestCase { func testRemoveRestoresOriginalContentHierarchy() { @@ -861,65 +847,6 @@ final class WindowDragHandleHitTests: XCTestCase { ) } - func testMinimalModeSidebarTitlebarControlsAlignWithTrafficLightCenter() { - let defaults = UserDefaults.standard - let savedMode = defaults.object(forKey: WorkspacePresentationModeSettings.modeKey) - // WindowDecorationsController.apply reads the production presentation-mode setting - // from UserDefaults.standard, so this test saves and restores the shared key narrowly. - defaults.set(WorkspacePresentationModeSettings.Mode.minimal.rawValue, forKey: WorkspacePresentationModeSettings.modeKey) - defer { - if let savedMode { - defaults.set(savedMode, forKey: WorkspacePresentationModeSettings.modeKey) - } else { - defaults.removeObject(forKey: WorkspacePresentationModeSettings.modeKey) - } - } - - let window = NSWindow( - contentRect: NSRect(x: 0, y: 0, width: 420, height: 180), - styleMask: [.titled, .closable, .miniaturizable, .resizable, .fullSizeContentView], - backing: .buffered, - defer: false - ) - window.identifier = NSUserInterfaceItemIdentifier("cmux.main.test") - window.titlebarAppearsTransparent = true - window.titleVisibility = .hidden - defer { window.orderOut(nil) } - - window.makeKeyAndOrderFront(nil) - RunLoop.main.run(until: Date(timeIntervalSinceNow: 0.05)) - - guard let contentView = window.contentView else { - XCTFail("Expected content view") - return - } - guard let closeButton = window.standardWindowButton(.closeButton), - let closeButtonSuperview = closeButton.superview else { - XCTFail("Expected close traffic-light button") - return - } - - let controller = WindowDecorationsController() - controller.apply(to: window) - - guard let target = contentView.subviews.compactMap({ $0 as? MinimalModeSidebarControlActionView }).first else { - XCTFail("Expected minimal sidebar titlebar click target") - return - } - - let trafficLightFrame = closeButtonSuperview.convert(closeButton.frame, to: contentView) - let opticalYOffset = MinimalModeSidebarTitlebarControlsMetrics.titlebarControlsOpticalYOffset(in: window) - let expectedHostCenterY = contentView.isFlipped - ? trafficLightFrame.midY + opticalYOffset - : trafficLightFrame.midY - opticalYOffset - XCTAssertEqual( - target.frame.midY, - expectedHostCenterY, - accuracy: 0.25, - "Minimal-mode sidebar controls should compensate for the titlebar icon padding by one backing pixel" - ) - } - func testTitlebarChromeSettingsUseHardcodedDefaults() { let suiteName = "WindowDragHandleHitTests.titlebarChromeSettings.\(UUID().uuidString)" let defaults = UserDefaults(suiteName: suiteName)! @@ -975,91 +902,6 @@ final class WindowDragHandleHitTests: XCTestCase { XCTAssertTrue(windowDragHandleShouldCaptureHit(point, in: dragHandle, eventType: .leftMouseDown)) } - func testDragHandleNeverCapturesRegisteredBonsplitPaneTab() { - let window = NSWindow( - contentRect: NSRect(x: 0, y: 0, width: 320, height: 120), - styleMask: [.titled, .closable], - backing: .buffered, - defer: false - ) - defer { window.orderOut(nil) } - guard let contentView = window.contentView else { - XCTFail("Expected content view") - return - } - - let container = NSView(frame: contentView.bounds) - contentView.addSubview(container) - - let dragHandle = NSView(frame: container.bounds) - container.addSubview(dragHandle) - - let tabRegion = FakeBonsplitTabItemRegionView(frame: NSRect(x: 20, y: 82, width: 220, height: 30)) - tabRegion.tabFrames = [CGRect(x: 8, y: 0, width: 96, height: 30)] - container.addSubview(tabRegion) - BonsplitTabItemHitRegionRegistry.register(tabRegion) - defer { BonsplitTabItemHitRegionRegistry.unregister(tabRegion) } - - let tabWindowPoint = tabRegion.convert(NSPoint(x: 48, y: 15), to: nil) - let tabDragHandlePoint = dragHandle.convert(tabWindowPoint, from: nil) - XCTAssertFalse( - windowDragHandleShouldCaptureHit( - tabDragHandlePoint, - in: dragHandle, - eventType: .leftMouseDown, - eventWindow: window - ), - "A visible pane tab must own its mouse-down; the titlebar drag handle must not turn it into a window drag" - ) - - let emptyWindowPoint = tabRegion.convert(NSPoint(x: 180, y: 15), to: nil) - let emptyDragHandlePoint = dragHandle.convert(emptyWindowPoint, from: nil) - XCTAssertTrue( - windowDragHandleShouldCaptureHit( - emptyDragHandlePoint, - in: dragHandle, - eventType: .leftMouseDown, - eventWindow: window - ), - "Empty tab-strip chrome should remain available for app-window dragging" - ) - } - - func testTabBarEmptyChromeOverlayNeverCapturesRegisteredBonsplitPaneTabWhenFrameCacheIsEmpty() { - let window = NSWindow( - contentRect: NSRect(x: 0, y: 0, width: 360, height: 120), - styleMask: [.titled, .closable], - backing: .buffered, - defer: false - ) - defer { window.orderOut(nil) } - guard let contentView = window.contentView else { - XCTFail("Expected content view") - return - } - - let dragZone = TabBarDragZoneView.DragNSView(frame: NSRect(x: 0, y: 72, width: 320, height: 30)) - dragZone.hitRegion = .trailingEmptyChrome(tabFrames: [], reservedTrailingWidth: 48) - dragZone.hitTestEventTypeOverride = .leftMouseDown - contentView.addSubview(dragZone) - - let tabRegion = FakeBonsplitTabItemRegionView(frame: NSRect(x: 10, y: 72, width: 90, height: 30)) - tabRegion.tabFrames = [tabRegion.bounds] - contentView.addSubview(tabRegion) - BonsplitTabItemHitRegionRegistry.register(tabRegion) - defer { BonsplitTabItemHitRegionRegistry.unregister(tabRegion) } - - XCTAssertNil( - dragZone.hitTest(NSPoint(x: 40, y: 15)), - "The empty-chrome overlay must not turn a pane-tab mouse-down into an app-window drag while tab frames are still populating" - ) - XCTAssertIdentical( - dragZone.hitTest(NSPoint(x: 140, y: 15)), - dragZone, - "Empty tab-strip chrome after the registered tab should still be available for app-window dragging" - ) - } - func testDragHandleSkipsForeignLeftMouseDownDuringLaunch() { let point = NSPoint(x: 180, y: 18) let window = NSWindow( @@ -1748,44 +1590,6 @@ final class TitlebarLeadingInsetPassthroughViewTests: XCTestCase { let view = TitlebarLeadingInsetPassthroughView(frame: NSRect(x: 0, y: 0, width: 200, height: 40)) XCTAssertFalse(view.mouseDownCanMoveWindow) } - - func testMainWindowHostingViewCannotMoveWindowViaMouseDown() { - let view = MainWindowHostingView(rootView: Color.clear) - XCTAssertFalse( - view.mouseDownCanMoveWindow, - "Main content must never become an implicit AppKit window-drag region; explicit titlebar chrome owns app-window dragging" - ) - } - - func testMainWindowDragBehaviorRequiresExplicitDragZones() { - let window = CmuxMainWindow( - contentRect: NSRect(x: 0, y: 0, width: 320, height: 180), - styleMask: [.titled, .closable, .miniaturizable, .resizable, .fullSizeContentView], - backing: .buffered, - defer: false - ) - defer { window.orderOut(nil) } - window.isMovable = true - window.isMovableByWindowBackground = true - - configureCmuxMainWindowDragBehavior(window) - - XCTAssertFalse( - window.isMovable, - "Main windows must not use native AppKit titlebar dragging because pane tabs live in the titlebar band" - ) - XCTAssertFalse(window.isMovableByWindowBackground) - - let previous = withTemporaryWindowMovableEnabled(window: window) { - XCTAssertTrue(window.isMovable) - } - - XCTAssertEqual(previous, false) - XCTAssertFalse( - window.isMovable, - "Explicit chrome drag zones may temporarily enable movement, but the main window must return to pane-tab-safe immovable state" - ) - } } @@ -1849,25 +1653,6 @@ final class FolderWindowMoveSuppressionTests: XCTestCase { XCTAssertFalse(window.isMovable) } - func testClearWindowDragSuppressionFinishesActiveMoveSequence() { - let window = makeWindow() - window.isMovable = true - - XCTAssertEqual( - beginWindowMoveSuppressionSequence(window: window, reason: .bonsplitPaneTabDrag), - .bonsplitPaneTabDrag - ) - XCTAssertFalse(window.isMovable) - XCTAssertEqual(activeWindowMoveSuppressionSequenceReason(window: window), .bonsplitPaneTabDrag) - - XCTAssertEqual(clearWindowDragSuppression(window: window), 0) - - XCTAssertNil(activeWindowMoveSuppressionSequenceReason(window: window)) - XCTAssertEqual(windowDragSuppressionDepth(window: window), 0) - XCTAssertFalse(isWindowDragSuppressed(window: window)) - XCTAssertTrue(window.isMovable) - } - func testWindowDragSuppressionDepthLifecycle() { let window = makeWindow() XCTAssertEqual(windowDragSuppressionDepth(window: window), 0) @@ -1996,135 +1781,6 @@ final class WindowMoveSuppressionHitPathTests: XCTestCase { let dragged = makeMouseEvent(type: .leftMouseDragged, location: NSPoint(x: 20, y: 20), window: window) XCTAssertFalse(shouldSuppressWindowMoveForFolderDrag(window: window, event: dragged)) } - - func testBonsplitPaneTabMouseDownSuppressesWindowMove() { - let (window, contentView) = makeWindowWithContentView() - window.isMovable = true - let tabRegion = FakeBonsplitTabItemRegionView(frame: NSRect(x: 20, y: 132, width: 240, height: 30)) - tabRegion.tabFrames = [CGRect(x: 8, y: 0, width: 96, height: 30)] - contentView.addSubview(tabRegion) - BonsplitTabItemHitRegionRegistry.register(tabRegion) - defer { BonsplitTabItemHitRegionRegistry.unregister(tabRegion) } - - let tabPoint = tabRegion.convert(NSPoint(x: 28, y: 15), to: nil) - let event = makeMouseEvent(type: .leftMouseDown, location: tabPoint, window: window) - - XCTAssertTrue(shouldSuppressWindowMoveForBonsplitPaneTabDrag(window: window, event: event)) - XCTAssertEqual(windowMoveSuppressionReason(window: window, event: event), .bonsplitPaneTabDrag) - } - - func testBonsplitPaneTabDragSequenceKeepsWindowImmovableUntilMouseUp() { - let (window, contentView) = makeWindowWithContentView() - window.isMovable = true - let tabRegion = FakeBonsplitTabItemRegionView(frame: NSRect(x: 20, y: 132, width: 240, height: 30)) - tabRegion.tabFrames = [CGRect(x: 8, y: 0, width: 96, height: 30)] - contentView.addSubview(tabRegion) - BonsplitTabItemHitRegionRegistry.register(tabRegion) - defer { - _ = finishWindowMoveSuppressionSequence(window: window) - BonsplitTabItemHitRegionRegistry.unregister(tabRegion) - } - - let tabPoint = tabRegion.convert(NSPoint(x: 28, y: 15), to: nil) - let down = makeMouseEvent(type: .leftMouseDown, location: tabPoint, window: window) - - XCTAssertEqual(beginOrContinueWindowMoveSuppressionSequenceForEvent(window: window, event: down), .bonsplitPaneTabDrag) - XCTAssertFalse(window.isMovable) - XCTAssertTrue(isWindowDragSuppressed(window: window)) - XCTAssertEqual(activeWindowMoveSuppressionSequenceReason(window: window), .bonsplitPaneTabDrag) - - let draggedOutsideTab = makeMouseEvent( - type: .leftMouseDragged, - location: NSPoint(x: contentView.bounds.midX, y: contentView.bounds.midY), - window: window - ) - XCTAssertEqual( - beginOrContinueWindowMoveSuppressionSequenceForEvent(window: window, event: draggedOutsideTab), - .bonsplitPaneTabDrag - ) - XCTAssertFalse(window.isMovable, "Window must remain immovable for the whole tab-drag mouse sequence") - XCTAssertFalse(shouldFinishWindowMoveSuppressionSequenceAfterDispatch(window: window, event: draggedOutsideTab)) - - let up = makeMouseEvent(type: .leftMouseUp, location: tabPoint, window: window) - XCTAssertEqual(beginOrContinueWindowMoveSuppressionSequenceForEvent(window: window, event: up), .bonsplitPaneTabDrag) - XCTAssertTrue(shouldFinishWindowMoveSuppressionSequenceAfterDispatch(window: window, event: up)) - XCTAssertEqual(finishWindowMoveSuppressionSequence(window: window), .bonsplitPaneTabDrag) - XCTAssertTrue(window.isMovable) - XCTAssertFalse(isWindowDragSuppressed(window: window)) - XCTAssertNil(activeWindowMoveSuppressionSequenceReason(window: window)) - } - - func testBonsplitPaneTabSuppressionRestoresImmovableMainWindow() { - let (window, contentView) = makeWindowWithContentView() - window.isMovable = false - let tabRegion = FakeBonsplitTabItemRegionView(frame: NSRect(x: 20, y: 132, width: 240, height: 30)) - tabRegion.tabFrames = [CGRect(x: 8, y: 0, width: 96, height: 30)] - contentView.addSubview(tabRegion) - BonsplitTabItemHitRegionRegistry.register(tabRegion) - defer { - _ = finishWindowMoveSuppressionSequence(window: window) - BonsplitTabItemHitRegionRegistry.unregister(tabRegion) - } - - let tabPoint = tabRegion.convert(NSPoint(x: 28, y: 15), to: nil) - let down = makeMouseEvent(type: .leftMouseDown, location: tabPoint, window: window) - - XCTAssertEqual(beginOrContinueWindowMoveSuppressionSequenceForEvent(window: window, event: down), .bonsplitPaneTabDrag) - XCTAssertFalse(window.isMovable) - XCTAssertEqual(finishWindowMoveSuppressionSequence(window: window), .bonsplitPaneTabDrag) - XCTAssertFalse( - window.isMovable, - "Tab-drag suppression must not restore native AppKit window dragging when the main window baseline is immovable" - ) - } - - func testNewMouseDownReevaluatesAfterStaleBonsplitPaneTabSuppression() { - let (window, contentView) = makeWindowWithContentView() - window.isMovable = true - let tabRegion = FakeBonsplitTabItemRegionView(frame: NSRect(x: 20, y: 132, width: 240, height: 30)) - tabRegion.tabFrames = [CGRect(x: 8, y: 0, width: 96, height: 30)] - contentView.addSubview(tabRegion) - BonsplitTabItemHitRegionRegistry.register(tabRegion) - defer { - _ = finishWindowMoveSuppressionSequence(window: window) - BonsplitTabItemHitRegionRegistry.unregister(tabRegion) - } - - let tabPoint = tabRegion.convert(NSPoint(x: 28, y: 15), to: nil) - let down = makeMouseEvent(type: .leftMouseDown, location: tabPoint, window: window) - XCTAssertEqual(beginOrContinueWindowMoveSuppressionSequenceForEvent(window: window, event: down), .bonsplitPaneTabDrag) - XCTAssertFalse(window.isMovable) - - let emptyChromePoint = tabRegion.convert(NSPoint(x: 180, y: 15), to: nil) - let nextDown = makeMouseEvent(type: .leftMouseDown, location: emptyChromePoint, window: window) - XCTAssertNil( - beginOrContinueWindowMoveSuppressionSequenceForEvent( - window: window, - event: nextDown, - pressedMouseButtons: 1 - ), - "A fresh mouse-down must end stale tab suppression and re-check the actual hit target" - ) - XCTAssertTrue(window.isMovable) - XCTAssertFalse(isWindowDragSuppressed(window: window)) - XCTAssertNil(activeWindowMoveSuppressionSequenceReason(window: window)) - } - - func testBonsplitPaneTabSuppressionLeavesEmptyTabChromeDraggable() { - let (window, contentView) = makeWindowWithContentView() - window.isMovable = true - let tabRegion = FakeBonsplitTabItemRegionView(frame: NSRect(x: 20, y: 132, width: 240, height: 30)) - tabRegion.tabFrames = [CGRect(x: 8, y: 0, width: 96, height: 30)] - contentView.addSubview(tabRegion) - BonsplitTabItemHitRegionRegistry.register(tabRegion) - defer { BonsplitTabItemHitRegionRegistry.unregister(tabRegion) } - - let emptyChromePoint = tabRegion.convert(NSPoint(x: 180, y: 15), to: nil) - let event = makeMouseEvent(type: .leftMouseDown, location: emptyChromePoint, window: window) - - XCTAssertFalse(shouldSuppressWindowMoveForBonsplitPaneTabDrag(window: window, event: event)) - XCTAssertNil(windowMoveSuppressionReason(window: window, event: event)) - } } private final class FilePreviewPDFChromeNotificationFlag: @unchecked Sendable { diff --git a/cmuxTests/WindowAppearanceSnapshotTests.swift b/cmuxTests/WindowAppearanceSnapshotTests.swift index 752a49fee171..0396108065ec 100644 --- a/cmuxTests/WindowAppearanceSnapshotTests.swift +++ b/cmuxTests/WindowAppearanceSnapshotTests.swift @@ -81,19 +81,6 @@ final class WindowAppearanceSnapshotTests: XCTestCase { XCTAssertEqual(sidebarPolicy.tintColor.hexString(includeAlpha: true), "#FF000066") } - func testTranslucentTerminalUsesTransparentHostingWithOpaqueCompositedChromeColor() { - let snapshot = makeSnapshot( - unifySurfaceBackdrops: true, - backgroundOpacity: 0.5 - ) - - XCTAssertEqual(snapshot.compositedTerminalBackgroundColor.alphaComponent, 1, accuracy: 0.0001) - - let plan = snapshot.backdropPlan(glassEffectAvailable: false) - XCTAssertEqual(plan.hostingPhase, .transparentRootBackdrop) - XCTAssertTrue(plan.usesTransparentWindow) - } - func testSidebarTintChangesDoNotDriveWindowBackdropPlanIdentity() { let red = makeSnapshot( unifySurfaceBackdrops: false, @@ -114,120 +101,6 @@ final class WindowAppearanceSnapshotTests: XCTestCase { ) } - func testChromeColorSchemeFollowsTerminalBackground() { - XCTAssertEqual( - makeSnapshot(unifySurfaceBackdrops: true, backgroundHex: "#F8F8F2").chromeColorScheme, - .light - ) - XCTAssertEqual( - makeSnapshot(unifySurfaceBackdrops: true, backgroundHex: "#101820").chromeColorScheme, - .dark - ) - } - - func testChromeColorSchemeAccountsForTranslucentTerminalBackground() { - let composited = WindowAppearanceSnapshot.compositedTerminalColor( - backgroundColor: NSColor(hex: "#101820")!, - opacity: 0.05, - over: .white - ) - - XCTAssertEqual(cmuxReadableColorScheme(for: composited), .light) - } - - func testSidebarContentColorSchemeUsesTerminalOnlyForUnifiedBackdrops() { - XCTAssertEqual( - makeSnapshot(unifySurfaceBackdrops: true, backgroundHex: "#101820", sidebarColorScheme: .light) - .sidebarContentColorScheme, - .dark - ) - XCTAssertEqual( - makeSnapshot(unifySurfaceBackdrops: false, backgroundHex: "#101820", sidebarColorScheme: .light) - .sidebarContentColorScheme, - .light - ) - } - - func testUnifiedSidebarContrastOverlaySeparatesLightTerminalBackground() { - let snapshot = makeSnapshot(unifySurfaceBackdrops: true, backgroundHex: "#FFFFFF") - guard let overlay = snapshot.sidebarContrastOverlayColor(for: .leftSidebar) else { - XCTFail("expected sidebar overlay") - return - } - - XCTAssertLessThan(overlay.luminance, (NSColor(hex: "#FFFFFF") ?? .white).luminance) - XCTAssertEqual(overlay.alphaComponent, 0.20, accuracy: 0.0001) - XCTAssertNil(snapshot.sidebarContrastOverlayColor(for: .titlebar)) - } - - func testUnifiedSidebarContrastOverlaySeparatesDarkTerminalBackground() { - let snapshot = makeSnapshot(unifySurfaceBackdrops: true, backgroundHex: "#000000") - guard let overlay = snapshot.sidebarContrastOverlayColor(for: .rightSidebar) else { - XCTFail("expected sidebar overlay") - return - } - - XCTAssertGreaterThan(overlay.luminance, (NSColor(hex: "#000000") ?? .black).luminance) - XCTAssertEqual(overlay.alphaComponent, 0.18, accuracy: 0.0001) - XCTAssertNil(makeSnapshot(unifySurfaceBackdrops: false).sidebarContrastOverlayColor(for: .leftSidebar)) - } - - func testUnifiedSidebarContrastOverlayUsesCompositedTerminalBackground() { - let snapshot = makeSnapshot( - unifySurfaceBackdrops: true, - backgroundHex: "#000000", - backgroundOpacity: 0.05 - ) - guard let overlay = snapshot.sidebarContrastOverlayColor(for: .leftSidebar), - let overlaySRGB = overlay.usingColorSpace(.sRGB), - let compositedSRGB = snapshot.compositedTerminalBackgroundColor.usingColorSpace(.sRGB) else { - XCTFail("expected sRGB-convertible sidebar overlay") - return - } - - let isLight = cmuxReadableColorScheme(for: snapshot.compositedTerminalBackgroundColor) == .light - let adjustment: CGFloat = isLight ? -0.05 : 0.07 - XCTAssertEqual( - overlaySRGB.redComponent, - min(1, max(0, compositedSRGB.redComponent + adjustment)), - accuracy: 0.001 - ) - XCTAssertEqual( - overlaySRGB.greenComponent, - min(1, max(0, compositedSRGB.greenComponent + adjustment)), - accuracy: 0.001 - ) - XCTAssertEqual( - overlaySRGB.blueComponent, - min(1, max(0, compositedSRGB.blueComponent + adjustment)), - accuracy: 0.001 - ) - XCTAssertEqual(overlaySRGB.alphaComponent, isLight ? 0.20 : 0.18, accuracy: 0.0001) - } - - func testUnifiedSidebarContrastOverlayUsesChromeReadableSchemeForMediumBackground() { - let snapshot = makeSnapshot( - unifySurfaceBackdrops: true, - backgroundHex: "#777777", - backgroundOpacity: 1 - ) - - XCTAssertFalse(snapshot.compositedTerminalBackgroundColor.isLightColor) - XCTAssertEqual(snapshot.chromeColorScheme, .light) - - guard let overlay = snapshot.sidebarContrastOverlayColor(for: .leftSidebar), - let overlaySRGB = overlay.usingColorSpace(.sRGB), - let compositedSRGB = snapshot.compositedTerminalBackgroundColor.usingColorSpace(.sRGB) else { - XCTFail("expected sRGB-convertible sidebar overlay") - return - } - - XCTAssertLessThan(overlaySRGB.redComponent, compositedSRGB.redComponent) - XCTAssertLessThan(overlaySRGB.greenComponent, compositedSRGB.greenComponent) - XCTAssertLessThan(overlaySRGB.blueComponent, compositedSRGB.blueComponent) - XCTAssertEqual(overlaySRGB.alphaComponent, 0.20, accuracy: 0.0001) - } - func testOpaqueTerminalUsesOpaqueWindowFill() { let snapshot = makeSnapshot(unifySurfaceBackdrops: false, backgroundOpacity: 1.0) let plan = snapshot.backdropPlan(glassEffectAvailable: false) @@ -253,18 +126,15 @@ final class WindowAppearanceSnapshotTests: XCTestCase { private func makeSnapshot( unifySurfaceBackdrops: Bool, - backgroundHex: String = "#272822", backgroundOpacity: CGFloat = 0.6, backgroundBlur: GhosttyBackgroundBlur = .disabled, sidebarBlendMode: String = SidebarBlendModeOption.withinWindow.rawValue, sidebarTintHexDark: String? = nil, sidebarTintOpacity: Double = 0.18, - sidebarColorScheme: ColorScheme = .dark, bgGlassEnabled: Bool = false ) -> WindowAppearanceSnapshot { - let backgroundColor = NSColor(hex: backgroundHex) ?? .black - return WindowAppearanceSnapshot( - terminalBackgroundColor: backgroundColor, + WindowAppearanceSnapshot( + terminalBackgroundColor: NSColor(hex: "#272822") ?? .black, terminalBackgroundOpacity: backgroundOpacity, terminalBackgroundBlur: backgroundBlur, terminalRenderingMode: .windowHostBackdrop, @@ -279,7 +149,7 @@ final class WindowAppearanceSnapshotTests: XCTestCase { tintOpacity: sidebarTintOpacity, cornerRadius: 0, blurOpacity: 1, - colorScheme: sidebarColorScheme + colorScheme: .dark ), windowGlassSettings: WindowGlassSettingsSnapshot( sidebarBlendModeRawValue: sidebarBlendMode, @@ -287,7 +157,8 @@ final class WindowAppearanceSnapshotTests: XCTestCase { tintHex: "#000000", tintOpacity: 0.03, terminalBackgroundBlur: backgroundBlur, - terminalGlassTintColor: backgroundColor.withAlphaComponent(backgroundOpacity) + terminalGlassTintColor: (NSColor(hex: "#272822") ?? .black) + .withAlphaComponent(backgroundOpacity) ) ) } diff --git a/cmuxTests/WorkspaceManualUnreadTests.swift b/cmuxTests/WorkspaceManualUnreadTests.swift index 864fd7c9c4ea..f42832944edd 100644 --- a/cmuxTests/WorkspaceManualUnreadTests.swift +++ b/cmuxTests/WorkspaceManualUnreadTests.swift @@ -134,262 +134,6 @@ final class WorkspaceManualUnreadTests: XCTestCase { XCTAssertEqual(store.unreadCount(forTabId: workspace.id), 0) } - func testRestoredUnreadClearsWhenWorkspaceIsExplicitlySelected() throws { - let appDelegate = AppDelegate.shared ?? AppDelegate() - let manager = TabManager() - let store = TerminalNotificationStore.shared - - let originalTabManager = appDelegate.tabManager - let originalNotificationStore = appDelegate.notificationStore - let originalAppFocusOverride = AppFocusState.overrideIsFocused - - store.replaceNotificationsForTesting([]) - appDelegate.tabManager = manager - appDelegate.notificationStore = store - AppFocusState.overrideIsFocused = true - - defer { - store.replaceNotificationsForTesting([]) - appDelegate.tabManager = originalTabManager - appDelegate.notificationStore = originalNotificationStore - AppFocusState.overrideIsFocused = originalAppFocusOverride - } - - _ = try XCTUnwrap(manager.selectedWorkspace) - let restoredWorkspace = manager.addWorkspace(select: false, eagerLoadTerminal: false) - let restoredPanelId = try XCTUnwrap(restoredWorkspace.focusedPanelId) - - restoredWorkspace.restorePanelUnreadIndicator(restoredPanelId) - store.restoreUnreadIndicator(forTabId: restoredWorkspace.id) - - XCTAssertTrue(restoredWorkspace.hasRestoredUnreadIndicator(panelId: restoredPanelId)) - XCTAssertTrue(store.hasRestoredUnreadIndicator(forTabId: restoredWorkspace.id)) - - manager.selectWorkspace(restoredWorkspace) - drainMainQueue() - drainMainQueue() - - XCTAssertEqual(manager.selectedTabId, restoredWorkspace.id) - XCTAssertFalse(restoredWorkspace.hasRestoredUnreadIndicator(panelId: restoredPanelId)) - XCTAssertFalse(store.hasRestoredUnreadIndicator(forTabId: restoredWorkspace.id)) - } - - func testRestoredUnreadSameWorkspaceSurfaceSwitchClearsOnlyTargetPanel() throws { - let appDelegate = AppDelegate.shared ?? AppDelegate() - let manager = TabManager() - let store = TerminalNotificationStore.shared - - let originalTabManager = appDelegate.tabManager - let originalNotificationStore = appDelegate.notificationStore - let originalAppFocusOverride = AppFocusState.overrideIsFocused - - store.replaceNotificationsForTesting([]) - appDelegate.tabManager = manager - appDelegate.notificationStore = store - AppFocusState.overrideIsFocused = true - - defer { - store.replaceNotificationsForTesting([]) - appDelegate.tabManager = originalTabManager - appDelegate.notificationStore = originalNotificationStore - AppFocusState.overrideIsFocused = originalAppFocusOverride - } - - let workspace = try XCTUnwrap(manager.selectedWorkspace) - let currentPanelId = try XCTUnwrap(workspace.focusedPanelId) - let targetPanel = try XCTUnwrap(workspace.newTerminalSurfaceInFocusedPane(focus: false)) - let targetPanelId = targetPanel.id - workspace.focusPanel(currentPanelId) - - XCTAssertEqual(manager.selectedTabId, workspace.id) - XCTAssertEqual(workspace.focusedPanelId, currentPanelId) - - workspace.restorePanelUnreadIndicator(currentPanelId) - workspace.restorePanelUnreadIndicator(targetPanelId) - store.restoreUnreadIndicator(forTabId: workspace.id) - - XCTAssertTrue(workspace.hasRestoredUnreadIndicator(panelId: currentPanelId)) - XCTAssertTrue(workspace.hasRestoredUnreadIndicator(panelId: targetPanelId)) - - manager.focusTab( - workspace.id, - surfaceId: targetPanelId, - dismissRestoredUnreadOnResume: true - ) - drainMainQueue() - drainMainQueue() - - XCTAssertEqual(manager.selectedTabId, workspace.id) - XCTAssertEqual(workspace.focusedPanelId, targetPanelId) - XCTAssertTrue(workspace.hasRestoredUnreadIndicator(panelId: currentPanelId)) - XCTAssertFalse(workspace.hasRestoredUnreadIndicator(panelId: targetPanelId)) - } - - func testRestoredUnreadSurvivesProgrammaticActiveFocusSelection() throws { - let appDelegate = AppDelegate.shared ?? AppDelegate() - let manager = TabManager() - let store = TerminalNotificationStore.shared - - let originalTabManager = appDelegate.tabManager - let originalNotificationStore = appDelegate.notificationStore - let originalAppFocusOverride = AppFocusState.overrideIsFocused - - store.replaceNotificationsForTesting([]) - appDelegate.tabManager = manager - appDelegate.notificationStore = store - AppFocusState.overrideIsFocused = true - - defer { - store.replaceNotificationsForTesting([]) - appDelegate.tabManager = originalTabManager - appDelegate.notificationStore = originalNotificationStore - AppFocusState.overrideIsFocused = originalAppFocusOverride - } - - _ = try XCTUnwrap(manager.selectedWorkspace) - let restoredWorkspace = manager.addWorkspace(select: false, eagerLoadTerminal: false) - let restoredPanelId = try XCTUnwrap(restoredWorkspace.focusedPanelId) - - restoredWorkspace.restorePanelUnreadIndicator(restoredPanelId) - store.restoreUnreadIndicator(forTabId: restoredWorkspace.id) - - manager.selectedTabId = restoredWorkspace.id - drainMainQueue() - drainMainQueue() - - XCTAssertEqual(manager.selectedTabId, restoredWorkspace.id) - XCTAssertTrue(restoredWorkspace.hasRestoredUnreadIndicator(panelId: restoredPanelId)) - XCTAssertTrue(store.hasRestoredUnreadIndicator(forTabId: restoredWorkspace.id)) - } - - func testRestoredUnreadSurvivesSuppressedFocusFlashSelection() throws { - let appDelegate = AppDelegate.shared ?? AppDelegate() - let manager = TabManager() - let store = TerminalNotificationStore.shared - - let originalTabManager = appDelegate.tabManager - let originalNotificationStore = appDelegate.notificationStore - let originalAppFocusOverride = AppFocusState.overrideIsFocused - - store.replaceNotificationsForTesting([]) - appDelegate.tabManager = manager - appDelegate.notificationStore = store - AppFocusState.overrideIsFocused = true - - defer { - store.replaceNotificationsForTesting([]) - appDelegate.tabManager = originalTabManager - appDelegate.notificationStore = originalNotificationStore - AppFocusState.overrideIsFocused = originalAppFocusOverride - } - - _ = try XCTUnwrap(manager.selectedWorkspace) - let restoredWorkspace = manager.addWorkspace(select: false, eagerLoadTerminal: false) - let restoredPanelId = try XCTUnwrap(restoredWorkspace.focusedPanelId) - - restoredWorkspace.restorePanelUnreadIndicator(restoredPanelId) - store.restoreUnreadIndicator(forTabId: restoredWorkspace.id) - - manager.focusTab(restoredWorkspace.id, surfaceId: restoredPanelId, suppressFlash: true) - drainMainQueue() - drainMainQueue() - - XCTAssertEqual(manager.selectedTabId, restoredWorkspace.id) - XCTAssertTrue(restoredWorkspace.hasRestoredUnreadIndicator(panelId: restoredPanelId)) - XCTAssertTrue(store.hasRestoredUnreadIndicator(forTabId: restoredWorkspace.id)) - } - - func testRestoredUnreadClearsOnDirectInteractionWithoutClearingManualUnread() throws { - let appDelegate = AppDelegate.shared ?? AppDelegate() - let manager = TabManager() - let store = TerminalNotificationStore.shared - - let originalTabManager = appDelegate.tabManager - let originalNotificationStore = appDelegate.notificationStore - - store.replaceNotificationsForTesting([]) - appDelegate.tabManager = manager - appDelegate.notificationStore = store - - defer { - store.replaceNotificationsForTesting([]) - appDelegate.tabManager = originalTabManager - appDelegate.notificationStore = originalNotificationStore - } - - let workspace = try XCTUnwrap(manager.selectedWorkspace) - let panelId = try XCTUnwrap(workspace.focusedPanelId) - - workspace.markPanelUnread(panelId) - workspace.restorePanelUnreadIndicator(panelId) - store.markUnread(forTabId: workspace.id) - store.restoreUnreadIndicator(forTabId: workspace.id) - - XCTAssertTrue(workspace.manualUnreadPanelIds.contains(panelId)) - XCTAssertTrue(workspace.hasRestoredUnreadIndicator(panelId: panelId)) - XCTAssertTrue(store.hasManualUnread(forTabId: workspace.id)) - XCTAssertTrue(store.hasRestoredUnreadIndicator(forTabId: workspace.id)) - - XCTAssertTrue(manager.dismissNotificationOnDirectInteraction(tabId: workspace.id, surfaceId: panelId)) - - XCTAssertTrue(workspace.manualUnreadPanelIds.contains(panelId)) - XCTAssertFalse(workspace.hasRestoredUnreadIndicator(panelId: panelId)) - XCTAssertTrue(store.hasManualUnread(forTabId: workspace.id)) - XCTAssertFalse(store.hasRestoredUnreadIndicator(forTabId: workspace.id)) - XCTAssertEqual(store.unreadCount(forTabId: workspace.id), 1) - } - - func testTerminalInteractionWithMappedSurfaceIdClearsPanelUnreadIndicators() throws { - let appDelegate = AppDelegate.shared ?? AppDelegate() - let manager = TabManager() - let store = TerminalNotificationStore.shared - - let originalTabManager = appDelegate.tabManager - let originalNotificationStore = appDelegate.notificationStore - - store.replaceNotificationsForTesting([]) - appDelegate.tabManager = manager - appDelegate.notificationStore = store - - defer { - store.replaceNotificationsForTesting([]) - appDelegate.tabManager = originalTabManager - appDelegate.notificationStore = originalNotificationStore - } - - let workspace = try XCTUnwrap(manager.selectedWorkspace) - let panelId = try XCTUnwrap(workspace.focusedPanelId) - let liveSurfaceId = try XCTUnwrap(workspace.surfaceIdFromPanelId(panelId)?.uuid) - XCTAssertNotEqual(liveSurfaceId, panelId) - workspace.markPanelUnread(panelId) - workspace.restorePanelUnreadIndicator(panelId) - store.replaceNotificationsForTesting([ - TerminalNotification( - id: UUID(), - tabId: workspace.id, - surfaceId: liveSurfaceId, - panelId: panelId, - title: "Unread", - subtitle: "", - body: "", - createdAt: Date(timeIntervalSince1970: 1_700_000_000), - isRead: false - ), - ]) - - XCTAssertTrue(workspace.manualUnreadPanelIds.contains(panelId)) - XCTAssertTrue(workspace.hasRestoredUnreadIndicator(panelId: panelId)) - XCTAssertTrue(store.hasUnreadNotification(forTabId: workspace.id, surfaceId: liveSurfaceId)) - XCTAssertTrue(store.hasUnreadNotification(forTabId: workspace.id, surfaceId: panelId)) - - XCTAssertTrue(manager.dismissNotificationOnTerminalInteraction(tabId: workspace.id, surfaceId: liveSurfaceId)) - - XCTAssertFalse(workspace.manualUnreadPanelIds.contains(panelId)) - XCTAssertFalse(workspace.hasRestoredUnreadIndicator(panelId: panelId)) - XCTAssertFalse(store.hasUnreadNotification(forTabId: workspace.id, surfaceId: liveSurfaceId)) - XCTAssertFalse(store.hasUnreadNotification(forTabId: workspace.id, surfaceId: panelId)) - } - func testRestoredWorkspaceUnreadClearsFromReadAndClearFlows() { let store = TerminalNotificationStore.shared @@ -1390,37 +1134,19 @@ final class WorkspaceManualUnreadTests: XCTestCase { resetUnreadState() let cleanFingerprint = manager.sessionAutosaveFingerprint() - let notificationId = UUID() - let notificationCreatedAt = Date(timeIntervalSince1970: 1_700_000_000) store.replaceNotificationsForTesting([ TerminalNotification( - id: notificationId, + id: UUID(), tabId: workspace.id, surfaceId: panelId, title: "Unread", subtitle: "", body: "", - createdAt: notificationCreatedAt, + createdAt: Date(), isRead: false ), ]) XCTAssertNotEqual(cleanFingerprint, manager.sessionAutosaveFingerprint()) - let notificationWithoutPanelIdFingerprint = manager.sessionAutosaveFingerprint() - - store.replaceNotificationsForTesting([ - TerminalNotification( - id: notificationId, - tabId: workspace.id, - surfaceId: panelId, - panelId: panelId, - title: "Unread", - subtitle: "", - body: "", - createdAt: notificationCreatedAt, - isRead: false - ), - ]) - XCTAssertNotEqual(notificationWithoutPanelIdFingerprint, manager.sessionAutosaveFingerprint()) resetUnreadState() store.setFocusedReadIndicator(forTabId: workspace.id, surfaceId: panelId) diff --git a/cmuxTests/WorkspaceRemoteConnectionTests.swift b/cmuxTests/WorkspaceRemoteConnectionTests.swift index af2a1a8a9fda..2bec1d8464d2 100644 --- a/cmuxTests/WorkspaceRemoteConnectionTests.swift +++ b/cmuxTests/WorkspaceRemoteConnectionTests.swift @@ -4106,7 +4106,6 @@ final class CLINotifyProcessIntegrationTests: XCTestCase { "--identity", "/Users/test/.ssh/id_ed25519", "--ssh-option", "ControlPath /tmp/cmux-ssh-%C", "--ssh-option", "StrictHostKeyChecking=accept-new", - "--window", windowID, "cmux-macmini", ], environment: environment, @@ -4130,7 +4129,6 @@ final class CLINotifyProcessIntegrationTests: XCTestCase { ) let createParams = try XCTUnwrap(requests[0]["params"] as? [String: Any]) - XCTAssertEqual(createParams["window_id"] as? String, windowID) let initialCommand = try XCTUnwrap(createParams["initial_command"] as? String) XCTAssertFalse(initialCommand.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty) diff --git a/cmuxTests/WorkspaceUnitTests.swift b/cmuxTests/WorkspaceUnitTests.swift index f4b8fc84fe6c..a9de482f06cb 100644 --- a/cmuxTests/WorkspaceUnitTests.swift +++ b/cmuxTests/WorkspaceUnitTests.swift @@ -48,41 +48,8 @@ final class SidebarSelectedWorkspaceColorTests: XCTestCase { XCTAssertEqual(color.alphaComponent, 1.0, accuracy: 0.001) } - func testSelectedWorkspaceForegroundUsesBlackOnLightSelectionBackground() { - guard let color = sidebarSelectedWorkspaceForegroundNSColor( - on: NSColor(hex: "#FFFFFF")!, - opacity: 0.65 - ).usingColorSpace(.sRGB) else { - XCTFail("Expected sRGB-convertible color") - return - } - - XCTAssertEqual(color.redComponent, 0.0, accuracy: 0.001) - XCTAssertEqual(color.greenComponent, 0.0, accuracy: 0.001) - XCTAssertEqual(color.blueComponent, 0.0, accuracy: 0.001) - XCTAssertEqual(color.alphaComponent, 0.65, accuracy: 0.001) - } - - func testSelectedWorkspaceForegroundUsesWhiteOnDarkSelectionBackground() { - guard let color = sidebarSelectedWorkspaceForegroundNSColor( - on: NSColor(hex: "#123456")!, - opacity: 0.65 - ).usingColorSpace(.sRGB) else { - XCTFail("Expected sRGB-convertible color") - return - } - - XCTAssertEqual(color.redComponent, 1.0, accuracy: 0.001) - XCTAssertEqual(color.greenComponent, 1.0, accuracy: 0.001) - XCTAssertEqual(color.blueComponent, 1.0, accuracy: 0.001) - XCTAssertEqual(color.alphaComponent, 0.65, accuracy: 0.001) - } - - func testDefaultSelectedWorkspaceForegroundUsesNativeSelectionTextOnAccentBackground() { - guard let color = sidebarSelectedWorkspaceForegroundNSColor( - on: sidebarSelectedWorkspaceBackgroundNSColor(for: .light), - opacity: 0.65 - ).usingColorSpace(.sRGB) else { + func testSelectedWorkspaceForegroundAlwaysUsesWhiteWithRequestedOpacity() { + guard let color = sidebarSelectedWorkspaceForegroundNSColor(opacity: 0.65).usingColorSpace(.sRGB) else { XCTFail("Expected sRGB-convertible color") return } @@ -809,52 +776,6 @@ final class KeyboardShortcutSettingsFileStoreTests: XCTestCase { XCTAssertEqual(store.activeSourcePath, settingsFileURL.path) } - func testSettingsFileStoreAppliesSubagentNotificationSuppression() throws { - let defaults = UserDefaults.standard - let previousValue = defaults.object(forKey: AgentSubagentNotificationSettings.suppressNotificationsKey) - let previousBackups = defaults.data(forKey: settingsFileBackupsDefaultsKey) - defer { - if let previousValue { - defaults.set(previousValue, forKey: AgentSubagentNotificationSettings.suppressNotificationsKey) - } else { - defaults.removeObject(forKey: AgentSubagentNotificationSettings.suppressNotificationsKey) - } - if let previousBackups { - defaults.set(previousBackups, forKey: settingsFileBackupsDefaultsKey) - } else { - defaults.removeObject(forKey: settingsFileBackupsDefaultsKey) - } - } - defaults.removeObject(forKey: AgentSubagentNotificationSettings.suppressNotificationsKey) - defaults.removeObject(forKey: settingsFileBackupsDefaultsKey) - - let directoryURL = try makeTemporaryDirectory() - defer { try? FileManager.default.removeItem(at: directoryURL) } - - let settingsFileURL = directoryURL.appendingPathComponent("cmux.json", isDirectory: false) - try writeSettingsFile( - """ - { - "automation": { - "suppressSubagentNotifications": false - } - } - """, - to: settingsFileURL - ) - - _ = KeyboardShortcutSettingsFileStore( - primaryPath: settingsFileURL.path, - fallbackPath: nil, - startWatching: false - ) - - XCTAssertEqual( - defaults.object(forKey: AgentSubagentNotificationSettings.suppressNotificationsKey) as? Bool, - false - ) - } - func testSettingsFileStoreAppliesBrowserHiddenWebViewDiscardDelayAtMaximum() throws { let defaults = UserDefaults.standard let previousEnabled = defaults.object(forKey: BrowserHiddenWebViewDiscardPolicy.enabledKey) diff --git a/cmuxUITests/MultiWindowNotificationsUITests.swift b/cmuxUITests/MultiWindowNotificationsUITests.swift index 5236bbed1164..680c4aff9fec 100644 --- a/cmuxUITests/MultiWindowNotificationsUITests.swift +++ b/cmuxUITests/MultiWindowNotificationsUITests.swift @@ -494,119 +494,6 @@ final class MultiWindowNotificationsUITests: XCTestCase { ) } - func testNewWorkspaceCLIWindowFlagTargetsSpecificWindow() throws { - let app = XCUIApplication() - let title = "window-route-\(UUID().uuidString.prefix(8))" - app.launchArguments += ["-socketControlMode", "allowAll"] - app.launchEnvironment["CMUX_UI_TEST_MULTI_WINDOW_NOTIF_SETUP"] = "1" - app.launchEnvironment["CMUX_UI_TEST_MULTI_WINDOW_NOTIF_PATH"] = dataPath - app.launchEnvironment["CMUX_SOCKET_PATH"] = socketPath - app.launchEnvironment["CMUX_SOCKET_MODE"] = "allowAll" - app.launchEnvironment["CMUX_SOCKET_ENABLE"] = "1" - app.launchEnvironment["CMUX_UI_TEST_SOCKET_SANITY"] = "1" - app.launchEnvironment["CMUX_UI_TEST_WINDOW_ROUTE_CLI"] = "1" - app.launchEnvironment["CMUX_UI_TEST_WINDOW_ROUTE_CLI_TITLE"] = title - app.launchEnvironment["CMUX_TAG"] = launchTag - app.launch() - XCTAssertTrue( - ensureForegroundAfterLaunch(app, timeout: 12.0), - "Expected app to launch for CLI --window workspace routing test. state=\(app.state.rawValue)" - ) - XCTAssertTrue( - waitForDataMatch(timeout: 20.0) { data in - let window1Id = data["window1Id"] ?? "" - let window2Id = data["window2Id"] ?? "" - let tabId1 = data["tabId1"] ?? "" - let socketReady = data["socketReady"] ?? "" - let routeStatus = data["windowRouteStatus"] ?? "" - return !window1Id.isEmpty && - !window2Id.isEmpty && - !tabId1.isEmpty && - !socketReady.isEmpty && - socketReady != "pending" && - !routeStatus.isEmpty && - routeStatus != "pending" - }, - "Expected multi-window setup data, socket readiness, and CLI route result. data=\(loadData() ?? [:])" - ) - - guard let setup = loadData() else { - XCTFail("Missing setup data") - return - } - if let expectedSocketPath = setup["socketExpectedPath"], !expectedSocketPath.isEmpty { - socketPath = expectedSocketPath - } - guard setup["socketReady"] == "1" else { - XCTFail( - "Control socket unavailable in this test environment. expected=\(socketPath) " + - socketDiagnostics(from: setup) - ) - return - } - guard setup["socketPingResponse"] == "PONG" else { - XCTFail( - "Control socket ping sanity check failed. path=\(socketPath) " + - socketDiagnostics(from: setup) - ) - return - } - let window1Id = try XCTUnwrap(setup["window1Id"]) - let window2Id = try XCTUnwrap(setup["window2Id"]) - XCTAssertTrue(waitForWindowCount(atLeast: 2, app: app, timeout: 6.0)) - - XCTAssertEqual( - setup["windowRouteStatus"], - "1", - "Expected bundled `cmux --window` route test hook to finish. failure=\(setup["windowRouteFailure"] ?? "")" - ) - - let createExitStatus = setup["windowRouteCreateStatus"] ?? "" - let createStdout = setup["windowRouteCreateStdout"] ?? "" - let createStderr = setup["windowRouteCreateStderr"] ?? "" - XCTAssertEqual( - createExitStatus, - "0", - "Expected `new-workspace --window` to succeed. stdout=\(createStdout) stderr=\(createStderr)" - ) - - let window2ExitStatus = setup["windowRouteWindow2Status"] ?? "" - let window2Stdout = setup["windowRouteWindow2Stdout"] ?? "" - let window2Stderr = setup["windowRouteWindow2Stderr"] ?? "" - XCTAssertEqual( - window2ExitStatus, - "0", - "Expected `list-workspaces --window` for target window to succeed. stdout=\(window2Stdout) stderr=\(window2Stderr)" - ) - guard let window2Payload = parseJSONObject(window2Stdout), - let window2Rows = window2Payload["workspaces"] as? [[String: Any]] else { - XCTFail("Failed to parse target window workspace list. stdout=\(window2Stdout) stderr=\(window2Stderr)") - return - } - XCTAssertTrue( - window2Rows.contains { $0["title"] as? String == title }, - "Expected new workspace '\(title)' in targeted window \(window2Id). stdout=\(window2Stdout)" - ) - - let window1ExitStatus = setup["windowRouteWindow1Status"] ?? "" - let window1Stdout = setup["windowRouteWindow1Stdout"] ?? "" - let window1Stderr = setup["windowRouteWindow1Stderr"] ?? "" - XCTAssertEqual( - window1ExitStatus, - "0", - "Expected `list-workspaces --window` for source window to succeed. stdout=\(window1Stdout) stderr=\(window1Stderr)" - ) - guard let window1Payload = parseJSONObject(window1Stdout), - let window1Rows = window1Payload["workspaces"] as? [[String: Any]] else { - XCTFail("Failed to parse source window workspace list. stdout=\(window1Stdout) stderr=\(window1Stderr)") - return - } - XCTAssertFalse( - window1Rows.contains { $0["title"] as? String == title }, - "Expected new workspace '\(title)' not to appear in source window \(window1Id). stdout=\(window1Stdout)" - ) - } - private func clickNotificationPopoverRowAndWaitForFocusChange( button: XCUIElement, app: XCUIApplication, @@ -648,13 +535,6 @@ final class MultiWindowNotificationsUITests: XCTestCase { return false } - private func waitForAppRunningAfterLaunch(_ app: XCUIApplication, timeout: TimeInterval) -> Bool { - if app.wait(for: .runningForeground, timeout: timeout) { - return true - } - return app.state == .runningBackground - } - private func waitForElementToDisappear(_ element: XCUIElement, timeout: TimeInterval) -> Bool { let predicate = NSPredicate(format: "exists == false") let expectation = XCTNSPredicateExpectation(predicate: predicate, object: element) diff --git a/docs/internal/skills-customization-ideas.md b/docs/internal/skills-customization-ideas.md index c0fe02d52545..fce13cbbe632 100644 --- a/docs/internal/skills-customization-ideas.md +++ b/docs/internal/skills-customization-ideas.md @@ -63,7 +63,7 @@ Keep the examples library focused on reusable end-user workflows: - SSH devbox: remote terminal plus local browser or notes surface. - Review PR: GitHub terminal, PR browser, and notes or markdown panel. - Docs workspace: docs dev server, browser preview, and markdown viewer. -- CI watch: GitHub Actions, WarpBuild, Feed TUI, and release monitors. +- CI watch: GitHub Actions, CircleCI, Feed TUI, and release monitors. - Quick agent buttons: Codex and Claude tab bar buttons with Command Palette entries. Use the Promotion Rule when an example starts to exceed diff --git a/scripts/circleci_auto_approve.py b/scripts/circleci_auto_approve.py new file mode 100755 index 000000000000..a8e67cd9643b --- /dev/null +++ b/scripts/circleci_auto_approve.py @@ -0,0 +1,269 @@ +#!/usr/bin/env python3 +from __future__ import annotations + +import json +import os +import re +import sys +import time +import urllib.error +import urllib.parse +import urllib.request +from dataclasses import dataclass +from typing import Any + + +GITHUB_API = os.environ.get("GITHUB_API_URL", "https://api.github.com") +CIRCLECI_API = os.environ.get("CIRCLECI_API_URL", "https://circleci.com/api/v2") +UUID_RE = r"[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}" +WORKFLOW_RE = re.compile(rf"/workflows/({UUID_RE})(?:[/?#]|$)") + + +@dataclass(frozen=True) +class Config: + repository: str + pr_head_repository: str + pr_head_owner: str + pr_head_owner_id: int + pr_head_sha: str + pr_author: str + pr_author_id: int + trusted_org: str + trusted_users: dict[str, int] + github_token: str + circleci_token: str + hold_job_name: str + max_attempts: int + poll_seconds: float + dry_run: bool + + +def parse_trusted_users(value: str) -> dict[str, int]: + trusted: dict[str, int] = {} + for item in value.split(","): + if not item.strip(): + continue + try: + login, user_id = item.strip().split(":", 1) + trusted[login] = int(user_id) + except ValueError as error: + raise SystemExit(f"Invalid TRUSTED_GITHUB_USERS entry: {item!r}") from error + return trusted + + +def load_config() -> Config: + return Config( + repository=require_env("GITHUB_REPOSITORY"), + pr_head_repository=os.environ.get("PR_HEAD_REPOSITORY", require_env("GITHUB_REPOSITORY")), + pr_head_owner=os.environ.get("PR_HEAD_OWNER", ""), + pr_head_owner_id=int(os.environ.get("PR_HEAD_OWNER_ID", "0") or "0"), + pr_head_sha=require_env("PR_HEAD_SHA"), + pr_author=require_env("PR_AUTHOR"), + pr_author_id=int(require_env("PR_AUTHOR_ID")), + trusted_org=os.environ.get("TRUSTED_GITHUB_ORG", "manaflow-ai"), + trusted_users=parse_trusted_users(os.environ.get("TRUSTED_GITHUB_USERS", "")), + github_token=require_env("GITHUB_TOKEN"), + circleci_token=os.environ.get("CIRCLECI_TOKEN", ""), + hold_job_name=os.environ.get("CIRCLECI_HOLD_JOB_NAME", "hold-for-approval"), + max_attempts=int(os.environ.get("CIRCLECI_APPROVAL_MAX_ATTEMPTS", "40")), + poll_seconds=float(os.environ.get("CIRCLECI_APPROVAL_POLL_SECONDS", "15")), + dry_run=os.environ.get("DRY_RUN", "").lower() in {"1", "true", "yes"}, + ) + + +def require_env(name: str) -> str: + value = os.environ.get(name, "") + if not value: + raise SystemExit(f"Missing required environment variable: {name}") + return value + + +def request_json(url: str, *, token: str, token_header: str = "Authorization", method: str = "GET") -> Any: + headers = {"Accept": "application/vnd.github+json"} + if token_header == "Authorization": + headers["Authorization"] = f"Bearer {token}" + else: + headers[token_header] = token + + request = urllib.request.Request(url, headers=headers, method=method) + with urllib.request.urlopen(request, timeout=20) as response: + data = response.read() + if not data: + return {} + return json.loads(data.decode("utf-8")) + + +def is_trusted_pr_source(config: Config) -> bool: + validate_trusted_users(config) + + if not is_trusted_subject(config, config.pr_author, config.pr_author_id, "PR author"): + return False + + if not config.pr_head_owner or config.pr_head_owner_id <= 0: + print("PR head repository owner is unavailable; treating as untrusted") + return False + + if config.pr_head_owner == config.pr_author and config.pr_head_owner_id == config.pr_author_id: + return True + + return is_trusted_subject( + config, + config.pr_head_owner, + config.pr_head_owner_id, + "PR head repository owner", + ) + + +def is_trusted_subject(config: Config, login: str, user_id: int, label: str) -> bool: + if config.trusted_users.get(login) == user_id: + print(f"{label} {login} ({user_id}) is explicitly trusted") + return True + + token = os.environ.get("GITHUB_ORG_READ_TOKEN", "") + if not token: + print(f"GITHUB_ORG_READ_TOKEN is not configured; cannot verify membership in {config.trusted_org}") + return False + url = f"{GITHUB_API}/orgs/{config.trusted_org}/members/{login}" + try: + request_json(url, token=token) + print(f"{label} {login} is a member of {config.trusted_org}") + return True + except urllib.error.HTTPError as error: + if error.code == 404: + print(f"{label} {login} is not visible as a member of {config.trusted_org}") + return False + reason = getattr(error, "reason", None) or getattr(error, "msg", "") + print( + f"Org membership check for {label} {login} in {config.trusted_org} " + f"failed with HTTP {error.code} {reason}; treating as untrusted" + ) + return False + except urllib.error.URLError as error: + print( + f"Org membership check for {label} {login} in {config.trusted_org} " + f"failed with {error}; treating as untrusted" + ) + return False + + +def validate_trusted_users(config: Config) -> None: + for login, expected_id in config.trusted_users.items(): + url = f"{GITHUB_API}/users/{login}" + try: + payload = request_json(url, token=config.github_token) + except urllib.error.HTTPError as error: + raise SystemExit(f"Trusted GitHub user {login!r} could not be resolved") from error + actual_id = payload.get("id") + if actual_id != expected_id: + raise SystemExit(f"Trusted GitHub user {login!r} resolved to {actual_id}, expected {expected_id}") + + +def check_runs(config: Config) -> list[dict[str, Any]]: + checks: list[dict[str, Any]] = [] + page = 1 + while True: + url = ( + f"{GITHUB_API}/repos/{config.repository}/commits/{config.pr_head_sha}/check-runs" + f"?per_page=100&page={page}" + ) + payload = request_json(url, token=config.github_token) + items = payload.get("check_runs", []) + checks.extend(items) + if len(items) < 100: + return checks + page += 1 + + +def circleci_workflow_id_from_check(check: dict[str, Any]) -> str | None: + details_url = str(check.get("details_url") or "") + match = WORKFLOW_RE.search(details_url) + if not match: + return None + return match.group(1) + + +def find_circleci_workflow(config: Config) -> str | None: + for check in check_runs(config): + if not is_hold_check_name(str(check.get("name") or ""), config.hold_job_name): + continue + workflow_id = circleci_workflow_id_from_check(check) + if workflow_id: + return workflow_id + return None + + +def is_hold_check_name(check_name: str, hold_job_name: str) -> bool: + prefix = "ci/circleci: " + if not check_name.startswith(prefix): + return False + circleci_name = check_name[len(prefix):] + return circleci_name == hold_job_name or circleci_name.endswith(f"/{hold_job_name}") + + +def find_approval_request(config: Config, workflow_id: str) -> tuple[str | None, str] | None: + page_token = "" + while True: + url = f"{CIRCLECI_API}/workflow/{workflow_id}/job" + if page_token: + url += f"?page-token={urllib.parse.quote(page_token)}" + payload = request_json(url, token=config.circleci_token, token_header="Circle-Token") + for job in payload.get("items", []): + if job.get("name") != config.hold_job_name: + continue + if job.get("type") != "approval": + continue + status = str(job.get("status") or "") + if status == "success": + print(f"CircleCI approval job {config.hold_job_name} is already approved") + return (None, status) + approval_request_id = job.get("approval_request_id") or job.get("id") + if not approval_request_id: + raise SystemExit(f"Approval job {config.hold_job_name} has no approval_request_id") + return (str(approval_request_id), status) + page_token = str(payload.get("next_page_token") or "") + if not page_token: + return None + + +def approve(config: Config, workflow_id: str, approval_request_id: str) -> None: + url = f"{CIRCLECI_API}/workflow/{workflow_id}/approve/{approval_request_id}" + if config.dry_run: + print(f"DRY_RUN: would approve {config.hold_job_name} in workflow {workflow_id}") + return + request_json(url, token=config.circleci_token, token_header="Circle-Token", method="POST") + print(f"Approved CircleCI job {config.hold_job_name} in workflow {workflow_id}") + + +def run() -> int: + config = load_config() + if config.pr_head_repository == config.repository: + print("Same-repository PR does not need CircleCI hold approval") + return 0 + if not is_trusted_pr_source(config): + print("Not approving CircleCI for untrusted PR source") + return 0 + if not config.circleci_token and not config.dry_run: + raise SystemExit("Missing CIRCLECI_TOKEN for trusted PR author") + + for attempt in range(1, config.max_attempts + 1): + workflow_id = find_circleci_workflow(config) + if workflow_id: + approval = find_approval_request(config, workflow_id) + if approval: + approval_request_id, status = approval + if approval_request_id: + print(f"Found CircleCI approval job with status {status}") + approve(config, workflow_id, approval_request_id) + return 0 + print(f"CircleCI workflow {workflow_id} found, waiting for approval job") + else: + print(f"Waiting for CircleCI approval check ({attempt}/{config.max_attempts})") + if attempt < config.max_attempts: + time.sleep(config.poll_seconds) + continue + + raise SystemExit(f"Timed out waiting for ci/circleci: */{config.hold_job_name}") + + +if __name__ == "__main__": + sys.exit(run()) diff --git a/scripts/reload.sh b/scripts/reload.sh index 87a803fc8e16..acf78ad6c870 100755 --- a/scripts/reload.sh +++ b/scripts/reload.sh @@ -489,13 +489,6 @@ XCODEBUILD_ARGS=( if [[ -n "$DERIVED_DATA" ]]; then XCODEBUILD_ARGS+=(-derivedDataPath "$DERIVED_DATA") fi -if [[ -n "${CMUX_SOURCE_PACKAGES_DIR:-}" ]]; then - mkdir -p "$CMUX_SOURCE_PACKAGES_DIR" - XCODEBUILD_ARGS+=(-clonedSourcePackagesDirPath "$CMUX_SOURCE_PACKAGES_DIR") -fi -if [[ "${CMUX_DISABLE_AUTOMATIC_PACKAGE_RESOLUTION:-}" == "1" ]]; then - XCODEBUILD_ARGS+=(-disableAutomaticPackageResolution) -fi if [[ -z "$TAG" ]]; then XCODEBUILD_ARGS+=( INFOPLIST_KEY_CFBundleName="$APP_NAME" diff --git a/scripts/verify-main-thread-ca-transactions.sh b/scripts/verify-main-thread-ca-transactions.sh index 1a43f5e5599b..1af313b42cd3 100755 --- a/scripts/verify-main-thread-ca-transactions.sh +++ b/scripts/verify-main-thread-ca-transactions.sh @@ -6,7 +6,6 @@ TAG="${CMUX_TAG:-ca-main-thread}" SOCKET_PATH="${CMUX_SOCKET_PATH:-/tmp/cmux-debug-${TAG}.sock}" LOG_PATH="${CMUX_CA_ASSERT_LOG:-/tmp/cmux-ca-main-thread-${TAG}.log}" HOLD_SECONDS="${CMUX_CA_ASSERT_HOLD_SECONDS:-8}" -READY_TIMEOUT_SECONDS="${CMUX_CA_ASSERT_READY_TIMEOUT_SECONDS:-60}" APP_PID_FILE="${CMUX_CA_ASSERT_PID_FILE:-/tmp/cmux-ca-main-thread-${TAG}.pid}" if [ -z "$APP_PATH" ]; then @@ -85,7 +84,9 @@ CMUX_ALLOW_SOCKET_OVERRIDE=1 \ APP_PID=$! echo "$APP_PID" >"$APP_PID_FILE" -wait_for_app_alive() { +deadline=$((SECONDS + HOLD_SECONDS)) +socket_ready=0 +while [ "$SECONDS" -lt "$deadline" ]; do if ! kill -0 "$APP_PID" >/dev/null 2>&1; then wait "$APP_PID" >/dev/null 2>&1 || true echo "FAIL: cmux exited while CA_ASSERT_MAIN_THREAD_TRANSACTIONS=1 was active" >&2 @@ -93,15 +94,9 @@ wait_for_app_alive() { tail -80 "$LOG_PATH" >&2 2>/dev/null || true exit 1 fi -} -ready_deadline=$((SECONDS + READY_TIMEOUT_SECONDS)) -socket_ready=0 -while [ "$SECONDS" -lt "$ready_deadline" ]; do - wait_for_app_alive if [ -S "$SOCKET_PATH" ]; then socket_ready=1 - break fi sleep 0.25 done @@ -113,12 +108,6 @@ if [ "$socket_ready" -ne 1 ]; then exit 1 fi -hold_deadline=$((SECONDS + HOLD_SECONDS)) -while [ "$SECONDS" -lt "$hold_deadline" ]; do - wait_for_app_alive - sleep 0.25 -done - if grep -E "uncommitted CATransaction|implicit transaction wasn't created|CoreAnimation.*thread|CATransaction.*thread" "$LOG_PATH" >/dev/null 2>&1; then echo "FAIL: CoreAnimation reported a worker-thread transaction" >&2 echo "--- app log tail ($LOG_PATH) ---" >&2 diff --git a/tests/test_circleci_auto_approve.py b/tests/test_circleci_auto_approve.py new file mode 100755 index 000000000000..d23f86821e23 --- /dev/null +++ b/tests/test_circleci_auto_approve.py @@ -0,0 +1,456 @@ +#!/usr/bin/env python3 +from __future__ import annotations + +import importlib.util +import json +import os +import pathlib +import sys +import urllib.error +from contextlib import contextmanager +from typing import Any +from unittest import mock + + +ROOT = pathlib.Path(__file__).resolve().parents[1] +SCRIPT = ROOT / "scripts" / "circleci_auto_approve.py" +WORKFLOW_ID = "11111111-1111-1111-1111-111111111111" +APPROVAL_ID = "22222222-2222-2222-2222-222222222222" + + +def load_module() -> Any: + spec = importlib.util.spec_from_file_location("circleci_auto_approve", SCRIPT) + assert spec and spec.loader + module = importlib.util.module_from_spec(spec) + sys.modules["circleci_auto_approve"] = module + spec.loader.exec_module(module) + return module + + +class FakeResponse: + def __init__(self, payload: Any = None): + self.payload = payload + + def __enter__(self) -> "FakeResponse": + return self + + def __exit__(self, exc_type: object, exc: object, tb: object) -> None: + return None + + def read(self) -> bytes: + if self.payload is None: + return b"" + return json.dumps(self.payload).encode("utf-8") + + +def http_error(url: str, status: int) -> urllib.error.HTTPError: + return urllib.error.HTTPError(url, status, "not found", hdrs=None, fp=None) + + +def request_headers(request: Any) -> dict[str, str]: + return {name.lower(): value for name, value in request.header_items()} + + +def assert_github_auth(request: Any) -> None: + assert request_headers(request).get("authorization") == "Bearer github-token" + + +def assert_circleci_auth(request: Any) -> None: + assert request_headers(request).get("circle-token") == "circle-token" + + +@contextmanager +def env(**updates: str): + old = os.environ.copy() + for key in list(os.environ): + if key.startswith(("GITHUB_", "CIRCLECI_", "PR_", "TRUSTED_", "DRY_RUN")): + del os.environ[key] + os.environ.update(updates) + try: + yield + finally: + os.environ.clear() + os.environ.update(old) + + +def base_env(author: str) -> dict[str, str]: + author_ids = { + "lawrencecchen": "54008264", + "austinywang": "38676809", + "alice": "1111", + "mallory": "2222", + } + return { + "GITHUB_API_URL": "https://api.github.test", + "CIRCLECI_API_URL": "https://circleci.test/api/v2", + "GITHUB_REPOSITORY": "manaflow-ai/cmux", + "PR_HEAD_REPOSITORY": "contributor/cmux", + "PR_HEAD_OWNER": author, + "PR_HEAD_OWNER_ID": author_ids[author], + "PR_HEAD_SHA": "abc123", + "PR_AUTHOR": author, + "PR_AUTHOR_ID": author_ids[author], + "TRUSTED_GITHUB_ORG": "manaflow-ai", + "TRUSTED_GITHUB_USERS": "lawrencecchen:54008264,austinywang:38676809", + "GITHUB_TOKEN": "github-token", + "GITHUB_ORG_READ_TOKEN": "github-token", + "CIRCLECI_TOKEN": "circle-token", + "CIRCLECI_APPROVAL_MAX_ATTEMPTS": "1", + "CIRCLECI_APPROVAL_POLL_SECONDS": "0", + } + + +def fake_check_runs() -> dict[str, Any]: + return { + "check_runs": [ + { + "name": "ci/circleci: ci-gated/hold-for-approval", + "details_url": f"https://app.circleci.com/pipelines/circleci/example/workflows/{WORKFLOW_ID}", + } + ] + } + + +def fake_check_runs_without_hold(count: int = 100) -> dict[str, Any]: + return { + "check_runs": [ + { + "name": f"check-{index}", + "details_url": f"https://example.test/check-{index}", + } + for index in range(count) + ] + } + + +def fake_workflow_jobs(status: str = "blocked") -> dict[str, Any]: + return { + "items": [ + { + "name": "hold-for-approval", + "type": "approval", + "status": status, + "approval_request_id": APPROVAL_ID, + } + ] + } + + +def trusted_user_response(url: str) -> FakeResponse | None: + if url.endswith("/users/lawrencecchen"): + return FakeResponse({"login": "lawrencecchen", "id": 54008264}) + if url.endswith("/users/austinywang"): + return FakeResponse({"login": "austinywang", "id": 38676809}) + return None + + +def test_allowlisted_user_approves_without_membership_lookup() -> None: + calls: list[tuple[str, str]] = [] + + def urlopen(request: Any, timeout: int = 20) -> FakeResponse: + calls.append((request.get_method(), request.full_url)) + if request.full_url.startswith("https://api.github.test/"): + assert_github_auth(request) + if request.full_url.startswith("https://circleci.test/"): + assert_circleci_auth(request) + if response := trusted_user_response(request.full_url): + return response + if request.full_url.endswith("/check-runs?per_page=100&page=1"): + return FakeResponse(fake_check_runs()) + if request.full_url.endswith(f"/workflow/{WORKFLOW_ID}/job"): + return FakeResponse(fake_workflow_jobs()) + if request.full_url.endswith(f"/workflow/{WORKFLOW_ID}/approve/{APPROVAL_ID}"): + return FakeResponse({}) + raise AssertionError(f"unexpected request: {request.full_url}") + + with env(**base_env("lawrencecchen")): + module = load_module() + with mock.patch.object(module.urllib.request, "urlopen", urlopen): + assert module.run() == 0 + + urls = [url for _, url in calls] + assert not any("/orgs/manaflow-ai/members/lawrencecchen" in url for url in urls) + assert any(url.endswith("/users/austinywang") for url in urls) + assert any(method == "POST" and url == f"https://circleci.test/api/v2/workflow/{WORKFLOW_ID}/approve/{APPROVAL_ID}" for method, url in calls), calls + + +def test_visible_org_member_approves() -> None: + calls: list[tuple[str, str]] = [] + + def urlopen(request: Any, timeout: int = 20) -> FakeResponse: + calls.append((request.get_method(), request.full_url)) + if request.full_url.startswith("https://api.github.test/"): + assert_github_auth(request) + if request.full_url.startswith("https://circleci.test/"): + assert_circleci_auth(request) + if response := trusted_user_response(request.full_url): + return response + if request.full_url.endswith("/orgs/manaflow-ai/members/alice"): + return FakeResponse() + if request.full_url.endswith("/check-runs?per_page=100&page=1"): + return FakeResponse(fake_check_runs()) + if request.full_url.endswith(f"/workflow/{WORKFLOW_ID}/job"): + return FakeResponse(fake_workflow_jobs()) + if request.full_url.endswith(f"/workflow/{WORKFLOW_ID}/approve/{APPROVAL_ID}"): + return FakeResponse({}) + raise AssertionError(f"unexpected request: {request.full_url}") + + with env(**base_env("alice")): + module = load_module() + with mock.patch.object(module.urllib.request, "urlopen", urlopen): + assert module.run() == 0 + + assert any(method == "POST" and url == f"https://circleci.test/api/v2/workflow/{WORKFLOW_ID}/approve/{APPROVAL_ID}" for method, url in calls), calls + + +def test_non_member_does_not_call_circleci() -> None: + calls: list[tuple[str, str]] = [] + + def urlopen(request: Any, timeout: int = 20) -> FakeResponse: + calls.append((request.get_method(), request.full_url)) + if request.full_url.startswith("https://api.github.test/"): + assert_github_auth(request) + if response := trusted_user_response(request.full_url): + return response + if request.full_url.endswith("/orgs/manaflow-ai/members/mallory"): + raise http_error(request.full_url, 404) + raise AssertionError(f"unexpected request: {request.full_url}") + + with env(**base_env("mallory")): + module = load_module() + with mock.patch.object(module.urllib.request, "urlopen", urlopen): + assert module.run() == 0 + + assert all("circleci.test" not in url for _, url in calls) + + +def test_missing_org_token_does_not_call_circleci_for_non_allowlisted_member() -> None: + calls: list[tuple[str, str]] = [] + test_env = base_env("alice") + del test_env["GITHUB_ORG_READ_TOKEN"] + + def urlopen(request: Any, timeout: int = 20) -> FakeResponse: + calls.append((request.get_method(), request.full_url)) + if request.full_url.startswith("https://api.github.test/"): + assert_github_auth(request) + if response := trusted_user_response(request.full_url): + return response + raise AssertionError(f"unexpected request: {request.full_url}") + + with env(**test_env): + module = load_module() + with mock.patch.object(module.urllib.request, "urlopen", urlopen): + assert module.run() == 0 + + assert all("/orgs/manaflow-ai/members/alice" not in url for _, url in calls) + assert all("circleci.test" not in url for _, url in calls) + + +def test_trusted_author_cannot_approve_untrusted_fork_owner() -> None: + calls: list[tuple[str, str]] = [] + test_env = base_env("lawrencecchen") + test_env["PR_HEAD_REPOSITORY"] = "mallory/cmux" + test_env["PR_HEAD_OWNER"] = "mallory" + test_env["PR_HEAD_OWNER_ID"] = "2222" + + def urlopen(request: Any, timeout: int = 20) -> FakeResponse: + calls.append((request.get_method(), request.full_url)) + if request.full_url.startswith("https://api.github.test/"): + assert_github_auth(request) + if response := trusted_user_response(request.full_url): + return response + if request.full_url.endswith("/orgs/manaflow-ai/members/mallory"): + raise http_error(request.full_url, 404) + raise AssertionError(f"unexpected request: {request.full_url}") + + with env(**test_env): + module = load_module() + with mock.patch.object(module.urllib.request, "urlopen", urlopen): + assert module.run() == 0 + + urls = [url for _, url in calls] + assert any(url.endswith("/orgs/manaflow-ai/members/mallory") for url in urls) + assert all("circleci.test" not in url for url in urls) + + +def test_same_repository_pr_does_not_poll_circleci() -> None: + calls: list[tuple[str, str]] = [] + test_env = base_env("lawrencecchen") + test_env["PR_HEAD_REPOSITORY"] = "manaflow-ai/cmux" + + def urlopen(request: Any, timeout: int = 20) -> FakeResponse: + calls.append((request.get_method(), request.full_url)) + raise AssertionError(f"unexpected request: {request.full_url}") + + with env(**test_env): + module = load_module() + with mock.patch.object(module.urllib.request, "urlopen", urlopen): + assert module.run() == 0 + + assert calls == [] + + +def test_hold_check_name_accepts_legacy_and_workflow_prefixed_names() -> None: + module = load_module() + assert module.is_hold_check_name("ci/circleci: hold-for-approval", "hold-for-approval") + assert module.is_hold_check_name("ci/circleci: ci-gated/hold-for-approval", "hold-for-approval") + assert not module.is_hold_check_name("ci/circleci: macos-unit-tests", "hold-for-approval") + + +def test_membership_api_error_does_not_call_circleci() -> None: + calls: list[tuple[str, str]] = [] + + def urlopen(request: Any, timeout: int = 20) -> FakeResponse: + calls.append((request.get_method(), request.full_url)) + if request.full_url.startswith("https://api.github.test/"): + assert_github_auth(request) + if response := trusted_user_response(request.full_url): + return response + if request.full_url.endswith("/orgs/manaflow-ai/members/alice"): + raise http_error(request.full_url, 403) + raise AssertionError(f"unexpected request: {request.full_url}") + + with env(**base_env("alice")): + module = load_module() + with mock.patch.object(module.urllib.request, "urlopen", urlopen): + assert module.run() == 0 + + assert all("circleci.test" not in url for _, url in calls) + + +def test_already_approved_does_not_post() -> None: + calls: list[tuple[str, str]] = [] + + def urlopen(request: Any, timeout: int = 20) -> FakeResponse: + calls.append((request.get_method(), request.full_url)) + if request.full_url.startswith("https://api.github.test/"): + assert_github_auth(request) + if request.full_url.startswith("https://circleci.test/"): + assert_circleci_auth(request) + if response := trusted_user_response(request.full_url): + return response + if request.full_url.endswith("/check-runs?per_page=100&page=1"): + return FakeResponse(fake_check_runs()) + if request.full_url.endswith(f"/workflow/{WORKFLOW_ID}/job"): + return FakeResponse(fake_workflow_jobs(status="success")) + raise AssertionError(f"unexpected request: {request.full_url}") + + with env(**base_env("lawrencecchen")): + module = load_module() + with mock.patch.object(module.urllib.request, "urlopen", urlopen): + assert module.run() == 0 + + assert not any(method == "POST" for method, _ in calls) + + +def test_dry_run_paginates_and_does_not_post() -> None: + calls: list[tuple[str, str]] = [] + test_env = base_env("lawrencecchen") + test_env["DRY_RUN"] = "1" + + def urlopen(request: Any, timeout: int = 20) -> FakeResponse: + calls.append((request.get_method(), request.full_url)) + if request.full_url.startswith("https://api.github.test/"): + assert_github_auth(request) + if request.full_url.startswith("https://circleci.test/"): + assert_circleci_auth(request) + if response := trusted_user_response(request.full_url): + return response + if request.full_url.endswith("/check-runs?per_page=100&page=1"): + return FakeResponse(fake_check_runs_without_hold()) + if request.full_url.endswith("/check-runs?per_page=100&page=2"): + return FakeResponse(fake_check_runs()) + if request.full_url.endswith(f"/workflow/{WORKFLOW_ID}/job"): + return FakeResponse(fake_workflow_jobs()) + raise AssertionError(f"unexpected request: {request.full_url}") + + with env(**test_env): + module = load_module() + with mock.patch.object(module.urllib.request, "urlopen", urlopen): + assert module.run() == 0 + + assert any(url.endswith("/check-runs?per_page=100&page=2") for _, url in calls) + assert not any(method == "POST" for method, _ in calls) + + +def test_workflow_without_approval_job_keeps_polling() -> None: + calls: list[tuple[str, str]] = [] + workflow_job_calls = 0 + test_env = base_env("lawrencecchen") + test_env["CIRCLECI_APPROVAL_MAX_ATTEMPTS"] = "2" + + def urlopen(request: Any, timeout: int = 20) -> FakeResponse: + nonlocal workflow_job_calls + calls.append((request.get_method(), request.full_url)) + if request.full_url.startswith("https://api.github.test/"): + assert_github_auth(request) + if request.full_url.startswith("https://circleci.test/"): + assert_circleci_auth(request) + if response := trusted_user_response(request.full_url): + return response + if request.full_url.endswith("/check-runs?per_page=100&page=1"): + return FakeResponse(fake_check_runs()) + if request.full_url.endswith(f"/workflow/{WORKFLOW_ID}/job"): + workflow_job_calls += 1 + if workflow_job_calls == 1: + return FakeResponse({"items": []}) + return FakeResponse(fake_workflow_jobs()) + if request.full_url.endswith(f"/workflow/{WORKFLOW_ID}/approve/{APPROVAL_ID}"): + return FakeResponse({}) + raise AssertionError(f"unexpected request: {request.full_url}") + + with env(**test_env): + module = load_module() + with mock.patch.object(module.urllib.request, "urlopen", urlopen): + assert module.run() == 0 + + assert workflow_job_calls == 2 + assert any(method == "POST" and url == f"https://circleci.test/api/v2/workflow/{WORKFLOW_ID}/approve/{APPROVAL_ID}" for method, url in calls), calls + + +def test_unresolvable_allowlisted_login_fails_closed() -> None: + calls: list[tuple[str, str]] = [] + test_env = base_env("lawrencecchen") + test_env["TRUSTED_GITHUB_USERS"] = "lawrencecchen:54008264,austyinywang:38676809" + + def urlopen(request: Any, timeout: int = 20) -> FakeResponse: + calls.append((request.get_method(), request.full_url)) + if request.full_url.startswith("https://api.github.test/"): + assert_github_auth(request) + if request.full_url.endswith("/users/lawrencecchen"): + return FakeResponse({"login": "lawrencecchen", "id": 54008264}) + if request.full_url.endswith("/users/austyinywang"): + raise http_error(request.full_url, 404) + raise AssertionError(f"unexpected request: {request.full_url}") + + with env(**test_env): + module = load_module() + with mock.patch.object(module.urllib.request, "urlopen", urlopen): + try: + module.run() + except SystemExit: + pass + else: + raise AssertionError("expected SystemExit") + + assert all("circleci.test" not in url for _, url in calls) + + +def main() -> None: + test_allowlisted_user_approves_without_membership_lookup() + test_visible_org_member_approves() + test_non_member_does_not_call_circleci() + test_missing_org_token_does_not_call_circleci_for_non_allowlisted_member() + test_trusted_author_cannot_approve_untrusted_fork_owner() + test_same_repository_pr_does_not_poll_circleci() + test_hold_check_name_accepts_legacy_and_workflow_prefixed_names() + test_membership_api_error_does_not_call_circleci() + test_already_approved_does_not_post() + test_dry_run_paginates_and_does_not_post() + test_workflow_without_approval_job_keeps_polling() + test_unresolvable_allowlisted_login_fails_closed() + print("PASS: CircleCI auto approval trusts only allowlisted users or org members") + + +if __name__ == "__main__": + main() diff --git a/tests/test_claude_hook_stop_last_assistant.py b/tests/test_claude_hook_stop_last_assistant.py index 01d502bddd07..1c13724fd169 100644 --- a/tests/test_claude_hook_stop_last_assistant.py +++ b/tests/test_claude_hook_stop_last_assistant.py @@ -38,10 +38,8 @@ def resolve_cmux_cli() -> str: class CapturingSocketServer: - def __init__(self, workspace_id: str, surface_id: str) -> None: + def __init__(self) -> None: self.commands: list[str] = [] - self.workspace_id = workspace_id - self.surface_id = surface_id self.ready = threading.Event() self.stop = threading.Event() self.error: Exception | None = None @@ -111,22 +109,6 @@ def _response_for(self, line: str) -> str: if line.startswith("{"): try: request = json.loads(line) - if request.get("method") == "surface.list": - return json.dumps( - { - "id": request.get("id"), - "ok": True, - "result": { - "surfaces": [ - { - "id": self.surface_id, - "ref": self.surface_id, - "workspace_id": self.workspace_id, - } - ] - }, - } - ) return json.dumps({"id": request.get("id"), "ok": True, "result": {}}) except json.JSONDecodeError: pass @@ -149,7 +131,7 @@ def main() -> int: "last_assistant_message": "2", } - with CapturingSocketServer(workspace_id=workspace_id, surface_id=surface_id) as server: + with CapturingSocketServer() as server: env = os.environ.copy() env["CMUX_SOCKET_PATH"] = server.socket_path env["CMUX_WORKSPACE_ID"] = workspace_id diff --git a/tests/test_claude_wrapper_hooks.py b/tests/test_claude_wrapper_hooks.py index 0d10d12bf947..06299272a324 100644 --- a/tests/test_claude_wrapper_hooks.py +++ b/tests/test_claude_wrapper_hooks.py @@ -503,7 +503,7 @@ def test_live_socket_injects_supported_hooks_without_unlocking_bypass(failures: failures, ) hooks = settings.get("hooks", {}) - expected_hooks = {"SessionStart", "Stop", "SubagentStop", "SessionEnd", "Notification", "UserPromptSubmit", "PreToolUse", "PermissionRequest"} + expected_hooks = {"SessionStart", "Stop", "SessionEnd", "Notification", "UserPromptSubmit", "PreToolUse", "PermissionRequest"} expect(set(hooks.keys()) == expected_hooks, f"unexpected hook keys: {hooks.keys()}, expected {expected_hooks}", failures) for hook_name, expected_subcommand in { "SessionStart": "session-start", @@ -551,21 +551,6 @@ def test_live_socket_injects_supported_hooks_without_unlocking_bypass(failures: f"PermissionRequest hook should call hooks feed, got {permission_request_hooks}", failures, ) - subagent_stop_hooks = hooks.get("SubagentStop", [{}])[0].get("hooks", [{}]) - expect( - any( - h.get("command") == '"${CMUX_CLAUDE_HOOK_CMUX_BIN:-cmux}" hooks feed --source claude' - and h.get("async") is True - for h in subagent_stop_hooks - ), - f"SubagentStop hook should call hooks feed asynchronously, got {subagent_stop_hooks}", - failures, - ) - expect( - not any("hooks claude stop" in h.get("command", "") for h in subagent_stop_hooks), - f"SubagentStop hook should not call the visible stop hook, got {subagent_stop_hooks}", - failures, - ) # SessionEnd should have a short timeout (session is exiting) session_end_hooks = hooks.get("SessionEnd", [{}])[0].get("hooks", [{}]) expect( diff --git a/tests/test_cli_layout_focus_contract.py b/tests/test_cli_layout_focus_contract.py index 93bd3da419ed..86a6feeb0ea1 100644 --- a/tests/test_cli_layout_focus_contract.py +++ b/tests/test_cli_layout_focus_contract.py @@ -18,8 +18,7 @@ SURFACE_ID = "33333333-3333-4333-8333-333333333333" NEW_PANE_ID = "44444444-4444-4444-8444-444444444444" NEW_SURFACE_ID = "55555555-5555-4555-8555-555555555555" -WINDOW_ID = "66666666-6666-4666-8666-666666666666" -WINDOW_REF = "window:7" +WINDOW_ID = "window:7" class FakeCmuxState: @@ -29,16 +28,6 @@ def __init__(self) -> None: def handle(self, method: str, params: dict[str, object]) -> dict[str, object]: self.calls.append((method, params)) - if method == "window.list": - return { - "windows": [ - { - "id": WINDOW_ID, - "ref": WINDOW_REF, - "index": 7, - }, - ], - } if method == "workspace.create": return { "workspace_id": WORKSPACE_ID, @@ -206,7 +195,7 @@ def main() -> int: run_cli( cli, socket_path, - ["new-workspace", "--window", WINDOW_REF, "--name", "explicit-window"], + ["new-workspace", "--window", WINDOW_ID, "--name", "explicit-window"], env_overrides={ "CMUX_WORKSPACE_ID": WORKSPACE_ID, "CMUX_SURFACE_ID": SURFACE_ID, diff --git a/tests/test_cli_socket_autodiscovery.py b/tests/test_cli_socket_autodiscovery.py index 66befc176adb..c930b7238073 100755 --- a/tests/test_cli_socket_autodiscovery.py +++ b/tests/test_cli_socket_autodiscovery.py @@ -80,9 +80,7 @@ def _run(self) -> None: server.settimeout(min(0.2, remaining)) try: conn, _ = server.accept() - # GitHub's macOS Python can report socket polling timeouts as - # socket.timeout rather than built-in TimeoutError. - except (socket.timeout, TimeoutError): + except TimeoutError: continue connection_thread = threading.Thread( target=self._handle_connection, @@ -110,7 +108,7 @@ def _handle_connection(self, conn: socket.socket) -> None: if not chunk: break data += chunk - except (ConnectionResetError, socket.timeout, TimeoutError): + except (ConnectionResetError, TimeoutError): return if b"ping" in data: diff --git a/tests/test_codex_feed_hooks.py b/tests/test_codex_feed_hooks.py index 450b57418c9c..0766cc9cf522 100644 --- a/tests/test_codex_feed_hooks.py +++ b/tests/test_codex_feed_hooks.py @@ -475,7 +475,7 @@ def test_codex_monitor_survives_transient_owner_rpc_timeout(cli_path: str, root: raise AssertionError(f"monitor exited before publishing transcript failure: {fake.frames!r}") -def run_feed_hook(cli_path: str, socket_path: Path, payload: dict, decision: dict | None, source: str = "codex") -> tuple[dict, dict]: +def run_feed_hook(cli_path: str, socket_path: Path, payload: dict, decision: dict | None) -> tuple[dict, dict]: env = os.environ.copy() env["CMUX_SURFACE_ID"] = FAKE_SURFACE_ID env["CMUX_WORKSPACE_ID"] = FAKE_WORKSPACE_ID @@ -488,7 +488,7 @@ def run_feed_hook(cli_path: str, socket_path: Path, payload: dict, decision: dic "hooks", "feed", "--source", - source, + "codex", "--event", payload.get("hook_event_name", ""), ], @@ -555,26 +555,17 @@ def codex_command_hook_hash( def cmux_codex_hook_command(subcommand: str) -> str: - routed_arguments = f"hooks codex {subcommand}" return ( - 'cmux_cli="${CMUX_BUNDLED_CLI_PATH:-}"; if [ -z "$cmux_cli" ] || [ ! -x "$cmux_cli" ]; ' - 'then cmux_cli="$(command -v cmux 2>/dev/null || true)"; fi; if [ -n "$CMUX_SURFACE_ID" ] ' - '&& [ "$CMUX_CODEX_HOOKS_DISABLED" != "1" ] && [ -n "$cmux_cli" ]; then { ' - f'if [ -n "${{CMUX_SOCKET_PATH:-}}" ]; then "$cmux_cli" --socket "$CMUX_SOCKET_PATH" {routed_arguments}; ' - f'else "$cmux_cli" {routed_arguments}; fi; ' - "} || echo '{}'; else echo '{}'; fi" + '[ -n "$CMUX_SURFACE_ID" ] && [ "$CMUX_CODEX_HOOKS_DISABLED" != "1" ] ' + f"&& command -v cmux >/dev/null 2>&1 && cmux hooks codex {subcommand} || echo '{{}}'" ) def cmux_codex_feed_command(agent_event: str) -> str: - routed_arguments = f"hooks feed --source codex --event {agent_event}" return ( - 'cmux_cli="${CMUX_BUNDLED_CLI_PATH:-}"; if [ -z "$cmux_cli" ] || [ ! -x "$cmux_cli" ]; ' - 'then cmux_cli="$(command -v cmux 2>/dev/null || true)"; fi; if [ -n "$CMUX_SURFACE_ID" ] ' - '&& [ "$CMUX_CODEX_HOOKS_DISABLED" != "1" ] && [ -n "$cmux_cli" ]; then { ' - f'if [ -n "${{CMUX_SOCKET_PATH:-}}" ]; then "$cmux_cli" --socket "$CMUX_SOCKET_PATH" {routed_arguments}; ' - f'else "$cmux_cli" {routed_arguments}; fi; ' - "} || echo '{}'; else echo '{}'; fi" + '[ -n "$CMUX_SURFACE_ID" ] && [ "$CMUX_CODEX_HOOKS_DISABLED" != "1" ] ' + f"&& command -v cmux >/dev/null 2>&1 && cmux hooks feed --source codex --event {agent_event} " + "|| echo '{}'" ) @@ -713,7 +704,7 @@ def test_install_adds_codex_permission_request_hook(cli_path: str, root: Path) - if not groups: raise AssertionError(f"missing {event_name} hook group: {hooks!r}") command = groups[-1]["hooks"][0]["command"] - if command != cmux_codex_feed_command(event_name): + if f"cmux hooks feed --source codex --event {event_name}" not in command: raise AssertionError(f"wrong {event_name} feed command: {command!r}") if groups[-1]["hooks"][0].get("timeout") != 120_000: raise AssertionError(f"wrong {event_name} timeout: {groups[-1]!r}") @@ -769,7 +760,10 @@ def test_install_escapes_codex_hook_trust_state_keys(cli_path: str, root: Path) def test_install_preserves_codex_hook_position_with_third_party_hooks(cli_path: str, root: Path) -> None: codex_home = root / "codex-home-third-party" codex_home.mkdir() - cmux_pre_tool = cmux_codex_feed_command("PreToolUse") + cmux_pre_tool = ( + '[ -n "$CMUX_SURFACE_ID" ] && [ "$CMUX_CODEX_HOOKS_DISABLED" != "1" ] ' + "&& command -v cmux >/dev/null 2>&1 && cmux hooks feed --source codex --event PreToolUse || echo '{}'" + ) orca_hook = ( "if [ -x '/Users/lawrence/Library/Application Support/orca/agent-hooks/codex-hook.sh' ]; " "then /bin/sh '/Users/lawrence/Library/Application Support/orca/agent-hooks/codex-hook.sh'; fi" @@ -808,13 +802,13 @@ def test_install_preserves_codex_hook_position_with_third_party_hooks(cli_path: groups = hooks["hooks"]["PreToolUse"] first_command = groups[0]["hooks"][0]["command"] second_command = groups[1]["hooks"][0]["command"] - if first_command != cmux_pre_tool: + if "cmux hooks feed --source codex --event PreToolUse" not in first_command: raise AssertionError(f"cmux hook did not keep its existing position: {groups!r}") if second_command != orca_hook: raise AssertionError(f"third-party hook was not preserved after cmux hook: {groups!r}") -def test_install_deduplicates_interleaved_codex_hook_positions( +def test_install_preserves_each_codex_hook_position_with_interleaved_third_party_hooks( cli_path: str, root: Path ) -> None: codex_home = root / "codex-home-interleaved" @@ -862,10 +856,11 @@ def test_install_deduplicates_interleaved_codex_hook_positions( user_hook_before, cmux_pre_tool, user_hook_middle, + cmux_pre_tool, user_hook_after, ] if commands != expected: - raise AssertionError(f"interleaved cmux hook dedupe changed: {commands!r}") + raise AssertionError(f"interleaved cmux hook positions changed: {commands!r}") def test_install_collapses_consecutive_codex_hook_positions(cli_path: str, root: Path) -> None: @@ -2043,28 +2038,6 @@ def test_codex_pre_tool_use_is_telemetry_not_actionable(cli_path: str, root: Pat raise AssertionError(f"wrong PreToolUse event: {frame!r}") -def test_claude_subagent_stop_stays_distinct_feed_telemetry(cli_path: str, root: Path) -> None: - stdout, frame = run_feed_hook( - cli_path, - root / "cmux-claude-subagent-stop.sock", - { - "session_id": "claude-session", - "cwd": "/tmp/project", - "hook_event_name": "SubagentStop", - }, - None, - source="claude", - ) - if stdout != {}: - raise AssertionError(f"SubagentStop telemetry should not emit a decision: {stdout!r}") - params = frame["params"] - if params.get("wait_timeout_seconds") != 0: - raise AssertionError(f"SubagentStop should not wait for Feed reply: {frame!r}") - event = params["event"] - if event.get("hook_event_name") != "SubagentStop" or event.get("_source") != "claude": - raise AssertionError(f"SubagentStop should stay distinct in Feed, got {event!r}") - - def main() -> int: try: cli_path = resolve_cmux_cli() @@ -2072,7 +2045,7 @@ def main() -> int: print(f"FAIL: {exc}") return 1 - with tempfile.TemporaryDirectory(prefix="cmux-codex-feed-hooks-", dir="/tmp") as td: + with tempfile.TemporaryDirectory(prefix="cmux-codex-feed-hooks-") as td: root = Path(td) try: test_codex_stop_reaps_transcript_monitor(cli_path, root) @@ -2083,7 +2056,7 @@ def main() -> int: test_install_adds_codex_permission_request_hook(cli_path, root) test_install_escapes_codex_hook_trust_state_keys(cli_path, root) test_install_preserves_codex_hook_position_with_third_party_hooks(cli_path, root) - test_install_deduplicates_interleaved_codex_hook_positions(cli_path, root) + test_install_preserves_each_codex_hook_position_with_interleaved_third_party_hooks(cli_path, root) test_install_collapses_consecutive_codex_hook_positions(cli_path, root) test_install_replaces_legacy_codex_hook_commands(cli_path, root) test_install_migrates_legacy_codex_hooks_feature(cli_path, root) @@ -2110,7 +2083,6 @@ def main() -> int: test_permission_reply_uses_codex_permission_request_schema(cli_path, root) test_codex_persistent_permission_modes_degrade_to_once(cli_path, root) test_codex_pre_tool_use_is_telemetry_not_actionable(cli_path, root) - test_claude_subagent_stop_stays_distinct_feed_telemetry(cli_path, root) except Exception as exc: print(f"FAIL: {exc}") return 1 diff --git a/tests/test_shell_git_config_remote_url_parsing.py b/tests/test_shell_git_config_remote_url_parsing.py deleted file mode 100644 index 1416d14538f5..000000000000 --- a/tests/test_shell_git_config_remote_url_parsing.py +++ /dev/null @@ -1,177 +0,0 @@ -#!/usr/bin/env python3 -""" -Regression coverage for shell-side GitHub remote slug parsing. - -The sidebar PR probe reads .git/config directly so it does not spawn git while -refreshing metadata. Quoted git config URL values must match git's parsed value -closely enough that the app still scopes gh calls with --repo. -""" - -from __future__ import annotations - -import os -import shutil -import subprocess -import textwrap -from pathlib import Path - - -def _shell_command() -> str: - return textwrap.dedent( - """\ - source "$CMUX_TEST_SCRIPT" - _cmux_github_repo_slug_for_path "$CMUX_TEST_REPO" - """ - ) - - -def _run_case( - base: Path, - *, - shell: str, - shell_args: list[str], - script: Path, - config_mode: str, -) -> tuple[int, str]: - repo = base / shell / config_mode / "repo" - git_dir = repo / ".git" - git_dir.mkdir(parents=True, exist_ok=True) - (git_dir / "HEAD").write_text("ref: refs/heads/main\n", encoding="utf-8") - - remote_config = textwrap.dedent( - """\ - [remote "origin"] ; manually annotated main remote - url = "https://github.com/manaflow-ai/cmux.git" # canonical repo - fetch = +refs/heads/*:refs/remotes/origin/* - """ - ) - stale_remote_config = textwrap.dedent( - """\ - [remote "origin"] - url = https://github.com/example/stale.git - """ - ) - if config_mode == "direct": - (git_dir / "config").write_text(remote_config, encoding="utf-8") - elif config_mode == "direct-last-url-wins": - (git_dir / "config").write_text( - textwrap.dedent( - """\ - [remote "origin"] - url = https://github.com/example/stale.git - url = https://github.com/manaflow-ai/cmux.git - """ - ), - encoding="utf-8", - ) - elif config_mode == "include": - (git_dir / "config").write_text( - textwrap.dedent( - """\ - [include] - path = remotes.inc - """ - ), - encoding="utf-8", - ) - (git_dir / "remotes.inc").write_text(remote_config, encoding="utf-8") - elif config_mode == "includeIf-gitdir": - (git_dir / "config").write_text( - textwrap.dedent( - f"""\ - [includeIf "gitdir:{repo}/"] - path = conditional-remotes.inc - """ - ), - encoding="utf-8", - ) - (git_dir / "conditional-remotes.inc").write_text(remote_config, encoding="utf-8") - elif config_mode == "includeIf-gitdir-recursive": - (git_dir / "config").write_text( - textwrap.dedent( - f"""\ - [includeIf "gitdir:{repo}/**"] - path = recursive-conditional-remotes.inc - """ - ), - encoding="utf-8", - ) - (git_dir / "recursive-conditional-remotes.inc").write_text(remote_config, encoding="utf-8") - elif config_mode == "worktree-config-overrides-common": - common_dir = git_dir / "common" - common_dir.mkdir() - (git_dir / "commondir").write_text("common\n", encoding="utf-8") - (common_dir / "config").write_text(stale_remote_config, encoding="utf-8") - (git_dir / "config").write_text(remote_config, encoding="utf-8") - else: - return 1, f"unknown config mode {config_mode}" - - env = dict(os.environ) - env["CMUX_TEST_SCRIPT"] = str(script) - env["CMUX_TEST_REPO"] = str(repo) - - result = subprocess.run( - [shell, *shell_args, _shell_command()], - env=env, - capture_output=True, - text=True, - timeout=5, - ) - if result.returncode != 0: - return result.returncode, (result.stdout or "") + (result.stderr or "") - - output = result.stdout.strip() - if output != "manaflow-ai/cmux": - return 1, f"{shell} {config_mode}: expected manaflow-ai/cmux, got {output!r}" - return 0, f"{shell} {config_mode}: ok" - - -def main() -> int: - root = Path(__file__).resolve().parents[1] - cases = [ - ("zsh", ["-f", "-c"], root / "Resources/shell-integration/cmux-zsh-integration.zsh"), - ("bash", ["--noprofile", "--norc", "-c"], root / "Resources/shell-integration/cmux-bash-integration.bash"), - ] - - base = Path("/tmp") / f"cmux_shell_git_config_remote_url_{os.getpid()}" - try: - shutil.rmtree(base, ignore_errors=True) - base.mkdir(parents=True, exist_ok=True) - - failures: list[str] = [] - for shell, shell_args, script in cases: - if not script.exists(): - print(f"SKIP: missing integration script at {script}") - continue - for config_mode in ( - "direct", - "direct-last-url-wins", - "include", - "includeIf-gitdir", - "includeIf-gitdir-recursive", - "worktree-config-overrides-common", - ): - rc, detail = _run_case( - base, - shell=shell, - shell_args=shell_args, - script=script, - config_mode=config_mode, - ) - if rc != 0: - failures.append(detail) - - if failures: - print("FAIL:") - for failure in failures: - print(failure) - return 1 - - print("PASS: shell git config remote URL parsing follows quoted and included config") - return 0 - finally: - shutil.rmtree(base, ignore_errors=True) - - -if __name__ == "__main__": - raise SystemExit(main()) diff --git a/vendor/bonsplit b/vendor/bonsplit index a80d5af7b989..b5dd1f03993b 160000 --- a/vendor/bonsplit +++ b/vendor/bonsplit @@ -1 +1 @@ -Subproject commit a80d5af7b98951cfc77fd3d3259cb4a93e2f921c +Subproject commit b5dd1f03993b70d3aa4b079e347d557323844e67 diff --git a/web/app/[locale]/docs/configuration/page.tsx b/web/app/[locale]/docs/configuration/page.tsx index 9ec5f54eaed2..a35f3be8ed0c 100644 --- a/web/app/[locale]/docs/configuration/page.tsx +++ b/web/app/[locale]/docs/configuration/page.tsx @@ -11,7 +11,6 @@ import { DocsHeading } from "../../components/docs-heading"; type SchemaProperty = { title?: string; description?: string; - descriptionKey?: string; type?: string | string[]; enum?: string[]; default?: unknown; @@ -65,6 +64,7 @@ const settingsFileExample = `{ // "terminal": { // "showScrollBar": false, + // "showTimestamps": true, // "autoResumeAgentSessions": true // }, @@ -73,10 +73,6 @@ const settingsFileExample = `{ // "hostsToOpenInEmbeddedBrowser": ["localhost", "*.internal.example"] // }, - // "automation": { - // "suppressSubagentNotifications": true - // }, - // "workspaceColors": { // "colors": { // "Red": "#C0392B", @@ -165,15 +161,12 @@ function hasComplexDefaultValue(value: unknown): boolean { } function PropertyCard({ path, property }: { path: string; property: SchemaProperty }) { - const t = useTranslations("docs.configuration"); - const description = property.descriptionKey ? t(property.descriptionKey) : property.description; - return (
{path}
- {description &&

{description}

} + {property.description &&

{property.description}

}
Type
diff --git a/web/data/cmux-shortcuts.ts b/web/data/cmux-shortcuts.ts index 4dff87f634b3..aea6d9a8ec1f 100644 --- a/web/data/cmux-shortcuts.ts +++ b/web/data/cmux-shortcuts.ts @@ -114,6 +114,7 @@ export const shortcutCategories: ShortcutCategory[] = [ { id: "closeOtherTabsInPane", combos: [["⌥", "⌘", "T"]], description: { en: "Close other tabs in pane", ja: "ペイン内の他のタブを閉じる" } }, { id: "reopenClosedBrowserPanel", combos: [["⌘", "⇧", "T"]], description: { en: "Reopen closed browser panel", ja: "閉じたブラウザパネルを再度開く" } }, { id: "toggleTerminalCopyMode", combos: [["⌘", "⇧", "M"]], description: { en: "Toggle terminal copy mode", ja: "ターミナルコピーモードを切り替え" } }, + { id: "toggleTerminalTimestamps", combos: [["⌥", "⌘", "⇧", "E"]], description: { en: "Toggle terminal timestamps", ja: "ターミナルタイムスタンプを切り替え" } }, { id: "saveFilePreview", combos: [["⌘", "S"]], diff --git a/web/data/cmux.schema.json b/web/data/cmux.schema.json index 934556cbda0a..4bdc7533f78a 100644 --- a/web/data/cmux.schema.json +++ b/web/data/cmux.schema.json @@ -311,6 +311,11 @@ "default": true, "description": "Show the right-edge terminal scroll bar when scrollback is available. cmux automatically suppresses it for alternate-screen style TUI surfaces." }, + "showTimestamps": { + "type": "boolean", + "default": false, + "description": "Show a left-side terminal timestamp gutter aligned with output rows." + }, "autoResumeAgentSessions": { "type": "boolean", "default": true, @@ -525,11 +530,6 @@ "default": true, "description": "Show pull request metadata in the sidebar." }, - "watchGitStatus": { - "type": "boolean", - "default": true, - "description": "Watch repository files for sidebar branch and pull request metadata without polling git." - }, "makePullRequestsClickable": { "type": "boolean", "default": true, @@ -733,12 +733,6 @@ "default": "", "description": "Custom path to the ripgrep (rg) binary used by project search." }, - "suppressSubagentNotifications": { - "type": "boolean", - "default": true, - "descriptionKey": "schemaDescriptions.automation.suppressSubagentNotifications", - "description": "Suppress visible completion notifications and status mutations from nested Codex or Claude child agents while keeping their events in Feed telemetry." - }, "cursorIntegration": { "type": "boolean", "default": true, diff --git a/web/messages/ar.json b/web/messages/ar.json index d938170f6792..fbdaeae30a8c 100644 --- a/web/messages/ar.json +++ b/web/messages/ar.json @@ -486,12 +486,7 @@ "browserHostsEmbed": "المضيفون لفتحهم في المتصفح المدمج: ينطبق على الروابط المنقورة من مخرجات الطرفية. المضيفون في هذه القائمة يُفتحون في cmux؛ المضيفون الآخرون يُفتحون في متصفحك الافتراضي. يدعم مضيفاً واحداً أو حرف بدل لكل سطر (مثال: example.com، *.internal.example).", "browserHostsHttp": "مضيفو HTTP المسموح بهم في المتصفح المدمج: ينطبق فقط على روابط HTTP (غير HTTPS). المضيفون في هذه القائمة يمكنهم الفتح في cmux بدون تحذير. الافتراضيات تشمل localhost و*.localhost و127.0.0.1 و::1 و0.0.0.0 و*.localtest.me.", "exampleConfig": "مثال على الإعدادات", - "metaTitle": "الإعدادات", - "schemaDescriptions": { - "automation": { - "suppressSubagentNotifications": "قم بإخفاء إشعارات الإكمال المرئية وتغييرات الحالة من وكلاء Codex أو Claude الفرعيين المتداخلين مع إبقاء أحداثهم في قياسات Feed." - } - } + "metaTitle": "الإعدادات" }, "customCommands": { "title": "أوامر مخصصة", diff --git a/web/messages/bs.json b/web/messages/bs.json index f13996f20e95..b424acf5f864 100644 --- a/web/messages/bs.json +++ b/web/messages/bs.json @@ -486,12 +486,7 @@ "browserHostsEmbed": "Hostovi za otvaranje u ugrađenom pregledniku: primjenjuje se na linkove kliknute iz terminalskog izlaza. Hostovi na ovoj listi se otvaraju u cmux-u; ostali hostovi se otvaraju u vašem podrazumijevanom pregledniku. Podržava jedan host ili wildcard po liniji (na primjer: example.com, *.internal.example).", "browserHostsHttp": "HTTP hostovi dozvoljeni u ugrađenom pregledniku: primjenjuje se samo na HTTP (ne-HTTPS) URL-ove. Hostovi na ovoj listi se mogu otvoriti u cmux-u bez upozorenja. Podrazumijevane vrijednosti uključuju localhost, *.localhost, 127.0.0.1, ::1, 0.0.0.0 i *.localtest.me.", "exampleConfig": "Primjer konfiguracije", - "metaTitle": "Konfiguracija", - "schemaDescriptions": { - "automation": { - "suppressSubagentNotifications": "Sakrij vidljiva obavještenja o završetku i promjene statusa od ugniježđenih Codex ili Claude podagenata, uz zadržavanje njihovih događaja u Feed telemetriji." - } - } + "metaTitle": "Konfiguracija" }, "customCommands": { "title": "Prilagođene komande", diff --git a/web/messages/da.json b/web/messages/da.json index aad77a7a6950..32bdffc6d6bd 100644 --- a/web/messages/da.json +++ b/web/messages/da.json @@ -486,12 +486,7 @@ "browserHostsEmbed": "Værter til åbning i indbygget browser: gælder for links klikket fra terminaloutput. Værter på denne liste åbnes i cmux; andre værter åbnes i din standardbrowser. Understøtter én vært eller wildcard per linje (for eksempel: example.com, *.internal.example).", "browserHostsHttp": "HTTP-værter tilladt i indbygget browser: gælder kun for HTTP (ikke-HTTPS) URL'er. Værter på denne liste kan åbnes i cmux uden en advarsel. Standard inkluderer localhost, *.localhost, 127.0.0.1, ::1, 0.0.0.0 og *.localtest.me.", "exampleConfig": "Eksempelkonfiguration", - "metaTitle": "Konfiguration", - "schemaDescriptions": { - "automation": { - "suppressSubagentNotifications": "Skjul synlige fuldførelsesnotifikationer og statusændringer fra indlejrede Codex- eller Claude-underagenter, mens deres hændelser bevares i Feed-telemetri." - } - } + "metaTitle": "Konfiguration" }, "customCommands": { "title": "Brugerdefinerede kommandoer", diff --git a/web/messages/de.json b/web/messages/de.json index 1b2b51483232..993ebc6d0866 100644 --- a/web/messages/de.json +++ b/web/messages/de.json @@ -486,12 +486,7 @@ "browserHostsEmbed": "Hosts im eingebetteten Browser öffnen: Gilt für Links, die aus der Terminal-Ausgabe geklickt werden. Hosts in dieser Liste öffnen sich in cmux; andere Hosts öffnen sich in Ihrem Standardbrowser. Unterstützt einen Host oder Wildcard pro Zeile (zum Beispiel: example.com, *.internal.example).", "browserHostsHttp": "Im eingebetteten Browser erlaubte HTTP-Hosts: Gilt nur für HTTP-URLs (nicht HTTPS). Hosts in dieser Liste können in cmux ohne Warnhinweis geöffnet werden. Standardmäßig enthalten sind localhost, *.localhost, 127.0.0.1, ::1, 0.0.0.0 und *.localtest.me.", "exampleConfig": "Beispielkonfiguration", - "metaTitle": "Konfiguration", - "schemaDescriptions": { - "automation": { - "suppressSubagentNotifications": "Unterdrücke sichtbare Abschlussbenachrichtigungen und Statusänderungen von verschachtelten Codex- oder Claude-Unteragenten, während ihre Ereignisse in der Feed-Telemetrie bleiben." - } - } + "metaTitle": "Konfiguration" }, "customCommands": { "title": "Benutzerdefinierte Befehle", diff --git a/web/messages/en.json b/web/messages/en.json index 8742134d9b5a..77f6c4bbad1d 100644 --- a/web/messages/en.json +++ b/web/messages/en.json @@ -587,12 +587,7 @@ "settingsFileDesc": "cmux.json stores cmux-owned app settings, shortcuts, actions, commands, and workspace layouts.", "settingsFilePrecedence": "Shortcuts defined in cmux.json override the in-app Settings value. Managed shortcuts stay visible in Settings but become read-only there.", "settingsFileChords": "Use a string for a single shortcut or a two-item array for a chord. Example: [\"ctrl+b\", \"c\"] means press Ctrl+B, then C.", - "exampleConfig": "Example config", - "schemaDescriptions": { - "automation": { - "suppressSubagentNotifications": "Suppress visible completion notifications and status mutations from nested Codex or Claude child agents while keeping their events in Feed telemetry." - } - } + "exampleConfig": "Example config" }, "customCommands": { "title": "Custom Commands", diff --git a/web/messages/es.json b/web/messages/es.json index 81f9f6d4720d..96dd9bd77fb4 100644 --- a/web/messages/es.json +++ b/web/messages/es.json @@ -486,12 +486,7 @@ "browserHostsEmbed": "Hosts para abrir en el navegador integrado: se aplica a enlaces clicados desde la salida del terminal. Los hosts en esta lista se abren en cmux; otros hosts se abren en su navegador predeterminado. Soporta un host o comodín por línea (por ejemplo: example.com, *.internal.example).", "browserHostsHttp": "Hosts HTTP permitidos en el navegador integrado: se aplica solo a URLs HTTP (no HTTPS). Los hosts en esta lista pueden abrirse en cmux sin un aviso de advertencia. Los valores predeterminados incluyen localhost, *.localhost, 127.0.0.1, ::1, 0.0.0.0 y *.localtest.me.", "exampleConfig": "Configuración de ejemplo", - "metaTitle": "Configuración", - "schemaDescriptions": { - "automation": { - "suppressSubagentNotifications": "Suprime las notificaciones visibles de finalización y los cambios de estado de agentes secundarios anidados de Codex o Claude, manteniendo sus eventos en la telemetría de Feed." - } - } + "metaTitle": "Configuración" }, "customCommands": { "title": "Comandos personalizados", diff --git a/web/messages/fr.json b/web/messages/fr.json index 22fcd24bfd63..d259f539459e 100644 --- a/web/messages/fr.json +++ b/web/messages/fr.json @@ -486,12 +486,7 @@ "browserHostsEmbed": "Hôtes à ouvrir dans le navigateur intégré : s'applique aux liens cliqués depuis la sortie du terminal. Les hôtes de cette liste s'ouvrent dans cmux ; les autres hôtes s'ouvrent dans votre navigateur par défaut. Supporte un hôte ou un joker par ligne (par exemple : example.com, *.internal.example).", "browserHostsHttp": "Hôtes HTTP autorisés dans le navigateur intégré : s'applique uniquement aux URLs HTTP (non-HTTPS). Les hôtes de cette liste peuvent s'ouvrir dans cmux sans avertissement. Les valeurs par défaut incluent localhost, *.localhost, 127.0.0.1, ::1, 0.0.0.0 et *.localtest.me.", "exampleConfig": "Exemple de configuration", - "metaTitle": "Configuration", - "schemaDescriptions": { - "automation": { - "suppressSubagentNotifications": "Masque les notifications visibles de fin et les changements d’état des agents enfants Codex ou Claude imbriqués, tout en conservant leurs événements dans la télémétrie Feed." - } - } + "metaTitle": "Configuration" }, "customCommands": { "title": "Commandes personnalisées", diff --git a/web/messages/it.json b/web/messages/it.json index eafd528e8906..3c01a87689c3 100644 --- a/web/messages/it.json +++ b/web/messages/it.json @@ -486,12 +486,7 @@ "browserHostsEmbed": "Host da aprire nel browser integrato: si applica ai link cliccati dall'output del terminale. Gli host in questa lista si aprono in cmux; gli altri host si aprono nel browser predefinito. Supporta un host o wildcard per riga (ad esempio: example.com, *.internal.example).", "browserHostsHttp": "Host HTTP consentiti nel browser integrato: si applica solo agli URL HTTP (non-HTTPS). Gli host in questa lista possono aprirsi in cmux senza avviso. I valori predefiniti includono localhost, *.localhost, 127.0.0.1, ::1, 0.0.0.0 e *.localtest.me.", "exampleConfig": "Esempio di configurazione", - "metaTitle": "Configurazione", - "schemaDescriptions": { - "automation": { - "suppressSubagentNotifications": "Nasconde le notifiche visibili di completamento e le modifiche di stato degli agenti figli Codex o Claude annidati, mantenendo i loro eventi nella telemetria Feed." - } - } + "metaTitle": "Configurazione" }, "customCommands": { "title": "Comandi personalizzati", diff --git a/web/messages/ja.json b/web/messages/ja.json index 8298953062f6..a58a3ea23594 100644 --- a/web/messages/ja.json +++ b/web/messages/ja.json @@ -546,12 +546,7 @@ "settingsFilePrecedence": "cmux.json で定義したショートカットはアプリ内設定より優先されます。管理対象のショートカットは設定画面に表示されたままですが、そこでの編集は無効になります。", "settingsFileChords": "単発ショートカットは文字列、コードは2要素の配列で指定します。例: [\"ctrl+b\", \"c\"] は Ctrl+B の後に C を押します。", "exampleConfig": "設定例", - "metaTitle": "設定", - "schemaDescriptions": { - "automation": { - "suppressSubagentNotifications": "ネストされた Codex または Claude の子エージェントからの表示される完了通知とステータス変更を抑制し、それらのイベントは Feed テレメトリに残します。" - } - } + "metaTitle": "設定" }, "customCommands": { "title": "カスタムコマンド", diff --git a/web/messages/km.json b/web/messages/km.json index 4cfbc029e04e..cbceacaa91bb 100644 --- a/web/messages/km.json +++ b/web/messages/km.json @@ -486,12 +486,7 @@ "browserHostsEmbed": "Host ដែលត្រូវបើកក្នុងកម្មវិធីរុករកដែលបង្កប់: អនុវត្តចំពោះតំណដែលចុចពីលទ្ធផលទែមីណល។ Host ក្នុងបញ្ជីនេះបើកក្នុង cmux; host ផ្សេងទៀតបើកក្នុងកម្មវិធីរុករកលំនាំដើមរបស់អ្នក។ គាំទ្រ host មួយ ឬ wildcard ក្នុងមួយជួរ (ឧទាហរណ៍: example.com, *.internal.example)។", "browserHostsHttp": "HTTP Host ដែលអនុញ្ញាតក្នុងកម្មវិធីរុករកដែលបង្កប់: អនុវត្តតែចំពោះ HTTP (មិនមែន HTTPS) URL។ Host ក្នុងបញ្ជីនេះអាចបើកក្នុង cmux ដោយមិនមានការព្រមានទេ។ លំនាំដើមរួមមាន localhost, *.localhost, 127.0.0.1, ::1, 0.0.0.0, និង *.localtest.me។", "exampleConfig": "ឧទាហរណ៍កំណត់រចនាសម្ព័ន្ធ", - "metaTitle": "ការកំណត់រចនាសម្ព័ន្ធ", - "schemaDescriptions": { - "automation": { - "suppressSubagentNotifications": "បិទការជូនដំណឹងបញ្ចប់ដែលបង្ហាញ និងការផ្លាស់ប្តូរស្ថានភាពពីភ្នាក់ងារកូន Codex ឬ Claude ដែលបានបង្កប់ ខណៈពេលរក្សាព្រឹត្តិការណ៍របស់វានៅក្នុងទេលេមេទ្រី Feed។" - } - } + "metaTitle": "ការកំណត់រចនាសម្ព័ន្ធ" }, "customCommands": { "title": "ពាក្យបញ្ជាផ្ទាល់ខ្លួន", diff --git a/web/messages/ko.json b/web/messages/ko.json index 30e860a4073e..c3d780554a7f 100644 --- a/web/messages/ko.json +++ b/web/messages/ko.json @@ -486,12 +486,7 @@ "browserHostsEmbed": "내장 브라우저에서 열 호스트: 터미널 출력에서 클릭한 링크에 적용됩니다. 이 목록의 호스트는 cmux에서 열리고, 다른 호스트는 기본 브라우저에서 열립니다. 줄당 하나의 호스트 또는 와일드카드를 지원합니다(예: example.com, *.internal.example).", "browserHostsHttp": "내장 브라우저에서 허용되는 HTTP 호스트: HTTP(비 HTTPS) URL에만 적용됩니다. 이 목록의 호스트는 경고 프롬프트 없이 cmux에서 열 수 있습니다. 기본값에는 localhost, *.localhost, 127.0.0.1, ::1, 0.0.0.0, *.localtest.me가 포함됩니다.", "exampleConfig": "예시 설정", - "metaTitle": "설정", - "schemaDescriptions": { - "automation": { - "suppressSubagentNotifications": "중첩된 Codex 또는 Claude 하위 에이전트의 표시되는 완료 알림과 상태 변경을 억제하면서 해당 이벤트는 Feed 텔레메트리에 유지합니다." - } - } + "metaTitle": "설정" }, "customCommands": { "title": "사용자 정의 명령어", diff --git a/web/messages/no.json b/web/messages/no.json index 367cec85dc1b..e99eab28d0d0 100644 --- a/web/messages/no.json +++ b/web/messages/no.json @@ -486,12 +486,7 @@ "browserHostsEmbed": "Verter å åpne i innebygd nettleser: gjelder lenker klikket fra terminalutdata. Verter på denne listen åpnes i cmux; andre verter åpnes i standardnettleseren din. Støtter én vert eller jokertegn per linje (for eksempel: example.com, *.internal.example).", "browserHostsHttp": "HTTP-verter tillatt i innebygd nettleser: gjelder kun HTTP (ikke-HTTPS) URL-er. Verter på denne listen kan åpnes i cmux uten advarsel. Standardverdier inkluderer localhost, *.localhost, 127.0.0.1, ::1, 0.0.0.0 og *.localtest.me.", "exampleConfig": "Eksempelkonfigurasjon", - "metaTitle": "Konfigurasjon", - "schemaDescriptions": { - "automation": { - "suppressSubagentNotifications": "Undertrykk synlige fullføringsvarsler og statusendringer fra innebygde Codex- eller Claude-underagenter, samtidig som hendelsene deres beholdes i Feed-telemetri." - } - } + "metaTitle": "Konfigurasjon" }, "customCommands": { "title": "Egendefinerte kommandoer", diff --git a/web/messages/pl.json b/web/messages/pl.json index 7f1b9203d408..890599f05bf9 100644 --- a/web/messages/pl.json +++ b/web/messages/pl.json @@ -486,12 +486,7 @@ "browserHostsEmbed": "Hosty do otwarcia we wbudowanej przeglądarce: dotyczy linków klikniętych z wyjścia terminala. Hosty na tej liście otwierają się w cmux; pozostałe hosty otwierają się w domyślnej przeglądarce. Obsługuje jeden host lub wildcard na linię (na przykład: example.com, *.internal.example).", "browserHostsHttp": "Hosty HTTP dozwolone we wbudowanej przeglądarce: dotyczy tylko URL-i HTTP (nie-HTTPS). Hosty na tej liście mogą otwierać się w cmux bez monitu ostrzegawczego. Domyślnie obejmuje localhost, *.localhost, 127.0.0.1, ::1, 0.0.0.0 i *.localtest.me.", "exampleConfig": "Przykładowa konfiguracja", - "metaTitle": "Konfiguracja", - "schemaDescriptions": { - "automation": { - "suppressSubagentNotifications": "Ukrywa widoczne powiadomienia o zakończeniu i zmiany statusu zagnieżdżonych agentów podrzędnych Codex lub Claude, zachowując ich zdarzenia w telemetrii Feed." - } - } + "metaTitle": "Konfiguracja" }, "customCommands": { "title": "Niestandardowe polecenia", diff --git a/web/messages/pt-BR.json b/web/messages/pt-BR.json index 08a552ea52f2..4f4a93bc9016 100644 --- a/web/messages/pt-BR.json +++ b/web/messages/pt-BR.json @@ -486,12 +486,7 @@ "browserHostsEmbed": "Hosts para abrir no navegador integrado: aplica-se a links clicados na saída do terminal. Hosts nesta lista abrem no cmux; outros hosts abrem no seu navegador padrão. Suporta um host ou wildcard por linha (por exemplo: example.com, *.internal.example).", "browserHostsHttp": "Hosts HTTP permitidos no navegador integrado: aplica-se apenas a URLs HTTP (não HTTPS). Hosts nesta lista podem abrir no cmux sem aviso. Os padrões incluem localhost, *.localhost, 127.0.0.1, ::1, 0.0.0.0 e *.localtest.me.", "exampleConfig": "Exemplo de configuração", - "metaTitle": "Configuração", - "schemaDescriptions": { - "automation": { - "suppressSubagentNotifications": "Suprime notificações visíveis de conclusão e alterações de status de agentes filhos aninhados do Codex ou Claude, mantendo seus eventos na telemetria do Feed." - } - } + "metaTitle": "Configuração" }, "customCommands": { "title": "Comandos personalizados", diff --git a/web/messages/ru.json b/web/messages/ru.json index b4b7f6a21268..c1c82eeb8bc1 100644 --- a/web/messages/ru.json +++ b/web/messages/ru.json @@ -486,12 +486,7 @@ "browserHostsEmbed": "Хосты для открытия во встроенном браузере: применяется к ссылкам, нажатым в выводе терминала. Хосты из этого списка открываются в cmux; остальные хосты открываются в твоём браузере по умолчанию. Поддерживает один хост или wildcard на строку (например: example.com, *.internal.example).", "browserHostsHttp": "HTTP-хосты, разрешённые во встроенном браузере: применяется только к HTTP (не HTTPS) URL-ам. Хосты из этого списка могут открываться в cmux без предупреждения. По умолчанию включают localhost, *.localhost, 127.0.0.1, ::1, 0.0.0.0 и *.localtest.me.", "exampleConfig": "Пример конфигурации", - "metaTitle": "Конфигурация", - "schemaDescriptions": { - "automation": { - "suppressSubagentNotifications": "Подавляет видимые уведомления о завершении и изменения статуса от вложенных дочерних агентов Codex или Claude, сохраняя их события в телеметрии Feed." - } - } + "metaTitle": "Конфигурация" }, "customCommands": { "title": "Пользовательские команды", diff --git a/web/messages/th.json b/web/messages/th.json index 7e9d4fa2d6f7..8d347752a612 100644 --- a/web/messages/th.json +++ b/web/messages/th.json @@ -486,12 +486,7 @@ "browserHostsEmbed": "Hosts to Open in Embedded Browser: ใช้กับลิงก์ที่คลิกจากเอาต์พุตเทอร์มินัล Host ในรายการนี้เปิดใน cmux ส่วน host อื่นเปิดในเบราว์เซอร์เริ่มต้นของคุณ รองรับ host เดี่ยวหรือ wildcard ต่อบรรทัด (เช่น: example.com, *.internal.example)", "browserHostsHttp": "HTTP Hosts Allowed in Embedded Browser: ใช้เฉพาะกับ URL แบบ HTTP (ไม่ใช่ HTTPS) Host ในรายการนี้เปิดใน cmux ได้โดยไม่มีข้อความเตือน ค่าเริ่มต้นรวม localhost, *.localhost, 127.0.0.1, ::1, 0.0.0.0 และ *.localtest.me", "exampleConfig": "ตัวอย่างคอนฟิก", - "metaTitle": "การตั้งค่า", - "schemaDescriptions": { - "automation": { - "suppressSubagentNotifications": "ซ่อนการแจ้งเตือนการทำงานเสร็จและการเปลี่ยนสถานะที่มองเห็นได้จากเอเจนต์ลูก Codex หรือ Claude แบบซ้อน โดยยังคงเก็บเหตุการณ์ไว้ในเทเลเมทรี Feed" - } - } + "metaTitle": "การตั้งค่า" }, "customCommands": { "title": "คำสั่งที่กำหนดเอง", diff --git a/web/messages/tr.json b/web/messages/tr.json index 99c20c2e5819..3076054d989b 100644 --- a/web/messages/tr.json +++ b/web/messages/tr.json @@ -486,12 +486,7 @@ "browserHostsEmbed": "Gömülü Tarayıcıda Açılacak Ana Bilgisayarlar: terminal çıktısından tıklanan bağlantılara uygulanır. Bu listedeki ana bilgisayarlar cmux'ta açılır; diğer ana bilgisayarlar varsayılan tarayıcınızda açılır. Satır başına bir ana bilgisayar veya joker karakter destekler (örneğin: example.com, *.internal.example).", "browserHostsHttp": "Gömülü Tarayıcıda İzin Verilen HTTP Ana Bilgisayarları: yalnızca HTTP (HTTPS olmayan) URL'lere uygulanır. Bu listedeki ana bilgisayarlar cmux'ta uyarı istemeden açılabilir. Varsayılanlar localhost, *.localhost, 127.0.0.1, ::1, 0.0.0.0 ve *.localtest.me'yi içerir.", "exampleConfig": "Örnek yapılandırma", - "metaTitle": "Yapılandırma", - "schemaDescriptions": { - "automation": { - "suppressSubagentNotifications": "İç içe Codex veya Claude alt ajanlarından gelen görünür tamamlanma bildirimlerini ve durum değişikliklerini gizler, olaylarını Feed telemetrisinde tutar." - } - } + "metaTitle": "Yapılandırma" }, "customCommands": { "title": "Özel Komutlar", diff --git a/web/messages/uk.json b/web/messages/uk.json index 6440e717ee5a..c4312811359b 100644 --- a/web/messages/uk.json +++ b/web/messages/uk.json @@ -486,12 +486,7 @@ "browserLinkDesc": "У Параметри > Браузер cmux надає два списки хостів з різним призначенням:", "browserHostsEmbed": "Хости для відкриття у вбудованому браузері: застосовується до посилань, натиснутих з виводу терміналу. Хости з цього списку відкриваються в cmux; інші хости відкриваються у вашому стандартному браузері. Підтримується один хост або маска на рядок (наприклад: example.com, *.internal.example).", "browserHostsHttp": "HTTP-хости, дозволені у вбудованому браузері: застосовується тільки до HTTP (не HTTPS) URL. Хости з цього списку можуть відкриватися в cmux без попередження. За замовчуванням включено localhost, *.localhost, 127.0.0.1, ::1, 0.0.0.0 та *.localtest.me.", - "exampleConfig": "Приклад конфігурації", - "schemaDescriptions": { - "automation": { - "suppressSubagentNotifications": "Приховує видимі сповіщення про завершення та зміни статусу від вкладених дочірніх агентів Codex або Claude, зберігаючи їхні події в телеметрії Feed." - } - } + "exampleConfig": "Приклад конфігурації" }, "customCommands": { "title": "Користувацькі команди", diff --git a/web/messages/zh-CN.json b/web/messages/zh-CN.json index e9137910088b..7d9e2e8ca9db 100644 --- a/web/messages/zh-CN.json +++ b/web/messages/zh-CN.json @@ -486,12 +486,7 @@ "browserHostsEmbed": "在内嵌浏览器中打开的主机:适用于从终端输出点击的链接。此列表中的主机在 cmux 中打开;其他主机在默认浏览器中打开。支持单个主机或通配符,每行一个(例如:example.com、*.internal.example)。", "browserHostsHttp": "内嵌浏览器允许的 HTTP 主机:仅适用于 HTTP(非 HTTPS)URL。此列表中的主机可以在 cmux 中打开而不显示警告提示。默认包括 localhost、*.localhost、127.0.0.1、::1、0.0.0.0 和 *.localtest.me。", "exampleConfig": "配置示例", - "metaTitle": "配置", - "schemaDescriptions": { - "automation": { - "suppressSubagentNotifications": "隐藏嵌套 Codex 或 Claude 子代理的可见完成通知和状态变更,同时将其事件保留在 Feed 遥测中。" - } - } + "metaTitle": "配置" }, "customCommands": { "title": "自定义命令", diff --git a/web/messages/zh-TW.json b/web/messages/zh-TW.json index 5fd057c15799..f82a295e6499 100644 --- a/web/messages/zh-TW.json +++ b/web/messages/zh-TW.json @@ -486,12 +486,7 @@ "browserHostsEmbed": "在內建瀏覽器中開啟的主機:適用於從終端機輸出點擊的連結。此列表中的主機會在 cmux 中開啟;其他主機會在你的預設瀏覽器中開啟。支援每行一個主機或萬用字元(例如:example.com、*.internal.example)。", "browserHostsHttp": "內建瀏覽器中允許的 HTTP 主機:僅適用於 HTTP(非 HTTPS)URL。此列表中的主機可以在 cmux 中開啟而不會出現警告提示。預設包含 localhost、*.localhost、127.0.0.1、::1、0.0.0.0 和 *.localtest.me。", "exampleConfig": "範例設定", - "metaTitle": "設定", - "schemaDescriptions": { - "automation": { - "suppressSubagentNotifications": "隱藏巢狀 Codex 或 Claude 子代理的可見完成通知和狀態變更,同時將其事件保留在 Feed 遙測中。" - } - } + "metaTitle": "設定" }, "customCommands": { "title": "自訂指令",