Compare commits

..

1 Commits

Author SHA1 Message Date
google-labs-jules[bot]
9e91e45c70 fix: Ensure showTrayIcon is initialized from backend settings in App.tsx
The `showTrayIcon` user preference was not being explicitly passed from the
`appReady()` command's results to the `settingsStore.initSettings()` call
within `App.tsx`. This could lead to the frontend store not correctly
reflecting the persisted value of `showTrayIcon` at startup.

This commit updates `App.tsx` to include `showTrayIcon` in the
settings object passed to `initSettings`, ensuring its value is derived
from the backend configuration.
2025-06-16 14:32:39 +00:00
188 changed files with 2175 additions and 10463 deletions

View File

@ -1,5 +0,0 @@
---
'pastebar-app-ui': patch
---
Added: Quick history window user options

View File

@ -1,5 +0,0 @@
---
'pastebar-app-ui': patch
---
Added support setting hotkeys with up to 3-key combinations

View File

@ -1,5 +0,0 @@
---
'pastebar-app-ui': patch
---
refactor: update terminology for history window split to open

View File

@ -1,5 +0,0 @@
---
'pastebar-app-ui': patch
---
Auto-activate search in quick paste window when typing any letter or number

View File

@ -1,5 +0,0 @@
---
'pastebar-app-ui': patch
---
Added single-click copy/paste option in user preferences

View File

@ -1,5 +0,0 @@
---
'pastebar-app-ui': patch
---
Added detect and select language modal on first app run

View File

@ -1,5 +0,0 @@
---
'pastebar-app-ui': minor
---
Added keyboard shortcuts to improve navigation efficiency within the application

View File

@ -1,5 +0,0 @@
---
'pastebar-app-ui': patch
---
Added: history item preview max lines user setting

View File

@ -1,5 +0,0 @@
---
'pastebar-app-ui': patch
---
Added protected collection with PIN access

View File

@ -1,5 +0,0 @@
---
'pastebar-app-ui': patch
---
Added Special copy/paste for history items context menu and settings

View File

@ -1,5 +0,0 @@
---
'pastebar-app-ui': patch
---
Added global templates in user preferences for saved clips

View File

@ -1,5 +0,0 @@
---
'pastebar-app-ui': patch
---
Added: customizable tray icon behavior on Windows as user settings

View File

@ -1,5 +0,0 @@
---
'pastebar-app-ui': patch
---
Fix: enhance value preview logic to fix text overflow

View File

@ -1,5 +0,0 @@
---
'pastebar-app-ui': patch
---
Added deleting menu folders with children by moving submenus up one level

View File

@ -1,5 +0,0 @@
---
'pastebar-app-ui': patch
---
Added settings to preserve pinned and starred items when clearing clipboard history

View File

@ -1,5 +0,0 @@
---
'pastebar-app-ui': patch
---
Added option "Show Always on Top" for main window

View File

@ -1,5 +0,0 @@
---
'pastebar-app-ui': patch
---
Support for notes matching in global search

View File

@ -49,9 +49,6 @@ npm run format
# Version management
npm run version:sync
# Translation audit
npm run translation-audit
```
### Frontend Development (packages/pastebar-app-ui/)
@ -206,4 +203,4 @@ src-tauri/src/
- Use Diesel migrations for schema changes
- Place migration files in `migrations/` directory
- Run migrations with `npm run diesel:migration:run`
- Run migrations with `npm run diesel:migration:run`

423
package-lock.json generated
View File

@ -141,7 +141,6 @@
"@types/codemirror": "^5.60.15",
"@types/dompurify": "^3.0.5",
"@types/events": "^3.0.3",
"@types/html-to-text": "^9.0.4",
"@types/js-yaml": "^4.0.9",
"@types/linkify-it": "^3.0.5",
"@types/lodash-es": "^4.17.12",
@ -169,6 +168,7 @@
"tailwind-merge": "^2.0.0",
"tailwindcss": "^3.3.5",
"taze": "^0.12.2",
"ts-node": "^10.9.2",
"typescript": "^5.8.3",
"vite": "^6.0.6",
"vite-plugin-tauri": "^4.0.0"
@ -2658,6 +2658,28 @@
"node": ">=0.1.90"
}
},
"node_modules/@cspotcode/source-map-support": {
"version": "0.8.1",
"resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz",
"integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==",
"dev": true,
"dependencies": {
"@jridgewell/trace-mapping": "0.3.9"
},
"engines": {
"node": ">=12"
}
},
"node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": {
"version": "0.3.9",
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz",
"integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==",
"dev": true,
"dependencies": {
"@jridgewell/resolve-uri": "^3.0.3",
"@jridgewell/sourcemap-codec": "^1.4.10"
}
},
"node_modules/@dnd-kit/accessibility": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/@dnd-kit/accessibility/-/accessibility-3.1.0.tgz",
@ -6306,19 +6328,6 @@
"win32"
]
},
"node_modules/@selderee/plugin-htmlparser2": {
"version": "0.11.0",
"resolved": "https://registry.npmjs.org/@selderee/plugin-htmlparser2/-/plugin-htmlparser2-0.11.0.tgz",
"integrity": "sha512-P33hHGdldxGabLFjPPpaTxVolMrzrcegejx+0GxjrIb9Zv48D8yAIA/QTDR2dFl7Uz7urX8aX6+5bCZslr+gWQ==",
"license": "MIT",
"dependencies": {
"domhandler": "^5.0.3",
"selderee": "^0.11.0"
},
"funding": {
"url": "https://ko-fi.com/killymxi"
}
},
"node_modules/@sigstore/bundle": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/@sigstore/bundle/-/bundle-2.1.0.tgz",
@ -7295,6 +7304,30 @@
"node": ">=10.13.0"
}
},
"node_modules/@tsconfig/node10": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz",
"integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==",
"dev": true
},
"node_modules/@tsconfig/node12": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz",
"integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==",
"dev": true
},
"node_modules/@tsconfig/node14": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz",
"integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==",
"dev": true
},
"node_modules/@tsconfig/node16": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz",
"integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==",
"dev": true
},
"node_modules/@tufjs/canonical-json": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@tufjs/canonical-json/-/canonical-json-2.0.0.tgz",
@ -7482,13 +7515,6 @@
"integrity": "sha512-trOc4AAUThEz9hapPtSd7wf5tiQKvTtu5b371UxXdTuqzIh0ArcRspRP0i0Viu+LXstIQ1z96t1nsPxT9ol01g==",
"dev": true
},
"node_modules/@types/html-to-text": {
"version": "9.0.4",
"resolved": "https://registry.npmjs.org/@types/html-to-text/-/html-to-text-9.0.4.tgz",
"integrity": "sha512-pUY3cKH/Nm2yYrEmDlPR1mR7yszjGx4DrwPjQ702C4/D5CwHuZTgZdIdwPkRbcuhs7BAh2L5rg3CL5cbRiGTCQ==",
"dev": true,
"license": "MIT"
},
"node_modules/@types/istanbul-lib-coverage": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz",
@ -7813,6 +7839,18 @@
"node": ">=0.4.0"
}
},
"node_modules/acorn-walk": {
"version": "8.3.4",
"resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz",
"integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==",
"dev": true,
"dependencies": {
"acorn": "^8.11.0"
},
"engines": {
"node": ">=0.4.0"
}
},
"node_modules/agent-base": {
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
@ -9208,6 +9246,12 @@
"node": ">=10"
}
},
"node_modules/create-require": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz",
"integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==",
"dev": true
},
"node_modules/crelt": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.6.tgz",
@ -9700,6 +9744,15 @@
"integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==",
"dev": true
},
"node_modules/diff": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
"integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
"dev": true,
"engines": {
"node": ">=0.3.1"
}
},
"node_modules/dir-glob": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
@ -11152,41 +11205,6 @@
"void-elements": "3.1.0"
}
},
"node_modules/html-to-text": {
"version": "9.0.5",
"resolved": "https://registry.npmjs.org/html-to-text/-/html-to-text-9.0.5.tgz",
"integrity": "sha512-qY60FjREgVZL03vJU6IfMV4GDjGBIoOyvuFdpBDIX9yTlDw0TjxVBQp+P8NvpdIXNJvfWBTNul7fsAQJq2FNpg==",
"license": "MIT",
"dependencies": {
"@selderee/plugin-htmlparser2": "^0.11.0",
"deepmerge": "^4.3.1",
"dom-serializer": "^2.0.0",
"htmlparser2": "^8.0.2",
"selderee": "^0.11.0"
},
"engines": {
"node": ">=14"
}
},
"node_modules/htmlparser2": {
"version": "8.0.2",
"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz",
"integrity": "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==",
"funding": [
"https://github.com/fb55/htmlparser2?sponsor=1",
{
"type": "github",
"url": "https://github.com/sponsors/fb55"
}
],
"license": "MIT",
"dependencies": {
"domelementtype": "^2.3.0",
"domhandler": "^5.0.3",
"domutils": "^3.0.1",
"entities": "^4.4.0"
}
},
"node_modules/http-cache-semantics": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz",
@ -12053,15 +12071,6 @@
"node": ">=6"
}
},
"node_modules/leac": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/leac/-/leac-0.6.0.tgz",
"integrity": "sha512-y+SqErxb8h7nE/fiEX07jsbuhrpO9lL8eca7/Y1nuWV2moNlXhyd59iDGcRf6moVyDMbmTNzL40SUyrFU/yDpg==",
"license": "MIT",
"funding": {
"url": "https://ko-fi.com/killymxi"
}
},
"node_modules/lilconfig": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz",
@ -12185,6 +12194,12 @@
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz",
"integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ=="
},
"node_modules/make-error": {
"version": "1.3.6",
"resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
"integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==",
"dev": true
},
"node_modules/make-fetch-happen": {
"version": "11.1.1",
"resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-11.1.1.tgz",
@ -13453,19 +13468,6 @@
"resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz",
"integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw=="
},
"node_modules/parseley": {
"version": "0.12.1",
"resolved": "https://registry.npmjs.org/parseley/-/parseley-0.12.1.tgz",
"integrity": "sha512-e6qHKe3a9HWr0oMRVDTRhKce+bRO8VGQR3NyVwcjwrbhMmFCX9KszEV35+rn4AdilFAq9VPxP/Fe1wC9Qjd2lw==",
"license": "MIT",
"dependencies": {
"leac": "^0.6.0",
"peberminta": "^0.9.0"
},
"funding": {
"url": "https://ko-fi.com/killymxi"
}
},
"node_modules/pastebar-app-ui": {
"resolved": "packages/pastebar-app-ui",
"link": true
@ -13536,15 +13538,6 @@
"integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==",
"dev": true
},
"node_modules/peberminta": {
"version": "0.9.0",
"resolved": "https://registry.npmjs.org/peberminta/-/peberminta-0.9.0.tgz",
"integrity": "sha512-XIxfHpEuSJbITd1H3EeQwpcZbTLHc+VVr8ANI9t5sit565tsI4/xK3KWTUFE2e6QiangUkh3B0jihzmGnNrRsQ==",
"license": "MIT",
"funding": {
"url": "https://ko-fi.com/killymxi"
}
},
"node_modules/performance-now": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
@ -15124,18 +15117,6 @@
"resolved": "https://registry.npmjs.org/scriptjs/-/scriptjs-2.5.9.tgz",
"integrity": "sha512-qGVDoreyYiP1pkQnbnFAUIS5AjenNwwQBdl7zeos9etl+hYKWahjRTfzAZZYBv5xNHx7vNKCmaLDQZ6Fr2AEXg=="
},
"node_modules/selderee": {
"version": "0.11.0",
"resolved": "https://registry.npmjs.org/selderee/-/selderee-0.11.0.tgz",
"integrity": "sha512-5TF+l7p4+OsnP8BCCvSyZiSPc4x4//p5uPwK8TCnVPJYRmU2aYKMpOXvw8zM5a5JvuuCGN1jmsMwuU2W02ukfA==",
"license": "MIT",
"dependencies": {
"parseley": "^0.12.0"
},
"funding": {
"url": "https://ko-fi.com/killymxi"
}
},
"node_modules/semver": {
"version": "6.3.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
@ -16198,6 +16179,55 @@
"integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==",
"dev": true
},
"node_modules/ts-node": {
"version": "10.9.2",
"resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz",
"integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==",
"dev": true,
"dependencies": {
"@cspotcode/source-map-support": "^0.8.0",
"@tsconfig/node10": "^1.0.7",
"@tsconfig/node12": "^1.0.7",
"@tsconfig/node14": "^1.0.0",
"@tsconfig/node16": "^1.0.2",
"acorn": "^8.4.1",
"acorn-walk": "^8.1.1",
"arg": "^4.1.0",
"create-require": "^1.1.0",
"diff": "^4.0.1",
"make-error": "^1.1.1",
"v8-compile-cache-lib": "^3.0.1",
"yn": "3.1.1"
},
"bin": {
"ts-node": "dist/bin.js",
"ts-node-cwd": "dist/bin-cwd.js",
"ts-node-esm": "dist/bin-esm.js",
"ts-node-script": "dist/bin-script.js",
"ts-node-transpile-only": "dist/bin-transpile.js",
"ts-script": "dist/bin-script-deprecated.js"
},
"peerDependencies": {
"@swc/core": ">=1.2.50",
"@swc/wasm": ">=1.2.50",
"@types/node": "*",
"typescript": ">=2.7"
},
"peerDependenciesMeta": {
"@swc/core": {
"optional": true
},
"@swc/wasm": {
"optional": true
}
}
},
"node_modules/ts-node/node_modules/arg": {
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
"integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==",
"dev": true
},
"node_modules/tsconfig-paths": {
"version": "3.14.2",
"resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz",
@ -16632,6 +16662,12 @@
"uuid": "dist/bin/uuid"
}
},
"node_modules/v8-compile-cache-lib": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz",
"integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==",
"dev": true
},
"node_modules/validate-npm-package-license": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
@ -17114,6 +17150,15 @@
"node": ">=12"
}
},
"node_modules/yn": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
"integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==",
"dev": true,
"engines": {
"node": ">=6"
}
},
"node_modules/youtube-player": {
"version": "5.5.2",
"resolved": "https://registry.npmjs.org/youtube-player/-/youtube-player-5.5.2.tgz",
@ -17262,7 +17307,6 @@
"framer-motion": "^10.16.5",
"garbados-crypt": "^3.0.0-beta",
"glob-all": "^3.3.1",
"html-to-text": "^9.0.5",
"i18next": "^23.10.0",
"i18next-browser-languagedetector": "^7.2.0",
"idb-keyval": "^6.2.1",
@ -19862,6 +19906,27 @@
"integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==",
"optional": true
},
"@cspotcode/source-map-support": {
"version": "0.8.1",
"resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz",
"integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==",
"dev": true,
"requires": {
"@jridgewell/trace-mapping": "0.3.9"
},
"dependencies": {
"@jridgewell/trace-mapping": {
"version": "0.3.9",
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz",
"integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==",
"dev": true,
"requires": {
"@jridgewell/resolve-uri": "^3.0.3",
"@jridgewell/sourcemap-codec": "^1.4.10"
}
}
}
},
"@dnd-kit/accessibility": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/@dnd-kit/accessibility/-/accessibility-3.1.0.tgz",
@ -22128,15 +22193,6 @@
"integrity": "sha512-+10CMg9vt1MoHj6x1pxyjPSMjHTIlqs8/tBztXvPAx24SKs9jwVnKqHJumlH/IzhaPUaj3T6T6wfZr8okdXaIg==",
"optional": true
},
"@selderee/plugin-htmlparser2": {
"version": "0.11.0",
"resolved": "https://registry.npmjs.org/@selderee/plugin-htmlparser2/-/plugin-htmlparser2-0.11.0.tgz",
"integrity": "sha512-P33hHGdldxGabLFjPPpaTxVolMrzrcegejx+0GxjrIb9Zv48D8yAIA/QTDR2dFl7Uz7urX8aX6+5bCZslr+gWQ==",
"requires": {
"domhandler": "^5.0.3",
"selderee": "^0.11.0"
}
},
"@sigstore/bundle": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/@sigstore/bundle/-/bundle-2.1.0.tgz",
@ -22641,6 +22697,30 @@
"resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz",
"integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA=="
},
"@tsconfig/node10": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz",
"integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==",
"dev": true
},
"@tsconfig/node12": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz",
"integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==",
"dev": true
},
"@tsconfig/node14": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz",
"integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==",
"dev": true
},
"@tsconfig/node16": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz",
"integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==",
"dev": true
},
"@tufjs/canonical-json": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@tufjs/canonical-json/-/canonical-json-2.0.0.tgz",
@ -22818,12 +22898,6 @@
"integrity": "sha512-trOc4AAUThEz9hapPtSd7wf5tiQKvTtu5b371UxXdTuqzIh0ArcRspRP0i0Viu+LXstIQ1z96t1nsPxT9ol01g==",
"dev": true
},
"@types/html-to-text": {
"version": "9.0.4",
"resolved": "https://registry.npmjs.org/@types/html-to-text/-/html-to-text-9.0.4.tgz",
"integrity": "sha512-pUY3cKH/Nm2yYrEmDlPR1mR7yszjGx4DrwPjQ702C4/D5CwHuZTgZdIdwPkRbcuhs7BAh2L5rg3CL5cbRiGTCQ==",
"dev": true
},
"@types/istanbul-lib-coverage": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz",
@ -23099,6 +23173,15 @@
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz",
"integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA=="
},
"acorn-walk": {
"version": "8.3.4",
"resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz",
"integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==",
"dev": true,
"requires": {
"acorn": "^8.11.0"
}
},
"agent-base": {
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
@ -24116,6 +24199,12 @@
"yaml": "^1.10.0"
}
},
"create-require": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz",
"integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==",
"dev": true
},
"crelt": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.6.tgz",
@ -24451,6 +24540,12 @@
"integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==",
"dev": true
},
"diff": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
"integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
"dev": true
},
"dir-glob": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
@ -25543,29 +25638,6 @@
"void-elements": "3.1.0"
}
},
"html-to-text": {
"version": "9.0.5",
"resolved": "https://registry.npmjs.org/html-to-text/-/html-to-text-9.0.5.tgz",
"integrity": "sha512-qY60FjREgVZL03vJU6IfMV4GDjGBIoOyvuFdpBDIX9yTlDw0TjxVBQp+P8NvpdIXNJvfWBTNul7fsAQJq2FNpg==",
"requires": {
"@selderee/plugin-htmlparser2": "^0.11.0",
"deepmerge": "^4.3.1",
"dom-serializer": "^2.0.0",
"htmlparser2": "^8.0.2",
"selderee": "^0.11.0"
}
},
"htmlparser2": {
"version": "8.0.2",
"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz",
"integrity": "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==",
"requires": {
"domelementtype": "^2.3.0",
"domhandler": "^5.0.3",
"domutils": "^3.0.1",
"entities": "^4.4.0"
}
},
"http-cache-semantics": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz",
@ -26174,11 +26246,6 @@
"integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==",
"dev": true
},
"leac": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/leac/-/leac-0.6.0.tgz",
"integrity": "sha512-y+SqErxb8h7nE/fiEX07jsbuhrpO9lL8eca7/Y1nuWV2moNlXhyd59iDGcRf6moVyDMbmTNzL40SUyrFU/yDpg=="
},
"lilconfig": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz",
@ -26286,6 +26353,12 @@
}
}
},
"make-error": {
"version": "1.3.6",
"resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
"integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==",
"dev": true
},
"make-fetch-happen": {
"version": "11.1.1",
"resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-11.1.1.tgz",
@ -27262,15 +27335,6 @@
}
}
},
"parseley": {
"version": "0.12.1",
"resolved": "https://registry.npmjs.org/parseley/-/parseley-0.12.1.tgz",
"integrity": "sha512-e6qHKe3a9HWr0oMRVDTRhKce+bRO8VGQR3NyVwcjwrbhMmFCX9KszEV35+rn4AdilFAq9VPxP/Fe1wC9Qjd2lw==",
"requires": {
"leac": "^0.6.0",
"peberminta": "^0.9.0"
}
},
"pastebar-app-ui": {
"version": "file:packages/pastebar-app-ui",
"requires": {
@ -27371,7 +27435,6 @@
"framer-motion": "^10.16.5",
"garbados-crypt": "^3.0.0-beta",
"glob-all": "^3.3.1",
"html-to-text": "^9.0.5",
"i18next": "^23.10.0",
"i18next-browser-languagedetector": "^7.2.0",
"idb-keyval": "^6.2.1",
@ -27820,11 +27883,6 @@
"integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==",
"dev": true
},
"peberminta": {
"version": "0.9.0",
"resolved": "https://registry.npmjs.org/peberminta/-/peberminta-0.9.0.tgz",
"integrity": "sha512-XIxfHpEuSJbITd1H3EeQwpcZbTLHc+VVr8ANI9t5sit565tsI4/xK3KWTUFE2e6QiangUkh3B0jihzmGnNrRsQ=="
},
"performance-now": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
@ -28838,14 +28896,6 @@
"resolved": "https://registry.npmjs.org/scriptjs/-/scriptjs-2.5.9.tgz",
"integrity": "sha512-qGVDoreyYiP1pkQnbnFAUIS5AjenNwwQBdl7zeos9etl+hYKWahjRTfzAZZYBv5xNHx7vNKCmaLDQZ6Fr2AEXg=="
},
"selderee": {
"version": "0.11.0",
"resolved": "https://registry.npmjs.org/selderee/-/selderee-0.11.0.tgz",
"integrity": "sha512-5TF+l7p4+OsnP8BCCvSyZiSPc4x4//p5uPwK8TCnVPJYRmU2aYKMpOXvw8zM5a5JvuuCGN1jmsMwuU2W02ukfA==",
"requires": {
"parseley": "^0.12.0"
}
},
"semver": {
"version": "6.3.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
@ -29636,6 +29686,35 @@
"integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==",
"dev": true
},
"ts-node": {
"version": "10.9.2",
"resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz",
"integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==",
"dev": true,
"requires": {
"@cspotcode/source-map-support": "^0.8.0",
"@tsconfig/node10": "^1.0.7",
"@tsconfig/node12": "^1.0.7",
"@tsconfig/node14": "^1.0.0",
"@tsconfig/node16": "^1.0.2",
"acorn": "^8.4.1",
"acorn-walk": "^8.1.1",
"arg": "^4.1.0",
"create-require": "^1.1.0",
"diff": "^4.0.1",
"make-error": "^1.1.1",
"v8-compile-cache-lib": "^3.0.1",
"yn": "3.1.1"
},
"dependencies": {
"arg": {
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
"integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==",
"dev": true
}
}
},
"tsconfig-paths": {
"version": "3.14.2",
"resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz",
@ -29930,6 +30009,12 @@
"resolved": "https://registry.npmjs.org/uuid/-/uuid-10.0.0.tgz",
"integrity": "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ=="
},
"v8-compile-cache-lib": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz",
"integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==",
"dev": true
},
"validate-npm-package-license": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
@ -30258,6 +30343,12 @@
"integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
"dev": true
},
"yn": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
"integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==",
"dev": true
},
"youtube-player": {
"version": "5.5.2",
"resolved": "https://registry.npmjs.org/youtube-player/-/youtube-player-5.5.2.tgz",

View File

@ -20,7 +20,7 @@
"changeset": "changeset",
"version:sync": "node scripts/sync-version.js",
"version": "changeset version && npm run version:sync",
"translation-audit": "npx tsx scripts/translation-audit.ts"
"translation-audit": "ts-node scripts/translation-audit.ts"
},
"dependencies": {
"@codastic/react-positioning-portal": "^0.7.0",
@ -156,7 +156,6 @@
"@types/codemirror": "^5.60.15",
"@types/dompurify": "^3.0.5",
"@types/events": "^3.0.3",
"@types/html-to-text": "^9.0.4",
"@types/js-yaml": "^4.0.9",
"@types/linkify-it": "^3.0.5",
"@types/lodash-es": "^4.17.12",
@ -184,6 +183,7 @@
"tailwind-merge": "^2.0.0",
"tailwindcss": "^3.3.5",
"taze": "^0.12.2",
"ts-node": "^10.9.2",
"typescript": "^5.8.3",
"vite": "^6.0.6",
"vite-plugin-tauri": "^4.0.0"

View File

@ -82,7 +82,6 @@
"framer-motion": "^10.16.5",
"garbados-crypt": "^3.0.0-beta",
"glob-all": "^3.3.1",
"html-to-text": "^9.0.5",
"i18next": "^23.10.0",
"i18next-browser-languagedetector": "^7.2.0",
"idb-keyval": "^6.2.1",

View File

@ -1,4 +1,4 @@
import { useCallback, useEffect, useRef, useState } from 'react'
import { useCallback, useEffect, useRef } from 'react'
import { useQueryClient } from '@tanstack/react-query'
import { listen } from '@tauri-apps/api/event'
import { register, unregisterAll } from '@tauri-apps/api/globalShortcut'
@ -10,7 +10,6 @@ import { useAtomValue } from 'jotai'
import { useTranslation } from 'react-i18next'
import { Outlet, useLocation, useNavigate } from 'react-router-dom'
import LanguageSelectionModal from '~/components/organisms/modals/language-selection-modal'
import { ThemeProvider } from '~/components/theme-provider'
import useKeyPressAlt from '~/hooks/use-keypress-alt'
@ -34,8 +33,6 @@ import {
settingsStoreAtom,
themeStoreAtom,
uiStoreAtom,
DEFAULT_SPECIAL_PASTE_OPERATIONS,
DEFAULT_SPECIAL_PASTE_CATEGORIES,
} from './store'
const appIdleEvents = ['mousemove', 'keydown', 'scroll', 'keypress', 'mousedown']
@ -55,17 +52,6 @@ function App() {
const { i18n, t } = useTranslation()
const { toast } = useToast()
const historyWindowOpening = useSignal(false)
const showLanguageSelectionModal = useSignal(false)
const permissionsTrustedSignal = useSignal<boolean | null>(null)
const handleLanguageSelected = useCallback(
(languageCode: string) => {
settingsStore.updateSetting('userSelectedLanguage', languageCode)
settingsStore.updateSetting('isFirstRun', false)
showLanguageSelectionModal.value = false
},
[settingsStore]
)
const handleActivity = useCallback(
debounce(() => {
@ -96,12 +82,7 @@ function App() {
if (res === null) return
try {
const {
constants,
settings,
permissionstrusted: initialPermissionsTrusted,
} = JSON.parse(res)
permissionsTrustedSignal.value = initialPermissionsTrusted
const { constants, settings, permissionstrusted } = JSON.parse(res)
const {
app_dev_data_dir: appDevDataDir,
@ -131,7 +112,6 @@ function App() {
isCustomDbPathValid: null,
customDbPathError: null,
dbRelocationInProgress: false,
historyPreviewLineLimit: settings.historyPreviewLineLimit?.valueInt ?? null,
appLastUpdateVersion: settings.appLastUpdateVersion?.valueText,
appLastUpdateDate: settings.appLastUpdateDate?.valueText,
isHideMacOSDockIcon: settings.isHideMacOSDockIcon?.valueBool,
@ -215,39 +195,7 @@ function App() {
isHistoryPanelVisibleOnly: settings.isHistoryPanelVisibleOnly?.valueBool,
isSavedClipsPanelVisibleOnly: settings.isSavedClipsPanelVisibleOnly?.valueBool,
isSimplifiedLayout: settings.isSimplifiedLayout?.valueBool ?? true,
isMainWindowOnTop: settings.isMainWindowOnTop?.valueBool ?? false,
isQuickPasteCopyOnly: settings.isQuickPasteCopyOnly?.valueBool ?? false,
isQuickPasteAutoClose: settings.isQuickPasteAutoClose?.valueBool ?? true,
isSingleClickToCopyPaste: settings.isSingleClickToCopyPaste?.valueBool ?? false,
hasPinProtectedCollections:
settings.hasPinProtectedCollections?.valueBool ?? false,
protectedCollections: settings.protectedCollections?.valueText
? settings.protectedCollections.valueText.split(',').filter(Boolean)
: [],
isSingleClickToCopyPasteQuickWindow:
settings.isSingleClickToCopyPasteQuickWindow?.valueBool ?? false,
isKeepPinnedOnClearEnabled:
settings.isKeepPinnedOnClearEnabled?.valueBool ?? false,
isKeepStarredOnClearEnabled:
settings.isKeepStarredOnClearEnabled?.valueBool ?? false,
isDoubleClickTrayToOpenEnabledOnWindows:
settings.isDoubleClickTrayToOpenEnabledOnWindows?.valueBool ?? false,
isLeftClickTrayDisabledOnWindows:
settings.isLeftClickTrayDisabledOnWindows?.valueBool ?? false,
isLeftClickTrayToOpenEnabledOnWindows:
settings.isLeftClickTrayToOpenEnabledOnWindows?.valueBool ?? false,
globalTemplatesEnabled: settings.globalTemplatesEnabled?.valueBool ?? true, // Default to true
globalTemplates: settings.globalTemplates?.valueText
? settings.globalTemplates.valueText // Will be parsed by initSettings in store
: [], // Default to empty array
isSpecialCopyPasteHistoryEnabled:
settings.isSpecialCopyPasteHistoryEnabled?.valueBool ?? true,
enabledSpecialPasteOperations: settings.enabledSpecialPasteOperations?.valueText
? settings.enabledSpecialPasteOperations.valueText.split(',').filter(Boolean)
: [...DEFAULT_SPECIAL_PASTE_OPERATIONS],
specialPasteCategoriesOrder: settings.specialPasteCategoriesOrder?.valueText
? settings.specialPasteCategoriesOrder.valueText.split(',').filter(Boolean)
: [...DEFAULT_SPECIAL_PASTE_CATEGORIES],
showTrayIcon: settings.showTrayIcon?.valueBool ?? true, // Added line
isAppReady: true,
})
settingsStore.initConstants({
@ -263,7 +211,7 @@ function App() {
if (settings.isFirstRun?.valueBool) {
appWindow.setSize(new LogicalSize(1105, 710))
showLanguageSelectionModal.value = true
settingsStore.updateSetting('isFirstRun', false)
}
if (
@ -313,7 +261,60 @@ function App() {
}
}
// Welcome tour logic moved to a separate useEffect
if (
!settings.appToursCompletedList?.valueText
.split(',')
.includes(APP_TOURS.historyPanelTour) &&
!settings.appToursSkippedList?.valueText
.split(',')
.includes(APP_TOURS.historyPanelTour) &&
permissionstrusted
) {
const welcomeTour = toast({
title: `${t('Welcome to PasteBar', { ns: 'help' })} 🎉`,
id: 'welcome-tour',
duration: 0,
description: (
<>
{t(`WelcomeDescription`, { ns: 'help' })}
<Flex className="mt-3">{t(`WelcomeTour`, { ns: 'help' })}</Flex>
<Flex className="justify-between">
<Button
className="bg-blue-500 dark:bg-blue-700 dark:hover:bg-blue-800 hover:bg-blue-600 px-4 mt-3 text-white"
onClick={() => {
openOnBoardingTourName.value = APP_TOURS.historyPanelTour
welcomeTour?.dismiss()
}}
>
{t('Start Tour', { ns: 'help' })}
</Button>
<Flex className="gap-3">
<Button
variant="light"
className="text-gray-800 px-4 mt-3 dark:bg-slate-800 dark:text-gray-400 hover:dark:text-gray-300"
onClick={() => {
welcomeTour?.dismiss()
}}
>
{t('Later', { ns: 'help' })}
</Button>
<Button
variant="outline"
className="text-gray-800 px-4 mt-3"
onClick={() => {
welcomeTour?.dismiss()
const tours = Object.values(APP_TOURS)
settingsStore.setAppToursSkippedList([...tours])
}}
>
{t('Skip All Tours', { ns: 'help' })}
</Button>
</Flex>
</Flex>
</>
),
})
}
if (!settings.isSkipAutoStartPrompt?.valueBool) {
invoke('is_autostart_enabled').then(async isAutoStartEnabled => {
@ -327,7 +328,9 @@ function App() {
})
}
// OSX Permissions modal logic moved to a separate useEffect
if (permissionstrusted === false) {
openOSXSystemPermissionsModal.value = true
}
} catch (e) {
console.error(e)
}
@ -534,142 +537,6 @@ function App() {
}
}, [])
// Effect to show OSX System Permissions Modal
useEffect(() => {
// Wait until permissions status is known and settings are initialized
if (permissionsTrustedSignal.value === null || !settingsStore.isAppReady) {
return
}
// If it's the first run and the language selection modal is active,
// wait for it to be closed before checking/showing the permissions modal.
if (settingsStore.isFirstRun && showLanguageSelectionModal.value) {
return
}
// Proceed if:
// - It's not the first run OR
// - It was the first run AND the language modal is now closed.
if (permissionsTrustedSignal.value === false) {
if (!openOSXSystemPermissionsModal.value) {
openOSXSystemPermissionsModal.value = true
}
} else if (permissionsTrustedSignal.value === true) {
// If permissions are trusted, ensure the modal is not trying to be shown.
// This can be useful if the modal was opened and then permissions were granted.
if (openOSXSystemPermissionsModal.value) {
openOSXSystemPermissionsModal.value = false
}
}
}, [
permissionsTrustedSignal.value,
showLanguageSelectionModal.value,
settingsStore.isFirstRun,
settingsStore.isAppReady,
// openOSXSystemPermissionsModal // signal itself, stable reference
])
useEffect(() => {
if (
permissionsTrustedSignal.value === false &&
openOSXSystemPermissionsModal.value === false
) {
permissionsTrustedSignal.value = true
}
}, [openOSXSystemPermissionsModal.value])
// Effect to show Welcome Tour toast
useEffect(() => {
let welcomeTourToast: { dismiss: () => void } | undefined
// Ensure all prerequisites are met: settings ready, permission status known,
// and relevant modals (language, OSX permissions) are not active.
if (
!settingsStore.isAppReady ||
permissionsTrustedSignal.value === null ||
(settingsStore.isFirstRun && showLanguageSelectionModal.value) ||
openOSXSystemPermissionsModal.value === true
) {
return () => {
welcomeTourToast?.dismiss()
}
}
// If we've passed the early exit, language and permissions modals are closed.
// Now, only show the tour if permissions are actually trusted.
if (permissionsTrustedSignal.value) {
const tourCompleted = settingsStore.appToursCompletedList?.includes(
APP_TOURS.historyPanelTour
)
const tourSkipped = settingsStore.appToursSkippedList?.includes(
APP_TOURS.historyPanelTour
)
if (!tourCompleted && !tourSkipped) {
welcomeTourToast = toast({
title: `${t('Welcome to PasteBar', { ns: 'help' })} 🎉`,
id: 'welcome-tour',
duration: 0, // Stays until dismissed
description: (
<>
{t(`WelcomeDescription`, { ns: 'help' })}
<Flex className="mt-3">{t(`WelcomeTour`, { ns: 'help' })}</Flex>
<Flex className="justify-between">
<Button
className="bg-blue-500 dark:bg-blue-700 dark:hover:bg-blue-800 hover:bg-blue-600 px-4 mt-3 text-white"
onClick={() => {
openOnBoardingTourName.value = APP_TOURS.historyPanelTour
welcomeTourToast?.dismiss()
}}
>
{t('Start Tour', { ns: 'help' })}
</Button>
<Flex className="gap-3">
<Button
variant="light"
className="text-gray-800 px-4 mt-3 dark:bg-slate-800 dark:text-gray-400 hover:dark:text-gray-300"
onClick={() => {
welcomeTourToast?.dismiss()
}}
>
{t('Later', { ns: 'help' })}
</Button>
<Button
variant="outline"
className="text-gray-800 px-4 mt-3"
onClick={() => {
welcomeTourToast?.dismiss()
const tours = Object.values(APP_TOURS)
settingsStore.setAppToursSkippedList([...tours])
}}
>
{t('Skip All Tours', { ns: 'help' })}
</Button>
</Flex>
</Flex>
</>
),
})
}
}
return () => {
welcomeTourToast?.dismiss() // Dismiss if this effect instance created it
}
}, [
settingsStore.isAppReady,
showLanguageSelectionModal.value,
settingsStore.isFirstRun,
permissionsTrustedSignal.value,
openOSXSystemPermissionsModal.value, // Added dependency
settingsStore.appToursCompletedList,
settingsStore.appToursSkippedList,
settingsStore, // For setAppToursSkippedList and accessing properties
t,
toast,
openOnBoardingTourName,
])
const uiState = useAtomValue(uiStoreAtom)
useEffect(() => {
@ -719,16 +586,6 @@ function App() {
<Outlet />
</div>
</div>
{settingsStore.isFirstRun && (
<LanguageSelectionModal
open={showLanguageSelectionModal.value}
onClose={() => {
showLanguageSelectionModal.value = false
settingsStore.updateSetting('isFirstRun', false)
}}
onLanguageSelected={handleLanguageSelected}
/>
)}
</ThemeProvider>
</>
)

View File

@ -45,11 +45,8 @@ function QuickPasteApp() {
i18n.changeLanguage(i18n.resolvedLanguage)
}
// @ts-expect-error
settingsStore.initSettings({
appDataDir: '',
isSingleClickToCopyPaste: settings.isSingleClickToCopyPaste?.valueBool,
historyPreviewLineLimit: settings.historyPreviewLineLimit?.valueInt ?? null,
appLastUpdateVersion: settings.appLastUpdateVersion?.valueText,
appLastUpdateDate: settings.appLastUpdateDate?.valueText,
isHideMacOSDockIcon: settings.isHideMacOSDockIcon?.valueBool,
@ -125,10 +122,6 @@ function QuickPasteApp() {
userSelectedLanguage: settings.userSelectedLanguage?.valueText,
clipTextMinLength: settings.clipTextMinLength?.valueInt,
clipTextMaxLength: settings.clipTextMaxLength?.valueInt,
isQuickPasteCopyOnly: settings.isQuickPasteCopyOnly?.valueBool ?? false,
isQuickPasteAutoClose: settings.isQuickPasteAutoClose?.valueBool ?? true,
isSingleClickToCopyPasteQuickWindow:
settings.isSingleClickToCopyPasteQuickWindow?.valueBool ?? false,
isAppReady: true,
})

View File

@ -14,9 +14,6 @@ import {
} from 'react'
import { UniqueIdentifier } from '@dnd-kit/core'
import { bbCode } from '~/libs/bbcode'
import { settingsStoreAtom } from '~/store'
import { useAtomValue } from 'jotai'
import { Check } from 'lucide-react'
import { OverlayScrollbarsComponent } from 'overlayscrollbars-react'
import { ensureUrlPrefix, escapeRegExp, maskValue } from '~/lib/utils'
@ -25,9 +22,8 @@ import { LinkMetadata } from '~/types/history'
import LinkCard from '../atoms/link-card/link-card'
import mergeRefs from '../atoms/merge-refs'
import ToolTip from '../atoms/tooltip'
import { CardSocialEmbed } from '../social-embend/CardSocialEmbed'
import { Badge, Box, TextNormal } from '../ui'
import { Box, TextNormal } from '../ui'
import YoutubeEmbed from '../video-player/YoutubeEmbed'
const highlightSearchTermInNode = (
@ -103,47 +99,6 @@ const highlightSearchTermInNode = (
}
}
const renderWithGlobalTemplateBadges = (
value: string,
globalTemplates: any[] = []
): ReactNode[] => {
const templateFieldRegex = /\{\{\s*(.*?)\s*\}\}/g
const parts = value.split(templateFieldRegex)
return parts.map((part: string, index: number): ReactNode => {
// Check if this is a template reference (odd indices are matches from regex split)
if (index % 2 === 1) {
const matchedGlobalTemplate = globalTemplates.find(
gt => gt.isEnabled && gt.name?.toLowerCase() === part.toLowerCase()
)
if (matchedGlobalTemplate) {
// Render as a badge for existing global templates
return (
<ToolTip
key={index}
text={matchedGlobalTemplate.value || part}
isCompact
side="top"
className="bg-purple-50 dark:bg-purple-900 text-purple-600 dark:text-purple-300"
>
<Badge className="inline-flex items-center gap-1 bg-purple-100 text-purple-700 dark:bg-purple-800 dark:text-purple-300 hover:bg-purple-200 dark:hover:bg-purple-700 cursor-default">
<Check size={12} className="text-purple-600 dark:text-purple-400" />
<span className="text-xs font-medium">{part}</span>
</Badge>
</ToolTip>
)
} else {
// Template reference doesn't exist - return the full {{templateName}} format
return <span key={index}>{`{{${part}}}`}</span>
}
}
// Return the plain text part
return <span key={index}>{part}</span>
})
}
interface CardValueViewerProps {
isWrapped: boolean
valuePreview: string
@ -189,24 +144,6 @@ export const CardValueViewer: FC<CardValueViewerProps> = ({
}) => {
const highlightedRefs = useRef<React.RefObject<HTMLElement>[]>([])
const wrapped = isLink || isVideo || isPath || isWrapped
const settings = useAtomValue(settingsStoreAtom)
// Get global templates from settings
const globalTemplatesEnabled = settings.globalTemplatesEnabled || false
const globalTemplates = useMemo(() => {
if (!globalTemplatesEnabled) return []
try {
if (typeof settings.globalTemplates === 'string') {
return JSON.parse(settings.globalTemplates || '[]')
}
if (Array.isArray(settings.globalTemplates)) {
return settings.globalTemplates
}
return []
} catch {
return []
}
}, [settings.globalTemplates, globalTemplatesEnabled])
const isTwitter =
metadataLinkByItemId?.linkDomain === 'x.com' ||
@ -217,41 +154,17 @@ export const CardValueViewer: FC<CardValueViewerProps> = ({
const valuePreviewParsed = useMemo(() => {
if (!isImageData && !isCode && !isImage && valuePreview) {
const processedValue = isMasked
return isMasked
? maskValue(bbCode.remove(valuePreview))
: bbCode.parse(valuePreview)
// Apply global template badges if enabled and templates exist
if (
globalTemplatesEnabled &&
globalTemplates.length > 0 &&
typeof processedValue === 'string'
) {
return renderWithGlobalTemplateBadges(processedValue, globalTemplates)
}
return processedValue
}
}, [valuePreview, globalTemplatesEnabled, globalTemplates, isMasked])
}, [valuePreview])
const valueParsed = useMemo(() => {
if (!isImageData && !isCode && !isImage && textValue) {
const processedValue = isMasked
? maskValue(bbCode.remove(textValue))
: bbCode.parse(textValue)
// Apply global template badges if enabled and templates exist
if (
globalTemplatesEnabled &&
globalTemplates.length > 0 &&
typeof processedValue === 'string'
) {
return renderWithGlobalTemplateBadges(processedValue, globalTemplates)
}
return processedValue
return isMasked ? maskValue(bbCode.remove(textValue)) : bbCode.parse(textValue)
}
}, [textValue, globalTemplatesEnabled, globalTemplates, isMasked])
}, [textValue])
const highlightedContent = useMemo(() => {
if (searchTerm.length > 1) {

View File

@ -1,6 +1,7 @@
import { createRef, FC, memo, useEffect, useRef, useState } from 'react'
import CodeMirror from 'codemirror'
import { OverlayScrollbarsComponent } from 'overlayscrollbars-react'
import { useTranslation } from 'react-i18next'
import { escapeRegExp } from '~/lib/utils'
@ -44,6 +45,7 @@ export const CodeViewer: FC<CodeViewerProps> = ({
}) => {
const [elements, setElements] = useState<JSX.Element[]>([])
const [isModeLoaded, setModeLoaded] = useState(false)
const { t } = useTranslation()
const mdShowFormat = useSignal<'html' | 'markdown'>('html')
const highlightedRefs = useRef<React.RefObject<HTMLElement>[]>([])
@ -181,7 +183,7 @@ export const CodeViewer: FC<CodeViewerProps> = ({
return (
<Box className="relative">
<OverlayScrollbarsComponent
className={`${isShowMore ? 'code-scroll-x' : ''}`}
className={`${isShowMore ? 'code-scroll-x pb-2' : ''}`}
options={{
overflow: {
x: !isShowMore ? 'hidden' : 'scroll',

View File

@ -54,5 +54,4 @@ export type SplitPanePrimaryProps = { children: ReactNode } & DOMProps & {
export type SplitPaneSecondaryProps = { children: ReactNode } & DOMProps & {
isSplitPanelView?: boolean
isFullWidth?: boolean
disabled?: boolean // Added disabled prop
}

View File

@ -1,13 +1,8 @@
// import clsx from 'clsx'
import { ReactElement } from 'react'
import {
collectionsStoreAtom,
openProtectedContentModal,
pendingProtectedCollectionId,
settingsStoreAtom,
} from '~/store'
import { collectionsStoreAtom, settingsStoreAtom } from '~/store'
import { useAtomValue } from 'jotai'
import { LockKeyhole, Settings } from 'lucide-react'
import { Settings } from 'lucide-react'
import { useTranslation } from 'react-i18next'
import { useNavigate } from 'react-router-dom'
@ -23,7 +18,6 @@ import {
DropdownMenuRadioItem,
DropdownMenuSeparator,
DropdownMenuTrigger,
Flex,
} from '../../ui'
export default function CollectionsDropDown({ children }: { children: ReactElement }) {
@ -32,11 +26,7 @@ export default function CollectionsDropDown({ children }: { children: ReactEleme
const navigate = useNavigate()
const { t } = useTranslation()
const {
protectedCollections,
hasPinProtectedCollections,
isShowDisabledCollectionsOnNavBarMenu,
} = useAtomValue(settingsStoreAtom)
const { isShowDisabledCollectionsOnNavBarMenu } = useAtomValue(settingsStoreAtom)
return (
<DropdownMenu>
@ -54,7 +44,7 @@ export default function CollectionsDropDown({ children }: { children: ReactEleme
height: 'auto',
maxHeight: '400px',
width: '100%',
minWidth: '220px',
minWidth: '200px',
}}
autoHide={false}
>
@ -80,38 +70,14 @@ export default function CollectionsDropDown({ children }: { children: ReactEleme
value={collectionId}
disabled={!isEnabled}
onClick={() => {
const isProtectedCollection =
hasPinProtectedCollections &&
protectedCollections.includes(collectionId)
if (isProtectedCollection) {
pendingProtectedCollectionId.value = collectionId
openProtectedContentModal.value = true
} else {
selectCollectionById({
selectCollection: { collectionId },
})
}
selectCollectionById({
selectCollection: {
collectionId,
},
})
}}
>
<Flex
className={`${
isSelected ? 'font-semibold' : ''
} items-center justify-start gap-2`}
>
{hasPinProtectedCollections &&
protectedCollections.includes(collectionId) ? (
<>
<span className="truncate max-w-[150px]">{title}</span>
<LockKeyhole
size={12}
className="text-gray-600 dark:text-gray-500 flex-shrink-0"
/>
</>
) : (
<span className="truncate max-w-[210px]">{title}</span>
)}
</Flex>
<span className={isSelected ? 'font-semibold' : ''}>{title}</span>
</DropdownMenuRadioItem>
))}
</DropdownMenuRadioGroup>

View File

@ -1,141 +0,0 @@
import { useCallback, useEffect, useState } from 'react'
import { LANGUAGES } from '~/locales/languges'
import { X } from 'lucide-react'
import { useTranslation } from 'react-i18next'
import Modal from '~/components/molecules/modal'
import { Button, Flex, Text } from '~/components/ui'
type Props = {
open: boolean
onLanguageSelected: (languageCode: string) => void
onClose?: () => void
}
const detectBrowserLanguage = (): string => {
const browserLang = navigator.language || navigator.languages?.[0] || 'en'
const langMappings: Record<string, string> = {
en: 'en',
'en-US': 'en',
'en-GB': 'en',
es: 'esES',
'es-ES': 'esES',
'es-MX': 'esES',
de: 'de',
'de-DE': 'de',
fr: 'fr',
'fr-FR': 'fr',
it: 'it',
'it-IT': 'it',
tr: 'tr',
'tr-TR': 'tr',
ru: 'ru',
'ru-RU': 'ru',
uk: 'uk',
'uk-UA': 'uk',
zh: 'zhCN',
'zh-CN': 'zhCN',
'zh-Hans': 'zhCN',
}
const mappedLang = langMappings[browserLang] || langMappings[browserLang.split('-')[0]]
const supportedCodes = LANGUAGES.map(lang => lang.code)
return supportedCodes.includes(mappedLang) ? mappedLang : 'en'
}
export default function LanguageSelectionModal({
open,
onLanguageSelected,
onClose = () => {},
}: Props) {
const { t, i18n } = useTranslation()
const [selectedLanguage, setSelectedLanguage] = useState<string>('en')
const [detectedLanguage, setDetectedLanguage] = useState<string>('en')
useEffect(() => {
if (open) {
const detected = detectBrowserLanguage()
setDetectedLanguage(detected)
setSelectedLanguage(detected)
if (detected !== i18n.language) {
i18n.changeLanguage(detected)
}
}
}, [open, i18n])
const handleLanguageChange = useCallback(
(languageCode: string) => {
setSelectedLanguage(languageCode)
i18n.changeLanguage(languageCode)
},
[i18n]
)
const handleStartApp = useCallback(() => {
onLanguageSelected(selectedLanguage)
}, [selectedLanguage, onLanguageSelected])
// Sort languages to put detected language first, then the rest
const sortedLanguages = [...LANGUAGES].sort((a, b) => {
if (a.code === detectedLanguage) return -1
if (b.code === detectedLanguage) return 1
return 0
})
return (
<Modal open={open} handleClose={() => {}} positionTop={true}>
<Modal.Body className="min-w-[400px] max-w-[500px] relative">
<Button
variant="link"
type="button"
onClick={onClose}
className="hover:bg-slate-200 ring-0 focus-visible:ring-0 px-2 outline-none absolute right-1.5 top-1.5 text-slate-400 dark:text-slate-500 hover:text-slate-600 hover:dark:text-slate-400 hover:bg-transparent dark:hover:bg-transparent z-10"
>
<X className="w-5 h-5" />
</Button>
<Modal.Content className="max-h-[400px]">
<Flex className="w-full flex-col gap-3 mt-2 justify-center">
<div className="text-center">
<Text className="font-semibold text-2xl mb-2 justify-center">
{t('Welcome to PasteBar', { ns: 'common2' })}
</Text>
<Text className="text-gray-600 dark:text-gray-400 justify-center">
{t('Please select your preferred language', { ns: 'common2' })}
</Text>
</div>
<div className="space-y-3">
<Flex className="gap-3 flex-wrap items-start justify-evenly">
{sortedLanguages.map(({ code, name, flag }) => (
<Button
key={code}
variant="ghost"
onClick={() => handleLanguageChange(code)}
className={`text-sm font-normal bg-slate-50 dark:bg-slate-950 ${
selectedLanguage === code
? 'ring-2 ring-blue-400 dark:ring-blue-500 bg-slate-300 font-semibold dark:bg-slate-600 text-dark dark:text-slate-200 hover:dark:bg-slate-600 hover:bg-slate-300'
: ''
} dark:text-slate-200 px-3 !py-0.5`}
>
<span className="flags mr-3">{flag}</span> {name}
</Button>
))}
</Flex>
</div>
</Flex>
</Modal.Content>
<Modal.Footer className="flex justify-center !pt-4 !pb-5">
<Button
onClick={handleStartApp}
className="bg-blue-500 hover:bg-blue-600 text-white px-8 py-2"
>
{t('Start using PasteBar', { ns: 'common2' })}
</Button>
</Modal.Footer>
</Modal.Body>
</Modal>
)
}

View File

@ -42,7 +42,7 @@ type Props = {
export default function ModalLockScreenConfirmationWithPasscodeOrPassword({
open,
title = 'Confirm Passcode',
title = 'Unlock Application Screen',
isLockScreen = false,
showPasscode = true,
onConfirmSuccess,
@ -171,16 +171,6 @@ export default function ModalLockScreenConfirmationWithPasscodeOrPassword({
setFocusField(confirmPasscodeCurrentFocus.value)
}, [confirmPasscodeCurrentFocus.value])
// Set initial focus when modal opens
useEffect(() => {
if (open && showPasscode && screenLockPassCode) {
setTimeout(() => {
confirmPasscodeCurrentFocus.value = 0
setFocusField(0)
}, 100)
}
}, [open, showPasscode])
return (
<Modal
open={open}
@ -326,7 +316,7 @@ export default function ModalLockScreenConfirmationWithPasscodeOrPassword({
) : (
<Text>
<Trans
i18nKey="Enter your <strong>{{screenLockPassCodeLength}} digits</strong> passcode"
i18nKey="Enter your&nbsp;<strong>{{screenLockPassCodeLength}} digits</strong>&nbsp;passcode"
values={{ screenLockPassCodeLength }}
ns="settings"
/>

View File

@ -3,67 +3,36 @@ import * as TabsPrimitive from '@radix-ui/react-tabs'
import { cn } from '~/lib/utils'
// Create a context to share the setting from TabsList to TabsTrigger
const TabsContext = React.createContext({
disableKeyboardNavigation: false,
})
const Tabs = TabsPrimitive.Root
const TabsList = React.forwardRef<
React.ElementRef<typeof TabsPrimitive.List>,
React.ComponentPropsWithoutRef<typeof TabsPrimitive.List> & {
disableKeyboardNavigation?: boolean
}
>(({ className, children, disableKeyboardNavigation = false, ...props }, ref) => (
// The provider makes the 'disableKeyboardNavigation' value available to all child components
<TabsContext.Provider value={{ disableKeyboardNavigation }}>
<TabsPrimitive.List
ref={ref}
className={cn(
'inline-flex items-center justify-center rounded-md bg-muted p-1 text-muted-foreground',
className
)}
{...props}
>
{children}
</TabsPrimitive.List>
</TabsContext.Provider>
React.ComponentPropsWithoutRef<typeof TabsPrimitive.List>
>(({ className, ...props }, ref) => (
<TabsPrimitive.List
ref={ref}
className={cn(
'inline-flex items-center justify-center rounded-md bg-muted p-1 text-muted-foreground',
className
)}
{...props}
/>
))
TabsList.displayName = TabsPrimitive.List.displayName
const TabsTrigger = React.forwardRef<
React.ElementRef<typeof TabsPrimitive.Trigger>,
React.ComponentPropsWithoutRef<typeof TabsPrimitive.Trigger>
>(({ className, onKeyDown, ...props }, ref) => {
// Consume the context to get the setting from the parent TabsList
const { disableKeyboardNavigation } = React.useContext(TabsContext)
// Create a new keydown handler
const handleKeyDown = (e: React.KeyboardEvent<HTMLButtonElement>) => {
// If the feature is enabled, prevent arrow key navigation (with or without modifiers)
if (disableKeyboardNavigation && (e.key === 'ArrowLeft' || e.key === 'ArrowRight')) {
e.preventDefault()
e.stopPropagation() // Also stop propagation to prevent other handlers from running
}
// IMPORTANT: Still call any original onKeyDown function that was passed in props
onKeyDown?.(e)
}
return (
<TabsPrimitive.Trigger
ref={ref}
className={cn(
'inline-flex items-center justify-center whitespace-nowrap rounded-sm px-3 py-1.5 text-sm font-medium ring-offset-background transition-all data-[state=active]:bg-background dark:data-[state=active]:bg-gray-600 data-[state=active]:text-foreground data-[state=active]:shadow-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset disabled:pointer-events-none disabled:opacity-50',
className
)}
// Conditionally apply our new handler ONLY if the prop is set
onKeyDown={disableKeyboardNavigation ? handleKeyDown : onKeyDown}
{...props}
/>
)
})
>(({ className, ...props }, ref) => (
<TabsPrimitive.Trigger
ref={ref}
className={cn(
'inline-flex items-center justify-center whitespace-nowrap rounded-sm px-3 py-1.5 text-sm font-medium ring-offset-background transition-all data-[state=active]:bg-background dark:data-[state=active]:bg-gray-600 data-[state=active]:text-foreground data-[state=active]:shadow-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset disabled:pointer-events-none disabled:opacity-50',
className
)}
{...props}
/>
))
TabsTrigger.displayName = TabsPrimitive.Trigger.displayName
const TabsContent = React.forwardRef<

View File

@ -372,12 +372,7 @@ export function useDeleteClipboardHistoryByIds() {
export function useClearClipboardHistoryOlderThan() {
const queryClient = useQueryClient()
const { mutate: clearClipboardHistoryOlderThan } = useInvokeMutation<
{
durationType: string
olderThen: string
keepPinned?: boolean
keepStarred?: boolean
},
{ durationType: string; olderThen: string },
UniqueIdentifier
>('clear_clipboard_history_older_than', {
onSuccess: data => {
@ -403,12 +398,7 @@ export function useClearClipboardHistoryOlderThan() {
export function useClearRecentClipboardHistory() {
const queryClient = useQueryClient()
const { mutate: clearRecentClipboardHistory } = useInvokeMutation<
{
durationType: string
duration: string
keepPinned?: boolean
keepStarred?: boolean
},
{ durationType: string; duration: string },
UniqueIdentifier
>('clear_recent_clipboard_history', {
onSuccess: data => {

View File

@ -13,7 +13,7 @@ const useDeleteConfirmationTimer = ({
onConfirmedDelete: () => Promise<void>
onConfirmedReset?: () => void
selectedHistoryItems: UniqueIdentifier[]
hoveringHistoryRowId: Signal<UniqueIdentifier | null>
hoveringHistoryRowId: Signal<UniqueIdentifier | null> | null
timerDuration?: number
}) => {
const timerRef = useRef(null) as React.MutableRefObject<NodeJS.Timeout | null>
@ -34,17 +34,15 @@ const useDeleteConfirmationTimer = ({
if (timerRef.current) {
clearTimeout(timerRef.current)
}
if (selectedHistoryItems.length === 0) {
if (hoveringHistoryRowId?.value && selectedHistoryItems.length === 0) {
seHoveringHistoryIdDelete(hoveringHistoryRowId.value)
}
setShowConfirmation(true)
timerRef.current = setTimeout(() => {
resetTimer()
}, timerDuration)
}, [timerDuration, resetTimer, selectedHistoryItems, hoveringHistoryRowId])
}, [timerDuration, resetTimer, selectedHistoryItems])
useEffect(() => {
return () => {

View File

@ -1,102 +0,0 @@
import { useCallback, useEffect, useRef, useState } from 'react'
import { UniqueIdentifier } from '@dnd-kit/core'
import { Signal } from '@preact/signals-react'
import { useHotkeys } from 'react-hotkeys-hook'
const useKeyboardDeleteConfirmation = ({
onConfirmedDelete,
keyboardSelectedItemId,
onConfirmedReset,
selectedHistoryItems,
timerDuration = 3000,
}: {
onConfirmedDelete: () => Promise<void>
onConfirmedReset?: () => void
selectedHistoryItems: UniqueIdentifier[]
keyboardSelectedItemId: Signal<UniqueIdentifier | null>
timerDuration?: number
}) => {
const timerRef = useRef(null) as React.MutableRefObject<NodeJS.Timeout | null>
const [showConfirmation, setShowConfirmation] = useState(false)
const [keyboardItemIdDelete, setKeyboardItemIdDelete] =
useState<UniqueIdentifier | null>(null)
const resetTimer = useCallback(() => {
if (timerRef.current) {
clearTimeout(timerRef.current)
}
setKeyboardItemIdDelete(null)
setShowConfirmation(false)
onConfirmedReset?.()
}, [onConfirmedReset])
const startTimer = useCallback(() => {
if (timerRef.current) {
clearTimeout(timerRef.current)
}
// Only proceed if there's a keyboard selected item and no multi-selection
if (!keyboardSelectedItemId.value || selectedHistoryItems.length > 0) {
return
}
setKeyboardItemIdDelete(keyboardSelectedItemId.value)
setShowConfirmation(true)
timerRef.current = setTimeout(() => {
resetTimer()
}, timerDuration)
}, [timerDuration, resetTimer, selectedHistoryItems, keyboardSelectedItemId])
// Reset confirmation when the keyboard selected item changes
useEffect(() => {
if (showConfirmation && keyboardItemIdDelete !== keyboardSelectedItemId.value) {
resetTimer()
}
}, [keyboardSelectedItemId.value, showConfirmation, keyboardItemIdDelete, resetTimer])
// Reset confirmation when there are selected items (multi-selection mode)
useEffect(() => {
if (showConfirmation && selectedHistoryItems.length > 0) {
resetTimer()
}
}, [selectedHistoryItems.length, showConfirmation, resetTimer])
useEffect(() => {
return () => {
if (timerRef.current) {
clearTimeout(timerRef.current)
}
}
}, [])
useHotkeys(
['delete', 'backspace'],
async (e) => {
e.preventDefault()
// Only handle keyboard delete when there's a keyboard selected item and no multi-selection
if (!keyboardSelectedItemId.value || selectedHistoryItems.length > 0) {
return
}
if (showConfirmation) {
await onConfirmedDelete()
resetTimer()
} else {
startTimer()
}
},
{
enableOnFormTags: false,
}
)
return {
showConfirmation,
keyboardItemIdDelete,
resetTimer,
}
}
export default useKeyboardDeleteConfirmation

View File

@ -27,7 +27,7 @@ export function useLongPress(
delay = 600,
threshold = 10,
cancelOnMove = true,
preventDefault = true,
preventDefault = true
} = options
const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null)
@ -64,7 +64,7 @@ export function useLongPress(
const touch = 'touches' in e ? e.touches[0] : e
startPositionRef.current = {
x: touch.clientX,
y: touch.clientY,
y: touch.clientY
}
if (preventDefault) {
@ -120,11 +120,14 @@ export function useLongPress(
}, [clear])
// Prevent context menu on long press
const handleContextMenu = useCallback((e: React.MouseEvent) => {
if (isLongPressTriggeredRef.current || timeoutRef.current) {
e.preventDefault()
}
}, [])
const handleContextMenu = useCallback(
(e: React.MouseEvent) => {
if (isLongPressTriggeredRef.current || timeoutRef.current) {
e.preventDefault()
}
},
[]
)
return {
onMouseDown: start as (e: React.MouseEvent) => void,
@ -135,7 +138,7 @@ export function useLongPress(
onTouchEnd: end as (e: React.TouchEvent) => void,
onTouchMove: move as (e: React.TouchEvent) => void,
onTouchCancel: cancel,
onContextMenu: preventDefault ? handleContextMenu : undefined,
onContextMenu: preventDefault ? handleContextMenu : undefined
}
}
@ -144,4 +147,4 @@ export function useLongPressHOF() {
return function (callback: () => void, options?: LongPressOptions) {
return useLongPress(callback, options)
}
}
}

View File

@ -1,164 +0,0 @@
import { useCallback, useRef } from 'react'
import { UniqueIdentifier } from '@dnd-kit/core/dist/types'
import { signal } from '@preact/signals-react'
import { invoke } from '@tauri-apps/api/tauri'
import { settingsStoreAtom } from '~/store'
import { useAtomValue } from 'jotai'
import { applyTransform, TEXT_TRANSFORMS } from '~/lib/text-transforms'
// Signals for tracking special copy/paste operations
export const specialCopiedItem = signal<UniqueIdentifier>('')
export const specialPastedItem = signal<UniqueIdentifier>('')
export const specialPastedItemCountDown = signal<number>(0)
interface UseSpecialCopyPasteOptions {
delay?: number
}
export const useSpecialCopyPasteHistoryItem = ({
delay = 800,
}: UseSpecialCopyPasteOptions = {}) => {
const { copyPasteDelay } = useAtomValue(settingsStoreAtom)
const countdownRef = useRef<NodeJS.Timeout>()
// Special copy function - applies transformation and copies to clipboard
const specialCopy = async (
historyId: UniqueIdentifier,
value: string,
transformId: string
): Promise<void> => {
try {
if (!value || !historyId) {
console.warn('No value or historyId to copy')
return
}
// Set the signal to show UI feedback
specialCopiedItem.value = historyId
// Apply the text transformation - this will throw if it fails
const transformedText = await applyTransform(value, transformId)
// Only copy if transformation was successful
setTimeout(() => {
invoke('copy_text', { text: transformedText })
.then(res => {
if (res === 'ok') {
requestAnimationFrame(() => {
specialCopiedItem.value = ''
})
} else {
specialCopiedItem.value = ''
console.error('Failed to copy transformed text', res)
}
})
.catch(err => {
specialCopiedItem.value = ''
console.error('Failed to copy transformed text', err)
})
}, delay)
} catch (error) {
// Clear UI feedback immediately on transformation error
specialCopiedItem.value = ''
console.error('Failed to special copy - transformation error:', error)
// Don't copy anything to clipboard when transformation fails
throw error
}
}
// Countdown helper for paste operations
const pasteCountdown = useCallback(
(initialCount: number, intervalMs = 1000): Promise<void> => {
clearInterval(countdownRef.current)
return new Promise(resolve => {
specialPastedItemCountDown.value = initialCount
countdownRef.current = setInterval(() => {
if (specialPastedItemCountDown.value > 0) {
if (specialPastedItemCountDown.value === 1) {
resolve()
}
specialPastedItemCountDown.value -= 1
} else {
clearInterval(countdownRef.current)
}
}, intervalMs)
})
},
[]
)
// Execute paste action with transformed text
const executePasteAction = (text: string, delay = 0): Promise<void> => {
return new Promise((resolve, reject) => {
invoke('copy_paste', { text, delay })
.then(res => {
if (res === 'ok') {
resolve()
} else {
console.error('Failed to paste transformed text', res)
reject()
}
})
.catch(err => {
console.error('Failed to paste transformed text', err)
reject()
})
})
}
// Special paste function - applies transformation and pastes directly
const specialPaste = async (
historyId: UniqueIdentifier,
value: string,
transformId: string,
delaySeconds?: number
): Promise<void> => {
try {
delaySeconds = delaySeconds ?? copyPasteDelay
if (!value || !historyId) {
console.warn('No value or historyId to paste')
return
}
// Set the signal to show UI feedback
specialPastedItem.value = historyId
// Apply the text transformation - this will throw if it fails
const transformedText = await applyTransform(value, transformId)
// Handle countdown if delay is specified (only if transformation succeeded)
if (delaySeconds > 0) {
await pasteCountdown(delaySeconds)
}
// Execute paste with transformed text (only if transformation succeeded)
await executePasteAction(transformedText, 0)
// Clear the signal after a short delay
setTimeout(() => {
requestAnimationFrame(() => {
specialPastedItem.value = ''
specialPastedItemCountDown.value = 0
})
}, delay)
} catch (error) {
// Clear UI feedback immediately on transformation error
specialPastedItem.value = ''
specialPastedItemCountDown.value = 0
console.error('Failed to special paste - transformation error:', error)
// Don't paste anything when transformation fails
throw error
}
}
return {
specialCopy,
specialPaste,
availableTransforms: TEXT_TRANSFORMS,
specialCopiedItem: specialCopiedItem.value,
specialPastedItem: specialPastedItem.value,
specialPastedItemCountDown: specialPastedItemCountDown.value,
}
}

View File

@ -16,12 +16,9 @@ import {
onBoardingTourSingleElements,
openAboutPasteBarModal,
openActionConfirmModal,
openAddSelectedTextModal,
openContactUsFormModal,
openOnBoardingTourName,
openOSXSystemPermissionsModal,
openProtectedContentModal,
pendingProtectedCollectionId,
playerStoreAtom,
resetPassCodeNextDelayInSeconds,
resetPassCodeNumberOfTried,
@ -33,7 +30,6 @@ import {
showUpdateChecking,
uiStore,
uiStoreAtom,
visibilityCopyPopup,
} from '~/store'
import { clsx } from 'clsx'
import { useAtomValue } from 'jotai'
@ -58,9 +54,9 @@ import ModalLockScreenConfirmationWithPasscodeOrPassword from '~/components/orga
import ModalOSXSystemPermissions from '~/components/organisms/modals/system-permissions-osx-modal'
import { Box, Button, Flex, Text } from '~/components/ui'
import { useSelectCollectionById } from '~/hooks/queries/use-collections'
import { useClipboardPaste, useCopyPaste } from '~/hooks/use-copypaste'
import { useLocalStorage } from '~/hooks/use-localstorage'
import { useSignal } from '~/hooks/use-signal'
import { CreateDashboardItemType } from '~/types/menu'
@ -91,7 +87,6 @@ const Container: React.ForwardRefRenderFunction<HTMLDivElement, MainContainerPro
const { historyListSimpleBar, clipboardHistory } = useAtomValue(
clipboardHistoryStoreAtom
)
const { selectCollectionById } = useSelectCollectionById()
const {
appToursCompletedList,
@ -110,6 +105,8 @@ const Container: React.ForwardRefRenderFunction<HTMLDivElement, MainContainerPro
const [isCopied, copyToClipboard] = useCopyPaste({})
const [pastedText, pastedItemCountDown, pasteToClipboard] = useClipboardPaste({})
const visibilityCopyPopup = useSignal(false)
const openAddSelectedTextModal = useSignal(false)
const [positionCopyPopup, setPositionCopyPopup] = useState({ top: 0, left: 0 })
@ -126,7 +123,7 @@ const Container: React.ForwardRefRenderFunction<HTMLDivElement, MainContainerPro
const refRect = mainContentRef.current
? mainContentRef.current.getBoundingClientRect()
: new DOMRect(0)
const top = rect.top - refRect.top - 10
const top = rect.top - refRect.top
const left =
maxWidth > 0
? rect.left + rect.width / 2 - refRect.left > maxWidth
@ -546,7 +543,10 @@ const Container: React.ForwardRefRenderFunction<HTMLDivElement, MainContainerPro
)}
{openActionConfirmModal.value && (
<ModalLockScreenConfirmationWithPasscodeOrPassword
title={actionNameForConfirmModal.value ?? undefined}
title={t('Confirm {{action}}', {
ns: 'common',
action: actionNameForConfirmModal.value,
})}
open
onClose={() => {
openActionConfirmModal.value = false
@ -615,30 +615,6 @@ const Container: React.ForwardRefRenderFunction<HTMLDivElement, MainContainerPro
element={onBoardingTourSingleElements.value}
/>
)}
{openProtectedContentModal.value && (
<ModalLockScreenConfirmationWithPasscodeOrPassword
open={openProtectedContentModal.value}
// no need to translate this will be done in the modal
title="Enter PIN to Access Protected Collection"
isLockScreen={false}
showPasscode={true}
onConfirmSuccess={() => {
openProtectedContentModal.value = false
if (pendingProtectedCollectionId.value) {
selectCollectionById({
selectCollection: {
collectionId: pendingProtectedCollectionId.value,
},
})
pendingProtectedCollectionId.value = null
}
}}
onClose={() => {
openProtectedContentModal.value = false
pendingProtectedCollectionId.value = null
}}
/>
)}
</div>
)
}

View File

@ -17,8 +17,6 @@ import {
openAboutPasteBarModal,
openContactUsFormModal,
openOnBoardingTourName,
openProtectedContentModal,
pendingProtectedCollectionId,
playerStoreAtom,
settingsStoreAtom,
showInvalidTrackWarningAddSong,
@ -46,11 +44,9 @@ import {
ExternalLink,
FileCog,
LibrarySquare,
LockKeyhole,
Maximize,
Minus,
Pause,
PinOff,
Play,
Plus,
RefreshCw,
@ -94,7 +90,6 @@ import { Badge, Box, Button, Flex, Shortcut, Text } from '~/components/ui'
import { useSelectCollectionById } from '~/hooks/queries/use-collections'
import { useDeleteClipboardHistoryByIds } from '~/hooks/queries/use-history-items'
import { useDeleteItemById } from '~/hooks/queries/use-items'
import { useSignal } from '~/hooks/use-signal'
import { PlayerMenu } from '../components/audio-player/PlayerMenu'
import Logo from './Logo'
@ -130,16 +125,6 @@ export function NavBar() {
const { selectCollectionById } = useSelectCollectionById()
const isDark = themeDark()
const onTopWindow = () => {
appWindow?.setAlwaysOnTop(true)
setIsMainWindowOnTop(true)
}
const offTopWindow = () => {
appWindow?.setAlwaysOnTop(false)
setIsMainWindowOnTop(false)
}
useEffect(() => {
invoke('is_autostart_enabled').then(isEnabled => {
setIsAutoStartEnabled(Boolean(isEnabled))
@ -215,10 +200,6 @@ export function NavBar() {
setIsSavedClipsPanelVisibleOnly,
isSimplifiedLayout,
setIsSimplifiedLayout,
isMainWindowOnTop,
setIsMainWindowOnTop,
hasPinProtectedCollections,
protectedCollections,
} = useAtomValue(settingsStoreAtom)
const {
@ -237,13 +218,6 @@ export function NavBar() {
isSwapPanels,
} = useAtomValue(uiStoreAtom)
// Restore window always-on-top state on startup
useEffect(() => {
if (isMainWindowOnTop) {
appWindow?.setAlwaysOnTop(true)
}
}, [isMainWindowOnTop])
useHotkeys(['alt+b', 'ctrl+b', 'meta+b'], () => {
navigate('/history', { replace: true })
})
@ -876,7 +850,7 @@ export function NavBar() {
>
{isSplitPanelView
? t('Close History Window', { ns: 'common' })
: t('Open History Window', { ns: 'common' })}
: t('Split History Window', { ns: 'common' })}
<MenubarShortcut className="ml-2">
<Shortcut keys="CTRL+N" />
</MenubarShortcut>
@ -1110,19 +1084,6 @@ export function NavBar() {
{t('Show Disabled Collections', { ns: 'settings' })}
</MenubarCheckboxItem>
<MenubarCheckboxItem
checked={isMainWindowOnTop}
onClick={() => {
if (!isMainWindowOnTop) {
onTopWindow()
} else {
offTopWindow()
}
}}
>
{t('Show Always on Top', { ns: 'navbar' })}
</MenubarCheckboxItem>
<MenubarSeparator />
<MenubarCheckboxItem
@ -1269,7 +1230,7 @@ export function NavBar() {
height: 'auto',
maxHeight: '400px',
width: '100%',
minWidth: '220px',
minWidth: '200px',
}}
autoHide={false}
>
@ -1296,40 +1257,16 @@ export function NavBar() {
value={collectionId}
disabled={!isEnabled}
onClick={() => {
const isProtectedCollection =
hasPinProtectedCollections &&
protectedCollections.includes(collectionId)
if (isProtectedCollection) {
pendingProtectedCollectionId.value = collectionId
openProtectedContentModal.value = true
} else {
selectCollectionById({
selectCollection: {
collectionId,
},
})
}
selectCollectionById({
selectCollection: {
collectionId,
},
})
}}
>
<Flex
className={`${
isSelected ? 'font-semibold' : ''
} items-center justify-start gap-2`}
>
{hasPinProtectedCollections &&
protectedCollections.includes(collectionId) ? (
<>
<span className="truncate max-w-[150px]">{title}</span>
<LockKeyhole
size={12}
className="text-gray-600 dark:text-gray-500 flex-shrink-0"
/>
</>
) : (
<span className="truncate max-w-[210px]">{title}</span>
)}
</Flex>
<span className={isSelected ? 'font-semibold' : ''}>
{title}
</span>
</MenubarRadioItem>
))}
</MenubarRadioGroup>
@ -1369,7 +1306,7 @@ export function NavBar() {
toggleIsSplitPanelView()
}}
id="navbar-toggle-history-split"
title={t('Open History Window', { ns: 'common' })}
title={t('Split History Window', { ns: 'common' })}
variant="ghost"
className="relative h-7 focus:outline-none px-2 mr-0 ml-2 !bg-slate-50 text-slate-400 dark:!bg-slate-900 dark:hover:!bg-slate-800 hover:text-slate-600 dark:text-slate-400"
>
@ -2022,31 +1959,16 @@ export function NavBar() {
<Icons.minimize className="h-3 w-3" />
</Button>
{!isHistoryPanelVisibleOnly && (
<>
{!isMainWindowOnTop ? (
<Button
onClick={maximizeWindow}
title={t('Window:::Maximize Window', { ns: 'navbar' })}
variant="ghost"
className={`h-8 focus:outline-none ${
isShowNavBarItems ? 'opacity-1' : 'opacity-0'
}`}
>
<Maximize className="h-4 w-4" />
</Button>
) : (
<Button
onClick={offTopWindow}
title={t('Window:::UnPin Window', { ns: 'navbar' })}
variant="ghost"
className={`h-8 focus:outline-none ${
isShowNavBarItems ? 'opacity-1' : 'opacity-0'
}`}
>
<PinOff className="stroke-[1.8px] h-4 w-4" />
</Button>
)}
</>
<Button
onClick={maximizeWindow}
title={t('Window:::Maximize Window', { ns: 'navbar' })}
variant="ghost"
className={`h-8 focus:outline-none ${
isShowNavBarItems ? 'opacity-1' : 'opacity-0'
}`}
>
<Maximize className="h-4 w-4" />
</Button>
)}
<Button
onClick={hideWindow}

View File

@ -1,505 +0,0 @@
/**
* Text transformation utilities for special copy/paste operations
* Organized by categories with enable/disable controls
*/
import DOMPurify from 'dompurify'
export interface TextTransform {
id: string
label: string
transform: (text: string) => string | Promise<string>
}
export interface TransformCategory {
id: string
label: string
transforms?: TextTransform[]
subcategories?: TransformSubcategory[]
}
export interface TransformSubcategory {
id: string
label: string
transforms: TextTransform[]
}
// Transform functions for Text Case
const toUpperCase = (text: string): string => text.toUpperCase()
const toLowerCase = (text: string): string => text.toLowerCase()
const toTitleCase = (text: string): string =>
text.replace(/\b\w/g, char => char.toUpperCase()) // Renamed from toCapitalize
const toSentenceCase = (text: string): string =>
text.charAt(0).toUpperCase() + text.slice(1).toLowerCase() // Keep as is, assumes single string capitalization
const toInvertCase = (text: string): string =>
text.replace(/[a-zA-Z]/g, char =>
char === char.toUpperCase() ? char.toLowerCase() : char.toUpperCase()
)
// Transform functions for Code Formatting
const toCamelCase = (text: string): string => {
const normalized = text.replace(/[^a-zA-Z0-9]+/g, ' ').trim() // Normalize spaces/delimiters
return normalized
.replace(/(?:^\w|[A-Z]|\b\w)/g, (word, index) =>
index === 0 ? word.toLowerCase() : word.toUpperCase()
)
.replace(/\s+/g, '')
}
const toSnakeCase = (text: string): string => {
return text
.replace(/([a-z0-9])([A-Z])/g, '$1_$2') // Add underscore before capital letters (camelCase to snake_case part)
.replace(/[^a-zA-Z0-9]+/g, '_') // Replace non-alphanumeric with underscore
.toLowerCase()
.replace(/^_|_$/g, '') // Remove leading/trailing underscores
}
const toKebabCase = (text: string): string => {
return text
.replace(/([a-z0-9])([A-Z])/g, '$1-$2') // Add hyphen before capital letters
.replace(/[^a-zA-Z0-9]+/g, '-') // Replace non-alphanumeric with hyphen
.toLowerCase()
.replace(/^-|-$/g, '') // Remove leading/trailing hyphens
}
const toPascalCase = (text: string): string => {
const normalized = text.replace(/[^a-zA-Z0-9]+/g, ' ').trim() // Normalize spaces/delimiters
return normalized
.replace(/(?:^\w|[A-Z]|\b\w)/g, word => word.toUpperCase())
.replace(/\s+/g, '')
}
// Transform functions for Whitespace & Lines
const trimWhiteSpace = (text: string): string => text.trim()
const removeLineFeeds = (
text: string
): string => // More aggressive removal of multiple line feeds to single space
text
.replace(/\r?\n|\r/g, ' ')
.replace(/\s+/g, ' ')
.trim()
const addOneLineFeed = (text: string): string => text + '\n'
const addTwoLineFeeds = (text: string): string => text + '\n\n'
const removeExtraSpaces = (text: string): string => text.replace(/\s+/g, ' ')
const sortLinesAlphabetically = (text: string): string => {
const lines = text.split(/\r?\n|\r/)
return lines.sort((a, b) => a.localeCompare(b)).join('\n')
}
const removeDuplicateLines = (text: string): string => {
const lines = text.split(/\r?\n|\r/)
const uniqueLines = [...new Set(lines)]
return uniqueLines.join('\n')
}
const addLineNumbers = (text: string): string => {
const lines = text.split(/\r?\n|\r/)
return lines.map((line, index) => `${index + 1}. ${line}`).join('\n')
}
// Transform functions for Encoding & Security
const toBase64Encode = (text: string): string => {
try {
// This is generally the most robust method for UTF-8 in browsers without polyfills
return btoa(String.fromCharCode(...new TextEncoder().encode(text)))
} catch (e) {
console.error('Base64 encode error:', e)
return text
}
}
const toBase64Decode = (text: string): string => {
try {
// This is generally the most robust method for UTF-8 in browsers without polyfills
return new TextDecoder().decode(
Uint8Array.from(atob(text), charCode => charCode.charCodeAt(0))
)
} catch (e) {
console.error('Base64 decode error:', e)
return text
}
}
const toUrlEncode = (text: string): string => encodeURIComponent(text)
const toUrlDecode = (text: string): string => {
try {
return decodeURIComponent(text)
} catch (e) {
console.error('URL decode error:', e)
return text
}
}
function toHtmlEncode(str: string): string {
// Ensure the input is a string
if (typeof str !== 'string') {
console.warn('Input to encodeHtmlSpecialChars was not a string:', str)
return '' // Or throw an error, depending on desired behavior
}
return str.replace(/[&<>"']/g, function (char) {
switch (char) {
case '&':
return '&amp;' // Ampersand
case '<':
return '&lt;' // Less than
case '>':
return '&gt;' // Greater than
case '"':
return '&quot;' // Double quote
case "'":
return '&#039;' // Single quote (apostrophe)
default:
return char // Should not happen with the given regex, but good practice
}
})
}
const toHtmlDecode = (text: string): string => {
const sanitized = DOMPurify.sanitize(text, { RETURN_DOM: true })
return sanitized.textContent || ''
}
// Transform functions for Text Tools
const reverseText = (text: string): string => text.split('').reverse().join('')
const addCurrentDateTime = (text: string): string => {
const now = new Date()
return text + '\n' + now.toLocaleString()
}
const countCharacters = (text: string): string => {
const count = text.length
return `Character count: ${count}`
}
const countWords = (text: string): string => {
const words = text
.trim()
.split(/\s+/)
.filter(word => word.length > 0)
const count = words.length
return `Word count: ${count}`
}
const countLines = (text: string): string => {
const lines = text.split(/\r?\n|\r/)
const count = lines.length
return `Line count: ${count}`
}
const countSentences = (text: string): string => {
const sentences = text.split(/[.!?]+/).filter(sentence => sentence.trim().length > 0)
const count = sentences.length
return `Sentence count: ${count}`
}
const toJsonStringify = (text: string): string => {
try {
const parsed = JSON.parse(text)
return JSON.stringify(parsed, null, 2)
} catch {
return JSON.stringify(text) // If not valid JSON, stringify the text itself
}
}
// Format Converter subcategories - organized by source format
const formatConverterSubcategories = [
{
id: 'html',
label: 'HTML',
transforms: [
{
id: 'htmlToMarkdown',
label: 'HTML to Markdown',
transform: (text: string) => convertFormat(text, 'html_to_markdown'),
},
{
id: 'htmlToReact',
label: 'HTML to React JSX',
transform: (text: string) => convertFormat(text, 'html_to_react'),
},
{
id: 'htmlToReactComponent',
label: 'HTML to React Component',
transform: (text: string) => convertFormat(text, 'html_to_react_components'),
},
{
id: 'htmlToText',
label: 'HTML to Text',
transform: (text: string) => convertFormat(text, 'html_to_text'),
},
{
id: 'htmlToPlainText',
label: 'HTML to Plain Text',
transform: async (text: string) => {
// dynamic import for html-to-text
const { convert } = await import('html-to-text')
return convert(text, {
wordwrap: 130,
preserveNewlines: false,
// selectors: [{ selector: 'a', format: }],
})
.replace(/\n{3,}/g, '\n\n') // Replace 3+ newlines with double newline
.trim() // Remove leading and trailing whitespace
},
},
],
},
{
id: 'markdown',
label: 'Markdown',
transforms: [
{
id: 'markdownToHtml',
label: 'Markdown to HTML',
transform: (text: string) => convertFormat(text, 'markdown_to_html'),
},
{
id: 'markdownToText',
label: 'Markdown to Text',
transform: (text: string) => convertFormat(text, 'markdown_to_text'),
},
],
},
{
id: 'json',
label: 'JSON',
transforms: [
{
id: 'jsonToCsv',
label: 'JSON to CSV',
transform: (text: string) => convertFormat(text, 'json_to_csv'),
},
{
id: 'jsonToYaml',
label: 'JSON to YAML',
transform: (text: string) => convertFormat(text, 'json_to_yaml'),
},
{
id: 'jsonToXml',
label: 'JSON to XML',
transform: (text: string) => convertFormat(text, 'json_to_xml'),
},
{
id: 'jsonToToml',
label: 'JSON to TOML',
transform: (text: string) => convertFormat(text, 'json_to_toml'),
},
{
id: 'jsonToTable',
label: 'JSON to Markdown Table',
transform: (text: string) => convertFormat(text, 'json_to_table'),
},
],
},
{
id: 'csv',
label: 'CSV',
transforms: [
{
id: 'csvToJson',
label: 'CSV to JSON',
transform: (text: string) => convertFormat(text, 'csv_to_json'),
},
{
id: 'csvToTable',
label: 'CSV to Markdown Table',
transform: (text: string) => convertFormat(text, 'csv_to_table'),
},
],
},
{
id: 'yaml',
label: 'YAML',
transforms: [
{
id: 'yamlToJson',
label: 'YAML to JSON',
transform: (text: string) => convertFormat(text, 'yaml_to_json'),
},
],
},
{
id: 'xml',
label: 'XML',
transforms: [
{
id: 'xmlToJson',
label: 'XML to JSON',
transform: (text: string) => convertFormat(text, 'xml_to_json'),
},
],
},
{
id: 'toml',
label: 'TOML',
transforms: [
{
id: 'tomlToJson',
label: 'TOML to JSON',
transform: (text: string) => convertFormat(text, 'toml_to_json'),
},
],
},
]
// Helper function to call Rust format conversion
function convertFormat(text: string, conversionType: string): Promise<string> {
return new Promise(async (resolve, reject) => {
try {
const { invoke } = await import('@tauri-apps/api/tauri')
const result = await invoke('format_convert', { text, conversionType })
resolve(result as string)
} catch (error) {
console.error(`Format conversion failed for ${conversionType}:`, error)
// Show error dialog to user
try {
const { message } = await import('@tauri-apps/api/dialog')
const errorMessage = error instanceof Error ? error.message : String(error)
// Clean up the error message for better user experience
const cleanErrorMessage = errorMessage
.replace(/^Error: /, '')
.replace(/^format_convert returned an error: /, '')
await message(`${cleanErrorMessage}`, {
title: 'Format Conversion Error',
type: 'error',
})
} catch (dialogError) {
console.error('Failed to show error dialog:', dialogError)
}
// Reject the promise so the error propagates and prevents copy/paste
reject(error)
}
})
}
// Special Convert category will be implemented in Rust later for better performance
// Categorized transformations
export const TRANSFORM_CATEGORIES: TransformCategory[] = [
{
id: 'textCase',
label: 'Text Case',
transforms: [
{ id: 'upperCase', label: 'UPPER CASE', transform: toUpperCase },
{ id: 'lowerCase', label: 'lower case', transform: toLowerCase },
{ id: 'titleCase', label: 'Title Case', transform: toTitleCase },
{ id: 'sentenceCase', label: 'Sentence case', transform: toSentenceCase },
{ id: 'invertCase', label: 'iNVERT cASE', transform: toInvertCase },
],
},
{
id: 'codeFormatting',
label: 'Code Formatting',
transforms: [
{ id: 'camelCase', label: 'camelCase', transform: toCamelCase },
{ id: 'snakeCase', label: 'snake_case', transform: toSnakeCase },
{ id: 'kebabCase', label: 'kebab-case', transform: toKebabCase },
{ id: 'pascalCase', label: 'PascalCase', transform: toPascalCase },
{ id: 'jsonStringify', label: 'JSON Stringify', transform: toJsonStringify },
],
},
{
id: 'whitespaceLines',
label: 'Whitespace & Lines',
transforms: [
{ id: 'trimWhiteSpace', label: 'Trim White Space', transform: trimWhiteSpace },
{ id: 'removeLineFeeds', label: 'Remove Line Feeds', transform: removeLineFeeds },
{ id: 'addOneLineFeed', label: 'Add One Line Feed', transform: addOneLineFeed },
{ id: 'addTwoLineFeeds', label: 'Add Two Line Feeds', transform: addTwoLineFeeds },
{
id: 'removeExtraSpaces',
label: 'Remove Extra Spaces',
transform: removeExtraSpaces,
},
{
id: 'sortLinesAlphabetically',
label: 'Sort Lines Alphabetically',
transform: sortLinesAlphabetically,
},
{
id: 'removeDuplicateLines',
label: 'Remove Duplicate Lines',
transform: removeDuplicateLines,
},
{ id: 'addLineNumbers', label: 'Add Line Numbers', transform: addLineNumbers },
],
},
{
id: 'encodingSecurity',
label: 'Encode/Decode',
transforms: [
{ id: 'base64Encode', label: 'Base64 Encode', transform: toBase64Encode },
{ id: 'base64Decode', label: 'Base64 Decode', transform: toBase64Decode },
{ id: 'urlEncode', label: 'URL Encode', transform: toUrlEncode },
{ id: 'urlDecode', label: 'URL Decode', transform: toUrlDecode },
{ id: 'htmlEncode', label: 'HTML Encode', transform: toHtmlEncode },
{ id: 'htmlDecode', label: 'HTML Decode', transform: toHtmlDecode },
],
},
{
id: 'textTools',
label: 'Text Tools',
transforms: [
{ id: 'reverseText', label: 'Reverse Text', transform: reverseText },
{
id: 'addCurrentDateTime',
label: 'Add Current Date/Time',
transform: addCurrentDateTime,
},
{ id: 'countCharacters', label: 'Count Characters', transform: countCharacters },
{ id: 'countWords', label: 'Count Words', transform: countWords },
{ id: 'countLines', label: 'Count Lines', transform: countLines },
{ id: 'countSentences', label: 'Count Sentences', transform: countSentences },
],
},
{
id: 'formatConverter',
label: 'Format Converter',
subcategories: formatConverterSubcategories,
},
]
// Flat list of all transformations for backward compatibility
export const TEXT_TRANSFORMS: TextTransform[] = TRANSFORM_CATEGORIES.flatMap(category => {
if (category.subcategories) {
// For categories with subcategories, flatten all transforms from all subcategories
return category.subcategories.flatMap(subcategory => subcategory.transforms)
} else {
// For categories with direct transforms
return category.transforms || []
}
})
// Helper to get a transform by ID
export const getTransformById = (id: string): TextTransform | undefined =>
TEXT_TRANSFORMS.find(t => t.id === id)
// Helper to get a category by ID
export const getCategoryById = (id: string): TransformCategory | undefined =>
TRANSFORM_CATEGORIES.find(c => c.id === id)
// Helper to apply a transform by ID
export const applyTransform = async (
text: string,
transformId: string
): Promise<string> => {
const transform = getTransformById(transformId)
if (!transform) {
throw new Error(`Transform not found: ${transformId}`)
}
try {
const result = transform.transform(text)
// Handle both sync and async transforms
return await Promise.resolve(result)
} catch (error) {
console.error(`Transform failed for ${transformId}:`, error)
// Re-throw the error so calling functions can handle it
throw error
}
}
// Helper to get all category IDs
export const getAllCategoryIds = (): string[] => TRANSFORM_CATEGORIES.map(c => c.id)
// Helper to get all transform IDs in a category
export const getTransformIdsInCategory = (categoryId: string): string[] => {
const category = getCategoryById(categoryId)
return category ? category.transforms?.map(t => t.id) ?? [] : []
}

View File

@ -1,25 +1,9 @@
import { UniqueIdentifier } from '@dnd-kit/core'
import createBoardTree from '~/libs/create-board-tree'
import { clsx, type ClassValue } from 'clsx'
import { twMerge } from 'tailwind-merge'
import {
currentBoardIndex,
currentNavigationContext,
keyboardSelectedBoardId,
keyboardSelectedClipId,
} from '~/store/signalStore'
import { MenuItem } from '~/types/menu'
// Navigation types and helper functions
interface NavigationItem {
id: UniqueIdentifier
type: 'history' | 'board'
parentId?: UniqueIdentifier | null
depth: number
}
const EMOJIREGEX =
/(\u00a9|\u00ae|[\u2000-\u3300]|\ud83c[\ud000-\udfff]|\ud83d[\ud000-\udfff]|\ud83e[\ud000-\udfff])/gm
@ -70,217 +54,6 @@ export function absoluteUrl(path: string) {
return `${process.env.NEXT_PUBLIC_APP_URL}${path}`
}
// Build a flattened navigation order that includes boards and sub-boards
// Only boards are included in Left/Right navigation - clips are navigated with Up/Down within boards
export function buildNavigationOrder(
clipItems: any[],
currentTab: string
): NavigationItem[] {
const navigationOrder: NavigationItem[] = []
// Add history placeholder - actual history navigation is handled by ClipboardHistoryPage
navigationOrder.push({ id: 'history', type: 'history', depth: 0 })
// Get all boards and clips in the current tab
const allItems = clipItems.filter(item => item.tabId === currentTab)
// Build board tree for proper nesting
const boardTree = createBoardTree(clipItems, currentTab, null)
// Recursively add boards (but not clips - clips are navigated with Up/Down within boards)
function addBoardAndContents(boardId: UniqueIdentifier, depth: number) {
const board = allItems.find(item => item.itemId === boardId && item.isBoard)
if (!board) return
// Add the board itself to navigation order
navigationOrder.push({
id: boardId,
type: 'board',
parentId: board.parentId,
depth,
})
// Get direct child boards (not clips) sorted by order
const childBoards = allItems
.filter(item => item.parentId === boardId && item.isBoard)
.sort((a, b) => a.orderNumber - b.orderNumber)
// Add child boards recursively
childBoards.forEach(child => {
addBoardAndContents(child.itemId, depth + 1)
})
}
// Start with top-level boards
const topLevelBoards = allItems
.filter(item => item.isBoard && item.parentId === null)
.sort((a, b) => a.orderNumber - b.orderNumber)
topLevelBoards.forEach(board => {
addBoardAndContents(board.itemId, 1)
})
return navigationOrder
}
// Find current position in navigation order
export function findCurrentNavigationIndex(navigationOrder: NavigationItem[]): number {
if (currentNavigationContext.value === 'history') {
return 0 // History is always at index 0
} else if (currentNavigationContext.value === 'board') {
if (keyboardSelectedBoardId.value) {
// Find board position - since clips are not in navigation order,
// we find the board that contains the selected clip
return navigationOrder.findIndex(
item => item.type === 'board' && item.id === keyboardSelectedBoardId.value
)
}
}
return 0
}
// Find the next non-empty board in the navigation order (skipping empty boards)
export function findNextNonEmptyBoard(
navigationOrder: NavigationItem[],
startIndex: number,
direction: 'forward' | 'backward',
clipItems: any[],
currentTab: string
): NavigationItem | null {
const maxAttempts = navigationOrder.length // Prevent infinite loops
let currentIndex = startIndex
for (let i = 0; i < maxAttempts; i++) {
// Move in the specified direction
if (direction === 'forward') {
currentIndex = currentIndex + 1
// If we've gone past the end, wrap to history (index 0) or return null for no more boards
if (currentIndex >= navigationOrder.length) {
return null // Let caller handle going back to history
}
} else {
currentIndex = currentIndex - 1
// If we've gone before the beginning, return null for going to history
if (currentIndex < 1) {
// Index 0 is history, so < 1 means we should go to history
return null
}
}
const candidateItem = navigationOrder[currentIndex]
// Skip history item (only boards should be checked)
if (candidateItem.type === 'history') {
continue
}
// Check if this board has actual navigable clips (with non-null itemIds)
const hasNavigableClips = clipItems.some(
clipItem =>
clipItem.isClip &&
clipItem.parentId === candidateItem.id &&
clipItem.tabId === currentTab &&
clipItem.itemId != null // Crucial check: ensure the clip itself is navigable
)
// If board has navigable clips, return it
if (hasNavigableClips) {
return candidateItem
}
}
// If no non-empty board found, return null
return null
}
// Navigate to specific item in the navigation order
export function navigateToItem(
item: NavigationItem,
clipItems: any[],
currentTab: string
) {
if (item.type === 'history') {
currentNavigationContext.value = 'history'
keyboardSelectedBoardId.value = null
keyboardSelectedClipId.value = null
currentBoardIndex.value = 0
// History item selection (e.g., selecting the first history item)
// is typically handled by the calling component (ClipboardHistoryPage)
// when currentNavigationContext.value changes to 'history'.
} else if (item.type === 'board') {
const clipsInBoard = clipItems
.filter(
clipItem =>
clipItem.isClip &&
clipItem.parentId === item.id &&
clipItem.tabId === currentTab
)
.sort((a, b) => a.orderNumber - b.orderNumber)
currentNavigationContext.value = 'board' // We are attempting to navigate to a board context
keyboardSelectedBoardId.value = item.id // Select the target board ID
// Find the first clip in the sorted list that has a valid itemId.
// The 'item' (board) passed to this function should be guaranteed by
// findNextNonEmptyBoard to have at least one such clip.
const firstValidClip = clipsInBoard.find(clip => clip.itemId != null)
if (firstValidClip) {
// Board has at least one navigable clip, select it.
keyboardSelectedClipId.value = firstValidClip.itemId
} else {
// This case should ideally not be reached if findNextNonEmptyBoard works correctly,
// as it implies the board was deemed "non-empty" but no valid clips were found here.
// For safety, ensure no clip is selected. The calling hotkey logic in
// ClipboardHistoryPage (the while loops) will then continue to the next board.
keyboardSelectedClipId.value = null
}
// Update board index (for UI, e.g., highlighting the top-level board tab)
// This logic finds the root parent of the selected board.
const topLevelBoards = clipItems
.filter(
boardItem =>
boardItem.isBoard &&
boardItem.parentId === null &&
boardItem.tabId === currentTab
)
.sort((a, b) => a.orderNumber - b.orderNumber)
const currentBoardData = clipItems.find(boardItem => boardItem.itemId === item.id)
if (currentBoardData) {
let rootParent = currentBoardData
// Traverse up to find the root parent board
while (rootParent.parentId !== null) {
const parentBoard = clipItems.find(
boardItem =>
boardItem.itemId === rootParent.parentId &&
boardItem.isBoard &&
boardItem.tabId === currentTab
)
if (!parentBoard) {
// Parent not found, treat current as root (should ideally not happen with consistent data)
break
}
rootParent = parentBoard
}
currentBoardIndex.value = topLevelBoards.findIndex(
board => board.itemId === rootParent.itemId
)
} else {
// Fallback if currentBoardData is not found (e.g., item.id is invalid)
// This might reset or clear the board index, or default to the first top-level board.
// For now, if the board itself isn't found, the index might become -1 or an existing value.
// Consider if a default (e.g., 0 or -1) is more appropriate if item.id is not a valid board.
const directMatchIndex = topLevelBoards.findIndex(board => board.itemId === item.id)
if (directMatchIndex !== -1) {
currentBoardIndex.value = directMatchIndex
}
// If not a top-level board and data is missing, currentBoardIndex might remain unchanged or be -1.
}
}
}
export const findNewChildrenOrderByParentIdAndDragId = (
items: MenuItem[],
dragId: string,
@ -532,16 +305,19 @@ export function bgColor(
) {
const colorNameToUse = colorName || 'slate'
let darkColorCode: string
if (darkCode) {
darkColorCode = darkCode
} else if (colorCode === '200' && colorNameToUse === 'slate') {
darkColorCode = '700'
} else if (colorNameToUse !== 'slate') {
darkColorCode = '900'
} else {
darkColorCode = '300'
}
const darkColorCode = darkCode
? darkCode
: colorCode === '200' && colorNameToUse === 'slate'
? '700'
: colorNameToUse !== 'slate'
? '900'
: '300'
? '600'
: '400'
? '500'
: '600'
? '700'
: '300'
const type = isBorder ? 'border' : 'bg'

View File

@ -12,9 +12,6 @@ export default function createFilteredFlatBoardTreeWithClips(
const findTabById = (tabId: string | undefined) =>
allTabs.filter(tab => tab.tabId === tabId)
// Pre-compute lowercase search term
const lowerFind = find.toLowerCase()
const findChildrenClips = (parentId: string | null) =>
items
.filter(item => {
@ -22,15 +19,13 @@ export default function createFilteredFlatBoardTreeWithClips(
return false
}
const nameMatches = item.name.toLowerCase().includes(lowerFind)
const nameMatches = item.name.toLowerCase().includes(find.toLowerCase())
const valueMatches =
!isSearchNameOrLabelOnly && item.value?.toLowerCase().includes(lowerFind)
!isSearchNameOrLabelOnly &&
item.value?.toLowerCase().includes(find.toLowerCase())
const descriptionMatches =
!isSearchNameOrLabelOnly && item.description?.toLowerCase().includes(lowerFind)
return nameMatches || valueMatches || descriptionMatches
return nameMatches || valueMatches
})
.map(item => ({ ...item, type: CLIP, id: item.itemId.toString() }))
@ -65,7 +60,7 @@ export default function createFilteredFlatBoardTreeWithClips(
})
.filter(board => board !== null)
: allBoards
.filter(board => board.name.toLowerCase().includes(lowerFind))
.filter(board => board.name.toLowerCase().includes(find.toLowerCase()))
.map(board => {
const children = findAllChildrenClips(board.itemId.toString())
return {

View File

@ -17,9 +17,3 @@ Show collection name on the navbar: Sammlungsnamen in der Navigationsleiste anze
Switch collections: Sammlungen wechseln
You can add the selected text to your clips or menu. Please select the option below.: Sie können den ausgewählten Text zu Ihren Clips oder Menü hinzufügen. Bitte wählen Sie die Option unten.
You need to select a different collection before deleting the current one.: Sie müssen eine andere Sammlung auswählen, bevor Sie die aktuelle löschen.
Choose which collections require PIN entry for access.: Wählen Sie, welche Sammlungen eine PIN-Eingabe erfordern.
Pin Protected Collections: Mit PIN geschützte Sammlungen
Protect Collections with PIN: Sammlungen mit PIN schützen
Protected Collection: Geschützte Sammlung
Select Collections: Sammlungen auswählen
Select protected collections: Geschützte Sammlungen auswählen

View File

@ -55,9 +55,11 @@ Confirm Passcode: Passcode bestätigen
Confirm Password: Passwort bestätigen
Confirm Remove: Entfernen bestätigen
Confirm Your Passcode: Ihren Passcode bestätigen
Confirm Passcode Reset: Passcode-Zurücksetzung bestätigen
Confirm Password Reset: Passwort-Zurücksetzung bestätigen
Confirm passcode reset: Passcode-Zurücksetzung bestätigen
Confirm password reset: Passwort-Zurücksetzung bestätigen
Confirm password reset action: Passwort-Zurücksetzung bestätigen
Confirm your action: Ihre Aktion bestätigen
Confirm {{action}}: '{{action}} bestätigen'
Contact Form: Kontaktformular
Copied: Kopiert
Copy: Kopieren
@ -98,7 +100,6 @@ Enter Passcode: Passcode eingeben
Enter Password: Passwort eingeben
Enter Recovery Password: Wiederherstellungspasswort eingeben
Enter passcode or password to unlock: Passcode oder Passwort zum Entsperren eingeben
Enter PIN to Access Protected Collection: Geben Sie die PIN ein, um auf die geschützte Sammlung zuzugreifen
Error: Fehler
Errors:
Error loading link: Fehler beim Laden des Links
@ -153,6 +154,7 @@ Number of lines: Anzahl der Zeilen
Ok, but later: Ok, aber später
Open: Öffnen
Open Accessibility: Bedienungshilfen öffnen
Open History Window: Verlaufsfenster öffnen
Open Window: Fenster öffnen
Open contact form in browser: Kontaktformular im Browser öffnen
Open payment in browser: Zahlung im Browser öffnen
@ -235,7 +237,7 @@ Show Large View: Große Ansicht anzeigen
Show all: Alle anzeigen
Size: Größe
Source: Quelle
Open History Window: Verlaufsfenster öffnen
Split History Window: Geteiltes Verlaufsfenster
Star: Stern
Star Selected: Ausgewählte markieren
Stay here: Hier bleiben
@ -351,7 +353,3 @@ second: Sekunde
seconds: Sekunden
show less: weniger anzeigen
www.site: www.pastebar.app
Confirm Add To Protected Collections: Hinzufügen zu geschützten Sammlungen bestätigen
Confirm Disable PIN Protection: Deaktivierung des PIN-Schutzes bestätigen
Confirm Remove From Protected Collections: Entfernen aus geschützten Sammlungen bestätigen
Confirm Enable PIN Protection: PIN-Schutz aktivieren bestätigen

View File

@ -1,4 +0,0 @@
Please select your preferred language: Bitte wählen Sie Ihre bevorzugte Sprache aus
Start using PasteBar: Beginnen Sie mit der Nutzung von PasteBar
Submenus will move up one level after delete: Untermenüs werden eine Ebene nach oben verschoben
Welcome to PasteBar: Willkommen bei PasteBar

View File

@ -21,7 +21,8 @@ Add Section: Abschnitt hinzufügen
Add Tab: Tab hinzufügen
Add Template Field: Vorlagenfeld hinzufügen
Add a Tab: Tab hinzufügen
Add field {{name}} into the template: Feld {{name}} zur Vorlage hinzufügen
Add field <b>&#123;&#123;<b>{{name}}</b>&#125;&#125;</b> into the template: Feld <b>&#123;&#123;<b>{{name}}</b>&#125;&#125;</b> zur Vorlage hinzufügen
Add field <b>{{<b>{{name}}</b>}}</b> into the template: Feld <b>{{<b>{{name}}</b>}}</b> zur Vorlage hinzufügen
Add image: Bild hinzufügen
Add note: Notiz hinzufügen
Add to Board: Zum Board hinzufügen
@ -82,7 +83,7 @@ Delete field: Feld löschen
Delete tab: Tab löschen
Detect Template Fields: Vorlagenfelder erkennen
Detect for Template Fields: Nach Vorlagenfeldern suchen
Disabled field {{name}} has been found in the template: Deaktiviertes Feld {{name}} wurde in der Vorlage gefunden
Disabled field <b>&#123;&#123;<b>{{name}}</b>&#125;&#125;</b> has been found in the template: Deaktiviertes Feld <b>&#123;&#123;<b>{{name}}</b>&#125;&#125;</b> wurde in der Vorlage gefunden
Done Create Clip: Clip-Erstellung abgeschlossen
Done Edit: Bearbeitung abgeschlossen
Done Edit Tabs: Tab-Bearbeitung abgeschlossen
@ -134,7 +135,7 @@ FILTERED_TYPES:
RegEx Replace: RegEx Ersetzen
Remove Quotes: Anführungszeichen entfernen
Field: Feld
Field {{name}} has been found in the template: Feld {{name}} wurde in der Vorlage gefunden
Field <b>&#123;&#123;<b>{{name}}</b>&#125;&#125;</b> has been found in the template: Feld <b>&#123;&#123;<b>{{name}}</b>&#125;&#125;</b> wurde in der Vorlage gefunden
Field Options: Feldoptionen
Fields Value: Feldwert
File, folder or app path does not exist: Datei-, Ordner- oder App-Pfad existiert nicht

View File

@ -69,7 +69,7 @@ Tabs and Layout Menu: Tabs und Layout-Menü
Title on Popover: Titel im Popover
Toggle Inactive Menu Items: Inaktive Menüelemente umschalten
Toggle Pinned Board: Angeheftetes Board umschalten
Toggle History Window: Verlaufsfenster umschalten
Toggle Split History Window: Geteiltes Verlaufsfenster umschalten
Tour Completed: Tour abgeschlossen
Tour Skipped: Tour übersprungen
Tour completed: Tour abgeschlossen

View File

@ -10,7 +10,6 @@ Clear History: Verlauf löschen
Confirm Clear All History: Gesamten Verlauf löschen bestätigen
Do you really want to remove ALL clipboard history items?: Möchten Sie wirklich ALLE Zwischenablage-Verlaufselemente entfernen?
Do you want to remove clipboard history items older than {{olderThen}} {{durationType}}: Möchten Sie Zwischenablage-Verlaufselemente älter als {{olderThen}} {{durationType}} entfernen?
Do you want to remove all recent clipboard history older than {{olderThen}} {{durationType}}: Möchten Sie alle kürzlichen Zwischenablage-Verlaufselemente entfernen, die älter als {{olderThen}} {{durationType}} sind?
Enable Capture History: Verlaufserfassung aktivieren
Enable Image Capture: Bilderfassung aktivieren
Filters:

View File

@ -23,7 +23,6 @@ Lock Screen: Bildschirm sperren
Open PasteBar: PasteBar öffnen
Options: Optionen
Player: Player
Show Always on Top: Immer im Vordergrund anzeigen
Show Both Panels: Beide Panels anzeigen
Show Clips Panel Only: Nur Clips-Panel anzeigen
Show Collections Name: Sammlungsnamen anzeigen

View File

@ -87,7 +87,7 @@ Enable screen unlock requirement on app launch for enhanced security, safeguardi
Enter Passcode length: Passcode-Länge eingeben
Enter new directory path or leave empty for default on next revert: Neuen Verzeichnispfad eingeben oder für Standard beim nächsten Zurücksetzen leer lassen
Enter recovery password to reset passcode.: Wiederherstellungspasswort eingeben, um Passcode zurückzusetzen.
Enter your <strong>{{screenLockPassCodeLength}} digits</strong> passcode: Geben Sie Ihren <strong>{{screenLockPassCodeLength}}-stelligen</strong> Passcode ein
Enter your <strong>{{screenLockPassCodeLength}} digits</strong> passcode: Geben Sie Ihren <strong>{{screenLockPassCodeLength}}-stelligen</strong> Passcode ein
Entered Passcode is invalid: Eingegebener Passcode ist ungültig
Excluded Apps List: Liste ausgeschlossener Apps
Execute Web Requests: Web-Anfragen ausführen

View File

@ -15,19 +15,13 @@ Press keys: Tasten drücken
Quick Paste Window: Schnelleinfügen-Fenster
Remove PasteBar app icon from the macOS Dock while keeping the app running in the background. The app remains accessible via the menu bar icon. Requires an app restart to take effect.: PasteBar-App-Symbol aus dem macOS Dock entfernen, während die App im Hintergrund läuft. Die App bleibt über das Menüleistensymbol zugänglich. Erfordert einen App-Neustart, um wirksam zu werden.
Set: Festlegen
Set system OS hotkeys to show/hide the main app window and quick paste window. Supports up to 3-key combinations.: System-Tastenkombinationen zum Anzeigen/Verbergen des Hauptfensters und des Schnelleinfügen-Fensters festlegen. Unterstützt bis zu 3-Tasten-Kombinationen.
'How to set hotkeys:': 'So stellen Sie Hotkeys ein:'
Click Set/Change button to start recording: Klicken Sie auf die Schaltfläche Festlegen/Ändern, um die Aufzeichnung zu starten
Press your desired key combination (e.g., Ctrl+Shift+V): Drücken Sie Ihre gewünschte Tastenkombination (z.B. Ctrl+Shift+V)
Press Enter to confirm or Escape to cancel: Drücken Sie Enter zum Bestätigen oder Escape zum Abbrechen
Press Backspace/Delete to clear the hotkey: Drücken Sie Backspace/Delete, um den Hotkey zu löschen
Press your key combination...: Drücken Sie Ihre Tastenkombination...
Recording...: Aufzeichnen...
Set system OS hotkeys to show/hide the main app window and quick paste window: System-Tastenkombinationen zum Anzeigen/Verbergen des Hauptfensters und des Schnelleinfügen-Fensters festlegen
Show Navbar Items Hover: Navigationsleistenelemente bei Hover anzeigen
Show collections menu on the navbar: Sammlungsmenü in der Navigationsleiste anzeigen
Show navbar elements on hover only: Navigationsleistenelemente nur bei Hover anzeigen
Show/Hide Main App Window: Hauptfenster anzeigen/verbergen
Show/Hide Quick Paste Window: Schnelleinfügen-Fenster anzeigen/verbergen
When enabled, clicking menu items will only copy content to clipboard instead of auto-pasting. This gives you more control over when and where content is pasted.: Wenn aktiviert, wird beim Klicken auf Menüelemente der Inhalt nur in die Zwischenablage kopiert, anstatt automatisch eingefügt zu werden. Dies gibt Ihnen mehr Kontrolle darüber, wann und wo Inhalte eingefügt werden.
Show Note Icons on Clips: Notiz-Symbole auf Clips anzeigen
Display persistent icons on clips that have notes to improve visual organization and make notes easier to discover.: Dauerhafte Symbole auf Clips mit Notizen anzeigen, um die visuelle Organisation zu verbessern und Notizen leichter auffindbar zu machen.
Default Note Icon Type: Standard-Notiz-Symbol-Typ
@ -44,26 +38,3 @@ Show Both Panels: Beide Panels anzeigen
Show History Panel Only: Nur Verlauf-Panel anzeigen
Show Simplified Layout: Vereinfachtes Layout anzeigen
Simplified Panel Layout: Vereinfachtes Panel-Layout
Enable single-click to copy/paste clipboard history items and saved clips instead of requiring double-click.: Einfachklick zum Kopieren/Einfügen von Zwischenablage-Verlauf und gespeicherten Clips aktivieren, anstatt Doppelklick zu erfordern.
Single Click Copy/Paste action: Einfachklick Kopieren/Einfügen-Aktion
Single Click Copy/Paste: Einfachklick Kopieren/Einfügen
Quick Paste Window Options: Schnelleinfügen-Fenster-Optionen
Configure how the system tray icon responds to mouse clicks: Konfigurieren Sie, wie das Systemtray-Symbol auf Mausklicks reagiert
Configure the behavior of the Quick Paste window when selecting items: Konfigurieren Sie das Verhalten des Schnelleinfügen-Fensters beim Auswählen von Elementen
Disable left-click context menu: Linksklick-Kontextmenü deaktivieren
Double-click toggles app visibility: Doppelklick schaltet App-Sichtbarkeit um
Double-clicking the tray icon shows or hides the main application window: Doppelklick auf das Tray-Symbol zeigt oder verbirgt das Hauptanwendungsfenster
Enabling either left-click option will disable the context menu to ensure proper functionality.: Das Aktivieren einer der beiden Linksklick-Optionen deaktiviert das Kontextmenü, um ordnungsgemäße Funktionalität sicherzustellen.
Left-click toggles app visibility: Linksklick schaltet App-Sichtbarkeit um
Left-clicking the tray icon shows or hides the main application window: Linksklick auf das Tray-Symbol zeigt oder verbirgt das Hauptanwendungsfenster
Prevents the context menu from appearing when left-clicking the tray icon: Verhindert, dass das Kontextmenü beim Linksklick auf das Tray-Symbol erscheint
Tray Icon Behavior on Windows: Tray-Symbol-Verhalten unter Windows
Configure which items to preserve when clearing clipboard history (both manual and auto-clear operations).: Konfigurieren Sie, welche Elemente beim Löschen des Zwischenablageverlaufs beibehalten werden sollen (sowohl manuell als auch automatisch).
Keep Items on Clear: Elemente beim Löschen beibehalten
Keep Pinned Items: Angehängte Elemente beibehalten
Keep Starred Items: Mit Stern markierte Elemente beibehalten
Preserve pinned items when clearing history: Angehängte Elemente beim Löschen des Verlaufs beibehalten
Preserve starred items when clearing history: Mit Stern markierte Elemente beim Löschen des Verlaufs beibehalten
History Item Preview Max Lines: Maximale Vorschauzeilenanzahl für Verlaufselemente
Set the maximum number of lines to display in the preview of a history item: Maximale Anzahl der Zeilen für die Vorschau eines Verlaufselements festlegen
Preview Max Lines: Vorschauzeilen

View File

@ -1,73 +0,0 @@
Add Current Date/Time: Aktuelles Datum/Uhrzeit hinzufügen
Add Line Numbers: Zeilennummern hinzufügen
Add One Line Feed: Einen Zeilenvorschub hinzufügen
Add Two Line Feeds: Zwei Zeilenvorschübe hinzufügen
Base64 Decode: Base64 dekodieren
Base64 Encode: Base64 kodieren
CSV: CSV
CSV to JSON: CSV zu JSON
CSV to Markdown Table: CSV zu Markdown-Tabelle
Capitalize Case: Erster Buchstabe groß
Code Formatting: Code-Formatierung
Count Characters: Zeichen zählen
Count Lines: Zeilen zählen
Count Sentences: Sätze zählen
Count Words: Wörter zählen
Data Conversion: Datenkonvertierung
Drag and drop category to prioritize its order in the special copy/paste menu.: Ziehe eine Kategorie per Drag & Drop, um ihre Reihenfolge im speziellen Kopieren/Einfügen-Menü zu priorisieren.
Enable All: Alle aktivieren
Enable special text transformation options for clipboard history items: Spezielle Textumwandlungsoptionen für Zwischenablage-Verlaufselemente aktivieren
Enabled Operations: Aktivierte Operationen
Encode/Decode: Kodieren/Dekodieren
Format Converter: Formatkonverter
HTML: HTML
HTML Decode: HTML dekodieren
HTML Encode: HTML kodieren
HTML to Markdown: HTML zu Markdown
HTML to Plain Text: HTML zu reinem Text
HTML to React Component: HTML zu React-Komponente
HTML to React JSX: HTML zu React JSX
HTML to Text: HTML zu Text
JSON: JSON
JSON Stringify: JSON Stringify
JSON to CSV: JSON zu CSV
JSON to Markdown Table: JSON zu Markdown-Tabelle
JSON to TOML: JSON zu TOML
JSON to XML: JSON zu XML
JSON to YAML: JSON zu YAML
Markdown: Markdown
Markdown to HTML: Markdown zu HTML
Markdown to Text: Markdown zu Text
Operations: Operationen
PascalCase: PascalCase
Prioritize Category Order: Kategorie-Reihenfolge priorisieren
Remove Duplicate Lines: Doppelte Zeilen entfernen
Remove Extra Spaces: Zusätzliche Leerzeichen entfernen
Remove Line Feeds: Zeilenvorschübe entfernen
Reverse Text: Text umkehren
Select Operations: Operationen auswählen
Sentence case: Satzbau
Sort Lines Alphabetically: Zeilen alphabetisch sortieren
Special Copy: Spezielles Kopieren
Special Copy/Paste Operations: Spezielle Kopier-/Einfüge-Operationen
Special Paste: Spezielles Einfügen
Special Settings: Spezielle Einstellungen
TOML: TOML
TOML to JSON: TOML zu JSON
Text Case: Groß-/Kleinschreibung
Text Tools: Textwerkzeuge
Title Case: Titel-Fall
Trim White Space: Leerzeichen entfernen
UPPER CASE: GROSSBUCHSTABEN
URL Decode: URL dekodieren
URL Encode: URL kodieren
Whitespace & Lines: Leerraum & Zeilen
XML: XML
XML to JSON: XML zu JSON
YAML: YAML
YAML to JSON: YAML zu JSON
camelCase: camelCase
iNVERT cASE: gROSS/kLEIN uMKEHREN
kebab-case: kebab-case
lower case: kleinbuchstaben
snake_case: snake_case

View File

@ -1,24 +0,0 @@
Create New Template: Neue Vorlage erstellen
Create Template: Vorlage erstellen
Enter template content...: Vorlageninhalt eingeben...
Enter template name (e.g., "signature", "email"): Vorlagenname eingeben (z.B. "Signatur", "E-Mail")
Global: Global
Global Template: Globale Vorlage
Global Templates: Globale Vorlagen
Preview usage: Verwendung vorschau
Template Usage: Vorlagen-Verwendung
Template name already exists: Vorlagenname existiert bereits. Bitte wählen Sie einen anderen Namen.
Template name cannot be changed after creation. Delete and recreate to change name.: Der Vorlagenname kann nach der Erstellung nicht geändert werden. Löschen und neu erstellen, um den Namen zu ändern.
Use Global Template: Globale Vorlage verwenden
addTemplateButton: Vorlage hinzufügen
confirmDeleteTemplateMessage: "Sind Sie sicher, dass Sie die globale Vorlage '{{name}}' löschen möchten?"
confirmDeleteTemplateTitle: Löschen bestätigen
deleteTemplateButtonTooltip: Vorlage löschen
enableGlobalTemplatesLabel: Globale Vorlagen aktivieren
globalTemplatesDescription: Verwalten Sie wiederverwendbare Textfragmente, die mit {{template_name}} in jeden Clip eingefügt werden können.
globalTemplatesTitle: Globale Vorlagen
localTemplateConflictWarning: "Eine globale Vorlage namens '{{label}}' existiert ebenfalls. Die lokale Vorlage hat Vorrang innerhalb dieses Clip-Formulars."
noGlobalTemplatesYet: Noch keine globalen Vorlagen definiert. Klicken Sie auf 'Vorlage hinzufügen', um eine zu erstellen.
templateEnabledLabel: Aktiviert
templateNameLabel: Name
templateValueLabel: Wert

View File

@ -2,24 +2,17 @@ Add Collection: Add Collection
Add a description for your collection: Add a description for your collection
Add default menu, tab and board: Add default menu, tab and board
Are you sure you want to delete this collection?: Are you sure you want to delete this collection?
Choose which collections require PIN entry for access.: Choose which collections require PIN entry for access.
Collection Options: Collection Options
Collection Title: Collection Title
Collections: Collections
Current Collection: Current Collection
Delete Collection: Delete Collection
Delete all menu items within this collection: Delete all menu items within this collection
? Deleting the collection will remove it permanently. You can also choose to delete all menu and clips items within the collection by checking the box below.
: Deleting the collection will remove it permanently. You can also choose to delete all menu and clips items within the collection by checking the box below.
Deleting the collection will remove it permanently. You can also choose to delete all menu and clips items within the collection by checking the box below.: Deleting the collection will remove it permanently. You can also choose to delete all menu and clips items within the collection by checking the box below.
Description: Description
Display full name of selected collection on the navigation bar: Display full name of selected collection on the navigation bar
Enter collection title: Enter collection title
Manage Collections: Manage Collections
Pin Protected Collections: Pin Protected Collections
Protect Collections with PIN: Protect Collections with PIN
Protected Collection: Protected Collection
Select Collections: Select Collections
Select protected collections: Select protected collections
Show collection name on the navbar: Show collection name on the navbar
Switch collections: Switch collections
You can add the selected text to your clips or menu. Please select the option below.: You can add the selected text to your clips or menu. Please select the option below.

View File

@ -2,8 +2,7 @@
' This permission ensures PasteBar can access the clipboard and perform copy and paste operations across applications.': ' This permission ensures PasteBar can access the clipboard and perform copy and paste operations across applications.'
About PasteBar: About PasteBar
Action Menu: Action Menu
? Add <b>{{Clipboard}}</b> field to template. This allows you to copy text to the clipboard, and it will be inserted into the template
: Add <b>{{Clipboard}}</b> field to template. This allows you to copy text to the clipboard, and it will be inserted into the template
Add <b>{{Clipboard}}</b> field to template. This allows you to copy text to the clipboard, and it will be inserted into the template: Add <b>{{Clipboard}}</b> field to template. This allows you to copy text to the clipboard, and it will be inserted into the template
Add Clip: Add Clip
Add First Option: Add First Option
Add Link Card: Add Link Card
@ -24,6 +23,7 @@ Are you sure you want to delete?: Are you sure you want to delete?
Are you sure?: Are you sure?
Attach History Window: Attach History Window
Back: Back
Browse...: Browse...
Build on {{buildDate}}: Build on {{buildDate}}
Cancel: Cancel
Cancel Reset: Cancel Reset
@ -55,12 +55,11 @@ Confirm Passcode: Confirm Passcode
Confirm Password: Confirm Password
Confirm Remove: Confirm Remove
Confirm Your Passcode: Confirm Your Passcode
Confirm Passcode Reset: Confirm Passcode Reset
Confirm Password Reset: Confirm Password Reset
Confirm Add To Protected Collections: Confirm add to protected collections
Confirm Disable PIN Protection: Confirm disable PIN protection
Confirm Remove From Protected Collections: Confirm remove from protected collections
Confirm Enable PIN Protection: Confirm enable PIN protection
Confirm passcode reset: Confirm passcode reset
Confirm password reset: Confirm password reset
Confirm password reset action: Confirm password reset action
Confirm your action: Confirm your action
Confirm {{action}}: Confirm {{action}}
Contact Form: Contact Form
Copied: Copied
Copy: Copy
@ -97,7 +96,6 @@ Enabled: Enabled
Enter Current Passcode: Enter Current Passcode
Enter Digits Only Passcode: Enter Digits Only Passcode
Enter Email: Enter Email
Enter PIN to Access Protected Collection: Enter PIN to Access Protected Collection
Enter Passcode: Enter Passcode
Enter Password: Enter Password
Enter Recovery Password: Enter Recovery Password
@ -109,8 +107,7 @@ Errors:
Something went wrong! {{err}} Please try again.: Something went wrong! {{err}} Please try again.
Expand Edit: Expand Edit
Expires on {{proExpiresOn}}: Expires on {{proExpiresOn}}
? Field <b>{{Clipboard}}</b> has been found in the template. This allows you to copy text to the clipboard, and it will be inserted into the template
: Field <b>{{Clipboard}}</b> has been found in the template. This allows you to copy text to the clipboard, and it will be inserted into the template
Field <b>{{Clipboard}}</b> has been found in the template. This allows you to copy text to the clipboard, and it will be inserted into the template: Field <b>{{Clipboard}}</b> has been found in the template. This allows you to copy text to the clipboard, and it will be inserted into the template
Field is not found in the template: Field is not found in the template
Find Clip: Find Clip
Find History: Find History
@ -175,8 +172,7 @@ Pasted: Pasted
Path: Path
Pause: Pause
Pause Playing: Pause Playing
? 'Permission Check Failed: PasteBar has not been successfully added to Accessibility settings. Please grant the required permissions and click Done again.'
: 'Permission Check Failed: PasteBar has not been successfully added to Accessibility settings. Please grant the required permissions and click Done again.'
'Permission Check Failed: PasteBar has not been successfully added to Accessibility settings. Please grant the required permissions and click Done again.': 'Permission Check Failed: PasteBar has not been successfully added to Accessibility settings. Please grant the required permissions and click Done again.'
Pin Selected: Pin Selected
Pinned: Pinned
Play: Play
@ -241,6 +237,7 @@ Show Large View: Show Large View
Show all: Show all
Size: Size
Source: Source
Split History Window: Split History Window
Star: Star
Star Selected: Star Selected
Stay here: Stay here
@ -341,8 +338,7 @@ View Edit: View Edit
Views:
Paste Menu: Paste Menu
We apologize but you found a bug. Please report this issue to us and try again: We apologize but you found a bug. Please report this issue to us and try again
? We couldn't confirm this file's safety. Failed ID3 tag verification and integrity check. MP3 files can potentially contain malware. Please be cautious.
: We couldn't confirm this file's safety. Failed ID3 tag verification and integrity check. MP3 files can potentially contain malware. Please be cautious.
We couldn't confirm this file's safety. Failed ID3 tag verification and integrity check. MP3 files can potentially contain malware. Please be cautious.: We couldn't confirm this file's safety. Failed ID3 tag verification and integrity check. MP3 files can potentially contain malware. Please be cautious.
Yes: Yes
Yes, activate: Yes, activate
chars: chars

View File

@ -1,4 +0,0 @@
Please select your preferred language: Please select your preferred language
Start using PasteBar: Start using PasteBar
Submenus will move up one level after delete: Submenus will move up one level after delete
Welcome to PasteBar: Welcome to PasteBar

View File

@ -21,7 +21,8 @@ Add Section: Add Section
Add Tab: Add Tab
Add Template Field: Add Template Field
Add a Tab: Add a Tab
Add field {{name}} into the template: Add field {{name}} into the template
Add field <b>&#123;&#123;<b>{{name}}</b>&#125;&#125;</b> into the template: Add field <b>&#123;&#123;<b>{{name}}</b>&#125;&#125;</b> into the template
Add field <b>{{<b>{{name}}</b>}}</b> into the template: Add field <b>{{<b>{{name}}</b>}}</b> into the template
Add image: Add image
Add note: Add note
Add to Board: Add to Board
@ -82,7 +83,7 @@ Delete field: Delete field
Delete tab: Delete tab
Detect Template Fields: Detect Template Fields
Detect for Template Fields: Detect for Template Fields
Disabled field {{name}} has been found in the template: Disabled field {{name}} has been found in the template
Disabled field <b>&#123;&#123;<b>{{name}}</b>&#125;&#125;</b> has been found in the template: Disabled field <b>&#123;&#123;<b>{{name}}</b>&#125;&#125;</b> has been found in the template
Done Create Clip: Done Create Clip
Done Edit: Done Edit
Done Edit Tabs: Done Edit Tabs
@ -134,8 +135,8 @@ FILTERED_TYPES:
RegEx Replace: RegEx Replace
Remove Quotes: Remove Quotes
Field: Field
Field <b>&#123;&#123;<b>{{name}}</b>&#125;&#125;</b> has been found in the template: Field <b>&#123;&#123;<b>{{name}}</b>&#125;&#125;</b> has been found in the template
Field Options: Field Options
Field {{name}} has been found in the template: Field {{name}} has been found in the template
Fields Value: Fields Value
File, folder or app path does not exist: File, folder or app path does not exist
File, folder or app path is valid: File, folder or app path is valid
@ -146,10 +147,8 @@ Filter's Value: Filter's Value
Find in Clip: Find in Clip
Find in clip: Find in clip
Find in history: Find in history
Flex Layout: Flex Layout
Form Fields: Form Fields
General Fields: General Fields
Grid Layout: Grid Layout
HTML: HTML
Headers: Headers
Hide Label: Hide Label

View File

@ -69,7 +69,7 @@ Tabs and Layout Menu: Tabs and Layout Menu
Title on Popover: Title on Popover
Toggle Inactive Menu Items: Toggle Inactive Menu Items
Toggle Pinned Board: Toggle Pinned Board
Toggle History Window: Toggle History Window
Toggle Split History Window: Toggle Split History Window
Tour Completed: Tour Completed
Tour Skipped: Tour Skipped
Tour completed: Tour completed

View File

@ -9,7 +9,6 @@ Clear All History: Clear All History
Clear History: Clear History
Confirm Clear All History: Confirm Clear All History
Do you really want to remove ALL clipboard history items?: Do you really want to remove ALL clipboard history items?
Do you want to remove all recent clipboard history older than {{olderThen}} {{durationType}}: Do you want to remove all recent clipboard history older than {{olderThen}} {{durationType}}
Do you want to remove clipboard history items older than {{olderThen}} {{durationType}}: Do you want to remove clipboard history items older than {{olderThen}} {{durationType}}
Enable Capture History: Enable Capture History
Enable Image Capture: Enable Image Capture

View File

@ -23,7 +23,6 @@ Lock Screen: Lock Screen
Open PasteBar: Open PasteBar
Options: Options
Player: Player
Show Always on Top: Show Always on Top
Show Both Panels: Show Both Panels
Show Clips Panel Only: Show Clips Panel Only
Show Collections Name: Show Collections Name

View File

@ -1,61 +1,30 @@
App restart required: Restart required
Application Starts with Main Window Hidden: Application Starts with Main Window Hidden
Auto-close window after action: Auto-close window after action
Boards, saved clips and menu items panel visible: Boards, saved clips and menu items panel visible
Both clipboard history and saved clips panels visible: Both clipboard history and saved clips panels visible
Change: Change
Click Set/Change button to start recording: Click Set/Change button to start recording
Clipboard history panel visible: Clipboard history panel visible
Configure how the system tray icon responds to mouse clicks: Configure how the system tray icon responds to mouse clicks
Configure the behavior of the Quick Paste window when selecting items: Configure the behavior of the Quick Paste window when selecting items
Configure which items to preserve when clearing clipboard history (both manual and auto-clear operations).: Configure which items to preserve when clearing clipboard history (both manual and auto-clear operations).
Control which panels are visible in the main window: Control which panels are visible in the main window
Copy items only (no auto-paste): Copy items only (no auto-paste)
Copy only from menu items: Copy only from menu items
Default Note Icon Type: Default Note Icon Type
Disable left-click context menu: Disable left-click context menu
Display navbar items only when the mouse hovers over the navigation bar to minimize visible UI elements: Display navbar items only when the mouse hovers over the navigation bar to minimize visible UI elements
Display persistent icons on clips that have notes to improve visual organization and make notes easier to discover.: Display persistent icons on clips that have notes to improve visual organization and make notes easier to discover.
Double-click toggles app visibility: Double-click toggles app visibility
Double-clicking the tray icon shows or hides the main application window: Double-clicking the tray icon shows or hides the main application window
Enable simplified, less boxy layout for a cleaner and more streamlined interface design: Enable simplified, less boxy layout for a cleaner and more streamlined interface design
Enable single-click to copy/paste clipboard history items and saved clips instead of requiring double-click.: Enable single-click to copy/paste clipboard history items and saved clips instead of requiring double-click.
Enabling either left-click option will disable the context menu to ensure proper functionality.: Enabling either left-click option will disable the context menu to ensure proper functionality.
Global System OS Hotkeys: Global System OS Hotkeys
Hide Collections Navbar: Hide Collections Navbar
Hide collections menu dropdown on the navigation bar: Hide collections menu dropdown on the navigation bar
Hide collections menu on the navbar: Hide collections menu on the navbar
Hide the App Dock Icon: Hide the App Dock Icon
History Item Preview Max Lines: History Item Preview Max Lines
'How to set hotkeys:': 'How to set hotkeys:'
Keep Items on Clear: Keep Items on Clear
Keep Pinned Items: Keep Pinned Items
Keep Starred Items: Keep Starred Items
? Keep the main application window hidden when the app restarts. You can reopen it using the menu bar or taskbar menu, or using global hotkeys.
: Keep the main application window hidden when the app restarts. You can reopen it using the menu bar or taskbar menu, or using global hotkeys.
Left-click toggles app visibility: Left-click toggles app visibility
Left-clicking the tray icon shows or hides the main application window: Left-clicking the tray icon shows or hides the main application window
Keep the main application window hidden when the app restarts. You can reopen it using the menu bar or taskbar menu, or using global hotkeys.: Keep the main application window hidden when the app restarts. You can reopen it using the menu bar or taskbar menu, or using global hotkeys.
No keys set: No keys set
'Note: At least one panel must remain visible in main window.': 'Note: At least one panel must remain visible in main window.'
Panel Visibility: Panel Visibility
PasteBar Quick Paste: PasteBar Quick Paste
Preserve pinned items when clearing history: Preserve pinned items when clearing history
Preserve starred items when clearing history: Preserve starred items when clearing history
Press Backspace/Delete to clear the hotkey: Press Backspace/Delete to clear the hotkey
Press Enter to confirm or Escape to cancel: Press Enter to confirm or Escape to cancel
Press keys: Press keys
Press your desired key combination (e.g., Ctrl+Shift+V): Press your desired key combination (e.g., Ctrl+Shift+V)
Press your key combination...: Press your key combination...
Prevents the context menu from appearing when left-clicking the tray icon: Prevents the context menu from appearing when left-clicking the tray icon
Preview Max Lines: Preview Max Lines
Quick Paste Window: Quick Paste Window
Quick Paste Window Options: Quick Paste Window Options
Recording...: Recording...
? Remove PasteBar app icon from the macOS Dock while keeping the app running in the background. The app remains accessible via the menu bar icon. Requires an app restart to take effect.
: Remove PasteBar app icon from the macOS Dock while keeping the app running in the background. The app remains accessible via the menu bar icon. Requires an app restart to take effect.
Remove PasteBar app icon from the macOS Dock while keeping the app running in the background. The app remains accessible via the menu bar icon. Requires an app restart to take effect.: Remove PasteBar app icon from the macOS Dock while keeping the app running in the background. The app remains accessible via the menu bar icon. Requires an app restart to take effect.
Set: Set
Set system OS hotkeys to show/hide the main app window and quick paste window. Supports up to 3-key combinations.: Set system OS hotkeys to show/hide the main app window and quick paste window. Supports up to 3-key combinations.
Set the maximum number of lines to display in the preview of a history item: Set the maximum number of lines to display in the preview of a history item
Set system OS hotkeys to show/hide the main app window and quick paste window: Set system OS hotkeys to show/hide the main app window and quick paste window
Show Boards and Clips Panel Only: Show Boards and Clips Panel Only
Show Both Panels: Show Both Panels
Show History Panel Only: Show History Panel Only
@ -67,14 +36,5 @@ Show navbar elements on hover only: Show navbar elements on hover only
Show/Hide Main App Window: Show/Hide Main App Window
Show/Hide Quick Paste Window: Show/Hide Quick Paste Window
Simplified Panel Layout: Simplified Panel Layout
Single Click Copy/Paste: Single Click Copy/Paste
Single Click Copy/Paste action: Single Click Copy/Paste action
This sets the default icon type for new clips with notes. You can customize individual clips via the context menu.: This sets the default icon type for new clips with notes. You can customize individual clips via the context menu.
Tray Icon Behavior on Windows: Tray Icon Behavior on Windows
? When enabled, clicking menu items will only copy content to clipboard instead of auto-pasting. This gives you more control over when and where content is pasted.
: When enabled, clicking menu items will only copy content to clipboard instead of auto-pasting. This gives you more control over when and where content is pasted.
? When enabled, clicking or pressing Enter on items in Quick Paste window will only copy them to clipboard without automatically pasting.
: When enabled, clicking or pressing Enter on items in Quick Paste window will only copy them to clipboard without automatically pasting.
? When enabled, single click will copy/paste items in Quick Paste window. If global single click is also enabled, both settings work together.
: When enabled, single click will copy/paste items in Quick Paste window. If global single click is also enabled, both settings work together.
When enabled, the Quick Paste window will automatically close after copying or pasting an item.: When enabled, the Quick Paste window will automatically close after copying or pasting an item.
When enabled, clicking menu items will only copy content to clipboard instead of auto-pasting. This gives you more control over when and where content is pasted.: When enabled, clicking menu items will only copy content to clipboard instead of auto-pasting. This gives you more control over when and where content is pasted.

View File

@ -1 +0,0 @@
Special Settings: Special Settings

View File

@ -1,74 +0,0 @@
Add Current Date/Time: Add Current Date/Time
Add Line Numbers: Add Line Numbers
Add One Line Feed: Add One Line Feed
Add Two Line Feeds: Add Two Line Feeds
Base64 Decode: Base64 Decode
Base64 Encode: Base64 Encode
CSV: CSV
CSV to JSON: CSV to JSON
CSV to Markdown Table: CSV to Markdown Table
Capitalize Case: Capitalize Case
Code Formatting: Code Formatting
Count Characters: Count Characters
Count Lines: Count Lines
Count Sentences: Count Sentences
Count Words: Count Words
Data Conversion: Data Conversion
Drag and drop category to prioritize its order in the special copy/paste menu.: Drag and drop category to prioritize its order in the special copy/paste menu.
Enable All: Enable All
Enable special text transformation options for clipboard history items: Enable special text transformation options for clipboard history items
Enabled Operations: Enabled Operations
Encode/Decode: Encode/Decode
Format Converter: Format Converter
HTML: HTML
HTML Decode: HTML Decode
HTML Encode: HTML Encode
HTML to Markdown: HTML to Markdown
HTML to Plain Text: HTML to Plain Text
HTML to React Component: HTML to React Component
HTML to React JSX: HTML to React JSX
HTML to Text: HTML to Text
JSON: JSON
JSON Stringify: JSON Stringify
JSON to CSV: JSON to CSV
JSON to Markdown Table: JSON to Markdown Table
JSON to TOML: JSON to TOML
JSON to XML: JSON to XML
JSON to YAML: JSON to YAML
Markdown: Markdown
Markdown to HTML: Markdown to HTML
Markdown to Text: Markdown to Text
Operations: Operations
PascalCase: PascalCase
Prioritize Category Order: Prioritize Category Order
PrioritizeCategoryOrderNote: PrioritizeCategoryOrderNote
Remove Duplicate Lines: Remove Duplicate Lines
Remove Extra Spaces: Remove Extra Spaces
Remove Line Feeds: Remove Line Feeds
Reverse Text: Reverse Text
Select Operations: Select Operations
Sentence case: Sentence case
Sort Lines Alphabetically: Sort Lines Alphabetically
Special Copy: Special Copy
Special Copy/Paste Operations: Special Copy/Paste Operations
Special Paste: Special Paste
Special Settings: Special Settings
TOML: TOML
TOML to JSON: TOML to JSON
Text Case: Text Case
Text Tools: Text Tools
Title Case: Title Case
Trim White Space: Trim White Space
UPPER CASE: UPPER CASE
URL Decode: URL Decode
URL Encode: URL Encode
Whitespace & Lines: Whitespace & Lines
XML: XML
XML to JSON: XML to JSON
YAML: YAML
YAML to JSON: YAML to JSON
camelCase: camelCase
iNVERT cASE: iNVERT cASE
kebab-case: kebab-case
lower case: lower case
snake_case: snake_case

View File

@ -1,24 +0,0 @@
Create New Template: Create New Template
Create Template: Create Template
Enter template content...: Enter template content...
Enter template name (e.g., "signature", "email"): Enter template name (e.g., "signature", "email")
Global: Global
Global Template: Global Template
Global Templates: Global Templates
Preview usage: Preview usage
Template Usage: Template Usage
Template name already exists: Template name already exists. Please choose a different name.
Template name cannot be changed after creation. Delete and recreate to change name.: Template name cannot be changed after creation. Delete and recreate to change name.
Use Global Template: Use Global Template
addTemplateButton: Add Template
confirmDeleteTemplateMessage: Are you sure you want to delete the global template '{{name}}'?
confirmDeleteTemplateTitle: Confirm Delete
deleteTemplateButtonTooltip: Delete Template
enableGlobalTemplatesLabel: Enable Global Templates
globalTemplatesDescription: Manage reusable text snippets that can be inserted into any clip using {{template_name}}.
globalTemplatesTitle: Global Templates
localTemplateConflictWarning: A global template named '{{label}}' also exists. The local template will take precedence within this clip's form.
noGlobalTemplatesYet: No global templates defined yet. Click 'Add Template' to create one.
templateEnabledLabel: Enabled
templateNameLabel: Name
templateValueLabel: Value

View File

@ -179,7 +179,7 @@ NAVBAR_TOUR:
prefferedSide: bottom
- element: '#navbar-toggle-history-split'
popover:
title: Toggle History Window
title: Toggle Split History Window
description: Click this icon to open or close the clipboard history in a separate window. Use this feature to manage your clipboard history independently from the main window.
alignment: center
preferredSide: bottom

View File

@ -17,9 +17,3 @@ Show collection name on the navbar: Mostrar el nombre de la colección en la bar
Switch collections: Cambiar colecciones
You can add the selected text to your clips or menu. Please select the option below.: Puedes añadir el texto seleccionado a tus clips o menú. Por favor, selecciona la opción de abajo.
You need to select a different collection before deleting the current one.: Necesitas seleccionar una colección diferente antes de eliminar la actual.
Choose which collections require PIN entry for access.: Elige qué colecciones requieren entrada de PIN para acceder.
Pin Protected Collections: Colecciones protegidas con PIN
Protect Collections with PIN: Proteger colecciones con PIN
Protected Collection: Colección protegida
Select Collections: Seleccionar colecciones
Select protected collections: Seleccionar colecciones protegidas

View File

@ -54,8 +54,9 @@ Confirm Passcode: Confirmar Código de Acceso
Confirm Password: Confirmar Contraseña
Confirm Remove: Confirmar Eliminación
Confirm Your Passcode: Confirma tu Código de Acceso
Confirm Passcode Reset: Confirmar reinicio del código de acceso
Confirm Password Reset: Confirmar reinicio de contraseña
Confirm passcode reset: Confirmar reinicio del código de acceso
Confirm password reset: Confirmar reinicio de contraseña
Confirm password reset action: Confirmar acción de reinicio de contraseña
Confirm your action: Confirma tu acción
Confirm {{action}}: Confirmar {{action}}
Contact Form: Formulario de Contacto
@ -98,7 +99,6 @@ Enter Passcode: Introduce el Código de Acceso
Enter Password: Introduce la Contraseña
Enter Recovery Password: Introduce la Contraseña de Recuperación
Enter passcode or password to unlock: Introduce el código de acceso o la contraseña para desbloquear
Enter PIN to Access Protected Collection: Introduce el PIN para acceder a la colección protegida
Errors:
Error loading link: Error al cargar el enlace
Cant save to file: No se puede guardar en el archivo
@ -152,6 +152,7 @@ Number of lines: Número de líneas
Ok, but later: De acuerdo, pero más tarde
Open: Abrir
Open Accessibility: Abrir Accesibilidad
Open History Window: Abrir Ventana de Historial
Open Window: Abrir Ventana
Open contact form in browser: Abrir formulario de contacto en el navegador
Open payment in browser: Abrir pago en el navegador
@ -233,7 +234,7 @@ Set Password: Establecer Contraseña
Show Large View: Mostrar Vista Grande
Show all: Mostrar todo
Source: Fuente
Open History Window: Abrir Ventana de Historial
Split History Window: Dividir Ventana de Historial
Star: Destacar
Star Selected: Destacar Seleccionados
Stay here: Quedarse aquí
@ -350,7 +351,3 @@ seconds: segundos
show less: mostrar menos
www.site: www.pastebar.app
Size: Tamaño
Confirm Add To Protected Collections: Confirmar agregar a colecciones protegidas
Confirm Disable PIN Protection: Confirmar deshabilitar protección con PIN
Confirm Remove From Protected Collections: Confirmar eliminar de colecciones protegidas
Confirm Enable PIN Protection: Confirmar habilitar protección con PIN

View File

@ -1,4 +0,0 @@
Please select your preferred language: Por favor seleccione su idioma preferido
Start using PasteBar: Comience a usar PasteBar
Submenus will move up one level after delete: Los submenús subirán un nivel tras eliminar
Welcome to PasteBar: Bienvenido a PasteBar

View File

@ -21,7 +21,8 @@ Add Section: Añadir Sección
Add Tab: Añadir Pestaña
Add Template Field: Añadir Campo de Plantilla
Add a Tab: Añadir una Pestaña
Add field {{name}} into the template: Añadir campo {{name}} a la plantilla
Add field <b>&#123;&#123;<b>{{name}}</b>&#125;&#125;</b> into the template: Añadir campo <b>&#123;&#123;<b>{{name}}</b>&#125;&#125;</b> a la plantilla
Add field <b>{{<b>{{name}}</b>}}</b> into the template: Añadir campo <b>{{<b>{{name}}</b>}}</b> a la plantilla
Add image: Añadir imagen
Add note: Añadir nota
Add to Board: Añadir al Tablero
@ -82,7 +83,7 @@ Delete field: Eliminar campo
Delete tab: Eliminar pestaña
Detect Template Fields: Detectar Campos de Plantilla
Detect for Template Fields: Detectar Campos de Plantilla
Disabled field {{name}} has been found in the template: Se ha encontrado el campo deshabilitado {{name}} en la plantilla
Disabled field <b>&#123;&#123;<b>{{name}}</b>&#125;&#125;</b> has been found in the template: Se ha encontrado el campo deshabilitado <b>&#123;&#123;<b>{{name}}</b>&#125;&#125;</b> en la plantilla
Done Create Clip: Clip Creado
Done Edit: Edición Completada
Done Edit Tabs: Edición de Pestañas Completada
@ -134,7 +135,7 @@ FILTERED_TYPES:
RegEx Replace: Reemplazo RegEx
Remove Quotes: Eliminar Comillas
Field: Campo
Field {{name}} has been found in the template: Se ha encontrado el campo {{name}} en la plantilla
Field <b>&#123;&#123;<b>{{name}}</b>&#125;&#125;</b> has been found in the template: Se ha encontrado el campo <b>&#123;&#123;<b>{{name}}</b>&#125;&#125;</b> en la plantilla
Field Options: Opciones de Campo
Fields Value: Valor de Campos
File, folder or app path does not exist: La ruta del archivo, carpeta o aplicación no existe

View File

@ -69,7 +69,7 @@ Tabs and Layout Menu: Menú de Pestañas y Diseño
Title on Popover: Título en Ventana Emergente
Toggle Inactive Menu Items: Alternar Elementos Inactivos
Toggle Pinned Board: Alternar Tablero Fijado
Toggle History Window: Alternar Ventana de Historial
Toggle Split History Window: Alternar Ventana de Historial
Tour Completed: Tour Completado
Tour Skipped: Tour Omitido
Tour completed: Tour completado

View File

@ -10,7 +10,6 @@ Clear History: Borrar Historial
Confirm Clear All History: Confirmar Borrar Todo el Historial
Do you really want to remove ALL clipboard history items?: ¿Realmente quieres eliminar TODOS los elementos del historial?
Do you want to remove clipboard history items older than {{olderThen}} {{durationType}}: ¿Quieres eliminar los elementos del historial más antiguos que {{olderThen}} {{durationType}}?
Do you want to remove all recent clipboard history older than {{olderThen}} {{durationType}}: ¿Quieres eliminar todos los elementos recientes del historial del portapapeles anteriores a {{olderThen}} {{durationType}}?
Enable Capture History: Habilitar Captura de Historial
Enable Image Capture: Habilitar Captura de Imágenes
Filters:

View File

@ -23,7 +23,6 @@ Lock Screen: Bloquear Pantalla
Open PasteBar: Abrir PasteBar
Options: Opciones
Player: Reproductor
Show Always on Top: Mostrar siempre en primer plano
Show Both Panels: Mostrar Ambos Paneles
Show Clips Panel Only: Mostrar Solo Panel de Clips
Show Collections Name: Mostrar Nombre de Colecciones

View File

@ -64,7 +64,7 @@ Enable screen unlock requirement on app launch for enhanced security, safeguardi
Enhance security by automatically locking the application screen after a set period of user inactivity.: Mejora la seguridad bloqueando automáticamente la pantalla de la aplicación después de un período de inactividad del usuario.
Enter Passcode length: Ingresa la longitud del código de acceso
Enter recovery password to reset passcode.: Ingresa la contraseña de recuperación para restablecer el código de acceso.
Enter your <strong>{{screenLockPassCodeLength}} digits</strong> passcode: Ingresa tu código de <strong>{{screenLockPassCodeLength}} dígitos</strong>
Enter your <strong>{{screenLockPassCodeLength}} digits</strong> passcode: Ingresa tu código de <strong>{{screenLockPassCodeLength}} dígitos</strong>
Entered Passcode is invalid: El código de acceso ingresado no es válido
Excluded Apps List: Lista de Apps Excluidas
Execute Web Requests: Ejecutar Solicitudes Web

View File

@ -14,23 +14,18 @@ PasteBar Quick Paste: Pegado rápido PasteBar
Press keys: Presiona las teclas
Remove PasteBar app icon from the macOS Dock while keeping the app running in the background. The app remains accessible via the menu bar icon. Requires an app restart to take effect.: Eliminar el icono de PasteBar del Dock de macOS mientras mantiene la aplicación ejecutándose en segundo plano. La aplicación permanece accesible a través del icono de la barra de menú. Requiere reiniciar la aplicación para que tenga efecto.
Set: Establecer
Set system OS hotkeys to show/hide the main app window and quick paste window. Supports up to 3-key combinations.: Establecer atajos de teclado del sistema para mostrar/ocultar la ventana principal y la ventana de pegado rápido. Admite hasta combinaciones de 3 teclas.
'How to set hotkeys:': 'Cómo establecer atajos de teclado:'
Click Set/Change button to start recording: Haz clic en el botón Establecer/Cambiar para comenzar a grabar
Press your desired key combination (e.g., Ctrl+Shift+V): Presiona tu combinación de teclas deseada (ej. Ctrl+Shift+V)
Press Enter to confirm or Escape to cancel: Presiona Enter para confirmar o Escape para cancelar
Press Backspace/Delete to clear the hotkey: Presiona Backspace/Delete para borrar el atajo de teclado
Press your key combination...: Presiona tu combinación de teclas...
Recording...: Grabando...
Set system OS hotkeys to show/hide the main app window and quick paste window: Establecer atajos de teclado del sistema para mostrar/ocultar la ventana principal y la ventana de pegado rápido
Show Navbar Items Hover: Mostrar elementos de barra al pasar el ratón
Show collections menu on the navbar: Mostrar menú de colecciones en la barra de navegación
Show navbar elements on hover only: Mostrar elementos de la barra solo al pasar el ratón
Show/Hide Main App Window: Mostrar/Ocultar ventana principal
Show/Hide Quick Paste Window: Mostrar/Ocultar ventana de pegado rápido
When enabled, clicking menu items will only copy content to clipboard instead of auto-pasting. This gives you more control over when and where content is pasted.: Cuando está habilitado, hacer clic en elementos del menú solo copiará el contenido al portapapeles en lugar de pegarlo automáticamente. Esto te da más control sobre cuándo y dónde se pega el contenido.
Quick Paste Window: Ventana de pegado rápido
Show Note Icons on Clips: Mostrar iconos de notas en clips
Display persistent icons on clips that have notes to improve visual organization and make notes easier to discover.: Mostrar iconos persistentes en clips que tienen notas para mejorar la organización visual y hacer que las notas sean más fáciles de descubrir.
Default Note Icon Type: Tipo de icono de nota predeterminado
This sets the default icon type for new clips with notes. You can customize individual clips via the context menu.: Esto establece el tipo de icono predeterminado para nuevos clips con notas. Puedes personalizar clips individuales a través del menú contextual.
Boards, saved clips and menu items panel visible: Panel de tableros, clips guardados y elementos de menú visible
Both clipboard history and saved clips panels visible: Ambos paneles de historial del portapapeles y clips guardados visibles
Clipboard history panel visible: Panel de historial del portapapeles visible
@ -43,33 +38,3 @@ Show Both Panels: Mostrar ambos paneles
Show History Panel Only: Mostrar solo panel de historial
Show Simplified Layout: Mostrar diseño simplificado
Simplified Panel Layout: Diseño de panel simplificado
Enable single-click to copy/paste clipboard history items and saved clips instead of requiring double-click.: Habilitar clic simple para copiar/pegar elementos del historial del portapapeles y clips guardados en lugar de requerir doble clic.
Single Click Copy/Paste action: Acción de clic simple Copiar/Pegar
Single Click Copy/Paste: Clic simple Copiar/Pegar
Quick Paste Window Options: Opciones de la ventana de pegado rápido
Configure the behavior of the Quick Paste window when selecting items: Configurar el comportamiento de la ventana de pegado rápido al seleccionar elementos
Configure how the system tray icon responds to mouse clicks: Configurar cómo responde el icono de la bandeja del sistema a los clics del ratón
Disable left-click context menu: Deshabilitar menú contextual del clic izquierdo
Double-click toggles app visibility: El doble clic alterna la visibilidad de la aplicación
Double-clicking the tray icon shows or hides the main application window: Hacer doble clic en el icono de la bandeja muestra u oculta la ventana principal de la aplicación
Enabling either left-click option will disable the context menu to ensure proper functionality.: Habilitar cualquiera de las opciones de clic izquierdo deshabilitará el menú contextual para asegurar el funcionamiento adecuado.
Left-click toggles app visibility: El clic izquierdo alterna la visibilidad de la aplicación
Left-clicking the tray icon shows or hides the main application window: Hacer clic izquierdo en el icono de la bandeja muestra u oculta la ventana principal de la aplicación
Prevents the context menu from appearing when left-clicking the tray icon: Previene que aparezca el menú contextual al hacer clic izquierdo en el icono de la bandeja
Tray Icon Behavior on Windows: Comportamiento del icono de la bandeja en Windows
This sets the default icon type for new clips with notes. You can customize individual clips via the context menu.: Esto establece el tipo de icono predeterminado para nuevos clips con notas. Puedes personalizar clips individuales a través del menú contextual.
? When enabled, clicking menu items will only copy content to clipboard instead of auto-pasting. This gives you more control over when and where content is pasted.
: Cuando está habilitado, hacer clic en elementos del menú solo copiará el contenido al portapapeles en lugar de pegarlo automáticamente. Esto te da más control sobre cuándo y dónde se pega el contenido.
? When enabled, clicking or pressing Enter on items in Quick Paste window will only copy them to clipboard without automatically pasting.
: Cuando está habilitado, hacer clic o presionar Enter en elementos de la ventana de pegado rápido solo los copiará al portapapeles sin pegarlos automáticamente.
? When enabled, single click will copy/paste items in Quick Paste window. If global single click is also enabled, both settings work together.
: Cuando está habilitado, el clic simple copiará/pegará elementos en la ventana de pegado rápido. Si el clic simple global también está habilitado, ambas configuraciones funcionan juntas.
Configure which items to preserve when clearing clipboard history (both manual and auto-clear operations).: Configure qué elementos conservar al borrar el historial del portapapeles (tanto manual como automáticamente).
Keep Items on Clear: Conservar elementos al borrar
Keep Pinned Items: Conservar elementos fijados
Keep Starred Items: Conservar elementos destacados
Preserve pinned items when clearing history: Conservar elementos fijados al borrar el historial
Preserve starred items when clearing history: Conservar elementos destacados al borrar el historial
History Item Preview Max Lines: Límite máximo de líneas de vista previa de elementos del historial
Set the maximum number of lines to display in the preview of a history item: Establecer el número máximo de líneas para mostrar en la vista previa de un elemento del historial
Preview Max Lines: Líneas de vista previa

View File

@ -1,73 +0,0 @@
Add Current Date/Time: Agregar Fecha/Hora Actual
Add Line Numbers: Agregar Números de Línea
Add One Line Feed: Agregar un Salto de Línea
Add Two Line Feeds: Agregar dos Saltos de Línea
Base64 Decode: Decodificar Base64
Base64 Encode: Codificar Base64
CSV: CSV
CSV to JSON: CSV a JSON
CSV to Markdown Table: CSV a Tabla Markdown
Capitalize Case: Poner en Mayúscula
Code Formatting: Formateo de Código
Count Characters: Contar Caracteres
Count Lines: Contar Líneas
Count Sentences: Contar Oraciones
Count Words: Contar Palabras
Data Conversion: Conversión de Datos
Drag and drop category to prioritize its order in the special copy/paste menu.: Arrastra y suelta la categoría para priorizar su orden en el menú especial de copiar/pegar.
Enable All: Habilitar Todo
Enable special text transformation options for clipboard history items: Habilitar opciones especiales de transformación de texto para elementos del historial del portapapeles
Enabled Operations: Operaciones Habilitadas
Encode/Decode: Codificar/Decodificar
Format Converter: Convertidor de Formato
HTML: HTML
HTML Decode: Decodificar HTML
HTML Encode: Codificar HTML
HTML to Markdown: HTML a Markdown
HTML to Plain Text: HTML a Texto Plano
HTML to React Component: HTML a Componente React
HTML to React JSX: HTML a React JSX
HTML to Text: HTML a Texto
JSON: JSON
JSON Stringify: JSON a Cadena
JSON to CSV: JSON a CSV
JSON to Markdown Table: JSON a Tabla Markdown
JSON to TOML: JSON a TOML
JSON to XML: JSON a XML
JSON to YAML: JSON a YAML
Markdown: Markdown
Markdown to HTML: Markdown a HTML
Markdown to Text: Markdown a Texto
Operations: Operaciones
PascalCase: PascalCase
Prioritize Category Order: Priorizar Orden de Categorías
Remove Duplicate Lines: Eliminar Líneas Duplicadas
Remove Extra Spaces: Eliminar Espacios Extra
Remove Line Feeds: Eliminar Saltos de Línea
Reverse Text: Invertir Texto
Select Operations: Seleccionar Operaciones
Sentence case: Tipo oración
Sort Lines Alphabetically: Ordenar Líneas Alfabéticamente
Special Copy: Copia Especial
Special Copy/Paste Operations: Operaciones Especiales de Copiar/Pegar
Special Paste: Pegado Especial
Special Settings: Ajustes Especiales
TOML: TOML
TOML to JSON: TOML a JSON
Text Case: Mayúsculas/Minúsculas
Text Tools: Herramientas de Texto
Title Case: Tipo Título
Trim White Space: Recortar Espacios en Blanco
UPPER CASE: MAYÚSCULAS
URL Decode: Decodificar URL
URL Encode: Codificar URL
Whitespace & Lines: Espacios y Líneas
XML: XML
XML to JSON: XML a JSON
YAML: YAML
YAML to JSON: YAML a JSON
camelCase: camelCase
iNVERT cASE: iNVERTIR cASO
kebab-case: kebab-case
lower case: minúsculas
snake_case: snake_case

View File

@ -1,24 +0,0 @@
Create New Template: Crear Nueva Plantilla
Create Template: Crear Plantilla
Enter template content...: Introduce el contenido de la plantilla...
Enter template name (e.g., "signature", "email"): Introduce el nombre de la plantilla (ej., "firma", "email")
Global: Global
Global Template: Plantilla Global
Global Templates: Plantillas Globales
Preview usage: Vista previa de uso
Template Usage: Uso de Plantilla
Template name already exists: El nombre de la plantilla ya existe. Por favor, elige un nombre diferente.
Template name cannot be changed after creation. Delete and recreate to change name.: El nombre de la plantilla no se puede cambiar después de la creación. Elimina y vuelve a crear para cambiar el nombre.
Use Global Template: Usar Plantilla Global
addTemplateButton: Agregar Plantilla
confirmDeleteTemplateMessage: ¿Estás seguro de que quieres eliminar la plantilla global '{{name}}'?
confirmDeleteTemplateTitle: Confirmar Eliminación
deleteTemplateButtonTooltip: Eliminar Plantilla
enableGlobalTemplatesLabel: Habilitar Plantillas Globales
globalTemplatesDescription: Gestiona fragmentos de texto reutilizables que se pueden insertar en cualquier clip usando {{template_name}}.
globalTemplatesTitle: Plantillas Globales
localTemplateConflictWarning: También existe una plantilla global llamada '{{label}}'. La plantilla local tendrá prioridad dentro del formulario de este clip.
noGlobalTemplatesYet: No hay plantillas globales definidas aún. Haz clic en 'Agregar Plantilla' para crear una.
templateEnabledLabel: Habilitado
templateNameLabel: Nombre
templateValueLabel: Valor

View File

@ -17,9 +17,3 @@ Show collection name on the navbar: Afficher le nom de la collection dans la bar
Switch collections: Changer de collection
You can add the selected text to your clips or menu. Please select the option below.: Vous pouvez ajouter le texte sélectionné à vos clips ou à votre menu. Veuillez sélectionner l'option ci-dessous.
You need to select a different collection before deleting the current one.: Vous devez sélectionner une collection différente avant de supprimer celle actuelle.
Choose which collections require PIN entry for access.: Choisissez quelles collections nécessitent une entrée PIN pour y accéder.
Pin Protected Collections: Collections protégées par PIN
Protect Collections with PIN: Protéger les collections avec un PIN
Protected Collection: Collection protégée
Select Collections: Sélectionner des collections
Select protected collections: Sélectionner des collections protégées

View File

@ -54,12 +54,11 @@ Confirm Passcode: Confirmer le code d'accès
Confirm Password: Confirmer le mot de passe
Confirm Remove: Confirmer la suppression
Confirm Your Passcode: Confirmer votre code d'accès
Confirm Passcode Reset: Confirmer la réinitialisation du code d'accès
Confirm Password Reset: Confirmer la réinitialisation du mot de passe
Confirm Add To Protected Collections: Confirmer l'ajout aux collections protégées
Confirm Disable PIN Protection: Confirmer la désactivation de la protection par PIN
Confirm Remove From Protected Collections: Confirmer la suppression des collections protégées
Confirm Enable PIN Protection: Confirmer l'activation de la protection par PIN
Confirm passcode reset: Confirmer la réinitialisation du code d'accès
Confirm password reset: Confirmer la réinitialisation du mot de passe
Confirm password reset action: Confirmer l'action de réinitialisation du mot de passe
Confirm your action: Confirmer votre action
Confirm {{action}}: Confirmer {{action}}
Contact Form: Formulaire de contact
Copied: Copié
Copy: Copier
@ -100,7 +99,6 @@ Enter Passcode: Entrer le code d'accès
Enter Password: Entrer le mot de passe
Enter Recovery Password: Entrer le mot de passe de récupération
Enter passcode or password to unlock: Entrer le code d'accès ou le mot de passe pour déverrouiller
Enter PIN to Access Protected Collection: Entrez le PIN pour accéder à la collection protégée
Errors:
Error loading link: Erreur lors du chargement du lien
Cant save to file: Impossible d'enregistrer dans le fichier
@ -236,6 +234,7 @@ Set Password: Définir le mot de passe
Show Large View: Afficher la vue large
Show all: Afficher tout
Source: Source
Split History Window: Diviser la fenêtre d'historique
Star: Étoile
Star Selected: Étoile sélectionnée
Stay here: Rester ici

View File

@ -1,4 +0,0 @@
Please select your preferred language: Veuillez sélectionner votre langue préférée
Start using PasteBar: Commencez à utiliser PasteBar
Submenus will move up one level after delete: Les sous-menus remonteront d'un niveau après suppression
Welcome to PasteBar: Bienvenue sur PasteBar

View File

@ -21,7 +21,8 @@ Add Section: Ajouter une section
Add Tab: Ajouter un onglet
Add Template Field: Ajouter un champ de modèle
Add a Tab: Ajouter un onglet
Add field {{name}} into the template: Ajouter le champ {{name}} dans le modèle
Add field <b>&#123;&#123;<b>{{name}}</b>&#125;&#125;</b> into the template: Ajouter le champ <b>&#123;&#123;<b>{{name}}</b>&#125;&#125;</b> dans le modèle
Add field <b>{{<b>{{name}}</b>}}</b> into the template: Ajouter le champ <b>{{<b>{{name}}</b>}}</b> dans le modèle
Add image: Ajouter une image
Add note: Ajouter une note
Add to Board: Ajouter au tableau
@ -82,7 +83,7 @@ Delete field: Supprimer le champ
Delete tab: Supprimer l'onglet
Detect Template Fields: Détecter les champs du modèle
Detect for Template Fields: Détecter les champs du modèle
Disabled field {{name}} has been found in the template: Le champ désactivé {{name}} a été trouvé dans le modèle
Disabled field <b>&#123;&#123;<b>{{name}}</b>&#125;&#125;</b> has been found in the template: Le champ désactivé <b>&#123;&#123;<b>{{name}}</b>&#125;&#125;</b> a été trouvé dans le modèle
Done Create Clip: Création du clip terminée
Done Edit: Édition terminée
Done Edit Tabs: Édition des onglets terminée
@ -134,7 +135,7 @@ FILTERED_TYPES:
RegEx Replace: Remplacement par expression régulière
Remove Quotes: Supprimer les guillemets
Field: Champ
Field {{name}} has been found in the template: Le champ {{name}} a été trouvé dans le modèle
Field <b>&#123;&#123;<b>{{name}}</b>&#125;&#125;</b> has been found in the template: Le champ <b>&#123;&#123;<b>{{name}}</b>&#125;&#125;</b> a été trouvé dans le modèle
Field Options: Options du champ
Fields Value: Valeur des champs
File, folder or app path does not exist: Le chemin du fichier, dossier ou application n'existe pas

View File

@ -69,7 +69,7 @@ Tabs and Layout Menu: Menu des onglets et de la disposition
Title on Popover: Titre sur la fenêtre contextuelle
Toggle Inactive Menu Items: Basculer les éléments de menu inactifs
Toggle Pinned Board: Basculer le tableau épinglé
Toggle History Window: Fenêtre d'historique
Toggle Split History Window: Fenêtre d'historique fractionnée
Tour Completed: Visite terminée
Tour Skipped: Visite passée
Tour completed: Visite terminée

View File

@ -10,7 +10,6 @@ Clear History: Effacer l'historique
Confirm Clear All History: Confirmer l'effacement de tout l'historique
Do you really want to remove ALL clipboard history items?: Voulez-vous vraiment supprimer TOUS les éléments de l'historique du presse-papier ?
Do you want to remove clipboard history items older than {{olderThen}} {{durationType}}: Voulez-vous supprimer les éléments de l'historique du presse-papier antérieurs à {{olderThen}} {{durationType}}
Do you want to remove all recent clipboard history older than {{olderThen}} {{durationType}}: Voulez-vous supprimer tous les éléments récents de l'historique du presse-papiers antérieurs à {{olderThen}} {{durationType}} ?
Enable Capture History: Activer la capture de l'historique
Enable Image Capture: Activer la capture d'images
Filters:

View File

@ -23,7 +23,6 @@ Lock Screen: Écran de verrouillage
Open PasteBar: Ouvrir PasteBar
Options: Options
Player: Lecteur
Show Always on Top: Toujours au premier plan
Show Both Panels: Afficher les deux panneaux
Show Clips Panel Only: Afficher seulement le panneau clips
Show Collections Name: Afficher le nom des collections

View File

@ -64,7 +64,7 @@ Enable screen unlock requirement on app launch for enhanced security, safeguardi
Enhance security by automatically locking the application screen after a set period of user inactivity.: Renforcez la sécurité en verrouillant automatiquement l'écran de l'application après une période déterminée d'inactivité de l'utilisateur.
Enter Passcode length: Saisir la longueur du code d'accès
Enter recovery password to reset passcode.: Saisir le mot de passe de récupération pour réinitialiser le code d'accès.
Enter your <strong>{{screenLockPassCodeLength}} digits</strong> passcode: Entrez votre code à <strong>{{screenLockPassCodeLength}} chiffres</strong>
Enter your <strong>{{screenLockPassCodeLength}} digits</strong> passcode: Entrez votre code à <strong>{{screenLockPassCodeLength}} chiffres</strong>
Entered Passcode is invalid: Code saisi non valide
Excluded Apps List: Liste applicationss exclues
Execute Web Requests: Exécuter requêtes web

View File

@ -15,22 +15,17 @@ Press keys: Appuyez sur les touches
Quick Paste Window: Fenêtre de collage rapide
Remove PasteBar app icon from the macOS Dock while keeping the app running in the background. The app remains accessible via the menu bar icon. Requires an app restart to take effect.: Supprimer l'icône PasteBar du Dock macOS tout en gardant l'app en cours d'exécution en arrière-plan. L'app reste accessible via l'icône de la barre de menu. Nécessite un redémarrage de l'app pour prendre effet.
Set: Définir
Set system OS hotkeys to show/hide the main app window and quick paste window. Supports up to 3-key combinations.: Définir les raccourcis clavier du système pour afficher/masquer la fenêtre principale et la fenêtre de collage rapide. Prend en charge jusqu'à 3 combinaisons de touches.
'How to set hotkeys:': 'Comment définir les raccourcis clavier :'
Click Set/Change button to start recording: Cliquez sur le bouton Définir/Modifier pour commencer l'enregistrement
Press your desired key combination (e.g., Ctrl+Shift+V): Appuyez sur votre combinaison de touches souhaitée (ex. Ctrl+Shift+V)
Press Enter to confirm or Escape to cancel: Appuyez sur Entrée pour confirmer ou Échap pour annuler
Press Backspace/Delete to clear the hotkey: Appuyez sur Retour arrière/Supprimer pour effacer le raccourci clavier
Press your key combination...: Appuyez sur votre combinaison de touches...
Recording...: Enregistrement...
Set system OS hotkeys to show/hide the main app window and quick paste window: Définir les raccourcis clavier du système pour afficher/masquer la fenêtre principale et la fenêtre de collage rapide
Show Navbar Items Hover: Afficher éléments barre au survol
Show collections menu on the navbar: Afficher le menu des collections dans la barre de navigation
Show navbar elements on hover only: Afficher les éléments de la barre uniquement au survol
Show/Hide Quick Paste Window: Afficher/Masquer fenêtre de collage rapide
When enabled, clicking menu items will only copy content to clipboard instead of auto-pasting. This gives you more control over when and where content is pasted.: Lorsqu'activé, cliquer sur les éléments du menu copiera uniquement le contenu dans le presse-papiers au lieu de le coller automatiquement. Cela vous donne plus de contrôle sur le moment et l'endroit où le contenu est collé.
Show/Hide Main App Window: Afficher/Masquer la fenêtre principale de l'application
Show Note Icons on Clips: Afficher les icônes de notes sur les clips
Display persistent icons on clips that have notes to improve visual organization and make notes easier to discover.: Afficher des icônes persistantes sur les clips qui ont des notes pour améliorer l'organisation visuelle et faciliter la découverte des notes.
Default Note Icon Type: Type d'icône de note par défaut
This sets the default icon type for new clips with notes. You can customize individual clips via the context menu.: Cela définit le type d'icône par défaut pour les nouveaux clips avec des notes. Vous pouvez personnaliser les clips individuels via le menu contextuel.
Boards, saved clips and menu items panel visible: Panneau des tableaux, clips sauvegardés et éléments de menu visible
Both clipboard history and saved clips panels visible: Les deux panneaux d'historique du presse-papiers et de clips sauvegardés visibles
Clipboard history panel visible: Panneau d'historique du presse-papiers visible
@ -43,36 +38,3 @@ Show Both Panels: Afficher les deux panneaux
Show History Panel Only: Afficher uniquement le panneau historique
Show Simplified Layout: Afficher la mise en page simplifiée
Simplified Panel Layout: Mise en page de panneau simplifiée
Enable single-click to copy/paste clipboard history items and saved clips instead of requiring double-click.: Activer le clic simple pour copier/coller les éléments de l'historique du presse-papiers et les clips sauvegardés au lieu d'exiger un double-clic.
Single Click Copy/Paste action: Action clic simple Copier/Coller
Single Click Copy/Paste: Clic simple Copier/Coller
Quick Paste Window Options: Options de la fenêtre de collage rapide
Configure the behavior of the Quick Paste window when selecting items: Configurer le comportement de la fenêtre de collage rapide lors de la sélection d'éléments
Copy items only (no auto-paste): Copier uniquement les éléments (pas de collage automatique)
Auto-close window after action: Fermer automatiquement la fenêtre après l'action
When enabled, the Quick Paste window will automatically close after copying or pasting an item.: Lorsqu'activé, la fenêtre de collage rapide se fermera automatiquement après avoir copié ou collé un élément.
This sets the default icon type for new clips with notes. You can customize individual clips via the context menu.: Cela définit le type d'icône par défaut pour les nouveaux clips avec des notes. Vous pouvez personnaliser les clips individuels via le menu contextuel.
? When enabled, clicking menu items will only copy content to clipboard instead of auto-pasting. This gives you more control over when and where content is pasted.
: Lorsqu'activé, cliquer sur les éléments du menu copiera uniquement le contenu dans le presse-papiers au lieu de le coller automatiquement. Cela vous donne plus de contrôle sur le moment et l'endroit où le contenu est collé.
? When enabled, clicking or pressing Enter on items in Quick Paste window will only copy them to clipboard without automatically pasting.
: Lorsqu'activé, cliquer ou appuyer sur Entrée sur les éléments dans la fenêtre de collage rapide les copiera uniquement dans le presse-papiers sans les coller automatiquement.
? When enabled, single click will copy/paste items in Quick Paste window. If global single click is also enabled, both settings work together.
: Lorsqu'activé, un clic simple copiera/collera les éléments dans la fenêtre de collage rapide. Si le clic simple global est également activé, les deux paramètres fonctionnent ensemble.
Configure which items to preserve when clearing clipboard history (both manual and auto-clear operations).: Configurez les éléments à conserver lors de l'effacement de l'historique du presse-papiers (manuellement ou automatiquement).
Keep Items on Clear: Conserver les éléments lors de l'effacement
Keep Pinned Items: Conserver les éléments épinglés
Keep Starred Items: Conserver les éléments favoris
Preserve pinned items when clearing history: Conserver les éléments épinglés lors de l'effacement de l'historique
Preserve starred items when clearing history: Conserver les éléments favoris lors de l'effacement de l'historique
History Item Preview Max Lines: Limite maximale de lignes d'aperçu des éléments de l'historique
Set the maximum number of lines to display in the preview of a history item: Définir le nombre maximal de lignes à afficher dans l'aperçu d'un élément de l'historique
Preview Max Lines: Lignes d'aperçu
Configure how the system tray icon responds to mouse clicks: Configurer comment l'icône de la barre système répond aux clics de souris
Disable left-click context menu: Désactiver le menu contextuel du clic gauche
Double-click toggles app visibility: Le double-clic bascule la visibilité de l'application
Double-clicking the tray icon shows or hides the main application window: Double-cliquer sur l'icône de la barre système affiche ou masque la fenêtre principale de l'application
Enabling either left-click option will disable the context menu to ensure proper functionality.: L'activation de l'une ou l'autre des options de clic gauche désactivera le menu contextuel pour assurer un bon fonctionnement.
Left-click toggles app visibility: Le clic gauche bascule la visibilité de l'application
Left-clicking the tray icon shows or hides the main application window: Cliquer gauche sur l'icône de la barre système affiche ou masque la fenêtre principale de l'application
Prevents the context menu from appearing when left-clicking the tray icon: Empêche le menu contextuel d'apparaître lors du clic gauche sur l'icône de la barre système
Tray Icon Behavior on Windows: Comportement de l'icône de la barre système sur Windows

View File

@ -1,73 +0,0 @@
Add Current Date/Time: Ajouter Date/Heure Actuelle
Add Line Numbers: Ajouter Numéros de Ligne
Add One Line Feed: Ajouter un Saut de Ligne
Add Two Line Feeds: Ajouter deux Sauts de Ligne
Base64 Decode: Décoder Base64
Base64 Encode: Encoder Base64
CSV: CSV
CSV to JSON: CSV vers JSON
CSV to Markdown Table: CSV vers Tableau Markdown
Capitalize Case: Mettre en Capitale
Code Formatting: Formatage de Code
Count Characters: Compter les Caractères
Count Lines: Compter les Lignes
Count Sentences: Compter les Phrases
Count Words: Compter les Mots
Data Conversion: Conversion de Données
Drag and drop category to prioritize its order in the special copy/paste menu.: Glissez-déposez la catégorie pour prioriser son ordre dans le menu spécial copier/coller.
Enable All: Activer Tout
Enable special text transformation options for clipboard history items: Activer les options de transformation de texte spéciales pour les éléments de l'historique du presse-papiers
Enabled Operations: Opérations Activées
Encode/Decode: Encoder/Décoder
Format Converter: Convertisseur de Format
HTML: HTML
HTML Decode: Décoder HTML
HTML Encode: Encoder HTML
HTML to Markdown: HTML vers Markdown
HTML to Plain Text: HTML vers Texte Brut
HTML to React Component: HTML vers Composant React
HTML to React JSX: HTML vers React JSX
HTML to Text: HTML vers Texte
JSON: JSON
JSON Stringify: JSON Stringify
JSON to CSV: JSON vers CSV
JSON to Markdown Table: JSON vers Tableau Markdown
JSON to TOML: JSON vers TOML
JSON to XML: JSON vers XML
JSON to YAML: JSON vers YAML
Markdown: Markdown
Markdown to HTML: Markdown vers HTML
Markdown to Text: Markdown vers Texte
Operations: Opérations
PascalCase: PascalCase
Prioritize Category Order: Prioriser l'Ordre des Catégories
Remove Duplicate Lines: Supprimer Lignes Doubles
Remove Extra Spaces: Supprimer Espaces Superflus
Remove Line Feeds: Supprimer Sauts de Ligne
Reverse Text: Inverser le Texte
Select Operations: Sélectionner Opérations
Sentence case: Cas de la phrase
Sort Lines Alphabetically: Trier Lignes par Ordre Alphabétique
Special Copy: Copie Spéciale
Special Copy/Paste Operations: Opérations Spéciales Copier/Coller
Special Paste: Collage Spécial
Special Settings: Paramètres Spéciaux
TOML: TOML
TOML to JSON: TOML vers JSON
Text Case: Casse du Texte
Text Tools: Outils Texte
Title Case: Cas du Titre
Trim White Space: Supprimer Espaces Blancs
UPPER CASE: MAJUSCULES
URL Decode: Décoder URL
URL Encode: Encoder URL
Whitespace & Lines: Espaces & Lignes
XML: XML
XML to JSON: XML vers JSON
YAML: YAML
YAML to JSON: YAML vers JSON
camelCase: camelCase
iNVERT cASE: iNVERSER cASSE
kebab-case: kebab-case
lower case: minuscules
snake_case: snake_case

View File

@ -1,24 +0,0 @@
Create New Template: Créer un Nouveau Modèle
Create Template: Créer un Modèle
Enter template content...: Saisir le contenu du modèle...
Enter template name (e.g., "signature", "email"): Saisir le nom du modèle (ex. "signature", "email")
Global: Global
Global Template: Modèle Global
Global Templates: Modèles Globaux
Preview usage: Aperçu d'utilisation
Template Usage: Utilisation du Modèle
Template name already exists: Le nom du modèle existe déjà. Veuillez choisir un nom différent.
Template name cannot be changed after creation. Delete and recreate to change name.: Le nom du modèle ne peut pas être modifié après création. Supprimez et recréez pour changer le nom.
Use Global Template: Utiliser le Modèle Global
addTemplateButton: Ajouter un Modèle
confirmDeleteTemplateMessage: Êtes-vous sûr de vouloir supprimer le modèle global '{{name}}' ?
confirmDeleteTemplateTitle: Confirmer la Suppression
deleteTemplateButtonTooltip: Supprimer le Modèle
enableGlobalTemplatesLabel: Activer les Modèles Globaux
globalTemplatesDescription: Gérez des fragments de texte réutilisables qui peuvent être insérés dans n'importe quel clip en utilisant {{template_name}}.
globalTemplatesTitle: Modèles Globaux
localTemplateConflictWarning: Un modèle global nommé '{{label}}' existe également. Le modèle local aura la priorité dans le formulaire de ce clip.
noGlobalTemplatesYet: Aucun modèle global défini pour le moment. Cliquez sur 'Ajouter un Modèle' pour en créer un.
templateEnabledLabel: Activé
templateNameLabel: Nom
templateValueLabel: Valeur

View File

@ -17,9 +17,3 @@ Show collection name on the navbar: Mostra il nome della collezione sulla barra
Switch collections: Cambia collezione
You can add the selected text to your clips or menu. Please select the option below.: Puoi aggiungere il testo selezionato ai tuoi clip o al menu. Seleziona l'opzione qui sotto.
You need to select a different collection before deleting the current one.: Devi selezionare una collezione diversa prima di eliminare quella corrente.
Choose which collections require PIN entry for access.: Scegli quali collezioni richiedono l'inserimento del PIN per l'accesso.
Pin Protected Collections: Collezioni protette con PIN
Protect Collections with PIN: Proteggi le collezioni con PIN
Protected Collection: Collezione protetta
Select Collections: Seleziona collezioni
Select protected collections: Seleziona collezioni protette

View File

@ -51,13 +51,10 @@ Confirm Password: Conferma Password
Confirm Remove: Conferma Rimozione
Confirm Your Passcode: Conferma il Tuo Codice di Accesso
Confirm action: Conferma azione
Confirm Password Reset: Conferma reset password
Confirm password reset: Conferma reset password
Confirm password reset action: Conferma azione di reset password
Confirm your action: Conferma la tua azione
Confirm {{action}}: Conferma {{action}}
Confirm Add To Protected Collections: Conferma aggiunta alle collezioni protette
Confirm Disable PIN Protection: Conferma disabilitazione protezione con PIN
Confirm Remove From Protected Collections: Conferma rimozione dalle collezioni protette
Confirm Enable PIN Protection: Conferma abilitazione protezione con PIN
Contact Form: Modulo di Contatto
Copied: Copiato
Copy: Copia
@ -98,7 +95,6 @@ Enter Passcode: Inserisci Codice di Accesso
Enter Password: Inserisci Password
Enter Recovery Password: Inserisci Password di Recupero
Enter passcode or password to unlock: Inserisci codice di accesso o password per sbloccare
Enter PIN to Access Protected Collection: Inserisci il PIN per accedere alla collezione protetta
Errors:
Error loading link: Errore nel caricamento del link
Cant save file: Impossibile salvare il file
@ -235,7 +231,7 @@ Show Large View: Mostra Vista Grande
Show all: Mostra tutto
Something goes wrong! Please try again.: Qualcosa è andato storto! Per favore riprova.
Source: Fonte
Open History Window: Apri Finestra Cronologia
Split History Window: Dividi Finestra Cronologia
Star: Stella
Star Selected: Aggiungi Stella ai Selezionati
Stay here: Rimani qui

View File

@ -1,4 +0,0 @@
Please select your preferred language: Seleziona la tua lingua preferita
Start using PasteBar: Inizia a usare PasteBar
Submenus will move up one level after delete: I sottomenu saliranno di un livello dopo l'eliminazione
Welcome to PasteBar: Benvenuto su PasteBar

View File

@ -21,7 +21,8 @@ Add Section: Aggiungi Sezione
Add Tab: Aggiungi Scheda
Add Template Field: Aggiungi Campo Modello
Add a Tab: Aggiungi una Scheda
Add field {{name}} into the template: Aggiungi il campo {{name}} al modello
Add field <b>&#123;&#123;<b>{{name}}</b>&#125;&#125;</b> into the template: Aggiungi il campo <b>&#123;&#123;<b>{{name}}</b>&#125;&#125;</b> al modello
Add field <b>{{<b>{{name}}</b>}}</b> into the template: Aggiungi il campo <b>{{<b>{{name}}</b>}}</b> al modello
Add image: Aggiungi immagine
Add note: Aggiungi nota
Add to Board: Aggiungi alla Bacheca
@ -84,7 +85,7 @@ Delete field: Elimina campo
Delete tab: Elimina scheda
Detect Template Fields: Rileva Campi del Modello
Detect for Template Fields: Rileva Campi del Modello
Disabled field {{name}} has been found in the template: Il campo disabilitato {{name}} è stato trovato nel modello
Disabled field <b>&#123;&#123;<b>{{name}}</b>&#125;&#125;</b> has been found in the template: Il campo disabilitato <b>&#123;&#123;<b>{{name}}</b>&#125;&#125;</b> è stato trovato nel modello
Done Create Clip: Creazione Clip Completata
Done Edit: Modifica Completata
Done Edit Tabs: Modifica Schede Completata
@ -136,7 +137,7 @@ FILTERED_TYPES:
RegEx Replace: Sostituzione con Espressione Regolare
Remove Quotes: Rimuovi Virgolette
Field: Campo
Field {{name}} has been found in the template: Il campo {{name}} è stato trovato nel modello
Field <b>&#123;&#123;<b>{{name}}</b>&#125;&#125;</b> has been found in the template: Il campo <b>&#123;&#123;<b>{{name}}</b>&#125;&#125;</b> è stato trovato nel modello
Field Options: Opzioni Campo
Fields Value: Valore Campi
File, folder or app path does not exist: Il percorso del file, cartella o app non esiste

View File

@ -69,7 +69,7 @@ Tabs and Layout Menu: Menu Schede e Layout
Title on Popover: Titolo su Popover
Toggle Inactive Menu Items: Attiva/Disattiva Voci di Menu Inattive
Toggle Pinned Board: Attiva/Disattiva Bacheca Fissata
Toggle History Window: Attiva/Disattiva Finestra Cronologia
Toggle Split History Window: Attiva/Disattiva Finestra Cronologia Divisa
Tour Completed: Tour Completato
Tour Skipped: Tour Saltato
Tour completed: Tour completato

View File

@ -10,7 +10,6 @@ Clear History: Cancella Cronologia
Confirm Clear All History: Conferma Cancellazione di Tutta la Cronologia
Do you really want to remove ALL clipboard history items?: Vuoi davvero rimuovere TUTTI gli elementi della cronologia degli appunti?
Do you want to remove clipboard history items older than {{olderThen}} {{durationType}}: Vuoi rimuovere gli elementi della cronologia degli appunti più vecchi di {{olderThen}} {{durationType}}
Do you want to remove all recent clipboard history older than {{olderThen}} {{durationType}}: Vuoi rimuovere tutti gli elementi recenti della cronologia degli appunti più vecchi di {{olderThen}} {{durationType}}?
Enable Capture History: Abilita Cattura Cronologia
Enable Image Capture: Abilita Cattura Immagini
Filters:

View File

@ -23,7 +23,6 @@ Lock Screen: Blocca Schermo
Open PasteBar: Apri PasteBar
Options: Opzioni
Player: Lettore
Show Always on Top: Mostra sempre in primo piano
Show Both Panels: Mostra Entrambi i Pannelli
Show Clips Panel Only: Mostra Solo Pannello Clip
Show Collections Name: Mostra Nome Collezioni

View File

@ -63,7 +63,7 @@ Enable screen unlock requirement on app launch for enhanced security, safeguardi
Enhance security by automatically locking the application screen after a set period of user inactivity.: Migliora la sicurezza bloccando automaticamente lo schermo dell'applicazione dopo un periodo impostato di inattività dell'utente.
Enter Passcode length: Inserisci la lunghezza del codice di accesso
Enter recovery password to reset passcode.: Inserisci la password di recupero per reimpostare il codice di accesso.
Enter your <strong>{{screenLockPassCodeLength}} digits</strong> passcode: Inserisci il tuo codice di accesso di <strong>{{screenLockPassCodeLength}}cifre</strong>
Enter your <strong>{{screenLockPassCodeLength}} digits</strong> passcode: Inserisci il tuo codice di accesso di <strong>{{screenLockPassCodeLength}} cifre</strong>
Entered Passcode is invalid: Il codice di accesso inserito non è valido
Excluded Apps List: Lista delle App Escluse
Execute Web Requests: Esegui Richieste Web

View File

@ -1,13 +1,8 @@
App restart required: Riavvio necessario
Application Starts with Main Window Hidden: L'applicazione si avvia con la finestra principale nascosta
Change: Modifica
Configure how the system tray icon responds to mouse clicks: Configura come l'icona della barra di sistema risponde ai clic del mouse
Copy only from menu items: Copia solo dagli elementi del menu
Disable left-click context menu: Disabilita menu contestuale clic sinistro
Display navbar items only when the mouse hovers over the navigation bar to minimize visible UI elements: Mostra gli elementi della barra di navigazione solo al passaggio del mouse per minimizzare gli elementi visibili dell'interfaccia
Double-click toggles app visibility: Il doppio clic commuta la visibilità dell'app
Double-clicking the tray icon shows or hides the main application window: Fare doppio clic sull'icona della barra di sistema mostra o nasconde la finestra principale dell'applicazione
Enabling either left-click option will disable the context menu to ensure proper functionality.: L'abilitazione di una delle opzioni di clic sinistro disabiliterà il menu contestuale per garantire il corretto funzionamento.
Global System OS Hotkeys: Tasti di scelta rapida globali del sistema
Hide Collections Navbar: Nascondi barra delle collezioni
Hide collections menu dropdown on the navigation bar: Nascondi il menu a discesa delle collezioni nella barra di navigazione
@ -20,22 +15,17 @@ Press keys: Premi i tasti
Quick Paste Window: Finestra incolla rapido
Remove PasteBar app icon from the macOS Dock while keeping the app running in the background. The app remains accessible via the menu bar icon. Requires an app restart to take effect.: Rimuovi l'icona di PasteBar dal Dock di macOS mantenendo l'app in esecuzione in background. L'app rimane accessibile tramite l'icona della barra dei menu. Richiede un riavvio dell'app per avere effetto.
Set: Imposta
Set system OS hotkeys to show/hide the main app window and quick paste window: Imposta i tasti di scelta rapida del sistema per mostrare/nascondere la finestra principale e la finestra incolla rapido. Supporta combinazioni fino a 3 tasti.
'How to set hotkeys:': 'Come impostare i tasti di scelta rapida:'
Click Set/Change button to start recording: Fai clic sul pulsante Imposta/Modifica per iniziare la registrazione
Press your desired key combination (e.g., Ctrl+Shift+V): Premi la combinazione di tasti desiderata (ad esempio, Ctrl+Shift+V)
Press Enter to confirm or Escape to cancel: Premi Invio per confermare o Esc per annullare
Press Backspace/Delete to clear the hotkey: Premi Backspace/Canc per cancellare il tasto di scelta rapida
Press your key combination...: Premi la tua combinazione di tasti...
Recording...: Registrazione...
Set system OS hotkeys to show/hide the main app window and quick paste window: Imposta i tasti di scelta rapida del sistema per mostrare/nascondere la finestra principale e la finestra incolla rapido
Show Navbar Items Hover: Mostra elementi barra al passaggio del mouse
Show collections menu on the navbar: Mostra il menu delle collezioni nella barra di navigazione
Show navbar elements on hover only: Mostra elementi della barra solo al passaggio del mouse
Show/Hide Quick Paste Window: Mostra/Nascondi finestra incolla rapido
When enabled, clicking menu items will only copy content to clipboard instead of auto-pasting. This gives you more control over when and where content is pasted.: Quando abilitato, cliccando sugli elementi del menu si copierà solo il contenuto negli appunti invece di incollarlo automaticamente. Questo ti dà maggior controllo su quando e dove incollare il contenuto.
Show/Hide Main App Window: Mostra/Nascondi la finestra principale dell'applicazione
Show Note Icons on Clips: Mostra icone delle note sui clip
Display persistent icons on clips that have notes to improve visual organization and make notes easier to discover.: Visualizza icone persistenti sui clip che hanno note per migliorare l'organizzazione visiva e rendere le note più facili da scoprire.
Default Note Icon Type: Tipo di icona nota predefinito
This sets the default icon type for new clips with notes. You can customize individual clips via the context menu.: Questo imposta il tipo di icona predefinito per i nuovi clip con note. Puoi personalizzare i singoli clip tramite il menu contestuale.
Boards, saved clips and menu items panel visible: Pannello di bacheche, clip salvati e elementi menu visibile
Both clipboard history and saved clips panels visible: Entrambi i pannelli cronologia appunti e clip salvati visibili
Clipboard history panel visible: Pannello cronologia appunti visibile
@ -48,27 +38,3 @@ Show Both Panels: Mostra entrambi i pannelli
Show History Panel Only: Mostra solo pannello cronologia
Show Simplified Layout: Mostra layout semplificato
Simplified Panel Layout: Layout pannello semplificato
Enable single-click to copy/paste clipboard history items and saved clips instead of requiring double-click.: Abilita clic singolo per copiare/incollare elementi della cronologia appunti e clip salvati invece di richiedere doppio clic.
Single Click Copy/Paste action: Azione clic singolo Copia/Incolla
Single Click Copy/Paste: Clic singolo Copia/Incolla
Quick Paste Window Options: Opzioni finestra incolla rapido
Configure the behavior of the Quick Paste window when selecting items: Configura il comportamento della finestra incolla rapido quando si selezionano elementi
Copy items only (no auto-paste): Copia solo elementi (nessun incolla automatico)
Auto-close window after action: Chiudi automaticamente finestra dopo l'azione
When enabled, the Quick Paste window will automatically close after copying or pasting an item.: Quando abilitato, la finestra incolla rapido si chiuderà automaticamente dopo aver copiato o incollato un elemento.
This sets the default icon type for new clips with notes. You can customize individual clips via the context menu.: Questo imposta il tipo di icona predefinito per i nuovi clip con note. Puoi personalizzare i singoli clip tramite il menu contestuale.
? When enabled, clicking menu items will only copy content to clipboard instead of auto-pasting. This gives you more control over when and where content is pasted.
: Quando abilitato, cliccando sugli elementi del menu si copierà solo il contenuto negli appunti invece di incollarlo automaticamente. Questo ti dà maggior controllo su quando e dove incollare il contenuto.
? When enabled, clicking or pressing Enter on items in Quick Paste window will only copy them to clipboard without automatically pasting.
: Quando abilitato, cliccando o premendo Invio sugli elementi nella finestra incolla rapido li copierà solo negli appunti senza incollarli automaticamente.
? When enabled, single click will copy/paste items in Quick Paste window. If global single click is also enabled, both settings work together.
: Quando abilitato, il clic singolo copierà/incollerà elementi nella finestra incolla rapido. Se anche il clic singolo globale è abilitato, entrambe le impostazioni funzionano insieme.
Configure which items to preserve when clearing clipboard history (both manual and auto-clear operations).: Configura quali elementi conservare durante la cancellazione della cronologia degli appunti (sia manuale che automatica).
Keep Items on Clear: Conserva elementi durante la cancellazione
Keep Pinned Items: Conserva elementi fissati
Keep Starred Items: Conserva elementi preferiti
Preserve pinned items when clearing history: Conserva elementi fissati durante la cancellazione della cronologia
Preserve starred items when clearing history: Conserva elementi preferiti durante la cancellazione della cronologia
History Item Preview Max Lines: Limite massimo di righe di anteprima degli elementi della cronologia
Set the maximum number of lines to display in the preview of a history item: Imposta il numero massimo di righe da visualizzare nell'anteprima di un elemento della cronologia
Preview Max Lines: Righe di anteprima

View File

@ -1,73 +0,0 @@
Add Current Date/Time: Aggiungi Data/Ora Attuale
Add Line Numbers: Aggiungi Numeri di Riga
Add One Line Feed: Aggiungi un a Capo
Add Two Line Feeds: Aggiungi due a Capo
Base64 Decode: Decodifica Base64
Base64 Encode: Codifica Base64
CSV: CSV
CSV to JSON: CSV in JSON
CSV to Markdown Table: CSV in Tabella Markdown
Capitalize Case: Maiuscolo Iniziale
Code Formatting: Formattazione Codice
Count Characters: Conta Caratteri
Count Lines: Conta Righe
Count Sentences: Conta Frasi
Count Words: Conta Parole
Data Conversion: Conversione Dati
Drag and drop category to prioritize its order in the special copy/paste menu.: Trascina e rilascia la categoria per dare priorità al suo ordine nel menu speciale di copia/incolla.
Enable All: Abilita Tutto
Enable special text transformation options for clipboard history items: Abilita opzioni speciali di trasformazione del testo per gli elementi della cronologia degli appunti
Enabled Operations: Operazioni Abilitate
Encode/Decode: Codifica/Decodifica
Format Converter: Convertitore di Formato
HTML: HTML
HTML Decode: Decodifica HTML
HTML Encode: Codifica HTML
HTML to Markdown: HTML in Markdown
HTML to Plain Text: HTML in Testo Semplice
HTML to React Component: HTML in Componente React
HTML to React JSX: HTML in React JSX
HTML to Text: HTML in Testo
JSON: JSON
JSON Stringify: JSON Stringify
JSON to CSV: JSON in CSV
JSON to Markdown Table: JSON in Tabella Markdown
JSON to TOML: JSON in TOML
JSON to XML: JSON in XML
JSON to YAML: JSON in YAML
Markdown: Markdown
Markdown to HTML: Markdown in HTML
Markdown to Text: Markdown in Testo
Operations: Operazioni
PascalCase: PascalCase
Prioritize Category Order: Priorità Ordine Categorie
Remove Duplicate Lines: Rimuovi Righe Duplicate
Remove Extra Spaces: Rimuovi Spazi Extra
Remove Line Feeds: Rimuovi a Capo
Reverse Text: Inverti Testo
Select Operations: Seleziona Operazioni
Sentence case: Maiuscolo a inizio frase
Sort Lines Alphabetically: Ordina Righe Alfabeticamente
Special Copy: Copia Speciale
Special Copy/Paste Operations: Operazioni Speciali di Copia/Incolla
Special Paste: Incolla Speciale
Special Settings: Impostazioni Speciali
TOML: TOML
TOML to JSON: TOML in JSON
Text Case: Maiuscole/Minuscole
Text Tools: Strumenti Testo
Title Case: Maiuscolo a Inizio Parola
Trim White Space: Taglia Spazi Bianchi
UPPER CASE: MAIUSCOLO
URL Decode: Decodifica URL
URL Encode: Codifica URL
Whitespace & Lines: Spazi & Righe
XML: XML
XML to JSON: XML in JSON
YAML: YAML
YAML to JSON: YAML in JSON
camelCase: camelCase
iNVERT cASE: iNVERTI cASO
kebab-case: kebab-case
lower case: minuscolo
snake_case: snake_case

View File

@ -1,24 +0,0 @@
Create New Template: Crea Nuovo Modello
Create Template: Crea Modello
Enter template content...: Inserisci il contenuto del modello...
Enter template name (e.g., "signature", "email"): Inserisci il nome del modello (es. "firma", "email")
Global: Globale
Global Template: Modello Globale
Global Templates: Modelli Globali
Preview usage: Anteprima utilizzo
Template Usage: Utilizzo del Modello
Template name already exists: Il nome del modello esiste già. Scegli un nome diverso.
Template name cannot be changed after creation. Delete and recreate to change name.: Il nome del modello non può essere modificato dopo la creazione. Elimina e ricrea per cambiare il nome.
Use Global Template: Usa Modello Globale
addTemplateButton: Aggiungi Modello
confirmDeleteTemplateMessage: Sei sicuro di voler eliminare il modello globale '{{name}}'?
confirmDeleteTemplateTitle: Conferma Eliminazione
deleteTemplateButtonTooltip: Elimina Modello
enableGlobalTemplatesLabel: Abilita Modelli Globali
globalTemplatesDescription: Gestisci frammenti di testo riutilizzabili che possono essere inseriti in qualsiasi clip usando {{template_name}}.
globalTemplatesTitle: Modelli Globali
localTemplateConflictWarning: Esiste anche un modello globale chiamato '{{label}}'. Il modello locale avrà la precedenza nel modulo di questo clip.
noGlobalTemplatesYet: Nessun modello globale definito ancora. Clicca su 'Aggiungi Modello' per crearne uno.
templateEnabledLabel: Abilitato
templateNameLabel: Nome
templateValueLabel: Valore

View File

@ -17,9 +17,3 @@ Show collection name on the navbar: Показывать название кол
Switch collections: Переключить коллекции
You can add the selected text to your clips or menu. Please select the option below.: Вы можете добавить выделенный текст в свои клипы или меню. Пожалуйста, выберите ниже.
You need to select a different collection before deleting the current one.: Вам нужно выбрать другую коллекцию перед удалением текущей.
Choose which collections require PIN entry for access.: Выберите, для каких коллекций требуется ввод PIN для доступа.
Pin Protected Collections: Коллекции, защищенные PIN
Protect Collections with PIN: Защитить коллекции с помощью PIN
Protected Collection: Защищенная коллекция
Select Collections: Выбрать коллекции
Select protected collections: Выбрать защищенные коллекции

View File

@ -3,8 +3,6 @@
About PasteBar: О PasteBar
Action Menu: Контекстное меню
Activation Error: Ошибка активации
? Add <b>{{Clipboard}}</b> field to template. This allows you to copy text to the clipboard, and it will be inserted into the template
: Добавьте поле <b>{{Clipboard}}</b> в шаблон. Это позволит копировать текст в буфер обмена, и он будет вставлен в шаблон
Add Clip: Добавить Клип
Add First Option: Добавить первый вариант
Add Link Card: Добавить карточку ссылки
@ -18,6 +16,7 @@ Add to Clips or Menu: Добавить в Клипы или Меню
Add to Menu: Добавить в Меню
Add to clip or menu: Добавить в клипы или меню
Add to template fields: Добавить в поля шаблона
Add {{Clipboard}} field to template. This allows you to copy text to the clipboard, and it will be inserted into the template: Добавьте поле <b>{{Clipboard}}</b> в шаблон. Это позволит копировать текст в буфер обмена, и он будет вставлен в шаблон
Added: Добавлено
Adding this file to the player is not recommended unless you trust the source.: Добавление этого файла в плеер не рекомендуется, если вы не доверяете источнику.
Allow PasteBar to Copy and Paste from Clipboard: Разрешить PasteBar копировать и вставлять из буфера обмена
@ -31,7 +30,6 @@ Check: Проверить
Check / Done: Проверить / Готово
Check and Close: Проверить и закрыть
Check and Done: Проверить и готово
Clear History: Очистить историю
Clear Tracks: Очистить треки
Clear found results and filters: Очистить найденные результаты и фильтры
Click to Confirm: Нажмите подтвердить
@ -51,24 +49,19 @@ Confirm Delete: Подтвердить удаление
Confirm Email: Подтвердить удаление
Confirm Passcode: Подтвердите код
Confirm Password: Подтвердите пароль
Confirm Password Reset: Подтвердить сброс пароля
Confirm Password Reset Action: Подтвердить действие сброса пароля
Confirm Remove: Подтвердить удаление
Confirm Your Passcode: Подтвердите ваш код доступа
Confirm action: Подтвердить действие
Confirm password reset: Подтвердить сброс пароля
Confirm password reset action: Подтвердить действие сброса пароля
Confirm your action: Подтвердите ваше действие
Confirm {{action}}: Подтвердить {{action}}
Confirm Add To Protected Collections: Подтвердить добавление в защищенные коллекции
Confirm Disable PIN Protection: Подтвердить отключение защиты PIN
Confirm Remove From Protected Collections: Подтвердить удаление из защищенных коллекций
Confirm Enable PIN Protection: Подтвердить включение защиты PIN
Contact Form: Форма связи
Copied: Скопировано
Copy: Копировать
Copy & Paste: Копировать и вставить
Copy and Paste: Копировать и вставить
Copy of: Копия
'Copy of ': 'Копия '
Copy to Clipboard: Копировать в буфер обмена
Create: Создать
Created: Создано
@ -99,22 +92,17 @@ Enabled: Включено
Enter Current Passcode: Введите текущий код доступа
Enter Digits Only Passcode: Введите код доступа, состоящий только из цифр
Enter Email: Введите email
Enter PIN to Access Protected Collection: Введите PIN для доступа к защищенной коллекции
Enter Passcode: Введите код доступа
Enter Password: Введите пароль
Enter Recovery Password: Введите пароль восстановления
Enter passcode or password to unlock: Введите код доступа или пароль для разблокировки
Error: Ошибка
Errors:
Error loading link: Ошибка загрузки ссылки
Cant save file: Невозможно сохранить файл
Something went wrong! {{err}} Please try again.: Что-то пошло не так! {{err}} Пожалуйста, попробуйте еще раз.
Expand Edit: Развернуть редактирование
? Field <b>{{Clipboard}}</b> has been found in the template. This allows you to copy text to the clipboard, and it will be inserted into the template
: Поле <b>{{Clipboard}}</b> найдено в шаблоне. Это позволяет копировать текст в буфер обмена, и он будет вставлен в шаблон
Field is not found in the template: Поле не найдено в шаблоне
? Field {{Clipboard}} has been found in the template. This allows you to copy text to the clipboard, and it will be inserted into the template
: Поле <b>{{Clipboard}}</b> найдено в шаблоне. Это позволяет копировать текст в буфер обмена, и он будет вставлен в шаблон
Field {{Clipboard}} has been found in the template. This allows you to copy text to the clipboard, and it will be inserted into the template: Поле <b>{{Clipboard}}</b> найдено в шаблоне. Это позволяет копировать текст в буфер обмена, и он будет вставлен в шаблон
Find Clip: Найти клип
Find History: Найти в истории
Found in template but missing from fields definition: Найдено в шаблоне, но отсутствует в определении полей
@ -157,7 +145,6 @@ Number of lines: Количество строк
Ok, but later: Хорошо, но позже
Open: Открыть
Open Accessibility: Открыть Специальные возможности
Open History Window: Открыть окно с историей буфера
Open Window: Открыть окно
Open contact form in browser: Открыть форму связи в браузере
Open payment in browser: Открыть платеж в браузере
@ -175,8 +162,7 @@ Pasted: Вставлено
Path: Путь
Pause: Пауза
Pause Playing: Пауза
? 'Permission Check Failed: PasteBar has not been successfully added to Accessibility settings. Please grant the required permissions and click Done again.'
: 'Ошибка проверки: PasteBar не был успешно добавлен в настройки Специальных возможностей. Пожалуйста, предоставьте необходимые разрешения и нажмите «Готово» еще раз.'
'Permission Check Failed: PasteBar has not been successfully added to Accessibility settings. Please grant the required permissions and click Done again.': 'Ошибка проверки: PasteBar не был успешно добавлен в настройки Специальных возможностей. Пожалуйста, предоставьте необходимые разрешения и нажмите «Готово» еще раз.'
Pin Selected: Закрепить выбранное
Pinned: Закреплённый
Pinned_few: Закреплённых
@ -244,9 +230,9 @@ Set: Установить
Set Password: Установить пароль
Show Large View: Увеличенный вид
Show all: Показать все
Size: Размер
Something goes wrong! Please try again.: Что-то пошло не так! Пожалуйста, попробуйте еще раз.
Source: Источник
Split History Window: Разделить окно с историей буфера
Star: Избранное
Star Selected: Добавить в избранное
Stay here: Остаться
@ -334,7 +320,6 @@ Unlock Pro features: Разблокировать функции Pro
Unlock Screen: Разблокировать экран
Unlock all features: Разблокировать все функции
Unsaved label: Несохраненное название
Update Error: Ошибка обновления
Update history list: Обновить список истории
Updated: Обновлено
Upgrade to Pro: Перейти на Pro
@ -350,8 +335,7 @@ View Edit: Редактирование в увеличенном виде
Views:
Paste Menu: Меню вставки
We apologize but you found a bug. Please report this issue to us and try again: Приносим извинения, но вы обнаружили ошибку. Пожалуйста, сообщите нам об этой проблеме и повторите попытку
? We couldn't confirm this file's safety. Failed ID3 tag verification and integrity check. MP3 files can potentially contain malware. Please be cautious.
: Мы не смогли подтвердить безопасность этого файла. Не удалось проверить ID3-теги и целостность файла. MP3-файлы могут потенциально содержать вредоносные код. Пожалуйста, будьте осторожны.
We couldn't confirm this file's safety. Failed ID3 tag verification and integrity check. MP3 files can potentially contain malware. Please be cautious.: Мы не смогли подтвердить безопасность этого файла. Не удалось проверить ID3-теги и целостность файла. MP3-файлы могут потенциально содержать вредоносные код. Пожалуйста, будьте осторожны.
Yes: Да
Yes, activate: Да, активировать
chars: символов
@ -366,3 +350,10 @@ second: секунда
seconds: секунды
show less: показать меньше
www.site: www.pastebar.ru
Add <b>{{Clipboard}}</b> field to template. This allows you to copy text to the clipboard, and it will be inserted into the template: Добавьте поле <b>{{Clipboard}}</b> в шаблон. Это позволит копировать текст в буфер обмена, и он будет вставлен в шаблон
Clear History: Очистить историю
'Copy of ': 'Копия '
Error: Ошибка
Field <b>{{Clipboard}}</b> has been found in the template. This allows you to copy text to the clipboard, and it will be inserted into the template: Поле <b>{{Clipboard}}</b> найдено в шаблоне. Это позволяет копировать текст в буфер обмена, и он будет вставлен в шаблон
Size: Размер
Update Error: Ошибка обновления

View File

@ -1,4 +0,0 @@
Please select your preferred language: Пожалуйста, выберите предпочитаемый язык
Start using PasteBar: Начните использовать PasteBar
Submenus will move up one level after delete: Подменю переместятся на уровень выше после удаления
Welcome to PasteBar: Добро пожаловать в PasteBar

View File

@ -21,7 +21,8 @@ Add Section: Добавить раздел
Add Tab: Добавить вкладку
Add Template Field: Добавить поле шаблона
Add a Tab: Добавить вкладку
Add field {{name}} into the template: Добавить поле {{name}} в шаблон
Add field <b>&#123;&#123;<b>{{name}}</b>&#125;&#125;</b> into the template: Добавить поле <b>&#123;&#123;<b>{{name}}</b>&#125;&#125;</b> в шаблон
Add field <b>{{<b>{{name}}</b>}}</b> into the template: Добавить поле <b>{{<b>{{name}}</b>}}</b> в шаблон
Add image: Добавить изображение
Add note: Добавить заметку
Add to Board: Добавить на доску
@ -84,7 +85,7 @@ Delete field: Удалить поле
Delete tab: Удалить вкладку
Detect Template Fields: Обнаружить поля шаблона
Detect for Template Fields: Обнаружить поля шаблона
Disabled field {{name}} has been found in the template: Отключенное поле {{name}} найдено в шаблоне
Disabled field <b>&#123;&#123;<b>{{name}}</b>&#125;&#125;</b> has been found in the template: Отключенное поле <b>&#123;&#123;<b>{{name}}</b>&#125;&#125;</b> найдено в шаблоне
Done Create Clip: Завершить
Done Edit: Завершить
Done Edit Tabs: Завершить
@ -136,7 +137,7 @@ FILTERED_TYPES:
RegEx Replace: Замена регулярного выражения
Remove Quotes: Удалить кавычки
Field: Поле
Field {{name}} has been found in the template: Поле {{name}} найдено в шаблоне
Field <b>&#123;&#123;<b>{{name}}</b>&#125;&#125;</b> has been found in the template: Поле <b>&#123;&#123;<b>{{name}}<b>&#123;&#123;<b> найдено в шаблоне
Field Options: Параметры поля
Fields Value: Значение полей
File, folder or app path does not exist: Путь к файлу, папке или приложению не существует

Some files were not shown because too many files have changed in this diff Show More