Compare commits

..
Author SHA1 Message Date
Armin Schrenk 24839985e9 Merge branch 'develop' into release/1.7.0 2023-02-14 11:40:10 +01:00
Armin Schrenk a7b2802f34 show correct error message when using custom mountpoint with webdav (Http address) 2023-02-14 11:39:16 +01:00
Armin Schrenk c85d0b4beb bump webdav-nio-adapter 2023-02-14 11:22:11 +01:00
Armin Schrenk 3dff3a8664 Fixes #2682
* allow windows installer to remove same version
* add revisionNumber to installer version
2023-02-14 11:20:22 +01:00
Armin Schrenk 5b0bbf539b improve FailOnRunningApp action 2023-02-13 23:34:43 +01:00
Armin Schrenk 1ff7c40fd9 Fixes #2672 and fixes #2668 2023-02-13 10:42:17 +01:00
Armin SchrenkandGitHub d0875ef49e Merge pull request #2669 from cryptomator/feature/virtual-volume-doc-link
Add link to volume type documentation
2023-02-09 13:06:03 +01:00
Armin Schrenk e35ed9af72 enable localization of tooltip 2023-02-08 20:11:34 +01:00
Armin Schrenk ac43efe149 change UI to be not so clunky:
* only use question mark icon
* use tooltip at icon instead of explicit label
* icon is the hyperlink
2023-02-08 11:33:41 +01:00
Armin Schrenk 202a2ea79f Load revealPathServiceProvider at app startup 2023-02-08 11:14:54 +01:00
Armin Schrenk c19a86a348 add link to mounting documentation 2023-02-07 15:23:04 +01:00
Armin Schrenk 539dcaa85a Update issue template 2023-02-07 12:23:25 +01:00
Armin Schrenk fb91c1a461 Merge branch 'develop' into release/1.7.0 2023-02-06 14:45:56 +01:00
CryptobotandGitHub bd75370dfd New Crowdin updates (#2646)
New translations strings.properties

Catalan; Chinese Simplified; Dutch; Italian; Persian; Polish; Slovak;

[ci skip]
2023-02-06 14:44:45 +01:00
Armin Schrenk 7a9a9cf4eb Follow up of 69d73d0fb9: Remove standalone launchers 2023-02-06 12:31:56 +01:00
Armin Schrenk 489e9fce90 bump integrations-win to 1.2.0-beta2
Closes #2657
2023-02-03 13:19:53 +01:00
Armin Schrenk d378d84832 bump fuse-nio-adapter 2023-02-03 13:19:43 +01:00
Armin Schrenk 69d73d0fb9 Remove standalone launchers 2023-02-03 13:15:03 +01:00
Armin Schrenk 97c0cb4f5f add to settings.json the app version written to it last 2023-02-02 16:44:03 +01:00
Armin Schrenk b4faae7fa0 make debug logs readable by filter out internal fuse-nio locking 2023-02-02 10:36:31 +01:00
Armin Schrenk 55d76b65cc Add IOException to log message during revealPath 2023-02-01 22:31:27 +01:00
Armin Schrenk fd6e1e6741 fix bug 2023-02-01 19:23:28 +01:00
Armin Schrenk 155558caa8 add style class to text object 2023-02-01 13:50:56 +01:00
Armin Schrenk 28217b2de3 only perform mountpoint move and cleanup, if mountpoint is not a drive letter 2023-02-01 13:44:57 +01:00
Armin SchrenkandGitHub b9e57ce895 Merge pull request #2654 from cryptomator/feature/2652-migrate-dir-mounts
Feature/2652 migrate dir mounts
2023-02-01 11:17:11 +01:00
Armin Schrenk 95ea23ee6e add more comments regarding removal evaluation of this workaround 2023-02-01 11:07:23 +01:00
Armin Schrenk c269184217 ensure that settings.json is a file 2023-01-31 18:05:31 +01:00
Armin Schrenk 68d32957e4 fix errors 2023-01-31 16:37:25 +01:00
Armin Schrenk a771f0a5b7 doc doc doc 2023-01-31 13:59:18 +01:00
Armin Schrenk e56e6a8359 integrate script into installer 2023-01-31 13:58:56 +01:00
Armin Schrenk 5f9b77241f extend migration script to all local users 2023-01-31 13:40:25 +01:00
Armin Schrenk fb54ee04a6 Remove Dokany advertisement from msi installer 2023-01-30 13:32:56 +01:00
Armin Schrenk a106b04c7e prototpye for powershell script to be executed after installation 2023-01-30 13:30:06 +01:00
Armin Schrenk 285d48b70b Merge branch 'develop' into release/1.7.0 2023-01-27 13:27:31 +01:00
Armin Schrenk 0d8d7e4ee5 fix debian artifact upload 2023-01-27 13:27:03 +01:00
Armin Schrenk f232f9d958 Merge branch 'develop' into release/1.7.0 2023-01-27 12:31:00 +01:00
Armin Schrenk 88c3b0cc4f remove tag-name from release action to just add to current release on debian build 2023-01-27 12:30:44 +01:00
Armin Schrenk ef190db739 Merge branch 'develop' into release/1.7.0 2023-01-27 11:36:28 +01:00
CryptobotandGitHub b378354bb9 New Crowdin updates (#2562)
New translations strings.properties

Arabic; Belarusian; Bengali; Bosnian; Catalan; Chinese Simplified; Chinese Traditional; Chinese Traditional, Hong Kong; Croatian(Cyrillic); Czech; Danish; Dutch; Filipino; French; Galician; German; Greek; Hebrew; Hindi; Hungarian; Indonesian; Italian; Japanese; Korean( Latin); Latvian; Macedonian; Norwegian Bokmal; Norwegian Nynorsk; Persian; Polish; Portuguese; Portuguese, Brazilian; Punjabi; Romanian; Russian; Sinhala; Slovak; Slovenian; Spanish; Swahili, Tanzania; Swedish; Tamil; Telugu; Thai; Turkish; Ukrainian; Vietnamese; 

[ci skip]
2023-01-27 11:35:50 +01:00
Armin Schrenk 822e863e27 partially revert 220782b84f 2023-01-26 16:29:43 +01:00
Armin Schrenk 40fbe4f59d remove more libffi workaround leftovers 2023-01-26 16:05:53 +01:00
Tobias Hagemann bf779b5b41 updated dmg background 2023-01-26 15:57:10 +01:00
Tobias Hagemann ce5dbd14d8 reverted be7ac50928 2023-01-26 15:57:10 +01:00
Armin Schrenk 48744018a2 Merge branch 'release/1.7.0' into develop 2023-01-26 15:56:48 +01:00
Armin Schrenk bd9f79cb56 add cryptomator.mountPointsDir property to macOS installer scripts 2023-01-26 15:54:31 +01:00
Armin Schrenk f4c4f72539 remove libjffi stuff from appimage 2023-01-26 14:31:23 +01:00
Armin Schrenk 74718754ad fix merge 2023-01-26 13:48:30 +01:00
Armin Schrenk eb595379d6 Merge branch 'develop' into release/1.7.0
# Conflicts:
#	dist/linux/debian/control
#	dist/linux/debian/cryptomator.sh
2023-01-26 13:47:46 +01:00
Armin Schrenk 220782b84f reduce jars neede to stay on classpath due to missing module info 2023-01-26 13:28:55 +01:00
Armin SchrenkandGitHub 1c104737c1 Merge pull request #2639 from cryptomator/feature/mount-provider
Refactoring: Use mount service
2023-01-26 13:20:11 +01:00
Armin Schrenk 7c8a519919 bump webdav-nio-adapter 2023-01-26 13:10:32 +01:00
Armin Schrenk ae1fa5851f remove traces of ActualMountService from volume preferences controller 2023-01-26 13:02:21 +01:00
Armin Schrenk 86ccb1a58f changing volume provider requires restart due to macFUSE/FUSE-T lib loaded in same JVM 2023-01-26 12:05:34 +01:00
Armin Schrenk c3fb58f7d0 bump fuse-nio-adapter 2023-01-25 16:49:00 +01:00
Armin Schrenk b4c384acc9 use speciaized translation key 2023-01-25 12:44:09 +01:00
Armin Schrenk 8580e97791 cleanup 2023-01-23 14:39:46 +01:00
Armin Schrenk 5d348ee229 Bump WebDAV dependency 2023-01-23 14:39:21 +01:00
Armin Schrenk dda0ff545c add point of automatic mount point selection 2023-01-23 13:47:00 +01:00
Armin Schrenk 708b5938ac Add info about the dependency of volume type and mountOptions 2023-01-23 13:11:01 +01:00
Armin SchrenkandGitHub a3cb8cd2f1 Merge pull request #2641 from purejava/jdk.security.auth
Add jdk.security.auth module as it's required by dbus-java-core

Closes #2640
2023-01-23 11:10:59 +01:00
Armin Schrenk 3587d53d15 bump integrations-mac, fixes NoSuchServiceException for RevealPathService on macOS 2023-01-23 11:09:15 +01:00
Tobias HagemannandGitHub 2f5e2af8d9 Merge pull request #2638 from cryptomator/feature/traymenu-onbeforeopenmenu-macos-fix
Fixed vault list refresh when tray icon is clicked on macOS
2023-01-23 10:24:57 +01:00
Ralph PlawetzkiandGitHub 8139cb8c38 Add jdk.security.auth module to rules 2023-01-22 20:05:13 +01:00
Armin Schrenk 09d5f71335 do not reset mountflags to default ones when window opens 2023-01-22 19:24:35 +01:00
Ralph Plawetzki 3a638735b7 Add jdk.security.auth module to appimage.yml 2023-01-22 18:11:50 +01:00
Ralph Plawetzki f1f5f7e02f Add jdk.security.auth module as it's required by dbus-java-core 2023-01-22 17:59:20 +01:00
Tobias Hagemann 94fe8ca449 updated string
[ci skip]
2023-01-20 17:18:05 +01:00
Tobias Hagemann 1251e1b873 updated separator styling 2023-01-20 17:14:02 +01:00
Armin Schrenk 50405c0bd5 remove debug message 2023-01-20 17:07:19 +01:00
Armin Schrenk 774d24625c change styling of volume preferences 2023-01-20 17:07:04 +01:00
Tobias Hagemann ba4902a5bc Fixed vault list refresh when tray icon is clicked on macOS 2023-01-20 16:45:35 +01:00
Armin Schrenk 90408504e2 Merge branch 'develop' into feature/mount-provider
# Conflicts:
#	pom.xml
#	src/main/java/org/cryptomator/common/vaults/Vault.java
#	src/main/java/org/cryptomator/ui/mainwindow/VaultDetailUnlockedController.java
2023-01-20 15:27:48 +01:00
Armin Schrenk c8c44e0554 bump fuse-nio-adapter dependency 2023-01-20 15:01:31 +01:00
Armin Schrenk 7afab6fe78 add auto option to volume type selection 2023-01-20 12:29:17 +01:00
Armin Schrenk ad321dfe55 migrate 1.6.x volumeimpl to hardcoded mountservices 2023-01-20 11:49:15 +01:00
d6388d6205 Added drop zone for revealing encrypted files or folders (#2592)
* Added drop zone for revealing encrypted files or folders

* Split god drop zone into distinct drop zones in vault list and vault detail unlocked

* Prevent cursor from changing if content doesn't match during drag over

[ci skip]

* Removed unused methods / css classes

[ci skip]

* Updated method name

* Refactor Vault::getCiphertextPath to only accept strings starting with "/"

* bump cryptofs

* ensure that path cleartext path always starts with "/"

* added file chooser for revealing encrypted items

* Trying to fix path parsing again

* Updated drag & drop design for buttons

* use RevealPathService to reveal files in file manager

* fix compilation error

* Copy paths to clipboard if no revealService is present

* reintegrate wongFileAlert

* Only accept TrasnferMode.LINK

* updated drag-n-drop button styling

* added tooltip

* updated string

* cleanup

Co-authored-by: Armin Schrenk <armin.schrenk@skymatic.de>
2023-01-20 10:46:00 +01:00
Armin SchrenkandGitHub b8326907bf Merge pull request #2624 from purejava/update-appimage-build-script
Update build.sh to .github/workflows/appimage.yml
2023-01-19 13:37:10 +01:00
Armin Schrenk 5beeeae27f Sign integrations.dll during build 2023-01-16 18:47:41 +01:00
Armin Schrenk fb1f3c4757 fix bug using wrong mount flags 2023-01-16 14:14:03 +01:00
Armin Schrenk 5e32cbcdd0 show supported mount features in preferences/volume 2023-01-13 18:11:36 +01:00
Armin Schrenk 08d741ecf5 address TODOs 2023-01-13 16:24:15 +01:00
Armin Schrenk 23060a8497 reinitate workaround for MOUNT_WITHIN_PARENT 2023-01-13 15:59:44 +01:00
Armin Schrenk 47a32893f0 Refactor mounter class 2023-01-13 13:46:41 +01:00
Armin Schrenk 0f7ba4e00e remove updating driveletter strings 2023-01-13 12:53:41 +01:00
Armin Schrenk 0d75b999a3 cleanup 2023-01-13 12:50:38 +01:00
Armin Schrenk b6d97528d2 fix driveletter selection 2023-01-13 12:49:20 +01:00
Armin Schrenk 94c53989b1 MountOptions window: Reset to auto mount, if no dir selected 2023-01-13 11:27:30 +01:00
Armin Schrenk a72ea1b9f5 move mount prepartions to own class 2023-01-13 11:20:23 +01:00
Armin Schrenk 6395f17736 Handle illegelArgumentException when setting custom mountpoint 2023-01-12 17:21:54 +01:00
Armin Schrenk 5c61944757 fix minor ui bugs 2023-01-12 12:53:58 +01:00
Armin Schrenk c641695a40 migrate 1.6.x vault settings on-the-fly 2023-01-12 12:11:03 +01:00
Armin Schrenk d93ef2e905 Reinitiate force lock 2023-01-11 16:40:14 +01:00
Armin Schrenk 8b9377cf4e only fix custom mount flags, if explicitly desired. Otherwise use the ones provided by mount service 2023-01-11 16:35:12 +01:00
Armin Schrenk 991b03e000 use function paramter, not instance variable 2023-01-11 16:21:49 +01:00
Armin Schrenk 73d8c4098e resolve TODOs 2023-01-11 16:18:05 +01:00
Armin Schrenk 6a52d15510 Show mountpath in reveal button 2023-01-11 16:01:59 +01:00
Armin Schrenk d07b1b96dd Use first available mount provider if none is selected or selected is not present 2023-01-11 16:01:51 +01:00
Armin Schrenk 24d472ed8b Merge branch 'develop' into feature/mount-provider
# Conflicts:
#	dist/linux/appimage/build.sh
#	dist/linux/debian/rules
2023-01-11 16:01:27 +01:00
Armin Schrenk 6fe2d73c52 copy uri to clipboard when using fallback mounter 2023-01-11 15:59:39 +01:00
Armin Schrenk 523e5d7904 bump webdav- and dokany-adapter 2023-01-11 15:59:17 +01:00
Tobias Hagemann 304064d9ab updated dependency-check version 2023-01-09 11:59:51 +01:00
Tobias Hagemann 0d49c60d4d reverted 1a6258eb17 2023-01-09 11:32:11 +01:00
Ralph Plawetzki 0e0e00f116 Remove stuff not needed when run locally
From: changes requested for PR #2624
2023-01-08 14:10:38 +01:00
Ralph Plawetzki 77c0a3e265 Update build.sh to .github/workflows/appimage.yml 2023-01-07 15:31:32 +01:00
Tobias Hagemann 1807888860 updated sponsors
[ci skip]
2023-01-05 11:16:22 +01:00
Tobias Hagemann be7ac50928 added new app icon for macos, fixes #2517 2023-01-04 16:32:40 +01:00
Julian Raufelder 9182c415eb Hello 2023 🎉 2023-01-04 13:35:58 +01:00
Armin Schrenk 1a6258eb17 revert eea568ca4e and e2898f0c8b 2023-01-04 12:52:16 +01:00
Armin SchrenkandGitHub 9c0c6a91fb Merge pull request #2580 from jacob-willden/develop
Add more info to Migration Screen
2023-01-03 16:47:18 +01:00
Armin Schrenk 53436520c9 fix using the wrong property 2023-01-03 12:38:18 +01:00
Armin Schrenk fd5aeaf90a Merge branch 'develop' into feature/mount-setting-per-vault 2023-01-02 13:47:30 +01:00
Armin Schrenk f3fcfc913b Remove unused class 2023-01-02 12:10:46 +01:00
Armin SchrenkandGitHub 0b0870e313 Merge pull request #2575 from VsevolodGolovanov/issue_2557_unlocked_status_indicator_in_tray_icon
Unlocked status indicator in tray icon 

Closes #2557
2022-12-30 11:40:51 +01:00
Armin SchrenkandGitHub 6704bb1f8c Merge pull request #2612 from cryptomator/feature/2597-no-keychain-dialog
Feature: Show dialog for hub vaults, if keychain is disabled'

Closes #2597
2022-12-30 11:32:40 +01:00
Armin Schrenk 48d1938b99 Refine dialog text 2022-12-30 11:19:37 +01:00
Armin Schrenk 6199277002 Add Button to open preferences 2022-12-29 18:26:13 +01:00
Armin Schrenk 9fefe8e462 Show info dialog when keychain is deactivated 2022-12-29 18:20:46 +01:00
Armin Schrenk 5fcd53be18 load device key before showing UI to prevent uncatched failure of UI loading 2022-12-29 18:17:47 +01:00
Jacob Willden 7147636428 Switch term for new vault migration dialog 2022-12-21 18:56:17 -07:00
Jacob Willden 690bd833e8 Add more info to Migration Screen 2022-12-16 13:28:57 -07:00
1e12590681 Update src/main/java/org/cryptomator/ui/traymenu/AwtTrayMenuController.java
Co-authored-by: Tobias Hagemann <tobias.hagemann@gmail.com>
2022-12-15 13:34:52 +04:00
Tobias Hagemann eea568ca4e GCM is explicitly ready! 2022-12-14 22:27:34 +01:00
Armin Schrenk 8009205da7 Merge branch 'main' into develop
# Conflicts:
#	pom.xml
2022-12-14 20:07:24 +01:00
Armin Schrenk c0f73a2802 Merge branch 'hotfix/1.6.17' 2022-12-14 20:06:35 +01:00
Armin Schrenk 8e902877a3 Update dependency-check plugin and exclude false positive
(cherry picked from commit ebcd0adf78)
2022-12-14 20:06:23 +01:00
Armin Schrenk fd76c89393 update metainfo 2022-12-14 20:02:12 +01:00
Armin Schrenk 975baf594c Fixes #2576 2022-12-14 19:58:22 +01:00
Vsevolod Golovanov 5a99c7bb61 Unlocked status indicator in tray icon #2557
Now tracking unlockedness and updating the icon accordingly.
2022-12-14 21:18:37 +04:00
Tobias Hagemann e2898f0c8b GCM is ready! 2022-12-14 17:36:06 +01:00
Tobias Hagemann cf2b236df5 added tray icons for unlocked state 2022-12-14 17:28:59 +01:00
Tobias Hagemann 819fa803f3 cleaned up tray icons 2022-12-14 16:47:07 +01:00
Armin Schrenk 980e2b184b use correct tag name for gh release in debian workflow 2022-12-13 12:48:29 +01:00
Sebastian Stenzel ebad677e84 fix path to downloaded jmod files 2022-12-12 09:14:24 +01:00
Sebastian Stenzel 4fda4a2b2e fix makefile 2022-12-12 09:09:25 +01:00
Sebastian Stenzel ffaf7ad360 adjust package dependencies to new mount api and jfuse 2022-12-12 09:03:56 +01:00
Sebastian Stenzel 76689705f5 remove LD_PRELOAD workaround, which should no longer be required with jfuse 2022-12-12 08:54:18 +01:00
Armin Schrenk 0d6d7b0dd6 directly use inputs object 2022-12-09 16:56:45 +01:00
Armin Schrenk 9dfd8adcce revert 0725a63b09 and fix workflow 2022-12-09 16:56:02 +01:00
Armin Schrenk 433eecc6a8 adjust matching rules for version type detection
(cherry picked from commit cd358916260e713d4119c20b1bcb5b448a017365)
2022-12-09 16:50:39 +01:00
Armin Schrenk 36ed4554b2 Fixes #2570
Dabian build: Make libffi7 a runtime dependency and preload it.
2022-12-09 15:12:04 +01:00
129 changed files with 2704 additions and 1249 deletions
+12 -7
View File
@@ -37,14 +37,19 @@ body:
id: volume-type
attributes:
label: Volume Type
description: What is selected under Settings → Virtual Drive?
multiple: true
options:
- FUSE
- Dokany
- WebDAV
description: What volume type is selected under Settings → Virtual Drive?
value: |
- WinFsp
- WinFsp (Local Drive)
- FUSE-T
- macFUSE
- WebDAV (Windows Explorer)
- WebDAV (AppleScript)
- WebDAV (gio)
- WebDAV (HTTP Address)
- Dokany (1.5)
validations:
required: false
required: true
- type: textarea
id: reproduction-steps
attributes:
+3 -10
View File
@@ -16,7 +16,7 @@ jobs:
get-version:
uses: ./.github/workflows/get-version.yml
with:
version: ${{ github.event.inputs.version }}
version: ${{ inputs.version }}
build:
name: Build AppImage
@@ -47,7 +47,6 @@ jobs:
- name: Patch target dir
run: |
cp LICENSE.txt target
cp dist/linux/launcher.sh target
cp target/cryptomator-*.jar target/mods
- name: Run jlink
run: >
@@ -55,7 +54,7 @@ jobs:
--verbose
--output runtime
--module-path "${JAVA_HOME}/jmods"
--add-modules java.base,java.desktop,java.instrument,java.logging,java.naming,java.net.http,java.scripting,java.sql,java.xml,javafx.base,javafx.graphics,javafx.controls,javafx.fxml,jdk.unsupported,jdk.crypto.ec,jdk.accessibility,jdk.management.jfr
--add-modules java.base,java.desktop,java.instrument,java.logging,java.naming,java.net.http,java.scripting,java.sql,java.xml,javafx.base,javafx.graphics,javafx.controls,javafx.fxml,jdk.unsupported,jdk.crypto.ec,jdk.security.auth,jdk.accessibility,jdk.management.jfr
--strip-native-commands
--no-header-files
--no-man-pages
@@ -78,7 +77,7 @@ jobs:
--dest appdir
--name Cryptomator
--vendor "Skymatic GmbH"
--copyright "(C) 2016 - 2022 Skymatic GmbH"
--copyright "(C) 2016 - 2023 Skymatic GmbH"
--app-version "${{ needs.get-version.outputs.semVerNum }}.${{ needs.get-version.outputs.revNum }}"
--java-options "--enable-preview"
--java-options "--enable-native-access=org.cryptomator.jfuse.linux.amd64,org.cryptomator.jfuse.linux.aarch64"
@@ -111,12 +110,6 @@ jobs:
ln -s usr/share/icons/hicolor/scalable/apps/org.cryptomator.Cryptomator.svg Cryptomator.AppDir/.DirIcon
ln -s usr/share/applications/org.cryptomator.Cryptomator.desktop Cryptomator.AppDir/Cryptomator.desktop
ln -s bin/cryptomator.sh Cryptomator.AppDir/AppRun
- name: Extract libjffi.so # workaround for https://github.com/cryptomator/cryptomator-linux/issues/27
run: |
JFFI_NATIVE_JAR=`ls lib/app/ | grep -e 'jffi-[1-9]\.[0-9]\{1,2\}.[0-9]\{1,2\}-native.jar'`
${JAVA_HOME}/bin/jar -xf lib/app/${JFFI_NATIVE_JAR} /jni/x86_64-Linux/
mv jni/x86_64-Linux/* lib/app/libjffi.so
working-directory: Cryptomator.AppDir
- name: Download AppImageKit
run: |
curl -L https://github.com/AppImage/AppImageKit/releases/download/13/appimagetool-x86_64.AppImage -o appimagetool.AppImage
+7 -10
View File
@@ -65,10 +65,10 @@ jobs:
unzip -j openjfx-aarch64.zip \*/javafx.base.jmod \*/javafx.controls.jmod \*/javafx.fxml.jmod \*/javafx.graphics.jmod -d jmods/aarch64
- name: Ensure major jfx version in pom and in jmods is the same
run: |
JMOD_VERSION_AMD64=$(jmod describe ${JAVA_HOME}/jmods/amd64/javafx.base.jmod | head -1)
JMOD_VERSION_AMD64=$(jmod describe jmods/amd64/javafx.base.jmod | head -1)
JMOD_VERSION_AMD64=${JMOD_VERSION_AMD64#*@}
JMOD_VERSION_AMD64=${JMOD_VERSION_AMD64%%.*}
JMOD_VERSION_AARCH64=$(jmod describe ${JAVA_HOME}/jmods/aarch64/javafx.base.jmod | head -1)
JMOD_VERSION_AARCH64=$(jmod describe jmods/aarch64/javafx.base.jmod | head -1)
JMOD_VERSION_AARCH64=${JMOD_VERSION_AARCH64#*@}
JMOD_VERSION_AARCH64=${JMOD_VERSION_AARCH64%%.*}
POM_JFX_VERSION=$(mvn help:evaluate "-Dexpression=javafx.version" -q -DforceStdout)
@@ -148,11 +148,8 @@ jobs:
echo "TAG_NAME=${REF##*/}" >> $GITHUB_ENV
- name: Publish Debian package on GitHub Releases
if: startsWith(inputs.ref, 'refs/tags/')
uses: softprops/action-gh-release@v1
with:
fail_on_unmatched_files: true
tag_name: ${{ github.env.TAG_NAME }}
token: ${{ secrets.CRYPTOBOT_RELEASE_TOKEN }}
files: |
cryptomator_*_amd64.deb
cryptomator_*.asc
env:
GITHUB_TOKEN: ${{ secrets.CRYPTOBOT_RELEASE_TOKEN }}
run: |
artifacts=$(ls | grep cryptomator*.deb)
gh release upload ${{ env.TAG_NAME }} $artifacts
+3 -3
View File
@@ -16,7 +16,7 @@ jobs:
get-version:
uses: ./.github/workflows/get-version.yml
with:
version: ${{ github.event.inputs.version }}
version: ${{ inputs.version }}
build:
name: Build Cryptomator.app for ${{ matrix.output-suffix }}
@@ -61,7 +61,6 @@ jobs:
- name: Patch target dir
run: |
cp LICENSE.txt target
cp dist/mac/launcher.sh target
cp target/cryptomator-*.jar target/mods
- name: Run jlink
run: >
@@ -87,7 +86,7 @@ jobs:
--dest appdir
--name Cryptomator
--vendor "Skymatic GmbH"
--copyright "(C) 2016 - 2022 Skymatic GmbH"
--copyright "(C) 2016 - 2023 Skymatic GmbH"
--app-version "${{ needs.get-version.outputs.semVerNum }}"
--java-options "--enable-preview"
--java-options "--enable-native-access=org.cryptomator.jfuse.mac"
@@ -103,6 +102,7 @@ jobs:
--java-options "-Dcryptomator.p12Path=\"~/Library/Application Support/Cryptomator/key.p12\""
--java-options "-Dcryptomator.ipcSocketPath=\"~/Library/Application Support/Cryptomator/ipc.socket\""
--java-options "-Dcryptomator.integrationsMac.keychainServiceName=\"Cryptomator\""
--java-options "-Dcryptomator.mountPointsDir=\"~/Cryptomator\""
--java-options "-Dcryptomator.showTrayIcon=true"
--java-options "-Dcryptomator.buildNumber=\"dmg-${{ needs.get-version.outputs.revNum }}\""
--mac-package-identifier org.cryptomator
+12 -6
View File
@@ -22,7 +22,7 @@ jobs:
get-version:
uses: ./.github/workflows/get-version.yml
with:
version: ${{ github.event.inputs.version }}
version: ${{ inputs.version }}
build-msi:
name: Build .msi Installer
@@ -55,7 +55,6 @@ jobs:
- name: Patch target dir
run: |
cp LICENSE.txt target
cp dist/linux/launcher.sh target
cp target/cryptomator-*.jar target/mods
- name: Run jlink
run: >
@@ -81,7 +80,7 @@ jobs:
--dest appdir
--name Cryptomator
--vendor "Skymatic GmbH"
--copyright "(C) 2016 - 2022 Skymatic GmbH"
--copyright "(C) 2016 - 2023 Skymatic GmbH"
--app-version "${{ needs.get-version.outputs.semVerNum }}.${{ needs.get-version.outputs.revNum }}"
--java-options "--enable-preview"
--java-options "--enable-native-access=org.cryptomator.jfuse.win"
@@ -118,6 +117,9 @@ jobs:
- name: Fix permissions
run: attrib -r appdir/Cryptomator/Cryptomator.exe
shell: pwsh
- name: Extract integrations DLL for code signing
shell: pwsh
run: gci ./appdir/Cryptomator/app/mods/ -File integrations-win-*.jar | ForEach-Object {Set-Location -Path $_.Directory; jar --file=$($_.FullName) --extract integrations.dll }
- name: Codesign
uses: skymatic/code-sign-action@v2
with:
@@ -128,6 +130,10 @@ jobs:
timestampUrl: 'http://timestamp.digicert.com'
folder: appdir/Cryptomator
recursive: true
- name: Repack signed DLL into jar
shell: pwsh
run: |
gci ./appdir/Cryptomator/app/mods/ -File integrations-win-*.jar | ForEach-Object {Set-Location -Path $_.Directory; jar --file=$($_.FullName) --update integrations.dll; Remove-Item integrations.dll}
- name: Generate license for MSI
run: >
mvn -B license:add-third-party
@@ -149,8 +155,8 @@ jobs:
--dest installer
--name Cryptomator
--vendor "Skymatic GmbH"
--copyright "(C) 2016 - 2022 Skymatic GmbH"
--app-version "${{ needs.get-version.outputs.semVerNum }}"
--copyright "(C) 2016 - 2023 Skymatic GmbH"
--app-version "${{ needs.get-version.outputs.semVerNum }}.${{ needs.get-version.outputs.revNum}}"
--win-menu
--win-dir-chooser
--win-shortcut-prompt
@@ -247,7 +253,7 @@ jobs:
-out dist/win/bundle/
-dBundleVersion="${{ needs.get-version.outputs.semVerNum }}.${{ needs.get-version.outputs.revNum }}"
-dBundleVendor="Skymatic GmbH"
-dBundleCopyright="(C) 2016 - 2022 Skymatic GmbH"
-dBundleCopyright="(C) 2016 - 2023 Skymatic GmbH"
-dAboutUrl="https://cryptomator.org"
-dHelpUrl="https://cryptomator.org/contact"
-dUpdateUrl="https://cryptomator.org/downloads/"
+1
View File
@@ -33,6 +33,7 @@ Cryptomator is provided free of charge as an open-source project despite the hig
<tr>
<td><a href="https://mowcapital.com/"><img src="https://cryptomator.org/img/sponsors/mowcapital.svg" alt="Mow Capital" height="40"></a></td>
<td><a href="https://www.easeus.com/"><img src="https://cryptomator.org/img/sponsors/easeus.png" alt="EaseUS" height="40"></a></td>
<td><a href="https://www.hassmann-it-forensik.de/"><img src="https://cryptomator.org/img/sponsors/hassmannitforensik.png" alt="Hassmann IT-Forensik" height="40"></a></td>
</tr>
</tbody>
</table>
+19 -14
View File
@@ -11,15 +11,20 @@ command -v curl >/dev/null 2>&1 || { echo >&2 "curl not found."; exit 1; }
VERSION=$(mvn -f ../../../pom.xml help:evaluate -Dexpression=project.version -q -DforceStdout)
SEMVER_STR=${VERSION}
mvn -f ../../../pom.xml versions:set -DnewVersion=${SEMVER_STR}
# compile
mvn -B -f ../../../pom.xml clean package -DskipTests -Plinux
mvn -B -f ../../../pom.xml clean package -Plinux -DskipTests
cp ../../../LICENSE.txt ../../../target
cp ../launcher.sh ../../../target
cp ../../../target/cryptomator-*.jar ../../../target/mods
# add runtime
${JAVA_HOME}/bin/jlink \
--verbose \
--output runtime \
--module-path "${JAVA_HOME}/jmods" \
--add-modules java.base,java.desktop,java.instrument,java.logging,java.naming,java.net.http,java.scripting,java.sql,java.xml,jdk.unsupported,jdk.crypto.ec,jdk.accessibility,jdk.management.jfr \
--add-modules java.base,java.desktop,java.instrument,java.logging,java.naming,java.net.http,java.scripting,java.sql,java.xml,javafx.base,javafx.graphics,javafx.controls,javafx.fxml,jdk.unsupported,jdk.crypto.ec,jdk.security.auth,jdk.accessibility,jdk.management.jfr \
--strip-native-commands \
--no-header-files \
--no-man-pages \
@@ -27,7 +32,7 @@ ${JAVA_HOME}/bin/jlink \
--compress=1
# create app dir
envsubst '${SEMVER_STR} ${REVISION_NUM}' < dist/linux/launcher-gtk2.properties > launcher-gtk2.properties
envsubst '${SEMVER_STR} ${REVISION_NUM}' < ../launcher-gtk2.properties > launcher-gtk2.properties
${JAVA_HOME}/bin/jpackage \
--verbose \
--type app-image \
@@ -35,12 +40,12 @@ ${JAVA_HOME}/bin/jpackage \
--input ../../../target/libs \
--module-path ../../../target/mods \
--module org.cryptomator.desktop/org.cryptomator.launcher.Cryptomator \
--dest . \
--dest appdir \
--name Cryptomator \
--vendor "Skymatic GmbH" \
--copyright "(C) 2016 - 2022 Skymatic GmbH" \
--java-options "--enable-preview" \
--java-options "--enable-native-access=org.cryptomator.jfuse.linux.amd64,org.cryptomator.jfuse.linux.aarch64" \
--copyright "(C) 2016 - 2023 Skymatic GmbH" \
--java-options "-Xss5m" \
--java-options "-Xmx256m" \
--app-version "${VERSION}.${REVISION_NO}" \
@@ -48,6 +53,7 @@ ${JAVA_HOME}/bin/jpackage \
--java-options "-Dcryptomator.logDir=\"~/.local/share/Cryptomator/logs\"" \
--java-options "-Dcryptomator.pluginDir=\"~/.local/share/Cryptomator/plugins\"" \
--java-options "-Dcryptomator.settingsPath=\"~/.config/Cryptomator/settings.json:~/.Cryptomator/settings.json\"" \
--java-options "-Dcryptomator.p12Path=\"~/.config/Cryptomator/key.p12\"" \
--java-options "-Dcryptomator.ipcSocketPath=\"~/.config/Cryptomator/ipc.socket\"" \
--java-options "-Dcryptomator.mountPointsDir=\"~/.local/share/Cryptomator/mnt\"" \
--java-options "-Dcryptomator.showTrayIcon=false" \
@@ -56,9 +62,8 @@ ${JAVA_HOME}/bin/jpackage \
--resource-dir ../resources
# transform AppDir
mv Cryptomator Cryptomator.AppDir
mv appdir/Cryptomator Cryptomator.AppDir
cp -r resources/AppDir/* Cryptomator.AppDir/
chmod +x Cryptomator.AppDir/lib/runtime/bin/java
envsubst '${REVISION_NO}' < resources/AppDir/bin/cryptomator.sh > Cryptomator.AppDir/bin/cryptomator.sh
cp ../common/org.cryptomator.Cryptomator256.png Cryptomator.AppDir/usr/share/icons/hicolor/256x256/apps/org.cryptomator.Cryptomator.png
cp ../common/org.cryptomator.Cryptomator512.png Cryptomator.AppDir/usr/share/icons/hicolor/512x512/apps/org.cryptomator.Cryptomator.png
@@ -72,12 +77,6 @@ ln -s usr/share/icons/hicolor/scalable/apps/org.cryptomator.Cryptomator.svg Cryp
ln -s usr/share/applications/org.cryptomator.Cryptomator.desktop Cryptomator.AppDir/Cryptomator.desktop
ln -s bin/cryptomator.sh Cryptomator.AppDir/AppRun
# extract jffi
JFFI_NATIVE_JAR=`ls Cryptomator.AppDir/lib/app | grep -e 'jffi-[1-9]\.[0-9]\{1,2\}.[0-9]\{1,2\}-native.jar'`
${JAVA_HOME}/bin/jar -xf Cryptomator.AppDir/lib/app/${JFFI_NATIVE_JAR} /jni/x86_64-Linux/
mv jni/x86_64-Linux/* Cryptomator.AppDir/lib/app/libjffi.so
rm -r jni/x86_64-Linux
# load AppImageTool
curl -L https://github.com/AppImage/AppImageKit/releases/download/13/appimagetool-x86_64.AppImage -o /tmp/appimagetool.AppImage
chmod +x /tmp/appimagetool.AppImage
@@ -85,5 +84,11 @@ chmod +x /tmp/appimagetool.AppImage
# create AppImage
/tmp/appimagetool.AppImage \
Cryptomator.AppDir \
cryptomator-SNAPSHOT-x86_64.AppImage \
cryptomator-${SEMVER_STR}-x86_64.AppImage \
-u 'gh-releases-zsync|cryptomator|cryptomator|latest|cryptomator-*-x86_64.AppImage.zsync'
echo ""
echo "Done. AppImage successfully created: cryptomator-${SEMVER_STR}-x86_64.AppImage"
echo ""
echo >&2 "To clean up, run: rm -rf Cryptomator.AppDir appdir jni runtime squashfs-root; rm launcher-gtk2.properties /tmp/appimagetool.AppImage"
echo ""
@@ -15,9 +15,6 @@ elif command -v pacman &> /dev/null; then # don't forget arch
GTK3_PRESENT=`pacman -Qi gtk3 &> /dev/null; echo $?`
fi
# workaround for https://github.com/cryptomator/cryptomator-linux/issues/27
export LD_PRELOAD=lib/app/libjffi.so
if [ "$GTK2_PRESENT" -eq 0 ] && [ "$GTK3_PRESENT" -ne 0 ]; then
bin/Cryptomator-gtk2 $@
else
@@ -66,6 +66,7 @@
</content_rating>
<releases>
<release date="2022-12-14" version="1.6.17"/>
<release date="2022-12-06" version="1.6.16"/>
<release date="2022-10-06" version="1.6.15"/>
<release date="2022-08-31" version="1.6.14"/>
+1 -1
View File
@@ -12,7 +12,7 @@ Package: cryptomator
Architecture: any
Section: utils
Priority: optional
Depends: ${shlibs:Depends}, ${misc:Depends}, libfuse2, xdg-utils, libjffi-jni
Depends: ${shlibs:Depends}, ${misc:Depends}, libfuse3-3
Recommends: gvfs-backends, gvfs-fuse, gnome-keyring
XB-AppName: Cryptomator
XB-Category: Utility;Security;FileTools;
+2 -2
View File
@@ -4,11 +4,11 @@ Upstream-Contact: Cryptomator <info@cryptomator.org>
Source: https://cryptomator.org
Files: *
Copyright: 2016-2022 Skymatic GmbH
Copyright: 2016-2023 Skymatic GmbH
License: GPL-3+
Files: debian/org.cryptomator.Cryptomator.appdata.xml
Copyright: 2016-2022 Skymatic GmbH
Copyright: 2016-2023 Skymatic GmbH
License: FSFAP
License: GPL-3+
-1
View File
@@ -1,5 +1,4 @@
cryptomator usr/lib
debian/cryptomator.sh usr/lib/cryptomator/bin
common/org.cryptomator.Cryptomator.desktop usr/share/applications
common/org.cryptomator.Cryptomator.svg usr/share/icons/hicolor/scalable/apps
common/org.cryptomator.Cryptomator256.png usr/share/icons/hicolor/256x256/apps
+1 -1
View File
@@ -1 +1 @@
usr/lib/cryptomator/bin/cryptomator.sh usr/bin/cryptomator
usr/lib/cryptomator/bin/cryptomator usr/bin/cryptomator
-6
View File
@@ -1,6 +0,0 @@
#!/bin/sh
# fix for https://github.com/cryptomator/cryptomator/issues/1370
export LD_PRELOAD=/usr/lib/x86_64-linux-gnu/jni/libjffi-1.2.so
/usr/lib/cryptomator/bin/cryptomator $@
+2 -9
View File
@@ -27,7 +27,7 @@ override_dh_auto_build:
$(JAVA_HOME)/bin/jlink \
--output runtime \
--module-path "${JMODS_PATH}" \
--add-modules java.base,java.desktop,java.instrument,java.logging,java.naming,java.net.http,java.scripting,java.sql,java.xml,javafx.base,javafx.graphics,javafx.controls,javafx.fxml,jdk.unsupported,jdk.crypto.ec,jdk.accessibility,jdk.management.jfr \
--add-modules java.base,java.desktop,java.instrument,java.logging,java.naming,java.net.http,java.scripting,java.sql,java.xml,javafx.base,javafx.graphics,javafx.controls,javafx.fxml,jdk.unsupported,jdk.crypto.ec,jdk.security.auth,jdk.accessibility,jdk.management.jfr \
--strip-native-commands \
--no-header-files \
--no-man-pages \
@@ -42,9 +42,9 @@ override_dh_auto_build:
--dest . \
--name cryptomator \
--vendor "Skymatic GmbH" \
--copyright "(C) 2016 - 2022 Skymatic GmbH" \
--java-options "--enable-preview" \
--java-options "--enable-native-access=org.cryptomator.jfuse.linux.amd64,org.cryptomator.jfuse.linux.aarch64" \
--copyright "(C) 2016 - 2023 Skymatic GmbH" \
--java-options "-Xss5m" \
--java-options "-Xmx256m" \
--java-options "-Dfile.encoding=\"utf-8\"" \
@@ -60,10 +60,3 @@ override_dh_auto_build:
--app-version "${VERSION_NUM}.${REVISION_NUM}" \
--resource-dir resources \
--verbose
override_dh_fixperms:
dh_fixperms
chmod +x debian/cryptomator/usr/lib/cryptomator/bin/cryptomator.sh
# override_dh_strip:
# no-op
-15
View File
@@ -1,15 +0,0 @@
#!/bin/sh
cd $(dirname $0)
java \
-p "mods" \
-cp "libs/*" \
-Dcryptomator.settingsPath="~/.config/Cryptomator/settings.json" \
-Dcryptomator.ipcSocketPath="~/.config/Cryptomator/ipc.socket" \
-Dcryptomator.logDir="~/.local/share/Cryptomator/logs" \
-Dcryptomator.mountPointsDir="~/.local/share/Cryptomator/mnt" \
-Djdk.gtk.version=2 \
-Xss2m \
-Xmx512m \
--enable-preview \
--enable-native-access=org.cryptomator.jfuse.linux.amd64,org.cryptomator.jfuse.linux.aarch64 \
-m org.cryptomator.desktop/org.cryptomator.launcher.Cryptomator
+2 -1
View File
@@ -21,7 +21,7 @@ rm -rf runtime dmg *.app *.dmg
# set variables
APP_NAME="Cryptomator"
VENDOR="Skymatic GmbH"
COPYRIGHT_YEARS="2016 - 2022"
COPYRIGHT_YEARS="2016 - 2023"
PACKAGE_IDENTIFIER="org.cryptomator"
MAIN_JAR_GLOB="cryptomator-*.jar"
MODULE_AND_MAIN_CLASS="org.cryptomator.desktop/org.cryptomator.launcher.Cryptomator"
@@ -79,6 +79,7 @@ ${JAVA_HOME}/bin/jpackage \
--java-options "-Dcryptomator.ipcSocketPath=\"~/Library/Application Support/${APP_NAME}/ipc.socket\"" \
--java-options "-Dcryptomator.p12Path=\"~/Library/Application Support/${APP_NAME}/key.p12\"" \
--java-options "-Dcryptomator.integrationsMac.keychainServiceName=\"${APP_NAME}\"" \
--java-options "-Dcryptomator.mountPointsDir=\"~/${APP_NAME}\"" \
--java-options "-Dcryptomator.showTrayIcon=true" \
--java-options "-Dcryptomator.buildNumber=\"dmg-${REVISION_NO}\"" \
--mac-package-identifier ${PACKAGE_IDENTIFIER} \
Binary file not shown.
+1 -1
View File
@@ -17,7 +17,7 @@
\f1\b0 \
\
\f0\b \'a9 2016 \'96 2022 Skymatic GmbH
\f0\b \'a9 2016 \'96 2023 Skymatic GmbH
\f1\b0 \
\
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\
-14
View File
@@ -1,14 +0,0 @@
#!/bin/sh
cd $(dirname $0)
java \
-p "mods" \
-cp "libs/*" \
-Dcryptomator.settingsPath="~/Library/Application Support/Cryptomator/settings.json" \
-Dcryptomator.ipcSocketPath="~/Library/Application Support/Cryptomator/ipc.socket" \
-Dcryptomator.logDir="~/Library/Logs/Cryptomator" \
-Dcryptomator.mountPointsDir="/Volumes" \
-Xss20m \
-Xmx512m \
--enable-preview \
--enable-native-access=org.cryptomator.jfuse.mac \
-m org.cryptomator.desktop/org.cryptomator.launcher.Cryptomator
+1 -1
View File
@@ -129,7 +129,7 @@ $Env:JP_WIXWIZARD_RESOURCES = "$buildDir\resources"
--name $AppName `
--vendor $Vendor `
--copyright $copyright `
--app-version "$semVerNo" `
--app-version "$semVerNo.$revisionNo" `
--win-menu `
--win-dir-chooser `
--win-shortcut-prompt `
+1 -1
View File
@@ -10,7 +10,7 @@
\vieww12000\viewh15840\viewkind0
\pard\tx283\tx567\tx850\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\b\fs16\lang7 Cryptomator is distributed under the GPLv3 License, found below. Please see the bottom of this document for any other license applicable to code used within Cryptomator.\b0\par
\par
\b\'a9 2016 \'96 2022 Skymatic GmbH \b0\par
\b\'a9 2016 \'96 2023 Skymatic GmbH \b0\par
\par
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\par
\par
-12
View File
@@ -1,12 +0,0 @@
@echo off
java ^
-p "app/mods" ^
-cp "app/*" ^
-Dcryptomator.settingsPath="~/AppData/Roaming/Cryptomator/settings.json" ^
-Dcryptomator.ipcSocketPath="~/AppData/Roaming/Cryptomator/ipc.socket" ^
-Dcryptomator.logDir="~/AppData/Roaming/Cryptomator" ^
-Dcryptomator.mountPointsDir="~/Cryptomator" ^
-Dcryptomator.keychainPath="~/AppData/Roaming/Cryptomator/keychain.json" ^
-Xss20m ^
-Xmx512m ^
-m org.cryptomator.desktop/org.cryptomator.launcher.Cryptomator
+5
View File
@@ -0,0 +1,5 @@
@echo off
:: see comments in file ./version170-migrate-settings.ps1
cd %~dp0
powershell -NoLogo -NonInteractive -ExecutionPolicy Unrestricted -Command .\version170-migrate-settings.ps1
+45
View File
@@ -0,0 +1,45 @@
# This script migrates Cryptomator settings for all local users on Windows in case the users uses custom directories as mountpoint
# See also https://github.com/cryptomator/cryptomator/pull/2654.
#
# TODO: This script should be evaluated in a yearly interval if it is still needed and if not, should be removed
#
#Requires -RunAsAdministrator
#Get all active, local user profiles
$profileList = 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList'
$localUsers = Get-LocalUser | Where-Object {$_.Enabled} | ForEach-Object { $_.Name}
Get-ChildItem $profileList | ForEach-Object { $_.GetValue("ProfileImagePath") } | Where-Object {
$profileNameMatches = ($_ | Select-String -Pattern "\\([^\\]+)$").Matches
if($profileNameMatches.Count -eq 1) {
#check if the last path part is contained in the local user name list
#otherwise do not touch it
return $localUsers.Contains($profileNameMatches[0].Groups[1].Value)
} else {
return $false;
}
} | ForEach-Object {
$settingsPath = "$_\AppData\Roaming\Cryptomator\settings.json"
if(!(Test-Path -Path $settingsPath -PathType Leaf)) {
#No settings file, nothing to do.
return;
}
$settings = Get-Content -Path $settingsPath | ConvertFrom-Json
if($settings.preferredVolumeImpl -ne "FUSE") {
#Fuse not used, nothing to do
return;
}
#check if customMountPoints are used
$atLeastOneCustomPath = $false;
foreach ($vault in $settings.directories){
$atLeastOneCustomPath = $atLeastOneCustomPath -or ($vault.useCustomMountPath -eq "True")
}
#if so, use WinFsp Local Drive
if( $atLeastOneCustomPath ) {
Add-Member -Force -InputObject $settings -Name "mountService" -Value "org.cryptomator.frontend.fuse.mount.WinFspMountProvider" -MemberType NoteProperty
$newSettings = $settings | Select-Object * -ExcludeProperty "preferredVolumeImpl"
ConvertTo-Json $newSettings | Set-Content -Path $settingsPath
}
}
+2 -5
View File
@@ -65,13 +65,10 @@
<Control Id="Title" Type="Text" X="135" Y="20" Width="220" Height="60" Transparent="yes" NoPrefix="yes" Text="!(loc.ExitDialogTitle)" />
<!-- TODO: localize? -->
<Control Id="Suggestion" Type="Text" X="135" Y="100" Width="220" Height="60" Transparent="yes" NoPrefix="yes">
<Text>We recommend for the best user experience to download and install one of the following third party Windows drivers:</Text>
<Text>We recommend for the best user experience to download and install the following third party Windows driver:</Text>
</Control>
<Control Id="WinFsp" Type="Hyperlink" X="140" Y="125" Width="220" Height="60" Transparent="yes">
<Text><![CDATA[WinFsp (<a href="http://www.secfs.net/winfsp/rel/">Homepage</a>)]]></Text>
</Control>
<Control Id="Dokany" Type="Hyperlink" X="140" Y="137" Width="220" Height="60" Transparent="yes">
<Text><![CDATA[• Dokany (<a href="https://dokan-dev.github.io/">Homepage</a>)]]></Text>
<Text><![CDATA[WinFsp (<a href="https://winfsp.dev/">Homepage</a>)]]></Text>
</Control>
</Dialog>
+1 -1
View File
@@ -10,7 +10,7 @@
\vieww12000\viewh15840\viewkind0
\pard\tx283\tx567\tx850\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\b\fs16\lang7 Cryptomator is distributed under the GPLv3 License, found below. Please see the bottom of this document for any other license applicable to code used within Cryptomator.\b0\par
\par
\b\'a9 2016 \'96 2022 Skymatic GmbH \b0\par
\b\'a9 2016 \'96 2023 Skymatic GmbH \b0\par
\par
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\par
\par
+8 -4
View File
@@ -54,7 +54,7 @@
Property="JP_UPGRADABLE_FOUND"
Maximum="$(var.JpAppVersion)"
MigrateFeatures="yes"
IncludeMaximum="$(var.JpUpgradeVersionOnlyDetectUpgrade)" />
IncludeMaximum="yes" /> <!-- TODO: check if this needs to be set to yes-->
<UpgradeVersion
OnlyDetect="$(var.JpUpgradeVersionOnlyDetectDowngrade)"
Property="JP_DOWNGRADABLE_FOUND"
@@ -132,6 +132,9 @@
<!-- WebDAV patches -->
<CustomAction Id="PatchWebDAV" Impersonate="no" ExeCommand="[INSTALLDIR]patchWebDAV.bat" Directory="INSTALLDIR" Execute="deferred" Return="asyncWait" />
<!-- Special Settings migration for 1.7.0,. Should be removed eventually, for more info, see ../contrib/version170-migrate-settings.ps1-->
<CustomAction Id="V170MigrateSettings" Impersonate="no" ExeCommand="[INSTALLDIR]version170-migrate-settings.bat" Directory="INSTALLDIR" Execute="deferred" Return="asyncWait" />
<!-- Running App detection and exit -->
<Property Id="FOUNDRUNNINGAPP" Admin="yes"/>
<util:CloseApplication
@@ -140,11 +143,11 @@
CloseMessage="no"
RebootPrompt="no"
PromptToContinue="yes"
Description="A running instance of $(var.JpAppName) is found. Please close it to continue."
Description="A running instance of $(var.JpAppName) is found, using files marked for update. Please close it to continue."
Property="FOUNDRUNNINGAPP"
>
</util:CloseApplication>
<CustomAction Id="FailOnRunningApp" Impersonate="no" ExeCommand="[SystemFolder]\cmd.exe /c &quot;exit 1&quot;" Directory="INSTALLDIR" Execute="immediate" Return="check" />
<CustomAction Id="FailOnRunningApp" Error="Installation aborted, because files marked for update are used by a running instance of $(var.JpAppName)."/>
<?ifdef JpIcon ?>
<Property Id="ARPPRODUCTICON" Value="JpARPPRODUCTICON"/>
@@ -179,9 +182,10 @@
<Custom Action="WixCloseApplications" Before="InstallValidate"></Custom>
<Custom Action="FailOnRunningApp" After="WixCloseApplications" >FOUNDRUNNINGAPP</Custom>
<RemoveExistingProducts After="InstallValidate"/>
<RemoveExistingProducts After="InstallValidate"/> <!-- Moved from CostInitialize, due to WixCloseApplications -->
<Custom Action="PatchWebDAV" After="InstallFiles">NOT Installed OR REINSTALL</Custom>
<Custom Action="V170MigrateSettings" After="InstallFiles">NOT Installed OR REINSTALL</Custom>
</InstallExecuteSequence>
<WixVariable Id="WixUIBannerBmp" Value="$(env.JP_WIXWIZARD_RESOURCES)\banner.bmp" />
+19 -12
View File
@@ -3,7 +3,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>org.cryptomator</groupId>
<artifactId>cryptomator</artifactId>
<version>1.7.0</version>
<version>1.7.0-SNAPSHOT</version>
<name>Cryptomator Desktop App</name>
<organization>
@@ -24,18 +24,19 @@
<project.jdk.version>19</project.jdk.version>
<!-- Group IDs of jars that need to stay on the class path for now -->
<!-- Check progress on https://github.com/swiesend/secret-service/issues/31 to remove hypfvieh, swiesend and jnr -->
<nonModularGroupIds>com.github.jnr,org.ow2.asm,org.apache.jackrabbit,org.apache.httpcomponents,de.swiesend,org.purejava,com.github.hypfvieh</nonModularGroupIds>
<!-- Once hypfvieh, swiesend, purejava and integrations-linux have module-info, remove them-->
<nonModularGroupIds>org.ow2.asm,org.apache.jackrabbit,org.apache.httpcomponents,de.swiesend,org.purejava,com.github.hypfvieh</nonModularGroupIds>
<!-- cryptomator dependencies -->
<cryptomator.cryptofs.version>2.5.3</cryptomator.cryptofs.version>
<cryptomator.integrations.version>1.2.0-beta2</cryptomator.integrations.version>
<cryptomator.integrations.win.version>1.1.2</cryptomator.integrations.win.version>
<cryptomator.integrations.mac.version>1.1.2</cryptomator.integrations.mac.version>
<cryptomator.integrations.linux.version>1.1.0</cryptomator.integrations.linux.version>
<cryptomator.fuse.version>2.0.0-beta2</cryptomator.fuse.version>
<cryptomator.dokany.version>2.0.0-beta1</cryptomator.dokany.version>
<cryptomator.webdav.version>2.0.0-beta1</cryptomator.webdav.version>
<cryptomator.cryptolib.version>2.1.1</cryptomator.cryptolib.version>
<cryptomator.cryptofs.version>2.6.1</cryptomator.cryptofs.version>
<cryptomator.integrations.version>1.2.0-beta4</cryptomator.integrations.version>
<cryptomator.integrations.win.version>1.2.0-beta3</cryptomator.integrations.win.version>
<cryptomator.integrations.mac.version>1.2.0-beta2</cryptomator.integrations.mac.version>
<cryptomator.integrations.linux.version>1.2.0-beta2</cryptomator.integrations.linux.version>
<cryptomator.fuse.version>2.0.0-beta5</cryptomator.fuse.version>
<cryptomator.dokany.version>2.0.0-beta2</cryptomator.dokany.version>
<cryptomator.webdav.version>2.0.0-beta5</cryptomator.webdav.version>
<!-- 3rd party dependencies -->
<commons-lang3.version>3.12.0</commons-lang3.version>
@@ -58,12 +59,18 @@
<!-- build-time dependencies -->
<jetbrains.annotations.version>23.0.0</jetbrains.annotations.version>
<dependency-check.version>7.4.0</dependency-check.version>
<dependency-check.version>7.4.4</dependency-check.version>
<jacoco.version>0.8.8</jacoco.version>
</properties>
<dependencies>
<!-- Cryptomator Libs -->
<dependency>
<!-- needed due to https://github.com/cryptomator/cryptolib/issues/34-->
<groupId>org.cryptomator</groupId>
<artifactId>cryptolib</artifactId>
<version>${cryptomator.cryptolib.version}</version>
</dependency>
<dependency>
<groupId>org.cryptomator</groupId>
<artifactId>cryptofs</artifactId>
@@ -16,6 +16,7 @@ import org.cryptomator.common.settings.SettingsProvider;
import org.cryptomator.common.vaults.VaultComponent;
import org.cryptomator.common.vaults.VaultListModule;
import org.cryptomator.cryptolib.common.MasterkeyFileAccess;
import org.cryptomator.integrations.revealpath.RevealPathService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -26,6 +27,7 @@ import java.net.InetSocketAddress;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Comparator;
import java.util.Optional;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.SynchronousQueue;
@@ -83,6 +85,13 @@ public abstract class CommonsModule {
return new SemVerComparator();
}
@Provides
@Singleton
static Optional<RevealPathService> provideRevealPathService() {
return RevealPathService.get().findFirst();
}
@Provides
@Singleton
static Settings provideSettings(SettingsProvider settingsProvider) {
@@ -0,0 +1,18 @@
package org.cryptomator.common;
import javafx.beans.binding.Bindings;
import javafx.beans.value.ObservableValue;
import java.util.function.Function;
public class ObservableUtil {
public static <T, U> ObservableValue<U> mapWithDefault(ObservableValue<T> observable, Function<? super T, ? extends U> mapper, U defaultValue) {
return Bindings.createObjectBinding(() -> {
if (observable.getValue() == null) {
return defaultValue;
} else {
return mapper.apply(observable.getValue());
}
}, observable);
}
}
@@ -0,0 +1,6 @@
package org.cryptomator.common.mount;
import org.cryptomator.integrations.mount.MountService;
public record ActualMountService(MountService service, boolean isDesired) {
}
@@ -0,0 +1,9 @@
package org.cryptomator.common.mount;
public class IllegalMountPointException extends IllegalArgumentException {
public IllegalMountPointException(String msg) {
super(msg);
}
}
@@ -6,6 +6,7 @@ import org.cryptomator.common.settings.Settings;
import org.cryptomator.integrations.mount.MountService;
import javax.inject.Singleton;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.value.ObservableValue;
import java.util.List;
@@ -18,13 +19,33 @@ public class MountModule {
return MountService.get().toList();
}
//currently not used, because macFUSE and FUSE-T cannot be used in the same JVM
/*
@Provides
@Singleton
static ObservableValue<MountService> provideMountService(Settings settings, List<MountService> serviceImpls) {
return settings.mountService().map(desiredServiceImpl -> {
var fallbackProvider = serviceImpls.stream().findFirst().orElse(null);
return serviceImpls.stream().filter(serviceImpl -> serviceImpl.getClass().getName().equals(desiredServiceImpl)).findAny().orElse(fallbackProvider);
});
static ObservableValue<ActualMountService> provideMountService(Settings settings, List<MountService> serviceImpls) {
var fallbackProvider = serviceImpls.stream().findFirst().orElse(null);
return ObservableUtil.mapWithDefault(settings.mountService(), //
desiredServiceImpl -> { //
var desiredService = serviceImpls.stream().filter(serviceImpl -> serviceImpl.getClass().getName().equals(desiredServiceImpl)).findAny(); //
return new ActualMountService(desiredService.orElse(fallbackProvider), desiredService.isPresent()); //
}, //
new ActualMountService(fallbackProvider, true));
}
*/
@Provides
@Singleton
static ActualMountService provideActualMountService(Settings settings, List<MountService> serviceImpls) {
var fallbackProvider = serviceImpls.stream().findFirst().orElse(null);
var desiredService = serviceImpls.stream().filter(serviceImpl -> serviceImpl.getClass().getName().equals(settings.mountService().getValue())).findFirst(); //
return new ActualMountService(desiredService.orElse(fallbackProvider), desiredService.isPresent()); //
}
@Provides
@Singleton
static ObservableValue<ActualMountService> provideMountService(ActualMountService service) {
return new SimpleObjectProperty<>(service);
}
}
@@ -0,0 +1,8 @@
package org.cryptomator.common.mount;
public class MountPointNotExistsException extends IllegalMountPointException {
public MountPointNotExistsException(String msg) {
super(msg);
}
}
@@ -0,0 +1,8 @@
package org.cryptomator.common.mount;
public class MountPointNotSupportedException extends IllegalMountPointException {
public MountPointNotSupportedException(String msg) {
super(msg);
}
}
@@ -0,0 +1,8 @@
package org.cryptomator.common.mount;
public class MountPointPreparationException extends RuntimeException {
public MountPointPreparationException(Throwable cause) {
super(cause);
}
}
@@ -0,0 +1,110 @@
package org.cryptomator.common.mount;
import org.apache.commons.lang3.SystemUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.nio.file.DirectoryNotEmptyException;
import java.nio.file.FileAlreadyExistsException;
import java.nio.file.Files;
import java.nio.file.LinkOption;
import java.nio.file.NoSuchFileException;
import java.nio.file.NotDirectoryException;
import java.nio.file.Path;
public final class MountWithinParentUtil {
private static final Logger LOG = LoggerFactory.getLogger(Mounter.class);
private static final String HIDEAWAY_PREFIX = ".~$";
private static final String HIDEAWAY_SUFFIX = ".tmp";
private static final String WIN_HIDDEN_ATTR = "dos:hidden";
private MountWithinParentUtil() {}
static void prepareParentNoMountPoint(Path mountPoint) throws MountPointPreparationException {
Path hideaway = getHideaway(mountPoint);
var mpExists = Files.exists(mountPoint, LinkOption.NOFOLLOW_LINKS);
var hideExists = Files.exists(hideaway, LinkOption.NOFOLLOW_LINKS);
//TODO: possible improvement by just deleting an _empty_ hideaway
if (mpExists && hideExists) { //both resources exist (whatever type)
throw new MountPointPreparationException(new FileAlreadyExistsException(hideaway.toString()));
} else if (!mpExists && !hideExists) { //neither mountpoint nor hideaway exist
throw new MountPointPreparationException(new NoSuchFileException(mountPoint.toString()));
} else if (!mpExists) { //only hideaway exists
checkIsDirectory(hideaway);
LOG.info("Mountpoint {} seems to be not properly cleaned up. Will be fixed on unmount.", mountPoint);
try {
if (SystemUtils.IS_OS_WINDOWS) {
Files.setAttribute(hideaway, WIN_HIDDEN_ATTR, true, LinkOption.NOFOLLOW_LINKS);
}
} catch (IOException e) {
throw new MountPointPreparationException(e);
}
} else { //only mountpoint exists
try {
checkIsDirectory(mountPoint);
checkIsEmpty(mountPoint);
Files.move(mountPoint, hideaway);
if (SystemUtils.IS_OS_WINDOWS) {
Files.setAttribute(hideaway, WIN_HIDDEN_ATTR, true, LinkOption.NOFOLLOW_LINKS);
}
} catch (IOException e) {
throw new MountPointPreparationException(e);
}
}
}
static void cleanup(Path mountPoint) {
Path hideaway = getHideaway(mountPoint);
try {
waitForMountpointRestoration(mountPoint);
Files.move(hideaway, mountPoint);
if (SystemUtils.IS_OS_WINDOWS) {
Files.setAttribute(mountPoint, WIN_HIDDEN_ATTR, false);
}
} catch (IOException e) {
LOG.error("Unable to restore hidden directory to mountpoint {}.", mountPoint, e);
}
}
//on Windows removing the mountpoint takes some time, so we poll for at most 3 seconds
private static void waitForMountpointRestoration(Path mountPoint) throws FileAlreadyExistsException {
int attempts = 0;
while (!Files.notExists(mountPoint, LinkOption.NOFOLLOW_LINKS)) {
attempts++;
if (attempts >= 5) {
throw new FileAlreadyExistsException("Timeout waiting for mountpoint cleanup for " + mountPoint + " .");
}
try {
Thread.sleep(300);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new FileAlreadyExistsException("Interrupted before mountpoint " + mountPoint + " was cleared");
}
}
}
private static void checkIsDirectory(Path toCheck) throws MountPointPreparationException {
if (!Files.isDirectory(toCheck, LinkOption.NOFOLLOW_LINKS)) {
throw new MountPointPreparationException(new NotDirectoryException(toCheck.toString()));
}
}
private static void checkIsEmpty(Path toCheck) throws MountPointPreparationException, IOException {
try (var dirStream = Files.list(toCheck)) {
if (dirStream.findFirst().isPresent()) {
throw new MountPointPreparationException(new DirectoryNotEmptyException(toCheck.toString()));
}
}
}
//visible for testing
static Path getHideaway(Path mountPoint) {
return mountPoint.resolveSibling(HIDEAWAY_PREFIX + mountPoint.getFileName().toString() + HIDEAWAY_SUFFIX);
}
}
@@ -0,0 +1,141 @@
package org.cryptomator.common.mount;
import org.cryptomator.common.Environment;
import org.cryptomator.common.settings.Settings;
import org.cryptomator.common.settings.VaultSettings;
import org.cryptomator.integrations.mount.Mount;
import org.cryptomator.integrations.mount.MountBuilder;
import org.cryptomator.integrations.mount.MountFailedException;
import org.cryptomator.integrations.mount.MountService;
import javax.inject.Inject;
import javax.inject.Singleton;
import javafx.beans.value.ObservableValue;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import static org.cryptomator.integrations.mount.MountCapability.MOUNT_AS_DRIVE_LETTER;
import static org.cryptomator.integrations.mount.MountCapability.MOUNT_TO_EXISTING_DIR;
import static org.cryptomator.integrations.mount.MountCapability.MOUNT_TO_SYSTEM_CHOSEN_PATH;
import static org.cryptomator.integrations.mount.MountCapability.MOUNT_WITHIN_EXISTING_PARENT;
import static org.cryptomator.integrations.mount.MountCapability.UNMOUNT_FORCED;
@Singleton
public class Mounter {
private final Settings settings;
private final Environment env;
private final WindowsDriveLetters driveLetters;
private final ObservableValue<ActualMountService> mountServiceObservable;
@Inject
public Mounter(Settings settings, Environment env, WindowsDriveLetters driveLetters, ObservableValue<ActualMountService> mountServiceObservable) {
this.settings = settings;
this.env = env;
this.driveLetters = driveLetters;
this.mountServiceObservable = mountServiceObservable;
}
private class SettledMounter {
private MountService service;
private MountBuilder builder;
private VaultSettings vaultSettings;
public SettledMounter(MountService service, MountBuilder builder, VaultSettings vaultSettings) {
this.service = service;
this.builder = builder;
this.vaultSettings = vaultSettings;
}
Runnable prepare() throws IOException {
for (var capability : service.capabilities()) {
switch (capability) {
case FILE_SYSTEM_NAME -> builder.setFileSystemName("cryptoFs");
case LOOPBACK_PORT ->
builder.setLoopbackPort(settings.port().get()); //TODO: move port from settings to vaultsettings (see https://github.com/cryptomator/cryptomator/tree/feature/mount-setting-per-vault)
case LOOPBACK_HOST_NAME -> env.getLoopbackAlias().ifPresent(builder::setLoopbackHostName);
case READ_ONLY -> builder.setReadOnly(vaultSettings.usesReadOnlyMode().get());
case MOUNT_FLAGS -> {
var mountFlags = vaultSettings.mountFlags().get();
if (mountFlags == null || mountFlags.isBlank()) {
builder.setMountFlags(service.getDefaultMountFlags());
} else {
builder.setMountFlags(mountFlags);
}
}
case VOLUME_ID -> builder.setVolumeId(vaultSettings.getId());
case VOLUME_NAME -> builder.setVolumeName(vaultSettings.mountName().get());
}
}
return prepareMountPoint();
}
private Runnable prepareMountPoint() throws IOException {
Runnable cleanup = () -> {};
var userChosenMountPoint = vaultSettings.getMountPoint();
var defaultMountPointBase = env.getMountPointsDir().orElseThrow();
var canMountToDriveLetter = service.hasCapability(MOUNT_AS_DRIVE_LETTER);
var canMountToParent = service.hasCapability(MOUNT_WITHIN_EXISTING_PARENT);
var canMountToDir = service.hasCapability(MOUNT_TO_EXISTING_DIR);
var canMountToSystem = service.hasCapability(MOUNT_TO_SYSTEM_CHOSEN_PATH);
if (userChosenMountPoint == null) {
if (canMountToSystem) {
// no need to set a mount point
} else if (canMountToDriveLetter) {
builder.setMountpoint(driveLetters.getFirstDesiredAvailable().orElseThrow()); //TODO: catch exception and translate
} else if (canMountToParent) {
Files.createDirectories(defaultMountPointBase);
builder.setMountpoint(defaultMountPointBase);
} else if (canMountToDir) {
var mountPoint = defaultMountPointBase.resolve(vaultSettings.mountName().get());
Files.createDirectories(mountPoint);
builder.setMountpoint(mountPoint);
}
} else {
var mpIsDriveLetter = userChosenMountPoint.toString().matches("[A-Z]:\\\\");
if (!mpIsDriveLetter && canMountToParent && !canMountToDir) {
MountWithinParentUtil.prepareParentNoMountPoint(userChosenMountPoint);
cleanup = () -> {
MountWithinParentUtil.cleanup(userChosenMountPoint);
};
}
try {
builder.setMountpoint(userChosenMountPoint);
} catch (IllegalArgumentException | UnsupportedOperationException e) {
var configNotSupported = (!canMountToDriveLetter && mpIsDriveLetter) //mounting as driveletter, albeit not supported
|| (!canMountToDir && !mpIsDriveLetter) //mounting to directory, albeit not supported
|| (!canMountToParent && !mpIsDriveLetter) //
|| (!canMountToDir && !canMountToParent && !canMountToSystem && !canMountToDriveLetter);
if (configNotSupported) {
throw new MountPointNotSupportedException(e.getMessage());
} else if (canMountToDir && !canMountToParent && !Files.exists(userChosenMountPoint)) {
//mountpoint must exist
throw new MountPointNotExistsException(e.getMessage());
} else {
//TODO: add specific exception for !canMountToDir && canMountToParent && !Files.notExists(userChosenMountPoint)
throw new IllegalMountPointException(e.getMessage());
}
}
}
return cleanup;
}
}
public MountHandle mount(VaultSettings vaultSettings, Path cryptoFsRoot) throws IOException, MountFailedException {
var mountService = this.mountServiceObservable.getValue().service();
var builder = mountService.forFileSystem(cryptoFsRoot);
var internal = new SettledMounter(mountService, builder, vaultSettings);
var cleanup = internal.prepare();
return new MountHandle(builder.mount(), mountService.hasCapability(UNMOUNT_FORCED), cleanup);
}
public record MountHandle(Mount mountObj, boolean supportsUnmountForced, Runnable specialCleanup) {
}
}
@@ -76,6 +76,11 @@ public class DeviceKey {
private P384KeyPair createAndStoreNewKeyPair(char[] passphrase, Path p12File) throws IOException {
var keyPair = P384KeyPair.generate();
var tmpFile = p12File.resolveSibling(p12File.getFileName().toString() + ".tmp");
if(Files.exists(tmpFile)) {
LOG.debug("Leftover from devicekey creation detected. Deleting {}", tmpFile);
Files.delete(tmpFile);
}
LOG.debug("Store new device key to {}", p12File);
keyPair.store(p12File, passphrase);
return keyPair;
@@ -9,6 +9,7 @@ import com.google.gson.TypeAdapter;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonToken;
import com.google.gson.stream.JsonWriter;
import org.apache.commons.lang3.SystemUtils;
import org.cryptomator.common.Environment;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -36,6 +37,7 @@ public class SettingsJsonAdapter extends TypeAdapter<Settings> {
@Override
public void write(JsonWriter out, Settings value) throws IOException {
out.beginObject();
out.name("lastWrittenByVersion").value(env.getAppVersion()+env.getBuildNumber().map("-"::concat).orElse(""));
out.name("directories");
writeVaultSettingsArray(out, value.getDirectories());
out.name("askedForUpdateCheck").value(value.askedForUpdateCheck().get());
@@ -73,7 +75,9 @@ public class SettingsJsonAdapter extends TypeAdapter<Settings> {
@Override
public Settings read(JsonReader in) throws IOException {
Settings settings = new Settings(env);
//1.6.x legacy
String volumeImpl = null;
//legacy end
in.beginObject();
while (in.hasNext()) {
String name = in.nextName();
@@ -105,18 +109,49 @@ public class SettingsJsonAdapter extends TypeAdapter<Settings> {
settings.mountService().set(in.nextString());
}
}
//1.6.x legacy
case "preferredVolumeImpl" -> volumeImpl = in.nextString();
//legacy end
default -> {
LOG.warn("Unsupported vault setting found in JSON: {}", name);
in.skipValue();
}
}
}
in.endObject();
//1.6.x legacy
if (volumeImpl != null) {
settings.mountService().set(convertLegacyVolumeImplToMountService(volumeImpl));
}
//legacy end
return settings;
}
private String convertLegacyVolumeImplToMountService(String volumeImpl) {
if (volumeImpl.equals("Dokany")) {
return "org.cryptomator.frontend.dokany.mount.DokanyMountProvider";
} else if (volumeImpl.equals("FUSE")) {
if(SystemUtils.IS_OS_WINDOWS) {
return "org.cryptomator.frontend.fuse.mount.WinFspNetworkMountProvider";
} else if (SystemUtils.IS_OS_MAC) {
return "org.cryptomator.frontend.fuse.mount.MacFuseMountProvider";
} else {
return "org.cryptomator.frontend.fuse.mount.LinuxFuseMountProvider";
}
} else {
if(SystemUtils.IS_OS_WINDOWS) {
return "org.cryptomator.frontend.webdav.mount.WindowsMounter";
} else if (SystemUtils.IS_OS_MAC) {
return "org.cryptomator.frontend.webdav.mount.MacAppleScriptMounter";
} else {
return "org.cryptomator.frontend.webdav.mount.LinuxGioMounter";
}
}
}
private UiTheme parseUiTheme(String uiThemeName) {
try {
return UiTheme.valueOf(uiThemeName.toUpperCase());
@@ -45,7 +45,7 @@ public class VaultSettings {
private final BooleanProperty unlockAfterStartup = new SimpleBooleanProperty(DEFAULT_UNLOCK_AFTER_STARTUP);
private final BooleanProperty revealAfterMount = new SimpleBooleanProperty(DEFAULT_REVEAL_AFTER_MOUNT);
private final BooleanProperty usesReadOnlyMode = new SimpleBooleanProperty(DEFAULT_USES_READONLY_MODE);
private final StringProperty mountFlags = new SimpleStringProperty(DEFAULT_MOUNT_FLAGS);
private final StringProperty mountFlags = new SimpleStringProperty(DEFAULT_MOUNT_FLAGS); //TODO: remove empty default mount flags and let this property be null if not used
private final IntegerProperty maxCleartextFilenameLength = new SimpleIntegerProperty(DEFAULT_MAX_CLEARTEXT_FILENAME_LENGTH);
private final ObjectProperty<WhenUnlocked> actionAfterUnlock = new SimpleObjectProperty<>(DEFAULT_ACTION_AFTER_UNLOCK);
private final BooleanProperty autoLockWhenIdle = new SimpleBooleanProperty(DEFAULT_AUTOLOCK_WHEN_IDLE);
@@ -38,8 +38,6 @@ class VaultSettingsJsonAdapter {
out.endObject();
}
//TODO: usesCustomMountPath, customMountPath and winDriveLetter removed
// -> migration required
public VaultSettings read(JsonReader in) throws IOException {
String id = null;
String path = null;
@@ -55,6 +53,12 @@ class VaultSettingsJsonAdapter {
boolean autoLockWhenIdle = VaultSettings.DEFAULT_AUTOLOCK_WHEN_IDLE;
int autoLockIdleSeconds = VaultSettings.DEFAULT_AUTOLOCK_IDLE_SECONDS;
//legacy from 1.6.x
boolean useCustomMountPath = false;
String customMountPath = "";
String winDriveLetter = "";
//legacy end
in.beginObject();
while (in.hasNext()) {
String name = in.nextName();
@@ -78,6 +82,11 @@ class VaultSettingsJsonAdapter {
case "actionAfterUnlock" -> actionAfterUnlock = parseActionAfterUnlock(in.nextString());
case "autoLockWhenIdle" -> autoLockWhenIdle = in.nextBoolean();
case "autoLockIdleSeconds" -> autoLockIdleSeconds = in.nextInt();
//legacy from 1.6.x
case "winDriveLetter" -> winDriveLetter = in.nextString();
case "usesIndividualMountPath", "useCustomMountPath" -> useCustomMountPath = in.nextBoolean();
case "individualMountPath", "customMountPath" -> customMountPath = in.nextString();
//legacy end
default -> {
LOG.warn("Unsupported vault setting found in JSON: {}", name);
in.skipValue();
@@ -102,6 +111,13 @@ class VaultSettingsJsonAdapter {
vaultSettings.autoLockWhenIdle().set(autoLockWhenIdle);
vaultSettings.autoLockIdleSeconds().set(autoLockIdleSeconds);
vaultSettings.mountPoint().set(mountPoint);
//legacy from 1.6.x
if(useCustomMountPath && !customMountPath.isBlank()) {
vaultSettings.mountPoint().set(parseMountPoint(customMountPath));
} else if(!winDriveLetter.isBlank() ) {
vaultSettings.mountPoint().set(parseMountPoint(winDriveLetter+":\\"));
}
//legacy end
return vaultSettings;
}
@@ -1,18 +0,0 @@
package org.cryptomator.common.settings;
public enum VolumeImpl {
WEBDAV("WebDAV"),
FUSE("FUSE"),
DOKANY("Dokany");
private String displayName;
VolumeImpl(String displayName) {
this.displayName = displayName;
}
public String getDisplayName() {
return displayName;
}
}
@@ -8,12 +8,10 @@
*******************************************************************************/
package org.cryptomator.common.vaults;
import com.google.common.base.Strings;
import org.apache.commons.lang3.SystemUtils;
import org.cryptomator.common.Constants;
import org.cryptomator.common.Environment;
import org.cryptomator.common.mount.Mounter;
import org.cryptomator.common.mount.WindowsDriveLetters;
import org.cryptomator.common.settings.Settings;
import org.cryptomator.common.settings.VaultSettings;
import org.cryptomator.cryptofs.CryptoFileSystem;
import org.cryptomator.cryptofs.CryptoFileSystemProperties;
@@ -23,11 +21,7 @@ import org.cryptomator.cryptofs.common.FileSystemCapabilityChecker;
import org.cryptomator.cryptolib.api.CryptoException;
import org.cryptomator.cryptolib.api.MasterkeyLoader;
import org.cryptomator.cryptolib.api.MasterkeyLoadingFailedException;
import org.cryptomator.integrations.mount.Mount;
import org.cryptomator.integrations.mount.MountBuilder;
import org.cryptomator.integrations.mount.MountCapability;
import org.cryptomator.integrations.mount.MountFailedException;
import org.cryptomator.integrations.mount.MountService;
import org.cryptomator.integrations.mount.Mountpoint;
import org.cryptomator.integrations.mount.UnmountFailedException;
import org.slf4j.Logger;
@@ -44,9 +38,7 @@ import javafx.beans.property.BooleanProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.ReadOnlyStringProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.value.ObservableValue;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.EnumSet;
@@ -54,11 +46,6 @@ import java.util.Objects;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
import static org.cryptomator.integrations.mount.MountCapability.MOUNT_AS_DRIVE_LETTER;
import static org.cryptomator.integrations.mount.MountCapability.MOUNT_TO_EXISTING_DIR;
import static org.cryptomator.integrations.mount.MountCapability.MOUNT_TO_SYSTEM_CHOSEN_PATH;
import static org.cryptomator.integrations.mount.MountCapability.MOUNT_WITHIN_EXISTING_PARENT;
@PerVault
public class Vault {
@@ -66,14 +53,10 @@ public class Vault {
private static final Path HOME_DIR = Paths.get(SystemUtils.USER_HOME);
private static final int UNLIMITED_FILENAME_LENGTH = Integer.MAX_VALUE;
private final Environment env;
private final Settings settings;
private final VaultSettings vaultSettings;
private final AtomicReference<CryptoFileSystem> cryptoFileSystem;
private final VaultState state;
private final ObjectProperty<Exception> lastKnownException;
private final ObservableValue<MountService> mountService;
private final ObservableValue<String> defaultMountFlags;
private final VaultConfigCache configCache;
private final VaultStats stats;
private final StringBinding displayablePath;
@@ -84,22 +67,18 @@ public class Vault {
private final BooleanBinding needsMigration;
private final BooleanBinding unknownError;
private final ObjectBinding<Mountpoint> mountPoint;
private final WindowsDriveLetters windowsDriveLetters;
private final Mounter mounter;
private final BooleanProperty showingStats;
private AtomicReference<MountHandle> mountHandle = new AtomicReference<>(null);
private AtomicReference<Mounter.MountHandle> mountHandle = new AtomicReference<>(null);
@Inject
Vault(Environment env, Settings settings, VaultSettings vaultSettings, VaultConfigCache configCache, AtomicReference<CryptoFileSystem> cryptoFileSystem, VaultState state, @Named("lastKnownException") ObjectProperty<Exception> lastKnownException, ObservableValue<MountService> mountService, VaultStats stats, WindowsDriveLetters windowsDriveLetters) {
this.env = env;
this.settings = settings;
Vault(VaultSettings vaultSettings, VaultConfigCache configCache, AtomicReference<CryptoFileSystem> cryptoFileSystem, VaultState state, @Named("lastKnownException") ObjectProperty<Exception> lastKnownException, VaultStats stats, WindowsDriveLetters windowsDriveLetters, Mounter mounter) {
this.vaultSettings = vaultSettings;
this.configCache = configCache;
this.cryptoFileSystem = cryptoFileSystem;
this.state = state;
this.lastKnownException = lastKnownException;
this.mountService = mountService;
this.defaultMountFlags = mountService.map(MountService::getDefaultMountFlags);
this.stats = stats;
this.displayablePath = Bindings.createStringBinding(this::getDisplayablePath, vaultSettings.path());
this.locked = Bindings.createBooleanBinding(this::isLocked, state);
@@ -109,7 +88,7 @@ public class Vault {
this.needsMigration = Bindings.createBooleanBinding(this::isNeedsMigration, state);
this.unknownError = Bindings.createBooleanBinding(this::isUnknownError, state);
this.mountPoint = Bindings.createObjectBinding(this::getMountPoint, state);
this.windowsDriveLetters = windowsDriveLetters;
this.mounter = mounter;
this.showingStats = new SimpleBooleanProperty(false);
}
@@ -159,45 +138,6 @@ public class Vault {
}
}
private MountBuilder prepareMount(Path cryptoRoot) throws IOException {
var mountProvider = mountService.getValue();
var builder = mountProvider.forFileSystem(cryptoRoot);
for (var capability : mountProvider.capabilities()) {
switch (capability) {
case FILE_SYSTEM_NAME -> builder.setFileSystemName("crypto");
case LOOPBACK_PORT -> builder.setLoopbackPort(settings.port().get()); //TODO: move port from settings to vaultsettings?
case LOOPBACK_HOST_NAME -> builder.setLoopbackHostName("cryptomator-vault"); //TODO: Read from system property
case READ_ONLY -> builder.setReadOnly(vaultSettings.usesReadOnlyMode().get());
case MOUNT_FLAGS -> builder.setMountFlags(defaultMountFlags.getValue()); // TODO use custom mount flags (pre-populated with default mount flags)
case VOLUME_ID -> builder.setVolumeId(vaultSettings.getId());
case VOLUME_NAME -> builder.setVolumeName(vaultSettings.mountName().get());
}
}
var userChosenMountPoint = vaultSettings.getMountPoint();
var defaultMountPointBase = env.getMountPointsDir().orElseThrow();
if (userChosenMountPoint == null) {
if (mountProvider.hasCapability(MOUNT_TO_SYSTEM_CHOSEN_PATH)) {
// no need to set a mount point
} else if (mountProvider.hasCapability(MOUNT_AS_DRIVE_LETTER)) {
builder.setMountpoint(windowsDriveLetters.getFirstDesiredAvailable().orElseThrow());
} else if (mountProvider.hasCapability(MOUNT_WITHIN_EXISTING_PARENT)) {
Files.createDirectories(defaultMountPointBase);
builder.setMountpoint(defaultMountPointBase);
} else if (mountProvider.hasCapability(MOUNT_TO_EXISTING_DIR) ) {
var mountPoint = defaultMountPointBase.resolve(vaultSettings.mountName().get());
Files.createDirectories(mountPoint);
builder.setMountpoint(mountPoint);
}
} else if (mountProvider.hasCapability(MOUNT_TO_EXISTING_DIR) || mountProvider.hasCapability(MOUNT_WITHIN_EXISTING_PARENT) || mountProvider.hasCapability(MOUNT_AS_DRIVE_LETTER)) {
// TODO: move the mount point away in case of MOUNT_WITHIN_EXISTING_PARENT?
builder.setMountpoint(userChosenMountPoint);
}
return builder;
}
public synchronized void unlock(MasterkeyLoader keyLoader) throws CryptoException, IOException, MountFailedException {
if (cryptoFileSystem.get() != null) {
throw new IllegalStateException("Already unlocked.");
@@ -207,8 +147,7 @@ public class Vault {
try {
cryptoFileSystem.set(fs);
var rootPath = fs.getRootDirectories().iterator().next();
var supportsForcedUnmount = mountService.getValue().hasCapability(MountCapability.UNMOUNT_FORCED);
var mountHandle = new MountHandle(prepareMount(rootPath).mount(), supportsForcedUnmount);
var mountHandle = mounter.mount(vaultSettings, rootPath);
success = this.mountHandle.compareAndSet(null, mountHandle);
} finally {
if (!success) {
@@ -217,7 +156,6 @@ public class Vault {
}
}
public synchronized void lock(boolean forced) throws UnmountFailedException, IOException {
var mountHandle = this.mountHandle.get();
if (mountHandle == null) {
@@ -225,14 +163,15 @@ public class Vault {
return;
}
if (forced && mountHandle.supportsUnmountForced) {
mountHandle.mount.unmountForced();
if (forced && mountHandle.supportsUnmountForced()) {
mountHandle.mountObj().unmountForced();
} else {
mountHandle.mount.unmount();
mountHandle.mountObj().unmount();
}
try {
mountHandle.mount.close();
mountHandle.mountObj().close();
mountHandle.specialCleanup().run();
} finally {
destroyCryptoFileSystem();
}
@@ -327,7 +266,7 @@ public class Vault {
public Mountpoint getMountPoint() {
var handle = mountHandle.get();
return handle == null ? null : handle.mount.getMountpoint();
return handle == null ? null : handle.mountObj().getMountpoint();
}
public StringBinding displayablePathProperty() {
@@ -375,35 +314,26 @@ public class Vault {
return vaultSettings.path().getValue();
}
public boolean isHavingCustomMountFlags() {
return !Strings.isNullOrEmpty(vaultSettings.mountFlags().get());
}
public ObservableValue<String> defaultMountFlagsProperty() {
return defaultMountFlags;
}
public String getDefaultMountFlags() {
return defaultMountFlags.getValue();
}
public String getEffectiveMountFlags() {
String mountFlags = vaultSettings.mountFlags().get();
if (Strings.isNullOrEmpty(mountFlags)) {
return ""; //TODO: should the provider provide dem defaults??
} else {
return mountFlags;
/**
* Gets from the cleartext path its ciphertext counterpart.
* The cleartext path has to start from the vault root (by starting with "/").
*
* @return Local os path to the ciphertext resource
* @throws IOException if an I/O error occurs
*/
public Path getCiphertextPath(String cleartextPath) throws IOException {
if (!cleartextPath.startsWith("/")) {
throw new IllegalArgumentException("Input path must be absolute from vault root by starting with \"/\".");
}
var fs = cryptoFileSystem.get();
var cryptoPath = fs.getPath(cleartextPath);
return fs.getCiphertextPath(cryptoPath);
}
public VaultConfigCache getVaultConfigCache() {
return configCache;
}
public void setCustomMountFlags(String mountFlags) {
vaultSettings.mountFlags().set(mountFlags);
}
public String getId() {
return vaultSettings.getId();
}
@@ -426,15 +356,12 @@ public class Vault {
}
}
/* TODO: reactivate/ needed at all?
public boolean supportsForcedUnmount() {
return volume.supportsForcedUnmount();
var mh = mountHandle.get();
if (mh == null) {
throw new IllegalStateException("Vault is not mounted");
}
return mountHandle.get().supportsUnmountForced();
}
*/
private record MountHandle(Mount mount, boolean supportsUnmountForced) {
}
}
@@ -84,6 +84,10 @@ public class LogbackConfigurator extends ContextAwareBase implements Configurato
upgrades.addAppender(upgrade);
upgrades.addAppender(file);
upgrades.setAdditive(false);
// configure fuse file locking logger:
Logger fuseLocking = context.getLogger("org.cryptomator.frontend.fuse.locks");
fuseLocking.setLevel(Level.OFF);
}
return ExecutionStatus.DO_NOT_INVOKE_NEXT_IF_ANY;
}
@@ -176,7 +176,7 @@ public class CreateNewVaultPasswordController implements FxController {
// 2. initialize vault:
try {
MasterkeyLoader loader = ignored -> masterkey.copy();
CryptoFileSystemProperties fsProps = CryptoFileSystemProperties.cryptoFileSystemProperties().withCipherCombo(CryptorProvider.Scheme.SIV_CTRMAC).withKeyLoader(loader).build();
CryptoFileSystemProperties fsProps = CryptoFileSystemProperties.cryptoFileSystemProperties().withCipherCombo(CryptorProvider.Scheme.SIV_GCM).withKeyLoader(loader).build();
CryptoFileSystemProvider.initialize(path, fsProps, DEFAULT_KEY_ID);
// 3. write vault-internal readme file:
@@ -13,6 +13,7 @@ public enum FxmlFile {
FORGET_PASSWORD("/fxml/forget_password.fxml"), //
HEALTH_START("/fxml/health_start.fxml"), //
HEALTH_CHECK_LIST("/fxml/health_check_list.fxml"), //
HUB_NO_KEYCHAIN("/fxml/hub_no_keychain.fxml"), //
HUB_AUTH_FLOW("/fxml/hub_auth_flow.fxml"), //
HUB_LICENSE_EXCEEDED("/fxml/hub_license_exceeded.fxml"), //
HUB_RECEIVE_KEY("/fxml/hub_receive_key.fxml"), //
@@ -25,6 +25,7 @@ public enum FontAwesome5Icon {
EYE_SLASH("\uF070"), //
FAST_FORWARD("\uF050"), //
FILE("\uF15B"), //
FILE_DOWNLOAD("\uF56D"), //
FILE_IMPORT("\uF56F"), //
FOLDER_OPEN("\uF07C"), //
FUNNEL("\uF0B0"), //
@@ -41,6 +42,7 @@ public enum FontAwesome5Icon {
PLUS("\uF067"), //
PRINT("\uF02F"), //
QUESTION("\uF128"), //
QUESTION_CIRCLE("\uf059"), //
REDO("\uF01E"), //
SEARCH("\uF002"), //
SPINNER("\uF110"), //
@@ -87,6 +87,13 @@ public abstract class HubKeyLoadingModule {
@StringKey(HubKeyLoadingStrategy.SCHEME_HUB_HTTPS)
abstract KeyLoadingStrategy bindHubKeyLoadingStrategyToHubHttps(HubKeyLoadingStrategy strategy);
@Provides
@FxmlScene(FxmlFile.HUB_NO_KEYCHAIN)
@KeyLoadingScoped
static Scene provideHubNoKeychainScene(@KeyLoading FxmlLoaderFactory fxmlLoaders) {
return fxmlLoaders.createScene(FxmlFile.HUB_NO_KEYCHAIN);
}
@Provides
@FxmlScene(FxmlFile.HUB_AUTH_FLOW)
@KeyLoadingScoped
@@ -136,6 +143,11 @@ public abstract class HubKeyLoadingModule {
return fxmlLoaders.createScene(FxmlFile.HUB_UNAUTHORIZED_DEVICE);
}
@Binds
@IntoMap
@FxControllerKey(NoKeychainController.class)
abstract FxController bindNoKeychainController(NoKeychainController controller);
@Binds
@IntoMap
@FxControllerKey(AuthFlowController.class)
@@ -3,6 +3,8 @@ package org.cryptomator.ui.keyloading.hub;
import com.google.common.base.Preconditions;
import com.nimbusds.jose.JWEObject;
import dagger.Lazy;
import org.cryptomator.common.keychain.KeychainManager;
import org.cryptomator.common.keychain.NoKeychainAccessProviderException;
import org.cryptomator.common.settings.DeviceKey;
import org.cryptomator.cryptolib.api.Masterkey;
import org.cryptomator.cryptolib.api.MasterkeyLoadingFailedException;
@@ -31,15 +33,19 @@ public class HubKeyLoadingStrategy implements KeyLoadingStrategy {
static final String SCHEME_HUB_HTTPS = SCHEME_PREFIX + "https";
private final Stage window;
private final KeychainManager keychainManager;
private final Lazy<Scene> authFlowScene;
private final Lazy<Scene> noKeychainScene;
private final CompletableFuture<JWEObject> result;
private final DeviceKey deviceKey;
@Inject
public HubKeyLoadingStrategy(@KeyLoading Stage window, @FxmlScene(FxmlFile.HUB_AUTH_FLOW) Lazy<Scene> authFlowScene, CompletableFuture<JWEObject> result, DeviceKey deviceKey, @Named("windowTitle") String windowTitle) {
public HubKeyLoadingStrategy(@KeyLoading Stage window, @FxmlScene(FxmlFile.HUB_AUTH_FLOW) Lazy<Scene> authFlowScene, @FxmlScene(FxmlFile.HUB_NO_KEYCHAIN) Lazy<Scene> noKeychainScene, CompletableFuture<JWEObject> result, DeviceKey deviceKey, KeychainManager keychainManager, @Named("windowTitle") String windowTitle) {
this.window = window;
this.keychainManager = keychainManager;
window.setTitle(windowTitle);
this.authFlowScene = authFlowScene;
this.noKeychainScene = noKeychainScene;
this.result = result;
this.deviceKey = deviceKey;
}
@@ -48,9 +54,16 @@ public class HubKeyLoadingStrategy implements KeyLoadingStrategy {
public Masterkey loadKey(URI keyId) throws MasterkeyLoadingFailedException {
Preconditions.checkArgument(keyId.getScheme().startsWith(SCHEME_PREFIX));
try {
startAuthFlow();
if (!keychainManager.isSupported()) {
throw new NoKeychainAccessProviderException();
}
var keypair = deviceKey.get();
showWindow(authFlowScene);
var jwe = result.get();
return JWEHelper.decrypt(jwe, deviceKey.get().getPrivate());
return JWEHelper.decrypt(jwe, keypair.getPrivate());
} catch (NoKeychainAccessProviderException e) {
showWindow(noKeychainScene);
throw new UnlockCancelledException("Unlock canceled due to missing prerequisites", e);
} catch (DeviceKey.DeviceKeyRetrievalException e) {
throw new MasterkeyLoadingFailedException("Failed to load keypair", e);
} catch (CancellationException e) {
@@ -63,9 +76,9 @@ public class HubKeyLoadingStrategy implements KeyLoadingStrategy {
}
}
private void startAuthFlow() {
private void showWindow(Lazy<Scene> scene) {
Platform.runLater(() -> {
window.setScene(authFlowScene.get());
window.setScene(scene.get());
window.show();
Window owner = window.getOwner();
if (owner != null) {
@@ -0,0 +1,31 @@
package org.cryptomator.ui.keyloading.hub;
import org.cryptomator.ui.common.FxController;
import org.cryptomator.ui.fxapp.FxApplicationWindows;
import org.cryptomator.ui.keyloading.KeyLoading;
import org.cryptomator.ui.preferences.SelectedPreferencesTab;
import javax.inject.Inject;
import javafx.stage.Stage;
public class NoKeychainController implements FxController {
private final Stage window;
private final FxApplicationWindows appWindows;
@Inject
public NoKeychainController(@KeyLoading Stage window, FxApplicationWindows appWindows) {
this.window = window;
this.appWindows = appWindows;
}
public void cancel() {
window.close();
}
public void openPreferences() {
appWindows.showPreferencesWindow(SelectedPreferencesTab.GENERAL);
window.close();
}
}
@@ -53,7 +53,7 @@ public class LockForcedController implements FxController {
}
public boolean isForceSupported() {
return false;//vault.supportsForcedUnmount(); TODO
return vault.supportsForcedUnmount();
}
}
@@ -3,33 +3,17 @@ package org.cryptomator.ui.mainwindow;
import org.apache.commons.lang3.SystemUtils;
import org.cryptomator.common.vaults.Vault;
import org.cryptomator.common.vaults.VaultListManager;
import org.cryptomator.cryptofs.CryptoFileSystemProvider;
import org.cryptomator.cryptofs.DirStructure;
import org.cryptomator.ui.common.FxController;
import org.cryptomator.ui.wrongfilealert.WrongFileAlertComponent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.inject.Inject;
import javafx.beans.Observable;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.ReadOnlyObjectProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.fxml.FXML;
import javafx.scene.input.DragEvent;
import javafx.scene.input.TransferMode;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.util.Set;
import java.util.stream.Collectors;
import static org.cryptomator.common.Constants.CRYPTOMATOR_FILENAME_EXT;
import static org.cryptomator.common.Constants.MASTERKEY_FILENAME;
import static org.cryptomator.common.Constants.VAULTCONFIG_FILENAME;
@MainWindowScoped
public class MainWindowController implements FxController {
@@ -37,28 +21,19 @@ public class MainWindowController implements FxController {
private static final Logger LOG = LoggerFactory.getLogger(MainWindowController.class);
private final Stage window;
private final VaultListManager vaultListManager;
private final ReadOnlyObjectProperty<Vault> selectedVault;
private final WrongFileAlertComponent.Builder wrongFileAlert;
private final BooleanProperty draggingOver = new SimpleBooleanProperty();
private final BooleanProperty draggingVaultOver = new SimpleBooleanProperty();
public StackPane root;
@Inject
public MainWindowController(@MainWindow Stage window, VaultListManager vaultListManager, ObjectProperty<Vault> selectedVault, WrongFileAlertComponent.Builder wrongFileAlert) {
public MainWindowController(@MainWindow Stage window, ObjectProperty<Vault> selectedVault) {
this.window = window;
this.vaultListManager = vaultListManager;
this.selectedVault = selectedVault;
this.wrongFileAlert = wrongFileAlert;
}
@FXML
public void initialize() {
LOG.trace("init MainWindowController");
root.setOnDragEntered(this::handleDragEvent);
root.setOnDragOver(this::handleDragEvent);
root.setOnDragDropped(this::handleDragEvent);
root.setOnDragExited(this::handleDragEvent);
if (SystemUtils.IS_OS_WINDOWS) {
root.getStyleClass().add("os-windows");
}
@@ -72,65 +47,4 @@ public class MainWindowController implements FxController {
}
}
private void handleDragEvent(DragEvent event) {
if (DragEvent.DRAG_ENTERED.equals(event.getEventType()) && event.getGestureSource() == null) {
draggingOver.set(true);
} else if (DragEvent.DRAG_OVER.equals(event.getEventType()) && event.getGestureSource() == null && event.getDragboard().hasFiles()) {
event.acceptTransferModes(TransferMode.ANY);
draggingVaultOver.set(event.getDragboard().getFiles().stream().map(File::toPath).anyMatch(this::containsVault));
} else if (DragEvent.DRAG_DROPPED.equals(event.getEventType()) && event.getGestureSource() == null && event.getDragboard().hasFiles()) {
Set<Path> vaultPaths = event.getDragboard().getFiles().stream().map(File::toPath).filter(this::containsVault).collect(Collectors.toSet());
if (vaultPaths.isEmpty()) {
wrongFileAlert.build().showWrongFileAlertWindow();
} else {
vaultPaths.forEach(this::addVault);
}
event.setDropCompleted(!vaultPaths.isEmpty());
event.consume();
} else if (DragEvent.DRAG_EXITED.equals(event.getEventType())) {
draggingOver.set(false);
draggingVaultOver.set(false);
}
}
private boolean containsVault(Path path) {
try {
if (path.getFileName().toString().endsWith(CRYPTOMATOR_FILENAME_EXT)) {
path = path.getParent();
}
return CryptoFileSystemProvider.checkDirStructureForVault(path, VAULTCONFIG_FILENAME, MASTERKEY_FILENAME) != DirStructure.UNRELATED;
} catch (IOException e) {
return false;
}
}
private void addVault(Path pathToVault) {
try {
if (pathToVault.getFileName().toString().endsWith(CRYPTOMATOR_FILENAME_EXT)) {
vaultListManager.add(pathToVault.getParent());
} else {
vaultListManager.add(pathToVault);
}
} catch (IOException e) {
LOG.debug("Not a vault: {}", pathToVault);
}
}
/* Getter/Setter */
public BooleanProperty draggingOverProperty() {
return draggingOver;
}
public boolean isDraggingOver() {
return draggingOver.get();
}
public BooleanProperty draggingVaultOverProperty() {
return draggingVaultOver;
}
public boolean isDraggingVaultOver() {
return draggingVaultOver.get();
}
}
@@ -1,54 +1,120 @@
package org.cryptomator.ui.mainwindow;
import com.google.common.base.Preconditions;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.tobiasdiez.easybind.EasyBind;
import org.cryptomator.common.vaults.Vault;
import org.cryptomator.common.vaults.VaultState;
import org.cryptomator.integrations.mount.Mountpoint;
import org.cryptomator.integrations.revealpath.RevealFailedException;
import org.cryptomator.integrations.revealpath.RevealPathService;
import org.cryptomator.ui.common.FxController;
import org.cryptomator.ui.common.VaultService;
import org.cryptomator.ui.fxapp.FxApplicationWindows;
import org.cryptomator.ui.stats.VaultStatisticsComponent;
import org.cryptomator.ui.wrongfilealert.WrongFileAlertComponent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.inject.Inject;
import javafx.beans.binding.Bindings;
import javafx.beans.binding.BooleanBinding;
import javafx.beans.binding.StringBinding;
import javafx.application.Platform;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.ReadOnlyObjectProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.value.ObservableValue;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.input.Clipboard;
import javafx.scene.input.ClipboardContent;
import javafx.scene.input.DataFormat;
import javafx.scene.input.DragEvent;
import javafx.scene.input.TransferMode;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
import java.net.URI;
import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.ResourceBundle;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
@MainWindowScoped
public class VaultDetailUnlockedController implements FxController {
private static final Logger LOG = LoggerFactory.getLogger(VaultDetailUnlockedController.class);
private static final String ACTIVE_CLASS = "active";
private final ReadOnlyObjectProperty<Vault> vault;
private final FxApplicationWindows appWindows;
private final VaultService vaultService;
private final WrongFileAlertComponent.Builder wrongFileAlert;
private final Stage mainWindow;
private final Optional<RevealPathService> revealPathService;
private final ResourceBundle resourceBundle;
private final LoadingCache<Vault, VaultStatisticsComponent> vaultStats;
private final VaultStatisticsComponent.Builder vaultStatsBuilder;
private final ObservableValue<Mountpoint> mountPoint;
private final ObservableValue<Boolean> accessibleViaPath;
private final ObservableValue<Boolean> accessibleViaUri;
private final ObservableValue<String> mountUri;
private final ObservableValue<String> mountPoint;
private final BooleanProperty draggingOver = new SimpleBooleanProperty();
private final BooleanProperty ciphertextPathsCopied = new SimpleBooleanProperty();
//FXML
public Button dropZone;
@Inject
public VaultDetailUnlockedController(ObjectProperty<Vault> vault, FxApplicationWindows appWindows, VaultService vaultService, VaultStatisticsComponent.Builder vaultStatsBuilder, @MainWindow Stage mainWindow) {
public VaultDetailUnlockedController(ObjectProperty<Vault> vault, FxApplicationWindows appWindows, VaultService vaultService, VaultStatisticsComponent.Builder vaultStatsBuilder, WrongFileAlertComponent.Builder wrongFileAlert, @MainWindow Stage mainWindow, Optional<RevealPathService> revealPathService, ResourceBundle resourceBundle) {
this.vault = vault;
this.appWindows = appWindows;
this.vaultService = vaultService;
this.wrongFileAlert = wrongFileAlert;
this.mainWindow = mainWindow;
this.revealPathService = revealPathService;
this.resourceBundle = resourceBundle;
this.vaultStats = CacheBuilder.newBuilder().weakValues().build(CacheLoader.from(this::buildVaultStats));
this.vaultStatsBuilder = vaultStatsBuilder;
this.mountPoint = vault.flatMap(Vault::mountPointProperty);
this.accessibleViaPath = mountPoint.map(m -> m instanceof Mountpoint.WithPath).orElse(false);
this.accessibleViaUri = mountPoint.map(m -> m instanceof Mountpoint.WithUri).orElse(false);
this.mountUri = mountPoint.map(Mountpoint::uri).map(URI::toASCIIString).orElse("");
var mp = vault.flatMap(Vault::mountPointProperty);
this.accessibleViaPath = mp.map(m -> m instanceof Mountpoint.WithPath).orElse(false);
this.accessibleViaUri = mp.map(m -> m instanceof Mountpoint.WithUri).orElse(false);
this.mountPoint = mp.map(m -> {
if (m instanceof Mountpoint.WithPath mwp) {
return mwp.path().toString();
} else {
return m.uri().toASCIIString();
}
});
}
public void initialize() {
dropZone.setOnDragEntered(this::handleDragEvent);
dropZone.setOnDragOver(this::handleDragEvent);
dropZone.setOnDragDropped(this::handleDragEvent);
dropZone.setOnDragExited(this::handleDragEvent);
EasyBind.includeWhen(dropZone.getStyleClass(), ACTIVE_CLASS, draggingOver);
}
private void handleDragEvent(DragEvent event) {
if (DragEvent.DRAG_OVER.equals(event.getEventType()) && event.getGestureSource() == null && event.getDragboard().hasFiles()) {
event.acceptTransferModes(TransferMode.LINK);
draggingOver.set(true);
} else if (DragEvent.DRAG_DROPPED.equals(event.getEventType()) && event.getGestureSource() == null && event.getDragboard().hasFiles()) {
List<Path> ciphertextPaths = event.getDragboard().getFiles().stream().map(File::toPath).map(this::getCiphertextPath).flatMap(Optional::stream).toList();
if (ciphertextPaths.isEmpty()) {
wrongFileAlert.build().showWrongFileAlertWindow();
} else {
revealOrCopyPaths(ciphertextPaths);
}
event.setDropCompleted(!ciphertextPaths.isEmpty());
event.consume();
} else if (DragEvent.DRAG_EXITED.equals(event.getEventType())) {
draggingOver.set(false);
}
}
private VaultStatisticsComponent buildVaultStats(Vault vault) {
@@ -62,7 +128,9 @@ public class VaultDetailUnlockedController implements FxController {
@FXML
public void copyMountUri() {
// TODO
ClipboardContent clipboardContent = new ClipboardContent();
clipboardContent.putString(mountPoint.getValue());
Clipboard.getSystemClipboard().setContent(clipboardContent);
}
@FXML
@@ -75,6 +143,69 @@ public class VaultDetailUnlockedController implements FxController {
vaultStats.getUnchecked(vault.get()).showVaultStatisticsWindow();
}
@FXML
public void chooseFileAndReveal() {
Preconditions.checkState(accessibleViaPath.getValue());
var fileChooser = new FileChooser();
fileChooser.setTitle(resourceBundle.getString("main.vaultDetail.filePickerTitle"));
fileChooser.setInitialDirectory(Path.of(mountPoint.getValue()).toFile());
var cleartextFile = fileChooser.showOpenDialog(mainWindow);
if (cleartextFile != null) {
var ciphertextPaths = getCiphertextPath(cleartextFile.toPath()).stream().toList();
revealOrCopyPaths(ciphertextPaths);
}
}
private boolean startsWithVaultAccessPoint(Path path) {
return path.startsWith(Path.of(mountPoint.getValue()));
}
private Optional<Path> getCiphertextPath(Path path) {
if (!startsWithVaultAccessPoint(path)) {
LOG.debug("Path does not start with access point of selected vault: {}", path);
return Optional.empty();
}
try {
var accessPoint = mountPoint.getValue();
var cleartextPath = path.toString().substring(accessPoint.length());
if (!cleartextPath.startsWith("/")) {
cleartextPath = "/" + cleartextPath;
}
return Optional.of(vault.get().getCiphertextPath(cleartextPath));
} catch (IOException e) {
LOG.warn("Unable to get ciphertext path from path: {}", path, e);
return Optional.empty();
}
}
private void revealOrCopyPaths(List<Path> paths) {
revealPathService.ifPresentOrElse(svc -> revealPaths(svc, paths), () -> {
LOG.warn("No service provider to reveal files found.");
copyPathsToClipboard(paths);
});
}
private void revealPaths(RevealPathService service, List<Path> paths) {
paths.forEach(path -> {
try {
LOG.debug("Revealing {}", path);
service.reveal(path);
} catch (RevealFailedException e) {
LOG.error("Revealing ciphertext file failed.", e);
}
});
}
private void copyPathsToClipboard(List<Path> paths) {
StringBuilder clipboardString = new StringBuilder();
paths.forEach(p -> clipboardString.append(p.toString()).append("\n"));
Clipboard.getSystemClipboard().setContent(Map.of(DataFormat.PLAIN_TEXT, clipboardString.toString()));
ciphertextPathsCopied.setValue(true);
CompletableFuture.delayedExecutor(2, TimeUnit.SECONDS, Platform::runLater).execute(() -> {
ciphertextPathsCopied.set(false);
});
}
/* Getter/Setter */
public ReadOnlyObjectProperty<Vault> vaultProperty() {
@@ -101,13 +232,19 @@ public class VaultDetailUnlockedController implements FxController {
return accessibleViaUri.getValue();
}
public ObservableValue<String> mountUriProperty() {
return mountUri;
public ObservableValue<String> mountPointProperty() {
return mountPoint;
}
public String getMountUri() {
return mountUri.getValue();
public String getMountPoint() {
return mountPoint.getValue();
}
public BooleanProperty ciphertextPathsCopiedProperty() {
return ciphertextPathsCopied;
}
public boolean isCiphertextPathsCopied() {
return ciphertextPathsCopied.get();
}
}
@@ -3,26 +3,43 @@ package org.cryptomator.ui.mainwindow;
import org.apache.commons.lang3.SystemUtils;
import org.cryptomator.common.vaults.Vault;
import org.cryptomator.common.vaults.VaultListManager;
import org.cryptomator.cryptofs.CryptoFileSystemProvider;
import org.cryptomator.cryptofs.DirStructure;
import org.cryptomator.ui.addvaultwizard.AddVaultWizardComponent;
import org.cryptomator.ui.common.FxController;
import org.cryptomator.ui.removevault.RemoveVaultComponent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.inject.Inject;
import javafx.beans.binding.Bindings;
import javafx.beans.binding.BooleanBinding;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.value.ObservableValue;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.scene.control.ListView;
import javafx.scene.input.ContextMenuEvent;
import javafx.scene.input.DragEvent;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.MouseEvent;
import javafx.scene.input.TransferMode;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.util.EnumSet;
import java.util.Set;
import java.util.stream.Collectors;
import static org.cryptomator.common.Constants.CRYPTOMATOR_FILENAME_EXT;
import static org.cryptomator.common.Constants.MASTERKEY_FILENAME;
import static org.cryptomator.common.Constants.VAULTCONFIG_FILENAME;
import static org.cryptomator.common.vaults.VaultState.Value.ERROR;
import static org.cryptomator.common.vaults.VaultState.Value.LOCKED;
import static org.cryptomator.common.vaults.VaultState.Value.MISSING;
@@ -31,6 +48,7 @@ import static org.cryptomator.common.vaults.VaultState.Value.NEEDS_MIGRATION;
@MainWindowScoped
public class VaultListController implements FxController {
private static final Logger LOG = LoggerFactory.getLogger(VaultListController.class);
private final Stage mainWindow;
private final ObservableList<Vault> vaults;
@@ -39,17 +57,21 @@ public class VaultListController implements FxController {
private final AddVaultWizardComponent.Builder addVaultWizard;
private final BooleanBinding emptyVaultList;
private final RemoveVaultComponent.Builder removeVaultDialogue;
private final VaultListManager vaultListManager;
private final BooleanProperty draggingVaultOver = new SimpleBooleanProperty();
public ListView<Vault> vaultList;
public StackPane root;
@Inject
VaultListController(@MainWindow Stage mainWindow, ObservableList<Vault> vaults, ObjectProperty<Vault> selectedVault, VaultListCellFactory cellFactory, AddVaultWizardComponent.Builder addVaultWizard, RemoveVaultComponent.Builder removeVaultDialogue) {
VaultListController(@MainWindow Stage mainWindow, ObservableList<Vault> vaults, ObjectProperty<Vault> selectedVault, VaultListCellFactory cellFactory, AddVaultWizardComponent.Builder addVaultWizard, RemoveVaultComponent.Builder removeVaultDialogue, VaultListManager vaultListManager) {
this.mainWindow = mainWindow;
this.vaults = vaults;
this.selectedVault = selectedVault;
this.cellFactory = cellFactory;
this.addVaultWizard = addVaultWizard;
this.removeVaultDialogue = removeVaultDialogue;
this.vaultListManager = vaultListManager;
this.emptyVaultList = Bindings.isEmpty(vaults);
@@ -100,6 +122,11 @@ public class VaultListController implements FxController {
keyEvent.consume();
}
});
root.setOnDragEntered(this::handleDragEvent);
root.setOnDragOver(this::handleDragEvent);
root.setOnDragDropped(this::handleDragEvent);
root.setOnDragExited(this::handleDragEvent);
}
private void deselect(MouseEvent released) {
@@ -128,6 +155,47 @@ public class VaultListController implements FxController {
}
}
private void handleDragEvent(DragEvent event) {
if (DragEvent.DRAG_OVER.equals(event.getEventType()) && event.getGestureSource() == null && event.getDragboard().hasFiles()) {
draggingVaultOver.set(event.getDragboard().getFiles().stream().map(File::toPath).anyMatch(this::containsVault));
if (draggingVaultOver.get()) {
event.acceptTransferModes(TransferMode.ANY);
}
} else if (DragEvent.DRAG_DROPPED.equals(event.getEventType()) && event.getGestureSource() == null && event.getDragboard().hasFiles()) {
Set<Path> vaultPaths = event.getDragboard().getFiles().stream().map(File::toPath).filter(this::containsVault).collect(Collectors.toSet());
if (!vaultPaths.isEmpty()) {
vaultPaths.forEach(this::addVault);
}
event.setDropCompleted(!vaultPaths.isEmpty());
event.consume();
} else if (DragEvent.DRAG_EXITED.equals(event.getEventType())) {
draggingVaultOver.set(false);
}
}
private boolean containsVault(Path path) {
try {
if (path.getFileName().toString().endsWith(CRYPTOMATOR_FILENAME_EXT)) {
path = path.getParent();
}
return CryptoFileSystemProvider.checkDirStructureForVault(path, VAULTCONFIG_FILENAME, MASTERKEY_FILENAME) != DirStructure.UNRELATED;
} catch (IOException e) {
return false;
}
}
private void addVault(Path pathToVault) {
try {
if (pathToVault.getFileName().toString().endsWith(CRYPTOMATOR_FILENAME_EXT)) {
vaultListManager.add(pathToVault.getParent());
} else {
vaultListManager.add(pathToVault);
}
} catch (IOException e) {
LOG.debug("Not a vault: {}", pathToVault);
}
}
// Getter and Setter
public BooleanBinding emptyVaultListProperty() {
@@ -138,4 +206,13 @@ public class VaultListController implements FxController {
return emptyVaultList.get();
}
public BooleanProperty draggingVaultOverProperty() {
return draggingVaultOver;
}
public boolean isDraggingVaultOver() {
return draggingVaultOver.get();
}
}
@@ -1,11 +1,14 @@
package org.cryptomator.ui.preferences;
import dagger.Lazy;
import org.cryptomator.common.ObservableUtil;
import org.cryptomator.common.settings.Settings;
import org.cryptomator.integrations.mount.MountCapability;
import org.cryptomator.integrations.mount.MountService;
import org.cryptomator.ui.common.FxController;
import javax.inject.Inject;
import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.beans.binding.BooleanExpression;
import javafx.beans.value.ObservableValue;
@@ -14,39 +17,58 @@ import javafx.scene.control.ChoiceBox;
import javafx.scene.control.TextField;
import javafx.util.StringConverter;
import java.util.List;
import java.util.Optional;
import java.util.ResourceBundle;
/**
* TODO: if WebDAV is selected under Windows, show warning that specific mount options (like selecting a directory as mount point) are _not_ supported
*/
@PreferencesScoped
public class VolumePreferencesController implements FxController {
private static final String DOCS_MOUNTING_URL = "https://docs.cryptomator.org/en/1.7/desktop/vault-mounting/";
private final Settings settings;
private final ObservableValue<MountService> selectedMountService;
private final ResourceBundle resourceBundle;
private final BooleanExpression loopbackPortSupported;
private final ObservableValue<Boolean> mountToDirSupported;
private final ObservableValue<Boolean> mountToDriveLetterSupported;
private final ObservableValue<Boolean> mountFlagsSupported;
private final ObservableValue<Boolean> readonlySupported;
private final Lazy<Application> application;
private final List<MountService> mountProviders;
public ChoiceBox<MountService> volumeTypeChoiceBox;
public TextField loopbackPortField;
public Button loopbackPortApplyButton;
@Inject
VolumePreferencesController(Settings settings, List<MountService> mountProviders, ObservableValue<MountService> selectedMountService) {
VolumePreferencesController(Settings settings, Lazy<Application> application, List<MountService> mountProviders, ResourceBundle resourceBundle) {
this.settings = settings;
this.application = application;
this.mountProviders = mountProviders;
this.selectedMountService = selectedMountService;
this.resourceBundle = resourceBundle;
var fallbackProvider = mountProviders.stream().findFirst().orElse(null);
this.selectedMountService = ObservableUtil.mapWithDefault(settings.mountService(), serviceName -> mountProviders.stream().filter(s -> s.getClass().getName().equals(serviceName)).findFirst().orElse(fallbackProvider), fallbackProvider);
this.loopbackPortSupported = BooleanExpression.booleanExpression(selectedMountService.map(s -> s.hasCapability(MountCapability.LOOPBACK_PORT)));
this.mountToDirSupported = selectedMountService.map(s -> s.hasCapability(MountCapability.MOUNT_WITHIN_EXISTING_PARENT) || s.hasCapability(MountCapability.MOUNT_TO_EXISTING_DIR));
this.mountToDriveLetterSupported = selectedMountService.map(s -> s.hasCapability(MountCapability.MOUNT_AS_DRIVE_LETTER));
this.mountFlagsSupported = selectedMountService.map(s -> s.hasCapability(MountCapability.MOUNT_FLAGS));
this.readonlySupported = selectedMountService.map(s -> s.hasCapability(MountCapability.READ_ONLY));
}
public void initialize() {
volumeTypeChoiceBox.getItems().add(null);
volumeTypeChoiceBox.getItems().addAll(mountProviders);
volumeTypeChoiceBox.setConverter(new MountServiceConverter());
volumeTypeChoiceBox.getSelectionModel().select(selectedMountService.getValue());
volumeTypeChoiceBox.valueProperty().addListener((observableValue, oldProvide, newProvider) -> settings.mountService().set(newProvider.getClass().getName()));
boolean autoSelected = settings.mountService().get() == null;
volumeTypeChoiceBox.getSelectionModel().select(autoSelected ? null : selectedMountService.getValue());
volumeTypeChoiceBox.valueProperty().addListener((observableValue, oldProvider, newProvider) -> {
var toSet = Optional.ofNullable(newProvider).map(nP -> nP.getClass().getName()).orElse(null);
settings.mountService().set(toSet);
});
loopbackPortField.setText(String.valueOf(settings.port().get()));
loopbackPortApplyButton.visibleProperty().bind(settings.port().asString().isNotEqualTo(loopbackPortField.textProperty()));
loopbackPortApplyButton.disableProperty().bind(Bindings.createBooleanBinding(this::validateLoopbackPort, loopbackPortField.textProperty()).not());
}
private boolean validateLoopbackPort() {
@@ -75,13 +97,49 @@ public class VolumePreferencesController implements FxController {
return loopbackPortSupported.get();
}
public ObservableValue<Boolean> readonlySupportedProperty() {
return readonlySupported;
}
public boolean isReadonlySupported() {
return readonlySupported.getValue();
}
public ObservableValue<Boolean> mountToDirSupportedProperty() {
return mountToDirSupported;
}
public boolean isMountToDirSupported() {
return mountToDirSupported.getValue();
}
public ObservableValue<Boolean> mountToDriveLetterSupportedProperty() {
return mountToDriveLetterSupported;
}
public boolean isMountToDriveLetterSupported() {
return mountToDriveLetterSupported.getValue();
}
public ObservableValue<Boolean> mountFlagsSupportedProperty() {
return mountFlagsSupported;
}
public boolean isMountFlagsSupported() {
return mountFlagsSupported.getValue();
}
/* Helpers */
private static class MountServiceConverter extends StringConverter<MountService> {
private class MountServiceConverter extends StringConverter<MountService> {
@Override
public String toString(MountService provider) {
return provider== null? "None" : provider.displayName(); //TODO: adjust message
if (provider == null) {
return resourceBundle.getString("preferences.volume.type.automatic");
} else {
return provider.displayName();
}
}
@Override
@@ -90,5 +148,7 @@ public class VolumePreferencesController implements FxController {
}
}
public void openDocs() {
application.get().getHostServices().showDocument(DOCS_MOUNTING_URL);
}
}
@@ -39,8 +39,8 @@ public class AwtTrayMenuController implements TrayMenuController {
}
@Override
public void showTrayIcon(byte[] rawImageData, Runnable defaultAction, String tooltip) throws TrayMenuException {
var image = Toolkit.getDefaultToolkit().createImage(rawImageData);
public void showTrayIcon(byte[] imageData, Runnable defaultAction, String tooltip) throws TrayMenuException {
var image = Toolkit.getDefaultToolkit().createImage(imageData);
trayIcon = new TrayIcon(image, tooltip, menu);
trayIcon.setImageAutoSize(true);
@@ -56,6 +56,15 @@ public class AwtTrayMenuController implements TrayMenuController {
}
}
@Override
public void updateTrayIcon(byte[] imageData) {
if (trayIcon == null) {
throw new IllegalStateException("Failed to update the icon as it has not yet been added");
}
var image = Toolkit.getDefaultToolkit().createImage(imageData);
trayIcon.setImage(image);
}
@Override
public void updateTrayMenu(List<TrayMenuItem> items) {
menu.removeAll();
@@ -67,7 +76,7 @@ public class AwtTrayMenuController implements TrayMenuController {
Preconditions.checkNotNull(this.trayIcon);
this.trayIcon.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
public void mousePressed(MouseEvent e) {
listener.run();
}
});
@@ -33,7 +33,9 @@ public class TrayMenuBuilder {
private static final Logger LOG = LoggerFactory.getLogger(TrayMenuBuilder.class);
private static final String TRAY_ICON_MAC = "/img/tray_icon_mac@2x.png";
private static final String TRAY_ICON = "/img/window_icon_32.png";
private static final String TRAY_ICON_UNLOCKED_MAC = "/img/tray_icon_unlocked_mac@2x.png";
private static final String TRAY_ICON = "/img/tray_icon.png";
private static final String TRAY_ICON_UNLOCKED = "/img/tray_icon_unlocked.png";
private final ResourceBundle resourceBundle;
private final VaultService vaultService;
@@ -62,8 +64,8 @@ public class TrayMenuBuilder {
v.displayNameProperty().addListener(this::vaultListChanged);
});
try (var image = getClass().getResourceAsStream(SystemUtils.IS_OS_MAC_OSX ? TRAY_ICON_MAC : TRAY_ICON)) {
trayMenu.showTrayIcon(image.readAllBytes(), this::showMainWindow, "Cryptomator");
try {
trayMenu.showTrayIcon(getAppropriateTrayIconImage(), this::showMainWindow, "Cryptomator");
trayMenu.onBeforeOpenMenu(() -> {
for (Vault vault : vaults) {
VaultListManager.redetermineVaultState(vault);
@@ -71,8 +73,6 @@ public class TrayMenuBuilder {
});
rebuildMenu();
initialized = true;
} catch (IOException e) {
throw new UncheckedIOException("Failed to load embedded resource", e);
} catch (TrayMenuException e) {
LOG.error("Adding tray icon failed", e);
}
@@ -84,6 +84,7 @@ public class TrayMenuBuilder {
private void vaultListChanged(@SuppressWarnings("unused") Observable observable) {
assert Platform.isFxApplicationThread();
trayMenu.updateTrayIcon(getAppropriateTrayIconImage());
rebuildMenu();
}
@@ -154,4 +155,22 @@ public class TrayMenuBuilder {
appWindows.showPreferencesWindow(SelectedPreferencesTab.ANY);
}
private byte[] getAppropriateTrayIconImage() {
boolean isAnyVaultUnlocked = vaults.stream().anyMatch(Vault::isUnlocked);
String resourceName;
if (SystemUtils.IS_OS_MAC_OSX) {
resourceName = isAnyVaultUnlocked ? TRAY_ICON_UNLOCKED_MAC : TRAY_ICON_MAC;
} else {
resourceName = isAnyVaultUnlocked ? TRAY_ICON_UNLOCKED : TRAY_ICON;
}
try (var image = getClass().getResourceAsStream(resourceName)) {
assert image != null;
return image.readAllBytes();
} catch (IOException e) {
throw new UncheckedIOException("Failed to load tray icon image: " + resourceName, e);
}
}
}
@@ -1,11 +1,18 @@
package org.cryptomator.ui.unlock;
import org.cryptomator.common.mount.MountPointNotExistsException;
import org.cryptomator.common.mount.MountPointNotSupportedException;
import org.cryptomator.common.vaults.Vault;
import org.cryptomator.ui.common.FxController;
import org.cryptomator.ui.controls.FormattedLabel;
import org.cryptomator.ui.fxapp.FxApplicationWindows;
import org.cryptomator.ui.preferences.SelectedPreferencesTab;
import javax.inject.Inject;
import javafx.fxml.FXML;
import javafx.stage.Stage;
import java.util.ResourceBundle;
import java.util.concurrent.atomic.AtomicReference;
//At the current point in time only the CustomMountPointChooser may cause this window to be shown.
@UnlockScoped
@@ -13,11 +20,32 @@ public class UnlockInvalidMountPointController implements FxController {
private final Stage window;
private final Vault vault;
private final AtomicReference<Throwable> unlockException;
private final FxApplicationWindows appWindows;
private final ResourceBundle resourceBundle;
public FormattedLabel dialogDescription;
@Inject
UnlockInvalidMountPointController(@UnlockWindow Stage window, @UnlockWindow Vault vault) {
UnlockInvalidMountPointController(@UnlockWindow Stage window, @UnlockWindow Vault vault, @UnlockWindow AtomicReference<Throwable> unlockException, FxApplicationWindows appWindows, ResourceBundle resourceBundle) {
this.window = window;
this.vault = vault;
this.unlockException = unlockException;
this.appWindows = appWindows;
this.resourceBundle = resourceBundle;
}
@FXML
public void initialize() {
var e = unlockException.get();
String translationKey = "unlock.error.customPath.description.generic";
if (e instanceof MountPointNotSupportedException) {
translationKey = "unlock.error.customPath.description.notSupported";
} else if (e instanceof MountPointNotExistsException) {
translationKey = "unlock.error.customPath.description.notExists";
}
dialogDescription.setFormat(resourceBundle.getString(translationKey));
dialogDescription.setArg1(e.getMessage());
}
@FXML
@@ -25,4 +53,10 @@ public class UnlockInvalidMountPointController implements FxController {
window.close();
}
@FXML
public void closeAndOpenPreferences() {
appWindows.showPreferencesWindow(SelectedPreferencesTab.VOLUME);
window.close();
}
}
@@ -23,6 +23,7 @@ import javafx.stage.Modality;
import javafx.stage.Stage;
import java.util.Map;
import java.util.ResourceBundle;
import java.util.concurrent.atomic.AtomicReference;
@Module(subcomponents = {KeyLoadingComponent.class})
abstract class UnlockModule {
@@ -57,6 +58,13 @@ abstract class UnlockModule {
return compBuilder.vault(vault).window(window).build().keyloadingStrategy();
}
@Provides
@UnlockWindow
@UnlockScoped
static AtomicReference<Throwable> unlockException() {
return new AtomicReference<>();
}
@Provides
@FxmlScene(FxmlFile.UNLOCK_SUCCESS)
@UnlockScoped
@@ -2,6 +2,7 @@ package org.cryptomator.ui.unlock;
import com.google.common.base.Throwables;
import dagger.Lazy;
import org.cryptomator.common.mount.IllegalMountPointException;
import org.cryptomator.common.vaults.Vault;
import org.cryptomator.common.vaults.VaultState;
import org.cryptomator.cryptolib.api.CryptoException;
@@ -20,6 +21,7 @@ import javafx.concurrent.Task;
import javafx.scene.Scene;
import javafx.stage.Stage;
import java.io.IOException;
import java.util.concurrent.atomic.AtomicReference;
/**
* A multi-step task that consists of background activities as well as user interaction.
@@ -38,9 +40,10 @@ public class UnlockWorkflow extends Task<Boolean> {
private final Lazy<Scene> invalidMountPointScene;
private final FxApplicationWindows appWindows;
private final KeyLoadingStrategy keyLoadingStrategy;
private final AtomicReference<Throwable> unlockFailedException;
@Inject
UnlockWorkflow(@UnlockWindow Stage window, @UnlockWindow Vault vault, VaultService vaultService, @FxmlScene(FxmlFile.UNLOCK_SUCCESS) Lazy<Scene> successScene, @FxmlScene(FxmlFile.UNLOCK_INVALID_MOUNT_POINT) Lazy<Scene> invalidMountPointScene, FxApplicationWindows appWindows, @UnlockWindow KeyLoadingStrategy keyLoadingStrategy) {
UnlockWorkflow(@UnlockWindow Stage window, @UnlockWindow Vault vault, VaultService vaultService, @FxmlScene(FxmlFile.UNLOCK_SUCCESS) Lazy<Scene> successScene, @FxmlScene(FxmlFile.UNLOCK_INVALID_MOUNT_POINT) Lazy<Scene> invalidMountPointScene, FxApplicationWindows appWindows, @UnlockWindow KeyLoadingStrategy keyLoadingStrategy, @UnlockWindow AtomicReference<Throwable> unlockFailedException) {
this.window = window;
this.vault = vault;
this.vaultService = vaultService;
@@ -48,6 +51,7 @@ public class UnlockWorkflow extends Task<Boolean> {
this.invalidMountPointScene = invalidMountPointScene;
this.appWindows = appWindows;
this.keyLoadingStrategy = keyLoadingStrategy;
this.unlockFailedException = unlockFailedException;
}
@Override
@@ -67,13 +71,15 @@ public class UnlockWorkflow extends Task<Boolean> {
} catch (Exception e) {
Throwables.propagateIfPossible(e, IOException.class);
Throwables.propagateIfPossible(e, CryptoException.class);
Throwables.propagateIfPossible(e, IllegalMountPointException.class);
Throwables.propagateIfPossible(e, MountFailedException.class);
throw new IllegalStateException("unexpected exception type", e);
}
}
private void showInvalidMountPointScene() {
private void handleIllegalMountPointError(IllegalMountPointException impe) {
Platform.runLater(() -> {
unlockFailedException.set(impe);
window.setScene(invalidMountPointScene.get());
window.show();
});
@@ -107,7 +113,11 @@ public class UnlockWorkflow extends Task<Boolean> {
protected void failed() {
LOG.info("Unlock of '{}' failed.", vault.getDisplayName());
Throwable throwable = super.getException();
handleGenericError(throwable);
if(throwable instanceof IllegalMountPointException impe) {
handleIllegalMountPointError(impe);
} else {
handleGenericError(throwable);
}
vault.stateProperty().transition(VaultState.Value.PROCESSING, VaultState.Value.LOCKED);
}
@@ -1,11 +1,14 @@
package org.cryptomator.ui.vaultoptions;
import org.cryptomator.common.Environment;
import com.google.common.base.Strings;
import org.cryptomator.common.mount.ActualMountService;
import org.cryptomator.common.mount.WindowsDriveLetters;
import org.cryptomator.common.settings.VaultSettings;
import org.cryptomator.common.vaults.Vault;
import org.cryptomator.integrations.mount.MountCapability;
import org.cryptomator.integrations.mount.MountService;
import org.cryptomator.ui.common.FxController;
import org.cryptomator.ui.fxapp.FxApplicationWindows;
import org.cryptomator.ui.preferences.SelectedPreferencesTab;
import javax.inject.Inject;
import javafx.beans.value.ObservableValue;
@@ -30,16 +33,17 @@ import java.util.Set;
public class MountOptionsController implements FxController {
private final Stage window;
private final Vault vault;
private final VaultSettings vaultSettings;
private final WindowsDriveLetters windowsDriveLetters;
private final ResourceBundle resourceBundle;
private final ObservableValue<String> defaultMountFlags;
private final ObservableValue<Boolean> mountpointDirSupported;
private final ObservableValue<Boolean> mountpointDriveLetterSupported;
private final ObservableValue<Boolean> readOnlySupported;
private final ObservableValue<Boolean> mountFlagsSupported;
private final ObservableValue<Path> driveLetter;
private final ObservableValue<String> directoryPath;
private final FxApplicationWindows applicationWindows;
//-- FXML objects --
@@ -54,59 +58,75 @@ public class MountOptionsController implements FxController {
public ChoiceBox<Path> driveLetterSelection;
@Inject
MountOptionsController(@VaultOptionsWindow Stage window, @VaultOptionsWindow Vault vault, ObservableValue<MountService> mountService, WindowsDriveLetters windowsDriveLetters, ResourceBundle resourceBundle, Environment environment) {
MountOptionsController(@VaultOptionsWindow Stage window, @VaultOptionsWindow Vault vault, ObservableValue<ActualMountService> mountService, WindowsDriveLetters windowsDriveLetters, ResourceBundle resourceBundle, FxApplicationWindows applicationWindows) {
this.window = window;
this.vault = vault;
this.vaultSettings = vault.getVaultSettings();
this.windowsDriveLetters = windowsDriveLetters;
this.resourceBundle = resourceBundle;
this.mountpointDirSupported = mountService.map(s -> s.hasCapability(MountCapability.MOUNT_TO_EXISTING_DIR) || s.hasCapability(MountCapability.MOUNT_WITHIN_EXISTING_PARENT));
this.mountpointDriveLetterSupported = mountService.map(s -> s.hasCapability(MountCapability.MOUNT_AS_DRIVE_LETTER));
this.mountFlagsSupported = mountService.map(s -> s.hasCapability(MountCapability.MOUNT_FLAGS));
this.readOnlySupported = mountService.map(s -> s.hasCapability(MountCapability.READ_ONLY));
this.driveLetter = vault.getVaultSettings().mountPoint().map(p -> isDriveLetter(p) ? p : null);
this.defaultMountFlags = mountService.map(as -> {
if (as.service().hasCapability(MountCapability.MOUNT_FLAGS)) {
return as.service().getDefaultMountFlags();
} else {
return "";
}
});
this.mountpointDirSupported = mountService.map(as -> as.service().hasCapability(MountCapability.MOUNT_TO_EXISTING_DIR) || as.service().hasCapability(MountCapability.MOUNT_WITHIN_EXISTING_PARENT));
this.mountpointDriveLetterSupported = mountService.map(as -> as.service().hasCapability(MountCapability.MOUNT_AS_DRIVE_LETTER));
this.mountFlagsSupported = mountService.map(as -> as.service().hasCapability(MountCapability.MOUNT_FLAGS));
this.readOnlySupported = mountService.map(as -> as.service().hasCapability(MountCapability.READ_ONLY));
this.directoryPath = vault.getVaultSettings().mountPoint().map(p -> isDriveLetter(p) ? null : p.toString());
this.applicationWindows = applicationWindows;
}
@FXML
public void initialize() {
// readonly:
readOnlyCheckbox.selectedProperty().bindBidirectional(vault.getVaultSettings().usesReadOnlyMode());
readOnlyCheckbox.selectedProperty().bindBidirectional(vaultSettings.usesReadOnlyMode());
// custom mount flags:
mountFlagsField.disableProperty().bind(customMountFlagsCheckbox.selectedProperty().not());
customMountFlagsCheckbox.setSelected(vault.isHavingCustomMountFlags());
customMountFlagsCheckbox.setSelected(!Strings.isNullOrEmpty(vaultSettings.mountFlags().getValue()));
toggleUseCustomMountFlags();
//driveLetter choice box
driveLetterSelection.getItems().addAll(windowsDriveLetters.getAll());
driveLetterSelection.setConverter(new WinDriveLetterLabelConverter(windowsDriveLetters, resourceBundle));
driveLetterSelection.setOnShowing(event -> driveLetterSelection.setConverter(new WinDriveLetterLabelConverter(windowsDriveLetters, resourceBundle))); //TODO: does this work?
//mountPoint toggle group
var mountPoint = vault.getVaultSettings().getMountPoint();
var mountPoint = vaultSettings.getMountPoint();
if (mountPoint == null) {
//prepare and select auto
mountPointToggleGroup.selectToggle(mountPointAutoBtn);
} else if (mountPoint.getParent() == null && isDriveLetter(mountPoint)) {
//prepare and select drive letter
mountPointToggleGroup.selectToggle(mountPointDriveLetterBtn);
} else if (driveLetterSelection.getValue() == null) {
driveLetterSelection.valueProperty().bindBidirectional(vaultSettings.mountPoint());
} else {
//prepare and select dir
mountPointToggleGroup.selectToggle(mountPointDirBtn);
}
mountPointToggleGroup.selectedToggleProperty().addListener(this::selectedToggleChanged);
}
@FXML
public void openVolumePreferences() {
applicationWindows.showPreferencesWindow(SelectedPreferencesTab.VOLUME);
}
@FXML
public void toggleUseCustomMountFlags() {
if (customMountFlagsCheckbox.isSelected()) {
readOnlyCheckbox.setSelected(false); // to prevent invalid states
mountFlagsField.textProperty().unbind();
vault.setCustomMountFlags(vault.defaultMountFlagsProperty().getValue());
mountFlagsField.textProperty().bindBidirectional(vault.getVaultSettings().mountFlags());
var mountFlags = vaultSettings.mountFlags().get();
if (mountFlags == null || mountFlags.isBlank()) {
vaultSettings.mountFlags().set(defaultMountFlags.getValue());
}
mountFlagsField.textProperty().bindBidirectional(vaultSettings.mountFlags());
} else {
mountFlagsField.textProperty().unbindBidirectional(vault.getVaultSettings().mountFlags());
vault.setCustomMountFlags(null);
mountFlagsField.textProperty().bind(vault.defaultMountFlagsProperty());
mountFlagsField.textProperty().unbindBidirectional(vaultSettings.mountFlags());
vaultSettings.mountFlags().set(null);
mountFlagsField.textProperty().bind(defaultMountFlags);
}
}
@@ -114,7 +134,7 @@ public class MountOptionsController implements FxController {
public void chooseCustomMountPoint() {
try {
Path chosenPath = chooseCustomMountPointInternal();
vault.getVaultSettings().mountPoint().set(chosenPath);
vaultSettings.mountPoint().set(chosenPath);
} catch (NoDirSelectedException e) {
//no-op
}
@@ -131,7 +151,7 @@ public class MountOptionsController implements FxController {
DirectoryChooser directoryChooser = new DirectoryChooser();
directoryChooser.setTitle(resourceBundle.getString("vaultOptions.mount.mountPoint.directoryPickerTitle"));
try {
var mp = vault.getVaultSettings().mountPoint().get();
var mp = vaultSettings.mountPoint().get();
var initialDir = mp != null && !isDriveLetter(mp) ? mp : Path.of(System.getProperty("user.home"));
if (Files.isDirectory(initialDir)) {
@@ -149,27 +169,30 @@ public class MountOptionsController implements FxController {
}
private void selectedToggleChanged(ObservableValue<? extends Toggle> observable, Toggle oldToggle, Toggle newToggle) {
Path mountPointToBe = null;
try {
//Remark: the mountpoint corresponding to the newToggle must be null, otherwise it would not be new!
if (mountPointDriveLetterBtn.equals(newToggle)) {
mountPointToBe = driveLetterSelection.getItems().get(0);
} else if (mountPointDirBtn.equals(newToggle)) {
mountPointToBe = chooseCustomMountPointInternal();
}
vault.getVaultSettings().mountPoint().set(mountPointToBe);
} catch (NoDirSelectedException e) {
if (!mountPointDirBtn.equals(oldToggle)) {
mountPointToggleGroup.selectToggle(oldToggle);
//Remark: the mountpoint corresponding to the newToggle must be null, otherwise it would not be new!
driveLetterSelection.valueProperty().unbindBidirectional(vaultSettings.mountPoint());
if (mountPointDriveLetterBtn.equals(newToggle)) {
vaultSettings.mountPoint().set(windowsDriveLetters.getFirstDesiredAvailable().orElse(windowsDriveLetters.getAll().stream().findAny().get()));
driveLetterSelection.valueProperty().bindBidirectional(vaultSettings.mountPoint());
} else if (mountPointDirBtn.equals(newToggle)) {
try {
vaultSettings.mountPoint().set(chooseCustomMountPointInternal());
} catch (NoDirSelectedException e) {
if (oldToggle != null && !mountPointDirBtn.equals(oldToggle)) {
mountPointToggleGroup.selectToggle(oldToggle);
} else {
mountPointToggleGroup.selectToggle(mountPointAutoBtn);
}
}
} else {
vaultSettings.mountPoint().set(null);
}
}
private boolean isDriveLetter(Path mountPoint) {
if (mountPoint != null) {
var s = mountPoint.toString();
return s.length() == 3 && mountPoint.toString().endsWith(":\\");
return s.length() == 3 && s.endsWith(":\\");
}
return false;
}
@@ -237,21 +260,13 @@ public class MountOptionsController implements FxController {
}
public ObservableValue<Boolean> readOnlySupportedProperty() {
return mountpointDriveLetterSupported;
return readOnlySupported;
}
public boolean isReadOnlySupported() {
return readOnlySupported.getValue();
}
public ObservableValue<Path> driveLetterProperty() {
return driveLetter;
}
public Path getDriveLetter() {
return driveLetter.getValue();
}
public ObservableValue<String> directoryPathProperty() {
return directoryPath;
}
@@ -259,5 +274,4 @@ public class MountOptionsController implements FxController {
public String getDirectoryPath() {
return directoryPath.getValue();
}
}
+48 -10
View File
@@ -204,16 +204,6 @@
-fx-effect: dropshadow(three-pass-box, rgba(0, 0, 0, 0.8), 2, 0, 0, 0);
}
.main-window .drag-n-drop-indicator {
-fx-border-color: SECONDARY;
-fx-border-width: 3px;
}
.main-window .drag-n-drop-indicator .drag-n-drop-header {
-fx-background-color: SECONDARY;
-fx-padding: 3px;
}
/*******************************************************************************
* *
* TabPane *
@@ -884,3 +874,51 @@
-fx-fill: linear-gradient(to bottom, PRIMARY, transparent);
-fx-stroke: transparent;
}
/*******************************************************************************
* *
* Drag and Drop *
* *
******************************************************************************/
.drag-n-drop-border {
-fx-border-color: SECONDARY;
-fx-border-width: 3px;
}
.button.drag-n-drop {
-fx-background-color: CONTROL_BG_NORMAL;
-fx-background-insets: 0;
-fx-padding: 1.4em 1em 1.4em 1em;
-fx-text-fill: TEXT_FILL_MUTED;
-fx-font-size: 0.8em;
-fx-border-color: CONTROL_BORDER_NORMAL;
-fx-border-radius: 4px;
-fx-border-style: dashed inside;
-fx-border-width: 1px;
}
.button.drag-n-drop:focused {
-fx-border-color: CONTROL_BORDER_FOCUSED;
}
.button.drag-n-drop:armed {
-fx-background-color: CONTROL_BG_ARMED;
}
.button.drag-n-drop.active {
-fx-border-color: SECONDARY;
-fx-border-style: solid inside;
-fx-border-width: 1px;
}
/*******************************************************************************
* *
* Separator *
* *
******************************************************************************/
.separator {
-fx-padding: 0.5px;
-fx-background-color: CONTROL_BORDER_NORMAL;
}
+48 -10
View File
@@ -203,16 +203,6 @@
-fx-effect: dropshadow(three-pass-box, rgba(0, 0, 0, 0.8), 2, 0, 0, 0);
}
.main-window .drag-n-drop-indicator {
-fx-border-color: SECONDARY;
-fx-border-width: 3px;
}
.main-window .drag-n-drop-indicator .drag-n-drop-header {
-fx-background-color: SECONDARY;
-fx-padding: 3px;
}
/*******************************************************************************
* *
* TabPane *
@@ -883,3 +873,51 @@
-fx-fill: linear-gradient(to bottom, PRIMARY, transparent);
-fx-stroke: transparent;
}
/*******************************************************************************
* *
* Drag and Drop *
* *
******************************************************************************/
.drag-n-drop-border {
-fx-border-color: SECONDARY;
-fx-border-width: 3px;
}
.button.drag-n-drop {
-fx-background-color: CONTROL_BG_NORMAL;
-fx-background-insets: 0;
-fx-padding: 1.4em 1em 1.4em 1em;
-fx-text-fill: TEXT_FILL_MUTED;
-fx-font-size: 0.8em;
-fx-border-color: CONTROL_BORDER_NORMAL;
-fx-border-radius: 4px;
-fx-border-style: dashed inside;
-fx-border-width: 1px;
}
.button.drag-n-drop:focused {
-fx-border-color: CONTROL_BORDER_FOCUSED;
}
.button.drag-n-drop:armed {
-fx-background-color: CONTROL_BG_ARMED;
}
.button.drag-n-drop.active {
-fx-border-color: SECONDARY;
-fx-border-style: solid inside;
-fx-border-width: 1px;
}
/*******************************************************************************
* *
* Separator *
* *
******************************************************************************/
.separator {
-fx-padding: 0.5px;
-fx-background-color: CONTROL_BORDER_NORMAL;
}
@@ -0,0 +1,56 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import org.cryptomator.ui.controls.FontAwesome5IconView?>
<?import org.cryptomator.ui.controls.FontAwesome5Spinner?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.ButtonBar?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.Group?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.Region?>
<?import javafx.scene.layout.StackPane?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.shape.Circle?>
<?import org.cryptomator.ui.controls.FormattedLabel?>
<HBox xmlns:fx="http://javafx.com/fxml"
xmlns="http://javafx.com/javafx"
fx:controller="org.cryptomator.ui.keyloading.hub.NoKeychainController"
minWidth="400"
maxWidth="400"
minHeight="145"
spacing="12"
alignment="TOP_LEFT">
<padding>
<Insets topRightBottomLeft="12"/>
</padding>
<children>
<Group>
<StackPane>
<padding>
<Insets topRightBottomLeft="6"/>
</padding>
<Circle styleClass="glyph-icon-primary" radius="24"/>
<FontAwesome5IconView styleClass="glyph-icon-white" glyph="EXCLAMATION" glyphSize="24"/>
</StackPane>
</Group>
<VBox HBox.hgrow="ALWAYS">
<Label styleClass="label-large" text="%hub.noKeychain.message" wrapText="true" textAlignment="LEFT">
<padding>
<Insets bottom="6" top="6"/>
</padding>
</Label>
<FormattedLabel format="%hub.noKeychain.description" arg1="%preferences.general.keychainBackend" wrapText="true" textAlignment="LEFT"/>
<Region VBox.vgrow="ALWAYS" minHeight="18"/>
<ButtonBar buttonMinWidth="120" buttonOrder="+CI">
<buttons>
<Button text="%generic.button.cancel" ButtonBar.buttonData="CANCEL_CLOSE" defaultButton="false" cancelButton="true" onAction="#cancel"/>
<Button text="%hub.noKeychain.openBtn" ButtonBar.buttonData="FINISH" defaultButton="true" onAction="#openPreferences"/>
</buttons>
</ButtonBar>
</VBox>
</children>
</HBox>
+4 -22
View File
@@ -1,10 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import org.cryptomator.ui.controls.FontAwesome5IconView?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.SplitPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.Region?>
<?import javafx.scene.layout.StackPane?>
<?import javafx.scene.layout.VBox?>
<StackPane xmlns:fx="http://javafx.com/fxml"
@@ -14,24 +10,10 @@
styleClass="main-window">
<VBox minWidth="650">
<fx:include source="main_window_title.fxml" VBox.vgrow="NEVER"/>
<StackPane VBox.vgrow="ALWAYS">
<SplitPane dividerPositions="0.33" orientation="HORIZONTAL">
<fx:include source="vault_list.fxml" SplitPane.resizableWithParent="false"/>
<fx:include source="vault_detail.fxml" SplitPane.resizableWithParent="true"/>
</SplitPane>
<VBox styleClass="drag-n-drop-indicator" visible="${controller.draggingOver}" alignment="TOP_CENTER">
<HBox visible="${!controller.draggingVaultOver}" managed="${!controller.draggingVaultOver}" spacing="6" styleClass="drag-n-drop-header" alignment="CENTER" VBox.vgrow="NEVER">
<FontAwesome5IconView glyph="EXCLAMATION_TRIANGLE"/>
<Label text="%main.dropZone.unknownDragboardContent"/>
</HBox>
<HBox visible="${controller.draggingVaultOver}" managed="${controller.draggingVaultOver}" spacing="6" styleClass="drag-n-drop-header" alignment="CENTER" VBox.vgrow="NEVER">
<FontAwesome5IconView glyph="CHECK"/>
<Label text="%main.dropZone.dropVault"/>
</HBox>
<Region VBox.vgrow="ALWAYS"/>
</VBox>
</StackPane>
<SplitPane dividerPositions="0.33" orientation="HORIZONTAL" VBox.vgrow="ALWAYS">
<fx:include source="vault_list.fxml" SplitPane.resizableWithParent="false"/>
<fx:include source="vault_detail.fxml" SplitPane.resizableWithParent="true"/>
</SplitPane>
</VBox>
<fx:include source="main_window_resize.fxml"/>
</StackPane>
+46 -8
View File
@@ -6,16 +6,20 @@
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.ButtonBar?>
<?import javafx.scene.control.CheckBox?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.StackPane?>
<?import javafx.scene.layout.Region?>
<?import javafx.scene.layout.RowConstraints?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.shape.Circle?>
<VBox xmlns:fx="http://javafx.com/fxml"
xmlns="http://javafx.com/javafx"
fx:controller="org.cryptomator.ui.migration.MigrationStartController"
minWidth="400"
maxWidth="400"
minHeight="145"
prefWidth="580"
prefHeight="350"
spacing="12">
<padding>
<Insets topRightBottomLeft="12"/>
@@ -23,13 +27,47 @@
<children>
<HBox spacing="12" alignment="CENTER_LEFT" VBox.vgrow="ALWAYS">
<StackPane alignment="CENTER" HBox.hgrow="NEVER">
<Circle styleClass="glyph-icon-primary" radius="24"/>
<FontAwesome5IconView styleClass="glyph-icon-white" glyph="FILE_IMPORT" glyphSize="24"/>
<padding>
<Insets left="12"/>
</padding>
<Circle styleClass="glyph-icon-primary" radius="48"/>
<FontAwesome5IconView styleClass="glyph-icon-white" glyph="FILE_IMPORT" glyphSize="48"/>
</StackPane>
<VBox spacing="6" HBox.hgrow="ALWAYS">
<FormattedLabel format="%migration.start.prompt" arg1="${controller.vault.displayName}" wrapText="true"/>
<CheckBox fx:id="confirmSyncDone" text="%migration.start.confirm"/>
<VBox HBox.hgrow="ALWAYS" alignment="CENTER">
<padding>
<Insets top="0" right="12" bottom="0" left="12"/>
</padding>
<Label text="%migration.start.header" styleClass="label-extra-large"/>
<Region minHeight="15"/>
<VBox>
<FormattedLabel format="%migration.start.text" arg1="${controller.vault.displayName}" wrapText="true"/>
<GridPane alignment="CENTER_LEFT" >
<padding>
<Insets left="6"/>
</padding>
<columnConstraints>
<ColumnConstraints minWidth="20" halignment="LEFT"/>
<ColumnConstraints fillWidth="true"/>
</columnConstraints>
<rowConstraints>
<RowConstraints valignment="TOP"/>
<RowConstraints valignment="TOP"/>
<RowConstraints valignment="TOP"/>
<RowConstraints valignment="TOP"/>
</rowConstraints>
<Label text="1." GridPane.rowIndex="0" GridPane.columnIndex="0" />
<Label text="%migration.start.remarkUndone" wrapText="true" GridPane.rowIndex="0" GridPane.columnIndex="1" />
<Label text="2." GridPane.rowIndex="1" GridPane.columnIndex="0" />
<Label text="%migration.start.remarkVersions" wrapText="true" GridPane.rowIndex="1" GridPane.columnIndex="1" />
<Label text="3." GridPane.rowIndex="2" GridPane.columnIndex="0" />
<Label text="%migration.start.remarkCanRun" wrapText="true" GridPane.rowIndex="2" GridPane.columnIndex="1" />
<Label text="4." GridPane.rowIndex="3" GridPane.columnIndex="0" />
<Label text="%migration.start.remarkSynced" wrapText="true" GridPane.rowIndex="3" GridPane.columnIndex="1" />
</GridPane>
<Region minHeight="15"/>
<CheckBox fx:id="confirmSyncDone" text="%migration.start.confirm"/>
</VBox>
</VBox>
</HBox>
@@ -22,7 +22,7 @@
</ImageView>
<VBox spacing="3" HBox.hgrow="ALWAYS" alignment="CENTER_LEFT">
<FormattedLabel styleClass="label-extra-large" format="Cryptomator %s" arg1="${controller.fullApplicationVersion}"/>
<Label text="© 2016 2022 Skymatic GmbH"/>
<Label text="© 2016 2023 Skymatic GmbH"/>
</VBox>
</HBox>
@@ -1,12 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import org.cryptomator.ui.controls.FontAwesome5IconView?>
<?import org.cryptomator.ui.controls.NumericTextField?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.ChoiceBox?>
<?import javafx.scene.control.Hyperlink?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.Separator?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.control.Tooltip?>
<VBox xmlns:fx="http://javafx.com/fxml"
xmlns="http://javafx.com/javafx"
fx:controller="org.cryptomator.ui.preferences.VolumePreferencesController"
@@ -18,12 +22,51 @@
<HBox spacing="12" alignment="CENTER_LEFT">
<Label text="%preferences.volume.type"/>
<ChoiceBox fx:id="volumeTypeChoiceBox"/>
<Hyperlink contentDisplay="GRAPHIC_ONLY" onAction="#openDocs">
<graphic>
<FontAwesome5IconView glyph="QUESTION_CIRCLE" styleClass="glyph-icon-muted"/>
</graphic>
<tooltip>
<Tooltip text="%preferences.volume.docsTooltip" showDelay="100ms"/>
</tooltip>
</Hyperlink>
</HBox>
<HBox spacing="12" alignment="CENTER_LEFT" visible="${controller.loopbackPortSupported}">
<HBox spacing="12" alignment="CENTER_LEFT" visible="${controller.loopbackPortSupported}" managed="${controller.loopbackPortSupported}">
<Label text="%preferences.volume.tcp.port"/>
<NumericTextField fx:id="loopbackPortField"/>
<Button text="%generic.button.apply" fx:id="loopbackPortApplyButton" onAction="#doChangeLoopbackPort"/>
</HBox>
<Separator orientation="HORIZONTAL"/>
<Label text="%preferences.volume.supportedFeatures"/>
<VBox spacing="12">
<Label text="%preferences.volume.feature.mountAuto">
<graphic>
<FontAwesome5IconView glyph="CHECK"/>
</graphic>
</Label>
<Label text="%preferences.volume.feature.mountToDir" visible="${controller.mountToDirSupported}" managed="${controller.mountToDirSupported}" contentDisplay="LEFT">
<graphic>
<FontAwesome5IconView glyph="CHECK"/>
</graphic>
</Label>
<Label text="%preferences.volume.feature.mountToDriveLetter" visible="${controller.mountToDriveLetterSupported}" managed="${controller.mountToDriveLetterSupported}">
<graphic>
<FontAwesome5IconView glyph="CHECK"/>
</graphic>
</Label>
<Label text="%preferences.volume.feature.mountFlags" visible="${controller.mountFlagsSupported}" managed="${controller.mountFlagsSupported}">
<graphic>
<FontAwesome5IconView glyph="CHECK"/>
</graphic>
</Label>
<Label text="%preferences.volume.feature.readOnly" visible="${controller.readonlySupported}" managed="${controller.readonlySupported}">
<graphic>
<FontAwesome5IconView glyph="CHECK"/>
</graphic>
</Label>
</VBox>
</children>
</VBox>
@@ -34,16 +34,19 @@
</StackPane>
</Group>
<VBox HBox.hgrow="ALWAYS">
<Label styleClass="label-large" text="%unlock.error.message" wrapText="true" textAlignment="LEFT">
<Label styleClass="label-large" text="%unlock.error.customPath.message" wrapText="true" textAlignment="LEFT">
<padding>
<Insets bottom="6" top="6"/>
</padding>
</Label>
<FormattedLabel fx:id="dialogDescription" wrapText="true" textAlignment="LEFT"/>
<Region VBox.vgrow="ALWAYS" minHeight="18"/>
<ButtonBar buttonMinWidth="120" buttonOrder="+C">
<ButtonBar buttonMinWidth="120" buttonOrder="+CI">
<buttons>
<Button text="%generic.button.cancel" ButtonBar.buttonData="CANCEL_CLOSE" cancelButton="true" onAction="#close"/>
<Button text="%hub.noKeychain.openBtn" ButtonBar.buttonData="FINISH" defaultButton="true" onAction="#closeAndOpenPreferences"/>
</buttons>
</ButtonBar>
</VBox>
@@ -2,10 +2,11 @@
<?import org.cryptomator.ui.controls.ThroughputLabel?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.Tooltip?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.Region?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.control.Tooltip?>
<?import javafx.geometry.Insets?>
<VBox xmlns:fx="http://javafx.com/fxml"
xmlns="http://javafx.com/javafx"
fx:controller="org.cryptomator.ui.mainwindow.VaultDetailUnlockedController"
@@ -18,6 +19,7 @@
<FontAwesome5IconView glyph="HDD" glyphSize="24"/>
<VBox spacing="4" alignment="CENTER_LEFT">
<Label text="%main.vaultDetail.revealBtn"/>
<Label styleClass="label-extra-small" text="${controller.mountPoint}" textOverrun="CENTER_ELLIPSIS"/>
</VBox>
</HBox>
</graphic>
@@ -27,8 +29,8 @@
<HBox spacing="12" alignment="CENTER">
<FontAwesome5IconView glyph="LINK" glyphSize="24"/>
<VBox spacing="4" alignment="CENTER_LEFT">
<Label text="%generic.button.copy"/> <!-- TODO -->
<Label styleClass="label-extra-small" text="${controller.mountUri}" textOverrun="CENTER_ELLIPSIS"/>
<Label text="%main.vaultDetail.copyUri"/>
<Label styleClass="label-extra-small" text="${controller.mountPoint}" textOverrun="CENTER_ELLIPSIS"/>
</VBox>
</HBox>
</graphic>
@@ -41,7 +43,28 @@
<Region VBox.vgrow="ALWAYS"/>
<HBox alignment="BOTTOM_RIGHT">
<HBox alignment="BOTTOM_CENTER">
<HBox visible="${controller.accessibleViaPath}" managed="${controller.accessibleViaPath}">
<padding>
<Insets topRightBottomLeft="0"/>
</padding>
<Button fx:id="dropZone" styleClass="drag-n-drop" text="%main.vaultDetail.locateEncryptedFileBtn" minWidth="120" maxWidth="180" wrapText="true" textAlignment="CENTER" onAction="#chooseFileAndReveal" contentDisplay="TOP" visible="${!controller.ciphertextPathsCopied}" managed="${!controller.ciphertextPathsCopied}">
<graphic>
<FontAwesome5IconView glyph="FILE_DOWNLOAD" glyphSize="15"/>
</graphic>
<tooltip>
<Tooltip text="%main.vaultDetail.locateEncryptedFileBtn.tooltip"/>
</tooltip>
</Button>
<Button styleClass="drag-n-drop" text="%main.vaultDetail.encryptedPathsCopied" minWidth="120" maxWidth="180" wrapText="true" textAlignment="CENTER" onAction="#chooseFileAndReveal" contentDisplay="TOP" visible="${controller.ciphertextPathsCopied}" managed="${controller.ciphertextPathsCopied}">
<graphic>
<FontAwesome5IconView glyph="CHECK" glyphSize="15"/>
</graphic>
</Button>
</HBox>
<Region HBox.hgrow="ALWAYS"/>
<Button text="%main.vaultDetail.stats" minWidth="120" onAction="#showVaultStatistics" contentDisplay="BOTTOM">
<graphic>
<VBox spacing="6">
+26 -22
View File
@@ -8,25 +8,29 @@
<?import javafx.scene.layout.StackPane?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.shape.Arc?>
<VBox xmlns:fx="http://javafx.com/fxml"
xmlns="http://javafx.com/javafx"
fx:controller="org.cryptomator.ui.mainwindow.VaultListController"
minWidth="206">
<StackPane VBox.vgrow="ALWAYS">
<ListView fx:id="vaultList" editable="true" fixedCellSize="60">
<contextMenu>
<fx:include source="vault_list_contextmenu.fxml"/>
</contextMenu>
</ListView>
<VBox visible="${controller.emptyVaultList}" spacing="6" alignment="CENTER">
<Region VBox.vgrow="ALWAYS"/>
<Label VBox.vgrow="NEVER" text="%main.vaultlist.emptyList.onboardingInstruction" textAlignment="CENTER" wrapText="true"/>
<Arc VBox.vgrow="NEVER" styleClass="onboarding-overlay-arc" type="OPEN" centerX="50" centerY="0" radiusY="100" radiusX="50" startAngle="0" length="-60" strokeWidth="1"/>
</VBox>
</StackPane>
<Button styleClass="toolbar-button" text="%main.vaultlist.addVaultBtn" onAction="#didClickAddVault" alignment="BASELINE_CENTER" maxWidth="Infinity">
<graphic>
<FontAwesome5IconView glyph="PLUS"/>
</graphic>
</Button>
</VBox>
<StackPane xmlns:fx="http://javafx.com/fxml"
xmlns="http://javafx.com/javafx"
fx:id="root"
fx:controller="org.cryptomator.ui.mainwindow.VaultListController"
minWidth="206">
<VBox>
<StackPane VBox.vgrow="ALWAYS">
<ListView fx:id="vaultList" editable="true" fixedCellSize="60">
<contextMenu>
<fx:include source="vault_list_contextmenu.fxml"/>
</contextMenu>
</ListView>
<VBox visible="${controller.emptyVaultList}" spacing="6" alignment="CENTER">
<Region VBox.vgrow="ALWAYS"/>
<Label VBox.vgrow="NEVER" text="%main.vaultlist.emptyList.onboardingInstruction" textAlignment="CENTER" wrapText="true"/>
<Arc VBox.vgrow="NEVER" styleClass="onboarding-overlay-arc" type="OPEN" centerX="50" centerY="0" radiusY="100" radiusX="50" startAngle="0" length="-60" strokeWidth="1"/>
</VBox>
</StackPane>
<Button styleClass="toolbar-button" text="%main.vaultlist.addVaultBtn" onAction="#didClickAddVault" alignment="BASELINE_CENTER" maxWidth="Infinity">
<graphic>
<FontAwesome5IconView glyph="PLUS"/>
</graphic>
</Button>
</VBox>
<Region styleClass="drag-n-drop-border" visible="${controller.draggingVaultOver}"/>
</StackPane>
@@ -5,12 +5,15 @@
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.CheckBox?>
<?import javafx.scene.control.ChoiceBox?>
<?import javafx.scene.control.Hyperlink?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.RadioButton?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.control.ToggleGroup?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Text?>
<?import javafx.scene.text.TextFlow?>
<VBox xmlns:fx="http://javafx.com/fxml"
xmlns="http://javafx.com/javafx"
fx:controller="org.cryptomator.ui.vaultoptions.MountOptionsController"
@@ -22,7 +25,11 @@
<Insets topRightBottomLeft="12"/>
</padding>
<children>
<Label text="Options depend on the selected volume provider in the general preferences"/>
<TextFlow>
<Text text="%vaultOptions.mount.info" styleClass="label"/>
<Text text=" "/>
<Hyperlink styleClass="hyperlink-underline" text="%vaultOptions.mount.linkToPreferences" onAction="#openVolumePreferences" wrapText="true"/>
</TextFlow>
<CheckBox fx:id="readOnlyCheckbox" text="%vaultOptions.mount.readonly" visible="${controller.readOnlySupported}" managed="${controller.readOnlySupported}"/>
<VBox visible="${controller.mountFlagsSupported}" managed="${controller.mountFlagsSupported}">
@@ -44,22 +51,24 @@
<HBox spacing="6" visible="${controller.mountpointDriveLetterSupported}" managed="${controller.mountpointDriveLetterSupported}">
<RadioButton toggleGroup="${mountPointToggleGroup}" fx:id="mountPointDriveLetterBtn" text="%vaultOptions.mount.mountPoint.driveLetter"/>
<ChoiceBox fx:id="driveLetterSelection" disable="${!mountPointDriveLetterBtn.selected}" value="${controller.driveLetter}"/>
<ChoiceBox fx:id="driveLetterSelection" disable="${!mountPointDriveLetterBtn.selected}"/>
</HBox>
<HBox spacing="6" alignment="CENTER_LEFT" visible="${controller.mountpointDirSupported}" managed="${controller.mountpointDirSupported}">
<RadioButton toggleGroup="${mountPointToggleGroup}" fx:id="mountPointDirBtn" text="%vaultOptions.mount.mountPoint.custom"/>
<Button text="%vaultOptions.mount.mountPoint.directoryPickerButton" onAction="#chooseCustomMountPoint" contentDisplay="LEFT" disable="${!mountPointDirBtn.selected}">
<graphic>
<FontAwesome5IconView glyph="FOLDER_OPEN" glyphSize="15"/>
</graphic>
</Button>
</HBox>
<TextField fx:id="directoryPathField" text="${controller.directoryPath}" visible="${mountPointDirBtn.selected}" managed="${mountPointDirBtn.managed}" maxWidth="Infinity" editable="false" >
<VBox.margin>
<Insets left="24"/>
</VBox.margin>
</TextField>
<VBox spacing="6" visible="${controller.mountpointDirSupported}" managed="${controller.mountpointDirSupported}">
<HBox spacing="6" alignment="CENTER_LEFT">
<RadioButton toggleGroup="${mountPointToggleGroup}" fx:id="mountPointDirBtn" text="%vaultOptions.mount.mountPoint.custom"/>
<Button text="%vaultOptions.mount.mountPoint.directoryPickerButton" onAction="#chooseCustomMountPoint" contentDisplay="LEFT" disable="${!mountPointDirBtn.selected}">
<graphic>
<FontAwesome5IconView glyph="FOLDER_OPEN" glyphSize="15"/>
</graphic>
</Button>
</HBox>
<TextField fx:id="directoryPathField" text="${controller.directoryPath}" visible="${mountPointDirBtn.selected}" managed="${mountPointDirBtn.managed}" maxWidth="Infinity" editable="false">
<VBox.margin>
<Insets left="24"/>
</VBox.margin>
</TextField>
</VBox>
</children>
</VBox>
+30 -11
View File
@@ -124,12 +124,14 @@ unlock.success.description=Content in vault "%s" is now accessible over its moun
unlock.success.rememberChoice=Remember my choice, don't ask again
unlock.success.revealBtn=Reveal Drive
## Failure
unlock.error.message=Unable to unlock vault
### Invalid Mount Point
unlock.error.invalidMountPoint.notExisting=Mount point "%s" is not a directory, not empty or does not exist.
unlock.error.invalidMountPoint.existing=Mount point "%s" already exists or parent folder is missing.
unlock.error.invalidMountPoint.driveLetterOccupied=Drive Letter "%s" is already in use.
unlock.error.customPath.message=Unable to mount vault to custom path
unlock.error.customPath.description.notSupported=If you wish to keep using the custom path, please go to the preferences and select a volume type that supports it. Otherwise, go to the vault options and choose a supported mount point.
unlock.error.customPath.description.notExists=The custom mount path does not exist. Either create it in your local filesystem or change it in the vault options.
unlock.error.customPath.description.generic=You have selected a custom mount path for this vault, but using it failed with the message: %s
## Hub
hub.noKeychain.message=Unable to access device key
hub.noKeychain.description=In order to unlock Hub vaults, a device key is required, which is secured using a keychain. To proceed, enable “%s” and select a keychain in the preferences.
hub.noKeychain.openBtn=Open Preferences
### Waiting
hub.auth.message=Waiting for authentication…
hub.auth.description=You should automatically be redirected to the login page.
@@ -170,8 +172,13 @@ lock.fail.description=Vault "%s" could not be locked. Ensure unsaved work is sav
# Migration
migration.title=Upgrade Vault
## Start
migration.start.prompt=Your vault "%s" needs to be updated to a newer format. Before proceeding, make sure there is no pending synchronization affecting this vault.
migration.start.confirm=Yes, my vault is fully synced
migration.start.header=Upgrade Vault
migration.start.text=In order to open your vault "%s" in this new version of Cryptomator, the vault needs to be upgraded to a newer format. Before doing this, you should know the following:
migration.start.remarkUndone=This upgrade cannot be undone.
migration.start.remarkVersions=Older versions of Cryptomator will not be able to open the upgraded vault.
migration.start.remarkCanRun=You must be sure that every device from which you access the vault can run this version of Cryptomator.
migration.start.remarkSynced=You must be sure that your vault is fully synced on this device, and on your other devices, before upgrading it.
migration.start.confirm=I have read and understood the above information
## Run
migration.run.enterPassword=Enter the password for "%s"
migration.run.startMigrationBtn=Migrate Vault
@@ -269,8 +276,16 @@ preferences.interface.showMinimizeButton=Show minimize button
preferences.interface.showTrayIcon=Show tray icon (requires restart)
## Volume
preferences.volume=Virtual Drive
preferences.volume.type=Volume Type
preferences.volume.type=Volume Type (requires restart)
preferences.volume.type.automatic=Automatic
preferences.volume.docsTooltip=Open the documentation to learn more about the different volume types.
preferences.volume.tcp.port=TCP Port
preferences.volume.supportedFeatures=The chosen volume type supports the following features:
preferences.volume.feature.mountAuto=Automatic mount point selection
preferences.volume.feature.mountToDir=Custom directory as mount point
preferences.volume.feature.mountToDriveLetter=Drive letter as mount point
preferences.volume.feature.mountFlags=Custom mount options
preferences.volume.feature.readOnly=Read-only mount
## Updates
preferences.updates=Updates
preferences.updates.currentVersion=Current Version: %s
@@ -329,9 +344,6 @@ main.minimizeBtn.tooltip=Minimize
main.preferencesBtn.tooltip=Preferences
main.debugModeEnabled.tooltip=Debug mode is enabled
main.supporterCertificateMissing.tooltip=Please consider donating
## Drag 'n' Drop
main.dropZone.dropVault=Add this vault
main.dropZone.unknownDragboardContent=If you want to add a vault, drag it to this window
## Vault List
main.vaultlist.emptyList.onboardingInstruction=Click here to add a vault
main.vaultlist.contextMenu.remove=Remove…
@@ -354,6 +366,7 @@ main.vaultDetail.passwordSavedInKeychain=Password saved
main.vaultDetail.unlockedStatus=UNLOCKED
main.vaultDetail.accessLocation=Your vault's contents are accessible here:
main.vaultDetail.revealBtn=Reveal Drive
main.vaultDetail.copyUri=Copy URI
main.vaultDetail.lockBtn=Lock
main.vaultDetail.bytesPerSecondRead=Read:
main.vaultDetail.bytesPerSecondWritten=Write:
@@ -361,6 +374,10 @@ main.vaultDetail.throughput.idle=idle
main.vaultDetail.throughput.kbps=%.1f kiB/s
main.vaultDetail.throughput.mbps=%.1f MiB/s
main.vaultDetail.stats=Vault Statistics
main.vaultDetail.locateEncryptedFileBtn=Locate Encrypted File
main.vaultDetail.locateEncryptedFileBtn.tooltip=Choose a file from your vault to locate its encrypted counterpart
main.vaultDetail.encryptedPathsCopied=Paths Copied to Clipboard!
main.vaultDetail.filePickerTitle=Select File Inside Vault
### Missing
main.vaultDetail.missing.info=Cryptomator could not find a vault at this path.
main.vaultDetail.missing.recheck=Recheck
@@ -399,6 +416,8 @@ vaultOptions.general.startHealthCheckBtn=Start Health Check
## Mount
vaultOptions.mount=Mounting
vaultOptions.mount.info=Options depend on the selected volume type.
vaultOptions.mount.linkToPreferences=Open virtual drive preferences
vaultOptions.mount.readonly=Read-only
vaultOptions.mount.customMountFlags=Custom mount flags
vaultOptions.mount.winDriveLetterOccupied=occupied
+11 -14
View File
@@ -103,10 +103,6 @@ unlock.success.description=تم فتح "%s" بنجاح! يمكنك الآن ال
unlock.success.rememberChoice=تذكر اختياري ولا تظهر هذا مرة أخرى
unlock.success.revealBtn=اظهار القرص
## Failure
unlock.error.message=غير قادر على فتح الخزنة
### Invalid Mount Point
unlock.error.invalidMountPoint.notExisting=نقطة التحميل ليست مجلد فارغ أو غير موجودة: %s
unlock.error.invalidMountPoint.existing=نقطة/مجلد التحميل موجود بالفعل أو المجلد الأصل مفقود: %s
## Hub
### Waiting
### Receive Key
@@ -129,8 +125,13 @@ lock.fail.description=فشل عملية قفل %s". تأكد من حفظ الع
# Migration
migration.title=ترقية الحافظة
## Start
migration.start.prompt=يجب تحديث المخزن الخاص بك "%s" إلى تنسيق أحدث. قبل المتابعة، يجب التأكد من عدم وجود مزامنة معلقة على هذا المخزن.
migration.start.confirm=نعم, محفظتي متزامنة بالكامل
migration.start.header=ترقية الخزنة
migration.start.text=من أجل فتح الخزنة الخاصة بك "%s" في هذا الإصدار الجديد من Cryptomator، يجب ترقية الخزنة إلى تنسيق جديد. وقبل القيام بذلك، ينبغي أن تعرف ما يلي:
migration.start.remarkUndone=هذه الترقية لا يمكن التراجع عنها.
migration.start.remarkVersions=لن تكون الإصدارات القديمة من Cryptomator قادرة على فتح الخزنة التي تم ترقيتها.
migration.start.remarkCanRun=يجب أن تكون متأكداً من أن كل جهاز تريد ان تستخدم الخزنة عليه يمكن تشغيل هذا الإصدار من Cryptomter.
migration.start.remarkSynced=يجب أن تكون متأكداً من أن خزنتك قد تمت مزامنتها بالكامل على هذا الجهاز، وعلى الأجهزة الأخرى الخاصة بك، قبل ترقيتها.
migration.start.confirm=لقد قرأت وفهمت المعلومات الواردة أعلاه
## Run
migration.run.enterPassword=أدخل كلمة المرور لـ "%s"
migration.run.startMigrationBtn=ترقية الحافظة
@@ -172,9 +173,6 @@ preferences.interface.theme.dark=مظلم (أسود)
preferences.interface.theme.light=فاتح (أبيض)
## Volume
preferences.volume=القرص الإفتراضي
preferences.volume.type=‮نوع المجلد
preferences.volume.webdav.port=منفذ WebDav
preferences.volume.webdav.scheme=مخطط WebDAV
## Updates
preferences.updates=تحديثات
preferences.updates.currentVersion=الإصدار الحالي: %s
@@ -210,9 +208,6 @@ main.minimizeBtn.tooltip=تصغير
main.preferencesBtn.tooltip=تفضيلات
main.debugModeEnabled.tooltip=تم تمكين وضع التصحيح
main.supporterCertificateMissing.tooltip=يرجى النظر في تقديم تبرعات
## Drag 'n' Drop
main.dropZone.dropVault=أضف هذا المخزن
main.dropZone.unknownDragboardContent=إذا كنت ترغب في إضافة مخزن، قم بسحبه إلى هذه النافذة
## Vault List
main.vaultlist.emptyList.onboardingInstruction=انقر هنا لإضافة خزنة
main.vaultlist.contextMenu.remove=حذف…
@@ -242,6 +237,10 @@ main.vaultDetail.throughput.idle=خمول
main.vaultDetail.throughput.kbps=%.1f كيلوبايت/ث
main.vaultDetail.throughput.mbps=%.1f ميجابايت/ث
main.vaultDetail.stats=إحصائيات الخزنة
main.vaultDetail.locateEncryptedFileBtn=تحديد موقع الملف المشفر
main.vaultDetail.locateEncryptedFileBtn.tooltip=اختر ملف من خزانتك لتحديد مكان نظيره المشفر
main.vaultDetail.encryptedPathsCopied=تم نسخ مسارات الملفات إلى الحافظة!
main.vaultDetail.filePickerTitle=إختر الملف من الخزنة
### Missing
main.vaultDetail.missing.info=لم يتمكن Cryptomator من العثور على خزنة في هذا المسار.
main.vaultDetail.missing.recheck=إعادة الفحص
@@ -280,9 +279,7 @@ vaultOptions.mount.winDriveLetterOccupied=مشغول
vaultOptions.mount.mountPoint=موقع التحميل الوهمي
vaultOptions.mount.mountPoint.auto=اختيار موقع مناسب تلقائياً
vaultOptions.mount.mountPoint.driveLetter=استخدام دالة قرص معين
vaultOptions.mount.mountPoint.custom=مسار مخصص
vaultOptions.mount.mountPoint.directoryPickerButton=اختر…
vaultOptions.mount.mountPoint.directoryPickerTitle=اختر مجلد فارغ
## Master Key
vaultOptions.masterkey=كلمة المرور
vaultOptions.masterkey.changePasswordBtn=تغيير كلمة المرور
+2 -15
View File
@@ -123,11 +123,6 @@ unlock.success.description=Змест скарбніцы "%s" цяпер дас
unlock.success.rememberChoice=Запомні мой выбар і больш не пытай
unlock.success.revealBtn=Паказаць дыск
## Failure
unlock.error.message=Немагчыма разамкнуць скарбніцу
### Invalid Mount Point
unlock.error.invalidMountPoint.notExisting=Пункт мантажу "%s" не з'яўляецца пустой тэчкаю альбо ўвогуле не існуе.
unlock.error.invalidMountPoint.existing=Пункт мантажу "%s" ужо існуе альбо адсутнічае бацькоўская тэчка.
unlock.error.invalidMountPoint.driveLetterOccupied=Дыскавая літара "%s" ужо выкарыстоўваецца.
## Hub
### Waiting
hub.auth.message=Чаканне спраўджання…
@@ -168,8 +163,7 @@ lock.fail.description=Скарбніцу "%s" не мажліва замкнуц
# Migration
migration.title=Абнавіць скарбніцу
## Start
migration.start.prompt=Тваю скарбніцу "%s" неабходна абнавіць у новы фармат. Перад тым, як пачаць, запэўніся, што не адбываецца працэсу сінхранавання, які можа ўздзейнічаць на скарбніцу.
migration.start.confirm=Так, мая скарбніца цалкам сінхранавана
migration.start.header=Абнавіць скарбніцу
## Run
migration.run.enterPassword=Увядзіце пароль да "%s"
migration.run.startMigrationBtn=Перамясціць скарбніцу
@@ -233,9 +227,7 @@ preferences.interface.showMinimizeButton=Паказаць кнопку згор
preferences.interface.showTrayIcon=Паказваць іконку на інфармацыйнай панэлі (спатрэбіцца перазапуск)
## Volume
preferences.volume=Віртуальны дыск
preferences.volume.type=Тып тому
preferences.volume.webdav.port=Порт WebDAV
preferences.volume.webdav.scheme=Схема WebDAV
preferences.volume.type.automatic=Аўтаматычна
## Updates
preferences.updates=Абнаўленні
preferences.updates.currentVersion=Бягучая версія: %s
@@ -288,9 +280,6 @@ main.minimizeBtn.tooltip=Згарнуць
main.preferencesBtn.tooltip=Налады
main.debugModeEnabled.tooltip=Функццыя дыягназавання выключана
main.supporterCertificateMissing.tooltip=Калі ласка, падумай пра ахвяраванне
## Drag 'n' Drop
main.dropZone.dropVault=Дадаць гэтую скарбніцу
main.dropZone.unknownDragboardContent=Калі ты хочаш дадаць скарбніцу, перацягні яе ў гэтае акно
## Vault List
main.vaultlist.emptyList.onboardingInstruction=Пстрыкні тут, каб дадаць скарбніцу
main.vaultlist.contextMenu.remove=Выдаліць…
@@ -361,9 +350,7 @@ vaultOptions.mount.winDriveLetterOccupied=занята
vaultOptions.mount.mountPoint=Пункт мантажавання
vaultOptions.mount.mountPoint.auto=Аўтаматычны выбар пасуючага месцазнаходжання
vaultOptions.mount.mountPoint.driveLetter=Назначыць літару для дыску
vaultOptions.mount.mountPoint.custom=Уласная сцежка
vaultOptions.mount.mountPoint.directoryPickerButton=Абраць…
vaultOptions.mount.mountPoint.directoryPickerTitle=Абяры парожнюю тэчку
## Master Key
vaultOptions.masterkey=Пароль
vaultOptions.masterkey.changePasswordBtn=Змяніць пароль
@@ -44,11 +44,19 @@ addvaultwizard.new.namePrompt=ভোল্ট এর নাম
addvaultwizard.new.locationInstruction=ভোল্ট এর এনক্রিপ্টেড ফাইলগুলো ক্রিপ্টোমেটর কোথায় সংরক্ষণ করবে?
addvaultwizard.new.locationLabel=স্টোরেজ লোকেশন
addvaultwizard.new.locationPrompt=
addvaultwizard.new.directoryPickerLabel=স্বনির্বাচিত লোকেশন
addvaultwizard.new.directoryPickerButton=নির্বাচন করুন…
addvaultwizard.new.directoryPickerTitle=ডিরেক্টরি নির্বাচন
addvaultwizard.new.fileAlreadyExists=ভোল্টের নামে একটি ফাইল অথবা ডিরেক্টরি ইতিমধ্যে বিদ্যমান
addvaultwizard.new.locationDoesNotExist=নিদিষ্ট করা পথে একটি ডিরেক্টরি বিদ্যমান নয় অথবা প্রবেশ করা যাচ্ছে না
addvaultwizard.new.locationIsNotWritable=নিদিষ্ট করা পথে কোনো কিছু পরিবর্তন করার অনুমতি নেই
addvaultwizard.new.locationIsOk=আপনার ভোল্টের জন্য উপযুক্ত ঠিকানা
addvaultwizard.new.invalidName=ভোল্টের নামটি বৈধ নয়
addvaultwizard.new.validName=ভোল্টের নামটি বৈধ
addvaultwizard.new.validCharacters.message=ভোল্টের নামটিতে নিম্নলিখিত অক্ষরগুলো থাকতে পারবে:
addvaultwizard.new.validCharacters.chars=শব্দের অক্ষরগুলো (যেমনঃ a, ж অথবা 수)
addvaultwizard.new.validCharacters.numbers=সংখ্যা
addvaultwizard.new.validCharacters.dashes=হাইফেন (%s) অথবা আন্ডারস্কোর (%s)
### Password
addvaultwizard.new.createVaultBtn=ভোল্ট তৈরি করুন
addvaultwizard.new.generateRecoveryKeyChoice=পাসওয়ার্ড ছাড়া আপনি আপনার তথ্যগুলো ব্যবহার করতে পারবেন না. তাই আপনি কি একটি পুনরুদ্ধার চাবি চান যদি আপনি পাসওয়ার্ড হারিয়ে ফেলেন?
@@ -79,7 +87,6 @@ unlock.unlockBtn=আনলক করুন
## Select
## Success
## Failure
### Invalid Mount Point
## Hub
### Waiting
### Receive Key
@@ -130,7 +137,6 @@ lock.forced.retryBtn=পুনরায় চেষ্টা করুন
# Main Window
main.closeBtn.tooltip=বন্ধ করুন
## Drag 'n' Drop
## Vault List
main.vaultlist.contextMenu.lock=লক করুন
main.vaultlist.addVaultBtn=ভোল্ট যুক্ত করুন
+1 -14
View File
@@ -103,10 +103,6 @@ unlock.success.description=Uspješno ste otključali "%s"! Vaš sef je sada dost
unlock.success.rememberChoice=Zapamtite izbor, ne pokazujte ovo ponovo
unlock.success.revealBtn=Otkrij pogon
## Failure
unlock.error.message=Sef nije moguće otključati
### Invalid Mount Point
unlock.error.invalidMountPoint.notExisting=Tačka postavljanja "%s" nije direktorij, nije prazna ili ne postoji.
unlock.error.invalidMountPoint.existing=Tačka povezivanja "%s" već postoji ili nadređeni folder nedostaje.
## Hub
### Waiting
### Receive Key
@@ -128,8 +124,7 @@ lock.fail.description=Sef "%s" nije moguće zaključati. Osigurajte da je nespre
# Migration
migration.title=Nadogradi sef
## Start
migration.start.prompt=Sef "%s" treba ažurirati na noviji format. Prije nastavka, provjerite da nije na čekanju sinkronizacija koja utječe na ovaj sef.
migration.start.confirm=Da, moj sef je u potpunosti sinhroniziran
migration.start.header=Nadogradi sef
## Run
migration.run.enterPassword=Unesite lozinku za "%s"
migration.run.startMigrationBtn=Nadogradi sef
@@ -171,9 +166,6 @@ preferences.interface.theme.dark=Tamno
preferences.interface.theme.light=Svijetlo
## Volume
preferences.volume=Virtuelni pogon
preferences.volume.type=Tip volumena
preferences.volume.webdav.port=WebDAV Port
preferences.volume.webdav.scheme=WebDAV Scheme
## Updates
preferences.updates=Ažuriranja
preferences.updates.currentVersion=Trenutna verzija: %s
@@ -225,9 +217,6 @@ main.minimizeBtn.tooltip=Minimiziraj
main.preferencesBtn.tooltip=Postavke
main.debugModeEnabled.tooltip=Omogućen je mod otklanjanja pogrešaka
main.supporterCertificateMissing.tooltip=Molimo razmislite o doniranju
## Drag 'n' Drop
main.dropZone.dropVault=Dodajte ovaj sef
main.dropZone.unknownDragboardContent=Ako želite dodati sef, povucite ga u ovaj prozor
## Vault List
main.vaultlist.emptyList.onboardingInstruction=Kliknite ovdje da dodate sef
main.vaultlist.contextMenu.remove=Ukloni…
@@ -295,9 +284,7 @@ vaultOptions.mount.winDriveLetterOccupied=zauzeto
vaultOptions.mount.mountPoint=Tačka povezivanja
vaultOptions.mount.mountPoint.auto=Automatski odaberi pogodnu lokaciju
vaultOptions.mount.mountPoint.driveLetter=Koristi dodjeljeno slovo (oznaku) diska
vaultOptions.mount.mountPoint.custom=Prilagođena adresa
vaultOptions.mount.mountPoint.directoryPickerButton=Odaberi…
vaultOptions.mount.mountPoint.directoryPickerTitle=Izaberi praznu mapu
## Master Key
vaultOptions.masterkey=Šifra
vaultOptions.masterkey.changePasswordBtn=Promjeni lozinku
+48 -21
View File
@@ -15,10 +15,10 @@ generic.button.next=Següent
generic.button.print=Imprimeix
# Error
error.message=Error %s
error.message=S'ha produït un error
error.description=Ui! Cryptomator no esperava que passés això. Podeu cercar alguna de les solucions existents per a aquest error. Si no ha estat reportat encara, sentiu-vos lliure de fer-ho vós mateix.
error.hyperlink.lookup=Cerca aquest error
error.hyperlink.report=Notifica un error
error.hyperlink.report=Notifica aquest error
error.technicalDetails=Detalls:
# Defaults
@@ -73,7 +73,7 @@ addvault.new.readme.storageLocation.4=• modifiqueu cap fitxer dins d'aquest d
addvault.new.readme.storageLocation.5=• enganxeu cap fitxer a xifrar en aquest directori.
addvault.new.readme.storageLocation.6=Si voleu xifrar fitxers i veure el contigut de la caixa forta, feu el següent:
addvault.new.readme.storageLocation.7=1. Afegiu aquesta caixa forta a Cryptomator.
addvault.new.readme.storageLocation.8=2. Desbloquejeu la caixa forta enCryptomator.
addvault.new.readme.storageLocation.8=2. Desbloqueu la caixa forta a Cryptomator.
addvault.new.readme.storageLocation.9=3. Feu click damunt del botó "Mostra" per obrir la ubicació d'accès.
addvault.new.readme.storageLocation.10=Si us cal ajuda, llegiu la documentació: %s
addvault.new.readme.accessLocation.fileName=BENVINGUTS.rtf
@@ -116,36 +116,46 @@ unlock.unlockBtn=Desbloqueja
unlock.chooseMasterkey.message=L'arxiu de contrasenyes no s'ha pogut trobar
unlock.chooseMasterkey.description=No es pot trobar el fitxer de clau mestra per aquesta bòveda a la ubicació esperada. Escull el fixer manualment.
unlock.chooseMasterkey.filePickerTitle=Seleccioneu el fitxer de Clau Mestra
unlock.chooseMasterkey.filePickerMimeDesc=La clau mestra de Cryptomator
## Success
unlock.success.message=Desbloqueig satisfactori
unlock.success.description=S'ha desblocat %s correctament! Podeu accedir a la vostra caixa forta a través de la unitat virtual.
unlock.success.rememberChoice=Recorda l'elecció. No ho tornis a mostrar.
unlock.success.revealBtn=Mostra la unitat
## Failure
unlock.error.message=No ha estat possible desblocar la caixa forta
### Invalid Mount Point
unlock.error.invalidMountPoint.notExisting=El punt de muntatge no és un directori buit, o no existeix: %s
unlock.error.invalidMountPoint.existing=El punt de muntatge o la carpeta ja existeix, o no es pot accedir al directori superior: %s
unlock.error.invalidMountPoint.driveLetterOccupied=La unitat o arxiu "%s" ja està en ús.
unlock.error.customPath.message=No es pot muntar la caixa forta en la ruta personalitzada
unlock.error.customPath.description.notSupported=Si vol continuar fent servir una ruta personalitzada, vagi si us plau a Preferències i seleccioni un tipus de volum que la suporti. Altrament, vagi a les opcions de la caixa forta i escolli un punt de muntatge suportat.
unlock.error.customPath.description.notExists=La ruta de muntatge personalitzada no existeix. Creï-la o canviï-la en les opcions de la caixa forta.
unlock.error.customPath.description.generic=Ha seleccionat una ruta personalitzada on muntar la caixa forta, però ha fallat amb aquest missatge: %s
## Hub
hub.noKeychain.message=No es pot accedir a la clau del dispositiu
hub.noKeychain.description=Per poder desblocar caixes fortes del Hub es requereix la clau d'un dispositiu, que s'emmagatzema de forma segura en un clauer. Per continuar, habiliti "%s" i seleccioni un clauer en les Preferències.
hub.noKeychain.openBtn=Obrir les Preferències
### Waiting
hub.auth.message=Sestà esperant lautenticació…
hub.auth.description=Hauríeu de ser redirigits a la pàgina d'accés.
hub.auth.loginLink=No heu estat redirigit? Feu clic aquí per a obrir-la.
### Receive Key
hub.receive.message=S'està processant la resposta…
hub.receive.description=Cryptomator està rebent i processant la resposta del Hub. Espereu, si us plau.
### Register Device
hub.register.message=Cal un nom de dispositiu
hub.register.description=Sembla que és el primer accés al Hub des d'aquest dispositiu. Per identificar-lo i poder autoritzar l'accés necessiteu anomenar aquest dispositiu.
hub.register.nameLabel=Nom del dispositiu
hub.register.occupiedMsg=El nom ja està en ús
hub.register.registerBtn=Confirma
### Registration Success
hub.registerSuccess.message=Unitat anomenada
hub.registerSuccess.description=Per a accedir a la caixa forta, el vostre dispositiu ha de ser autoritzat pel propietari de la caixa.
### Registration Failed
hub.registerFailed.message=Error al nombrar el dispositiu
hub.registerFailed.description=S'ha produït un error en el procés de nomenament. Per més detalls vegeu el registre de l'aplicació.
### Unauthorized
hub.unauthorized.message=Accés denegat
hub.unauthorized.description=El vostre dispositiu no ha estat encara autoritzat a accedir a aquesta caixa forta. Demaneu autorització al propietari.
### License Exceeded
hub.licenseExceeded.message=Llicència caducada
hub.licenseExceeded.description=Cryptomator Hub ha donat accés a més usuaris dels permesos en la llicència. Si us plau contacteu amb l'administrador del Hub per actualitzar la llicència o amb l'administrador de la caixa forta per treure usuaris.
# Lock
@@ -161,8 +171,13 @@ lock.fail.description=La caixa forta "%s" no s'ha pogut blocar. Assegureu-vos qu
# Migration
migration.title=Actualitza la caixa forta
## Start
migration.start.prompt=La vostra caixa forta "%s" ha de ser actualitzada a un format més nou. Abans de continuar, assegureu-vos de que no hi haja cap sincronització pendent que puga afectar a aquesta caixa forta.
migration.start.confirm=Sí, la meua caixa forta està completament sicronitzada
migration.start.header=Actualitza la caixa forta
migration.start.text=Per obrir la caixa forta "%s" en aquesta nova versió de Cryptomator, la caixa forta necessita actualitzar-se al nou format. Abans de fer-ho, cal que sabeu el següent:
migration.start.remarkUndone=Aquesta actualització no pot ser desfeta.
migration.start.remarkVersions=Versions antigues de Cryptomator no podran obrir la caixa forta actualitzada.
migration.start.remarkCanRun=Assegureu-vos que tots els dispositius des dels quals accediu a la caixa forta poden executar aquesta versió de Cryptomator.
migration.start.remarkSynced=Assegureu-vos que la caixa forta està completament sincronitzada en aquest i altres dispositius abans d'actualitzar-la.
migration.start.confirm=He llegit i entès la informació anterior
## Run
migration.run.enterPassword=Introduïu la contrasenya per a "%s"
migration.run.startMigrationBtn=Migrar la caixa forta
@@ -211,8 +226,6 @@ health.check.detail.checkFinishedAndFound=La comprovació ha finalitzat. Si us p
health.check.detail.checkFailed=La comprovació ha acabat a causa d'un error.
health.check.detail.checkCancelled=S'ha cancel·lat la prova.
health.check.detail.listFilters.label=Filtre
health.check.detail.listFilters.severity=Gravetat
health.check.detail.listFilters.fixState=Estat de la reparació
health.check.detail.fixAllSpecificBtn=Qualsevol reparació
health.check.exportBtn=Exporta informe
## Result view
@@ -221,6 +234,10 @@ health.result.severityFilter.good=Bé
health.result.severityFilter.info=Info
health.result.severityFilter.warn=Avís
health.result.severityFilter.crit=Crític
health.result.severityTip.good=Gravetat: Bona.\nEstructura de la caixa forta correcta.
health.result.severityTip.info=Gravetat: Informació\nCaixa forta intacta, es recomana però arreglar-la.
health.result.severityTip.warn=Gravetat: Avís\nCaixa forta corrompuda, és altament recomanable arreglar-la.
health.result.severityTip.crit=Gravetat: Crítica\nCaixa forta corrompuda, s'ha determinat que s'han perdut dades.
health.result.fixStateFilter.all=Estat de reparació - Tot
health.result.fixStateFilter.fixable=Es pot arreglar
health.result.fixStateFilter.notFixable=No es pot arreglar
@@ -258,9 +275,15 @@ preferences.interface.showMinimizeButton=Mostra el botó 'minimitzar'
preferences.interface.showTrayIcon=Mostra la icona en la barra (cal reiniciar)
## Volume
preferences.volume=Unitat virtual
preferences.volume.type=Tipus de volum
preferences.volume.webdav.port=Port WebDAV
preferences.volume.webdav.scheme=Esquema WebDAV
preferences.volume.type=Tipus de volum (requereix reiniciar)
preferences.volume.type.automatic=Automàtic
preferences.volume.tcp.port=Port TCP
preferences.volume.supportedFeatures=El tipus de volum escollit suporta les següents característiques:
preferences.volume.feature.mountAuto=Selecció automàtica del punt de muntatge
preferences.volume.feature.mountToDir=Directori personalitzat com a punt de muntatge
preferences.volume.feature.mountToDriveLetter=Lletra de la unitat com a punt de muntatge
preferences.volume.feature.mountFlags=Opcions de muntatge personalitzades
preferences.volume.feature.readOnly=Muntar de només lectura
## Updates
preferences.updates=Actualitzacions
preferences.updates.currentVersion=Versió actual: %s
@@ -319,9 +342,6 @@ main.minimizeBtn.tooltip=Minimitza
main.preferencesBtn.tooltip=Preferències
main.debugModeEnabled.tooltip=Mode depuració activat
main.supporterCertificateMissing.tooltip=Si us plau, considereu fer una donació
## Drag 'n' Drop
main.dropZone.dropVault=Afegeix aquesta caixa forta
main.dropZone.unknownDragboardContent=Si voleu afegir una caixa forta, arrossegueu-la a aquesta finestra
## Vault List
main.vaultlist.emptyList.onboardingInstruction=Feu clic aquí per afegir una caixa forta
main.vaultlist.contextMenu.remove=Elimina…
@@ -344,6 +364,7 @@ main.vaultDetail.passwordSavedInKeychain=Contrasenya desada
main.vaultDetail.unlockedStatus=DESBLOQUEJADA
main.vaultDetail.accessLocation=Els continguts de la vostra caixa forta són accessibles aquí:
main.vaultDetail.revealBtn=Mostra la unitat
main.vaultDetail.copyUri=Copiar URI
main.vaultDetail.lockBtn=Bloqueja
main.vaultDetail.bytesPerSecondRead=Lectura:
main.vaultDetail.bytesPerSecondWritten=Escriu:
@@ -351,8 +372,12 @@ main.vaultDetail.throughput.idle=inactiu
main.vaultDetail.throughput.kbps=%.1f kiB/s
main.vaultDetail.throughput.mbps=%.1f MiB/s
main.vaultDetail.stats=Estadístiques de la caixa forta
main.vaultDetail.locateEncryptedFileBtn=Trobar fitxer xifrat
main.vaultDetail.locateEncryptedFileBtn.tooltip=Esculli un fitxer de la caixa forta per trobar el seu homòleg xifrat
main.vaultDetail.encryptedPathsCopied=Rutes copiades al porta-retalls!
main.vaultDetail.filePickerTitle=Seleccioni un fitxer dins la caixa forta
### Missing
main.vaultDetail.missing.info=Cryptomator no ha trobat una caixa forta en aquest camí.
main.vaultDetail.missing.info=Cryptomator no ha trobat una caixa forta en aquesta ruta.
main.vaultDetail.missing.recheck=Torna a comprovar
main.vaultDetail.missing.remove=Eliminar de la llista de la caixa forta…
main.vaultDetail.missing.changeLocation=Canvia la localització de la caixa forta…
@@ -389,15 +414,17 @@ vaultOptions.general.startHealthCheckBtn=Inicia la comprovació
## Mount
vaultOptions.mount=Muntatge
vaultOptions.mount.info=Les opcions depenen del tipus de volum escollit.
vaultOptions.mount.linkToPreferences=Obre les preferències del disc virtual
vaultOptions.mount.readonly=Només lectura
vaultOptions.mount.customMountFlags=Senyaladors de muntatge personalitzats
vaultOptions.mount.winDriveLetterOccupied=ocupat
vaultOptions.mount.mountPoint=Punt de muntatge
vaultOptions.mount.mountPoint.auto=Tria automàticament una ubicació adequada
vaultOptions.mount.mountPoint.driveLetter=Utilitza la lletra de la unitat assignada
vaultOptions.mount.mountPoint.custom=Camí personalitzat
vaultOptions.mount.mountPoint.custom=Faci servir el directori escollit
vaultOptions.mount.mountPoint.directoryPickerButton=Trieu…
vaultOptions.mount.mountPoint.directoryPickerTitle=Esculliu un directori buit
vaultOptions.mount.mountPoint.directoryPickerTitle=Triï un directori
## Master Key
vaultOptions.masterkey=Contrasenya
vaultOptions.masterkey.changePasswordBtn=Canvi de contrasenya
+45 -15
View File
@@ -53,6 +53,12 @@ addvaultwizard.new.fileAlreadyExists=Soubor nebo složka s tímto názvem trezor
addvaultwizard.new.locationDoesNotExist=Složka v zadané cestě neexistuje nebo není přístupná
addvaultwizard.new.locationIsNotWritable=Není možné zapisovat na zadané cestě
addvaultwizard.new.locationIsOk=Vhodné umístění pro váš trezor
addvaultwizard.new.invalidName=Neplatný název trezoru
addvaultwizard.new.validName=Platné jméno trezoru
addvaultwizard.new.validCharacters.message=Název trezoru může obsahovat tyto znaky:
addvaultwizard.new.validCharacters.chars=Slovní znaky (např. a, ж nebo 수)
addvaultwizard.new.validCharacters.numbers=Čísla
addvaultwizard.new.validCharacters.dashes=Pomlčka (%s) nebo podtržítko (%s)
### Password
addvaultwizard.new.createVaultBtn=Vytvořit trezor
addvaultwizard.new.generateRecoveryKeyChoice=Nebudete mít přístup k datům bez hesla. Chcete recovery klíč pro případ, že ztratíte heslo?
@@ -86,6 +92,7 @@ addvaultwizard.success.unlockNow=Odemknout nyní
# Remove Vault
removeVault.title=Odstranit trezor
removeVault.message=Odstranit trezor?
removeVault.description=Toto jen umožní Cryptomatoru zapomenout tento trezor. Později jej můžete opět přidat. Žádné šifrované soubory nebudou z vašeho disku smazány.
removeVault.confirmBtn=Odstranit trezor
@@ -96,6 +103,7 @@ changepassword.finalConfirmation=Chápu, že pokud zapomenu své heslo, nebudu m
# Forget Password
forgetPassword.title=Zapomenout heslo
forgetPassword.message=Zapomenout uložené heslo?
forgetPassword.description=Toto smaže uložené heslo pro tento trezor.
forgetPassword.confirmBtn=Zapomenout heslo
@@ -105,28 +113,37 @@ unlock.passwordPrompt=Zadejte heslo pro "%s":
unlock.savePassword=Zapamatovat heslo
unlock.unlockBtn=Odemknout
## Select
unlock.chooseMasterkey.message=Masterkey soubor nebyl nalezen
unlock.chooseMasterkey.description=Nepodařilo se najít soubor hlavního klíče pro tento trezor v očekávaném umístění. Vyberte prosím soubor klíče ručně.
unlock.chooseMasterkey.filePickerTitle=Vyberte soubor s hlavním klíčem
unlock.chooseMasterkey.filePickerMimeDesc=Hlavní klíč Cryptomatoru
## Success
unlock.success.message=Odemknutí bylo úspěšné
unlock.success.description=Trezor "%s" byl úspěšně odemčen a nyní je dostupný jako virtuální jednotka.
unlock.success.rememberChoice=Pamatovat si volbu, nezobrazovat to znovu
unlock.success.revealBtn=Zobrazit jednotku
## Failure
unlock.error.message=Nelze odemknout trezor
### Invalid Mount Point
unlock.error.invalidMountPoint.notExisting=Připojovací bod %s není složkou, není prázdný nebo neexistuje.
unlock.error.invalidMountPoint.existing=Připojovací bod %s již existuje nebo nadřazená složka chybí.
unlock.error.invalidMountPoint.driveLetterOccupied=Písmeno „%s“ už je používáno pro jiný disk.
## Hub
hub.noKeychain.openBtn=Otevřít předvolby
### Waiting
hub.auth.message=Čekání na ověření…
### Receive Key
### Register Device
hub.register.message=Je vyžadován název zařízení
hub.register.nameLabel=Název zařízení
hub.register.occupiedMsg=Jméno je již používáno
hub.register.registerBtn=Potvrdit
### Registration Success
hub.registerSuccess.message=Jméno zařízení
hub.registerSuccess.description=Pro přístup k trezoru musí být vaše zařízení autorizováno majitelem trezoru.
### Registration Failed
hub.registerFailed.message=Pojmenování zařízení se nezdařilo
### Unauthorized
hub.unauthorized.message=Přístup odepřen
hub.unauthorized.description=Vaše zařízení dosud nebylo oprávněno k přístupu k tomuto trezoru. Požádejte vlastníka trezoru, aby jej autorizoval.
### License Exceeded
hub.licenseExceeded.message=Licence byla překročena
hub.licenseExceeded.description=Cryptomator Hub poskytl přístup více uživatelům, než jsou jeho licenční povolení. Obraťte se na správce Hubu pro aktualizaci licence nebo správce trezoru pro odstranění uživatelů z trezoru.
# Lock
@@ -142,8 +159,13 @@ lock.fail.description=Trezor "%s" nelze uzamknout. Ujistěte se, že je neulože
# Migration
migration.title=Upgrade trezoru
## Start
migration.start.prompt=Váš trezor "%s" musí být aktualizován na nový formát.\nNež začnete, ujistěte se, že není žádná probíhající či čekající synchronizace na tomto trezoru.
migration.start.confirm=Ano, můj trezor je plně synchronizován.
migration.start.header=Upgrade trezoru
migration.start.text=Pro otevření trezoru "%s" v této nové verzi Cryptomatoru je třeba aktualizovat trezor na novější formát. Před tím byste měli vědět následující:
migration.start.remarkUndone=Tuto aktualizaci nelze vrátit zpět.
migration.start.remarkVersions=Starší verze Cryptomator nebudou moci otevřít aktualizovaný trezor.
migration.start.remarkCanRun=Musíte si být jisti, že každé zařízení, ze kterého máte přístup k trezoru, může spustit tuto verzi Cryptomatoru.
migration.start.remarkSynced=Před aktualizací se musíte ujistit, že je váš trezor plně synchronizován na tomto zařízení a na vašich dalších zařízeních.
migration.start.confirm=Přečetl jsem si výše uvedené informace a rozumím jim
## Run
migration.run.enterPassword=Zadejte heslo pro "%s"
migration.run.startMigrationBtn=Migrovat trezor
@@ -191,8 +213,15 @@ health.check.detail.checkFinished=Kontrola byla úspěšně dokončena.
health.check.detail.checkFinishedAndFound=Kontrola byla dokončena. Zkontrolujte prosím výsledky.
health.check.detail.checkFailed=Kontrola byla ukončena z důvodu chyby.
health.check.detail.checkCancelled=Kontrola byla zrušena.
health.check.detail.listFilters.label=Filtr
health.check.detail.fixAllSpecificBtn=Opravit všechny typy
health.check.exportBtn=Exportovat sestavu
## Result view
health.result.severityFilter.all=Závažnost - vše
health.result.severityFilter.good=Dobré
health.result.severityFilter.info=Informace
health.result.severityFilter.warn=Varování
health.result.severityFilter.crit=Kritické
## Fix Application
health.fix.fixBtn=Opravit
health.fix.successTip=Oprava byla úspěšná
@@ -223,9 +252,7 @@ preferences.interface.showMinimizeButton=Zobrazit tlačítko minimalizovat
preferences.interface.showTrayIcon=Zobrazit ikonu v liště (vyžaduje restart)
## Volume
preferences.volume=Virtuální jednotky
preferences.volume.type=Typ připojení
preferences.volume.webdav.port=WebDAV Port
preferences.volume.webdav.scheme=WebDAV schéma
preferences.volume.type.automatic=Automatické
## Updates
preferences.updates=Aktualizace
preferences.updates.currentVersion=Aktuální verze: %s
@@ -274,6 +301,8 @@ stats.encr.total.data.gib=Zašifrováno: %.1f GiB
stats.write.accessCount=Celkem zapsáno: %d
## Accesses
stats.access.current=Přístup: %d
stats.access.total=Přístup celkem: %d
# Main Window
@@ -282,9 +311,6 @@ main.minimizeBtn.tooltip=Minimalizovat
main.preferencesBtn.tooltip=Nastavení
main.debugModeEnabled.tooltip=Režim ladění je povolen
main.supporterCertificateMissing.tooltip=Prosím, zvažte darování
## Drag 'n' Drop
main.dropZone.dropVault=Přidat tento trezor
main.dropZone.unknownDragboardContent=Pokud chcete přidat trezor, přetáhněte jej do tohoto okna
## Vault List
main.vaultlist.emptyList.onboardingInstruction=Klikněte zde pro přidání nového trezoru
main.vaultlist.contextMenu.remove=Odstranit…
@@ -358,28 +384,31 @@ vaultOptions.mount.winDriveLetterOccupied=obsazeno
vaultOptions.mount.mountPoint=Přípojný bod
vaultOptions.mount.mountPoint.auto=Automaticky vybrat vhodné místo
vaultOptions.mount.mountPoint.driveLetter=Použít zvolenou jednotku
vaultOptions.mount.mountPoint.custom=Vlastní cesta
vaultOptions.mount.mountPoint.directoryPickerButton=Vybrat...
vaultOptions.mount.mountPoint.directoryPickerTitle=Vyberte prázdný adresář
## Master Key
vaultOptions.masterkey=Heslo
vaultOptions.masterkey.changePasswordBtn=Změnit heslo
vaultOptions.masterkey.forgetSavedPasswordBtn=Zapomenout uložené heslo
vaultOptions.masterkey.recoveryKeyExplanation=Obnovovací klíč je váš jediný způsob, jak obnovit přístup k trezoru, pokud ztratíte své heslo.
vaultOptions.masterkey.showRecoveryKeyBtn=Zobrazit klíč k obnově
vaultOptions.masterkey.recoverPasswordBtn=Resetovat heslo
# Recovery Key
## Display Recovery Key
recoveryKey.display.title=Zobrazit obnovovací klíč
recoveryKey.create.message=Vyžadováno heslo
recoveryKey.create.description=Zadejte své heslo pro zobrazení obnovovacího klíče pro "%s":
recoveryKey.display.description=Následující obnovovací klíč může být použit k obnovení přístupu k "%s":
recoveryKey.display.StorageHints=Uchovejte ho někde velmi bezpečně, např.\n • Uložit pomocí správce hesel\n • Uložit na USB flash disk\n • Vytisknout na papír
## Reset Password
### Enter Recovery Key
recoveryKey.recover.title=Resetovat heslo
recoveryKey.recover.prompt=Zadejte váš obnovovací klíč pro "%s":
recoveryKey.recover.validKey=Toto je platný obnovovací klíč
recoveryKey.printout.heading=Obnovovací klíč Cryptomator\n"%s"\n
### Reset Password
recoveryKey.recover.resetBtn=Resetovat
### Recovery Key Password Reset Success
# New Password
@@ -395,6 +424,7 @@ passwordStrength.messageLabel.3=silné
passwordStrength.messageLabel.4=velmi silné
# Quit
quit.title=Ukončit aplikaci
quit.lockAndQuitBtn=Uzamknout a zavřít
# Forced Quit
+30 -15
View File
@@ -123,12 +123,10 @@ unlock.success.description=Indholdet i boksen "%s" er nu tilgængeligt der hvor
unlock.success.rememberChoice=Husk mit valg. Spørg ikke igen
unlock.success.revealBtn=Vis drev
## Failure
unlock.error.message=Kan ikke låse boksen op
### Invalid Mount Point
unlock.error.invalidMountPoint.notExisting=Placeringen "%s" er ikke en mappe, er ikke tom, eller findes ikke.
unlock.error.invalidMountPoint.existing=Placeringen "%s" findes allerede, eller den overordnede mappe mangler.
unlock.error.invalidMountPoint.driveLetterOccupied=Drevbogstavet "%s" er allerede i brug.
## Hub
hub.noKeychain.message=Kan ikke tilgå enhedsnøgle
hub.noKeychain.description=En enhedsnøgle er påkrævet for at låse Hub bokse op. Enhedsnøglen er sikret i en nøglering. For at fortsætte, aktivér “%s” og vælg en nøglering i indstillingerne.
hub.noKeychain.openBtn=Åbn Indstillinger
### Waiting
hub.auth.message=Afventer godkendelse…
hub.auth.description=Du burde automatisk blive omdirigeret til login-siden.
@@ -169,8 +167,13 @@ lock.fail.description=Boksen "%s" kunne ikke låses. Sørg for, at ikke-gemt arb
# Migration
migration.title=Opgradér boks
## Start
migration.start.prompt=Din boks "%s" skal opdateres til et nyere format. Før du fortsætter, skal du sørge for, at der ikke er nogen afventende eller igangværende synkronisering.
migration.start.confirm=Ja. Min boks er fuldt synkroniseret
migration.start.header=Opgradér boks
migration.start.text=For at åbne din boks "%s" i denne nye version af Cryptomator, skal boksen opgraderes til et nyere format. Før dette gøres, bør du vide følgende:
migration.start.remarkUndone=Denne opgradering kan ikke fortrydes.
migration.start.remarkVersions=Ældre versioner af Cryptomator vil ikke være i stand til at åbne den opgraderede boks.
migration.start.remarkCanRun=Du skal være sikker på, at hver enhed, hvorfra du tilgår boksen, kan køre denne version af Cryptomator.
migration.start.remarkSynced=Du skal sikre at din boks er fuldt synkroniseret på denne enhed, og på dine andre enheder, før du opgraderer den.
migration.start.confirm=Jeg har læst og forstået ovenstående oplysninger
## Run
migration.run.enterPassword=Indtast adgangskoden for "%s"
migration.run.startMigrationBtn=Migrér boks
@@ -218,8 +221,25 @@ health.check.detail.checkFinished=Kontrolproceduren er afsluttet.
health.check.detail.checkFinishedAndFound=Kontrolproceduren er kørt færdig. Gennemse venligst resultatet.
health.check.detail.checkFailed=Kontrolproceduren blev afbrudt af en fejl.
health.check.detail.checkCancelled=Kontrolproceduren blev annulleret.
health.check.detail.listFilters.label=Filter
health.check.detail.fixAllSpecificBtn=Løs alle af type
health.check.exportBtn=Eksportér rapport
## Result view
health.result.severityFilter.all=Status - Alle
health.result.severityFilter.good=God
health.result.severityFilter.info=Info
health.result.severityFilter.warn=Advarsel
health.result.severityFilter.crit=Kritisk
health.result.severityTip.good=Status: God\nNormal boks struktur.
health.result.severityTip.info=Alvorlighed: Info\nBoks struktur intakt, løsning foreslået.
health.result.severityTip.warn=Status: Advarsel\nBoks struktur beskadiget, løsning stærkt anbefalet.
health.result.severityTip.crit=Status: Kritisk\nBoks struktur beskadiget, datatab med sikkerhed.
health.result.fixStateFilter.all=Løsningstilstand - Alle
health.result.fixStateFilter.fixable=Kan repareres
health.result.fixStateFilter.notFixable=Kan ikke repareres
health.result.fixStateFilter.fixing=Reparerer…
health.result.fixStateFilter.fixed=Repareret
health.result.fixStateFilter.fixFailed=Reparation mislykkedes
## Fix Application
health.fix.fixBtn=Reparér
health.fix.successTip=Repareret
@@ -251,9 +271,7 @@ preferences.interface.showMinimizeButton=Vis knap til minimering
preferences.interface.showTrayIcon=Vis ikon i system-bakken (kræver genstart)
## Volume
preferences.volume=Virtuelt drev
preferences.volume.type=Drev-type
preferences.volume.webdav.port=WebDAV port
preferences.volume.webdav.scheme=WebDAV skema
preferences.volume.type.automatic=Automatisk
## Updates
preferences.updates=Opdateringer
preferences.updates.currentVersion=Nuværende version: %s
@@ -302,6 +320,8 @@ stats.encr.total.data.gib=Data krypteret: %.1f GiB
stats.write.accessCount=Totalt antal skrivninger: %d
## Accesses
stats.access.current=Adgang: %d
stats.access.total=Samlede adgang: %d
# Main Window
@@ -310,9 +330,6 @@ main.minimizeBtn.tooltip=Minimér
main.preferencesBtn.tooltip=Præferencer
main.debugModeEnabled.tooltip=Fejlfindingstilstand er aktiveret
main.supporterCertificateMissing.tooltip=Overvej venligst at donere
## Drag 'n' Drop
main.dropZone.dropVault=Tilføj denne boks
main.dropZone.unknownDragboardContent=Hvis du vil tilføje en boks, så træk den til dette vindue
## Vault List
main.vaultlist.emptyList.onboardingInstruction=Klik her for at tilføje en boks
main.vaultlist.contextMenu.remove=Fjern…
@@ -386,9 +403,7 @@ vaultOptions.mount.winDriveLetterOccupied=optaget
vaultOptions.mount.mountPoint=Monterings-sted
vaultOptions.mount.mountPoint.auto=Vælg automatisk en passende placering
vaultOptions.mount.mountPoint.driveLetter=Brug et ledigt drevbogstav
vaultOptions.mount.mountPoint.custom=Brugerdefineret sti
vaultOptions.mount.mountPoint.directoryPickerButton=Vælg…
vaultOptions.mount.mountPoint.directoryPickerTitle=Vælg en tom mappe
## Master Key
vaultOptions.masterkey=Adgangskode
vaultOptions.masterkey.changePasswordBtn=Skift adgangskode
+23 -28
View File
@@ -93,7 +93,7 @@ addvaultwizard.success.unlockNow=Jetzt entsperren
# Remove Vault
removeVault.title=„%s“ entfernen
removeVault.message=Tresor entfernen?
removeVault.description=Dieser Tresor wird nur aus der Tresorliste entfernt. Du kannst den Tresor später jederzeit wieder hinzufügen. Es werden keine verschlüsselten Daten gelöscht.
removeVault.description=Dieser Tresor wird nur aus der Tresorliste entfernt; du kannst ihn später jederzeit wieder hinzufügen. Es werden keine verschlüsselten Daten gelöscht.
removeVault.confirmBtn=Tresor entfernen
# Change Password
@@ -123,12 +123,10 @@ unlock.success.description=Der Inhalt des Tresors „%s“ ist nun über dessen
unlock.success.rememberChoice=Auswahl merken und nicht mehr fragen
unlock.success.revealBtn=Laufwerk anzeigen
## Failure
unlock.error.message=Tresor konnte nicht entsperrt werden
### Invalid Mount Point
unlock.error.invalidMountPoint.notExisting=Einhängepunkt „%s“ ist kein leeres Verzeichnis oder existiert nicht.
unlock.error.invalidMountPoint.existing=Einhängepunkt „%s“ besteht bereits oder übergeordneter Ordner fehlt.
unlock.error.invalidMountPoint.driveLetterOccupied=Laufwerksbuchstabe „%s“ wird bereits verwendet.
## Hub
hub.noKeychain.message=Zugriff auf Geräteschlüssel nicht möglich
hub.noKeychain.description=Um Hub Tresore zu entsperren, wird ein Geräteschlüssel benötigt, der mit einem Schlüsselbund gesichert ist. Um fortzufahren, aktiviere “%s” und wähle einen Schlüsselbund in den Einstellungen.
hub.noKeychain.openBtn=Einstellungen öffnen
### Waiting
hub.auth.message=Warten auf Authentifizierung …
hub.auth.description=Du solltest automatisch zur Anmeldeseite weitergeleitet werden.
@@ -153,7 +151,7 @@ hub.unauthorized.message=Zugriff verweigert
hub.unauthorized.description=Dein Gerät wurde noch nicht für den Zugriff auf diesen Tresor autorisiert. Bitte den Tresorbesitzer, dein Gerät zu autorisieren.
### License Exceeded
hub.licenseExceeded.message=Lizenz überschritten
hub.licenseExceeded.description=Im Cryptomator Hub wurden mehr Benutzern ein Zugriff gewährt, als die Lizenz erlaubt. Bitte kontaktieren Sie Ihren Hub-Administrator, um die Lizenz zu erweitern oder einen Tresoradministrator, um Benutzer aus dem Tresor zu entfernen.
hub.licenseExceeded.description=Im Cryptomator Hub wurden mehr Benutzern Zugriff gewährt, als dessen Lizenz erlaubt. Bitte kontaktiere deinen Hub-Administrator für ein Lizenz-Upgrade oder einen Tresor-Administrator, um Benutzer aus Tresoren zu entfernen.
# Lock
@@ -169,8 +167,13 @@ lock.fail.description=Der Tresor „%s“ konnte nicht gesperrt werden. Stelle s
# Migration
migration.title=Tresor upgraden
## Start
migration.start.prompt=Dein Tresor „%s“ muss auf ein neueres Format aktualisiert werden. Stell bitte zuvor sicher, dass dieser Tresor vollständig synchronisiert ist.
migration.start.confirm=Ja, mein Tresor ist vollständig synchronisiert
migration.start.header=Tresor upgraden
migration.start.text=Um deinen Tresor "%s" in dieser neuen Version von Cryptomator zu öffnen, muss der Tresor auf ein neueres Format aktualisiert werden. Bevor du dies tust, solltest du Folgendes wissen:
migration.start.remarkUndone=Dieser Vorgang kann nicht rückgängig gemacht werden.
migration.start.remarkVersions=Ältere Versionen von Cryptomator können den aktualisierten Tresor nicht öffnen.
migration.start.remarkCanRun=Du musst sicherstellen, dass jedes Gerät, von dem aus du auf den Tresor zugreifst, diese Version von Cryptomator ausführen kann.
migration.start.remarkSynced=Du musst sicherstellen, dass dein Tresor auf diesem Gerät und auf deinen anderen Geräten vollständig synchronisiert ist, bevor du ihn aktualisierst.
migration.start.confirm=Ich habe die oben genannten Informationen gelesen und verstanden
## Run
migration.run.enterPassword=Gib das Passwort für „%s“ ein
migration.run.startMigrationBtn=Tresor migrieren
@@ -219,9 +222,7 @@ health.check.detail.checkFinishedAndFound=Die Prüfung wurde abgeschlossen. Bitt
health.check.detail.checkFailed=Die Prüfung wurde wegen eines Fehlers abgebrochen.
health.check.detail.checkCancelled=Die Prüfung wurde abgebrochen.
health.check.detail.listFilters.label=Filter
health.check.detail.listFilters.severity=Schweregrad
health.check.detail.listFilters.fixState=Fix Status
health.check.detail.fixAllSpecificBtn=Behebe alle mit Status
health.check.detail.fixAllSpecificBtn=Alle dieses Typs reparieren
health.check.exportBtn=Bericht exportieren
## Result view
health.result.severityFilter.all=Schweregrad - Alle
@@ -230,14 +231,15 @@ health.result.severityFilter.info=Info
health.result.severityFilter.warn=Warnung
health.result.severityFilter.crit=Kritisch
health.result.severityTip.good=Schweregrad: Gut\nNormale Tresorstruktur.
health.result.severityTip.info=Schweregrad: Info\nTresorstruktur intakt, Beheben empfohlen.
health.result.severityTip.warn=Schweregrad: Warnung\nTresorstruktur beschädigt, Beheben dringend empfohlen.
health.result.severityTip.crit=Schweregrad: Kritisch\nTresorstruktur beschädigt, Datenverlust möglich.
health.result.fixStateFilter.all=Fix-Status - Alle
health.result.fixStateFilter.fixable=Fixierbar
health.result.fixStateFilter.notFixable=Nicht behebbar
health.result.fixStateFilter.fixed=Behoben
health.result.fixStateFilter.fixFailed=Fix fehlgeschlagen
health.result.severityTip.info=Schweregrad: Info\nTresorstruktur intakt, Reparatur empfohlen.
health.result.severityTip.warn=Schweregrad: Warnung\nTresorstruktur beschädigt, Reparatur dringend empfohlen.
health.result.severityTip.crit=Schweregrad: Kritisch\nTresorstruktur beschädigt, Datenverlust festgestellt.
health.result.fixStateFilter.all=Reparaturstatus - Alle
health.result.fixStateFilter.fixable=Reparabel
health.result.fixStateFilter.notFixable=Irreparabel
health.result.fixStateFilter.fixing=Wird repariert …
health.result.fixStateFilter.fixed=Repariert
health.result.fixStateFilter.fixFailed=Reparatur gescheitert
## Fix Application
health.fix.fixBtn=Beheben
health.fix.successTip=Fehlerbehebung erfolgreich
@@ -269,9 +271,7 @@ preferences.interface.showMinimizeButton=Schaltfläche zum Minimieren anzeigen
preferences.interface.showTrayIcon=Symbol im Infobereich anzeigen (Neustart erforderlich)
## Volume
preferences.volume=Tresorlaufwerk
preferences.volume.type=Laufwerkstyp
preferences.volume.webdav.port=WebDAV-Port
preferences.volume.webdav.scheme=WebDAV-Schema
preferences.volume.type.automatic=Automatisch
## Updates
preferences.updates=Updates
preferences.updates.currentVersion=Aktuelle Version: %s
@@ -330,9 +330,6 @@ main.minimizeBtn.tooltip=Minimieren
main.preferencesBtn.tooltip=Einstellungen
main.debugModeEnabled.tooltip=Diagnosemodus ist aktiviert
main.supporterCertificateMissing.tooltip=Zieh bitte eine Spende in Betracht
## Drag 'n' Drop
main.dropZone.dropVault=Diesen Tresor hinzufügen
main.dropZone.unknownDragboardContent=Falls du einen Tresor hinzufügen möchtest, zieh ihn in dieses Fenster
## Vault List
main.vaultlist.emptyList.onboardingInstruction=Klicke hier, um einen Tresor hinzuzufügen
main.vaultlist.contextMenu.remove=Entfernen …
@@ -406,9 +403,7 @@ vaultOptions.mount.winDriveLetterOccupied=belegt
vaultOptions.mount.mountPoint=Einhängepunkt
vaultOptions.mount.mountPoint.auto=Automatisch einen geeigneten Ort auswählen
vaultOptions.mount.mountPoint.driveLetter=Laufwerksbuchstaben zuweisen
vaultOptions.mount.mountPoint.custom=Eigener Pfad
vaultOptions.mount.mountPoint.directoryPickerButton=Durchsuchen …
vaultOptions.mount.mountPoint.directoryPickerTitle=Wähle ein leeres Verzeichnis
## Master Key
vaultOptions.masterkey=Passwort
vaultOptions.masterkey.changePasswordBtn=Passwort ändern
+51 -15
View File
@@ -123,12 +123,14 @@ unlock.success.description=Το περιεχόμενο στην κρύπτη "%s
unlock.success.rememberChoice=Απομνημόνευση επιλογής, μη ρωτήσεις ξανά
unlock.success.revealBtn=Αποκάλυψη εικονικού δίσκου
## Failure
unlock.error.message=Αδυναμία ξεκλειδώματος κρύπτης
### Invalid Mount Point
unlock.error.invalidMountPoint.notExisting=Το σημείο προσάρτησης δεν είναι κενός φάκελος ή δεν υπάρχει: %s
unlock.error.invalidMountPoint.existing=Το σημείο/φάκελος προσάρτησης υπάρχει ήδη ή ο γονικός φάκελος λείπει: %s
unlock.error.invalidMountPoint.driveLetterOccupied=Το Γράμμα Δίσκου "%s" χρησιμοποιείται ήδη.
unlock.error.customPath.message=Αδυναμία προσάρτησης της κρύπτης στην προσαρμοσμένη διαδρομή
unlock.error.customPath.description.notSupported=Εάν θέλετε να συνεχίσετε να χρησιμοποιείτε την προσαρμοσμένη διαδρομή, μεταβείτε στις προτιμήσεις και επιλέξτε έναν τύπο τόμου που την υποστηρίζει. Διαφορετικά, μεταβείτε στις επιλογές της κρύπτης και επιλέξτε ένα υποστηριζόμενο σημείο προσάρτησης.
unlock.error.customPath.description.notExists=Η προσαρμοσμένη διαδρομή προσάρτησης δεν υπάρχει. Είτε δημιουργήστε την στο τοπικό σύστημα αρχείων σας είτε αλλάξτε την στις επιλογές κρύπτης.
unlock.error.customPath.description.generic=Έχετε επιλέξει μια προσαρμοσμένη διαδρομή προσάρτησης για αυτή την κρύπτη, αλλά η χρήση της απέτυχε με το μήνυμα: %s
## Hub
hub.noKeychain.message=Δεν είναι δυνατή η πρόσβαση στο κλειδί της συσκευής
hub.noKeychain.description=Για να ξεκλειδώσετε τις κρύπτες Hub, απαιτείται ένα κλειδί συσκευής, το οποίο ασφαλίζεται με χρήση μπρελόκ. Για να συνεχίσετε, ενεργοποιήστε το "%s" και επιλέξτε ένα keychain στις προτιμήσεις.
hub.noKeychain.openBtn=Άνοιγμα Προτιμήσεων
### Waiting
hub.auth.message=Αναμονή για επαλήθευση…
hub.auth.description=Θα πρέπει να ανακατευθυνθείτε αυτόματα στη σελίδα σύνδεσης.
@@ -169,8 +171,13 @@ lock.fail.description=Η κρυπτη "%s" δεν ήταν δυνατό να κ
# Migration
migration.title=Αναβάθμιση Vault
## Start
migration.start.prompt=Το vault "%s" πρέπει να αναβαθμιστεί σε νεότερο format. Προτού προχωρήσετε, σιγουρευτείτε πως δεν εκτελούνται εργασίες συγχρονισμού που μπορεί να επηρεάσουν το vault.
migration.start.confirm=Ναι, το vault μου είναι πλήρως συγχρονισμένο
migration.start.header=Αναβάθμιση Κρύπτης
migration.start.text=Για να ανοίξετε την κρύπτη σας "%s" σε αυτήν τη νέα έκδοση του Cryptomator, η κρύπτη πρέπει να αναβαθμιστεί σε νεότερη μορφή. Πριν το κάνετε αυτό, θα πρέπει να γνωρίζετε τα εξής:
migration.start.remarkUndone=Αυτή η αναβάθμιση δεν μπορεί να αναιρεθεί.
migration.start.remarkVersions=Οι παλαιότερες εκδόσεις του Cryptomator δεν θα μπορούν να ανοίξουν την αναβαθμισμένη κρύπτη.
migration.start.remarkCanRun=Πρέπει να είστε βέβαιοι ότι κάθε συσκευή από την οποία αποκτάτε πρόσβαση στην κρύπτη μπορεί να εκτελέσει αυτήν την έκδοση του Cryptomator.
migration.start.remarkSynced=Πρέπει να βεβαιωθείτε ότι η κρύπτη σας είναι πλήρως συγχρονισμένη σε αυτήν τη συσκευή και σε άλλες συσκευές σας, προτού την αναβαθμίσετε.
migration.start.confirm=Έχω διαβάσει και κατανοήσει τις παραπάνω πληροφορίες
## Run
migration.run.enterPassword=Εισάγετε τον κωδικό για "%s"
migration.run.startMigrationBtn=Ενσωμάτωση Vault
@@ -218,8 +225,25 @@ health.check.detail.checkFinished=Ο έλεγχος ολοκληρώθηκε μ
health.check.detail.checkFinishedAndFound=Ο έλεγχος σταμάτησε να εκτελείται. Παρακαλώ εξετάστε τα αποτελέσματα.
health.check.detail.checkFailed=Ο έλεγχος τερματίστηκε λόγω σφάλματος.
health.check.detail.checkCancelled=Ο έλεγχος ακυρώθηκε.
health.check.detail.listFilters.label=Φίλτρο
health.check.detail.fixAllSpecificBtn=Επισκευή όλων των τύπων
health.check.exportBtn=Εξαγωγή Αναφοράς
## Result view
health.result.severityFilter.all=Σοβαρότητα - Όλα
health.result.severityFilter.good=Καλή
health.result.severityFilter.info=Πληροφορίες
health.result.severityFilter.warn=Προειδοποίηση
health.result.severityFilter.crit=Κρίσιμο
health.result.severityTip.good=Σοβαρότητα: Καλή\nΚανονική δομή κρύπτης.
health.result.severityTip.info=Σοβαρότητα: Πληροφορίες\n Η δομή της κρύπτης άθικτη, προτείνεται επισκευή.
health.result.severityTip.warn=Σοβαρότητα: Προειδοποίηση\n Η δομή της κρύπτης είναι κατεστραμμένη, η επισκευή συνιστάται ιδιαίτερα.
health.result.severityTip.crit=Σοβαρότητα: Κρίσιμη\n Η δομή της κρύπτης είναι κατεστραμμένη, η απώλεια δεδομένων προσδιορίστηκε.
health.result.fixStateFilter.all=Κατάσταση Επισκευής - Όλα
health.result.fixStateFilter.fixable=Επισκευάσιμο
health.result.fixStateFilter.notFixable=Μη επισκευάσιμο
health.result.fixStateFilter.fixing=Επισκευή…
health.result.fixStateFilter.fixed=Διορθώθηκε
health.result.fixStateFilter.fixFailed=Αποτυχία διόρθωσης
## Fix Application
health.fix.fixBtn=Επιδιόρθωση
health.fix.successTip=Επιτυχής επιδιόρθωση
@@ -251,9 +275,15 @@ preferences.interface.showMinimizeButton=Εμφάνιση κουμπιού ελ
preferences.interface.showTrayIcon=Εμφάνιση εικονιδίου tray (απαιτεί επανεκκίνηση)
## Volume
preferences.volume=Εικονικός δίσκος
preferences.volume.type=Τύπος τόμου
preferences.volume.webdav.port=Θύρα WebDAV
preferences.volume.webdav.scheme=Σχήμα WebDAV
preferences.volume.type=Τύπος Τόμου (απαιτείται επανεκκίνηση)
preferences.volume.type.automatic=Αυτόματα
preferences.volume.tcp.port=Θύρα TCP
preferences.volume.supportedFeatures=Ο επιλεγμένος τύπος τόμου υποστηρίζει τις ακόλουθες δυνατότητες:
preferences.volume.feature.mountAuto=Αυτόματη επιλογή σημείου προσάρτησης
preferences.volume.feature.mountToDir=Προσαρμοσμένος κατάλογος ως σημείο προσάρτησης
preferences.volume.feature.mountToDriveLetter=Γράμμα Δίσκου ως σημείο προσάρτησης
preferences.volume.feature.mountFlags=Προσαρμοσμένες επιλογές προσάρτησης
preferences.volume.feature.readOnly=Προσάρτηση μόνο για ανάγνωση
## Updates
preferences.updates=Ενημερώσεις
preferences.updates.currentVersion=Τρέχουσα έκδοση: %s
@@ -302,6 +332,8 @@ stats.encr.total.data.gib=Δεδομένα που κρυπτογραφήθηκα
stats.write.accessCount=Συνολικές εγγραφές: %d
## Accesses
stats.access.current=Πρόσβαση: %d
stats.access.total=Συνολική πρόσβαση: %d
# Main Window
@@ -310,9 +342,6 @@ main.minimizeBtn.tooltip=Ελαχιστοποίηση
main.preferencesBtn.tooltip=Προτιμήσεις
main.debugModeEnabled.tooltip=Έχει ενεργοποιηθεί η λειτουργία αποσφαλμάτωσης
main.supporterCertificateMissing.tooltip=Παρακαλούμε σκεφτείτε να κάνετε δωρεά
## Drag 'n' Drop
main.dropZone.dropVault=Προσθήκη vault
main.dropZone.unknownDragboardContent=Αν θέλετε να προσθέσετε ένα vault, σύρετε το σε αυτό το παράθυρο
## Vault List
main.vaultlist.emptyList.onboardingInstruction=Κάντε κλικ εδώ για να προσθέσετε ένα vault
main.vaultlist.contextMenu.remove=Αφαίρεση…
@@ -335,6 +364,7 @@ main.vaultDetail.passwordSavedInKeychain=Ο κωδικός αποθηκεύτη
main.vaultDetail.unlockedStatus=ΞΕΚΛΕΙΔΩΜΕΝΟ
main.vaultDetail.accessLocation=Τα δεδομένα του vault σας είναι διαθέσιμα εδώ:
main.vaultDetail.revealBtn=Αποκάλυψη εικονικού δίσκου
main.vaultDetail.copyUri=Αντιγραφή URI
main.vaultDetail.lockBtn=Κλείδωμα
main.vaultDetail.bytesPerSecondRead=Ανάγνωση:
main.vaultDetail.bytesPerSecondWritten=Εγγραφή:
@@ -342,6 +372,10 @@ main.vaultDetail.throughput.idle=σε αδράνεια
main.vaultDetail.throughput.kbps=%.1f kiB/s
main.vaultDetail.throughput.mbps=%.1f MiB/s
main.vaultDetail.stats=Στατιστικά Vault
main.vaultDetail.locateEncryptedFileBtn=Εντοπισμός Κρυπτογραφημένου Αρχείου
main.vaultDetail.locateEncryptedFileBtn.tooltip=Επιλέξτε ένα αρχείο από την κρύπτη σας για να εντοπίσετε το κρυπτογραφημένο αντίστοιχο
main.vaultDetail.encryptedPathsCopied=Οι Διαδρομές Αντιγράφηκαν στο Πρόχειρο!
main.vaultDetail.filePickerTitle=Επιλογή Αρχείου Μέσα Στην Κρύπτη
### Missing
main.vaultDetail.missing.info=Cryptomator δεν βρήκε vault σε αυτόν τον κατάλογο.
main.vaultDetail.missing.recheck=Επανέλεγχος
@@ -380,15 +414,17 @@ vaultOptions.general.startHealthCheckBtn=Έναρξη ελέγχου Υγεία
## Mount
vaultOptions.mount=Προσάρτηση
vaultOptions.mount.info=Οι επιλογές εξαρτώνται από τον επιλεγμένο τύπο τόμου.
vaultOptions.mount.linkToPreferences=Άνοιγμα προτιμήσεων εικονικής μονάδας δίσκου
vaultOptions.mount.readonly=Μόνο για ανάγνωση
vaultOptions.mount.customMountFlags=Προσαρμοσμένες ετικέτες προσάρτησης
vaultOptions.mount.winDriveLetterOccupied=κατειλημμένο
vaultOptions.mount.mountPoint=Σημείο προσάρτησης
vaultOptions.mount.mountPoint.auto=Επιλογή κατάλληλης τοποθεσίας αυτόματα
vaultOptions.mount.mountPoint.driveLetter=Χρήση επιλεγμένου γράμματος δίσκου
vaultOptions.mount.mountPoint.custom=Προσαρμοσμένη διαδρομή
vaultOptions.mount.mountPoint.custom=Χρήση επιλεγμένου καταλόγου
vaultOptions.mount.mountPoint.directoryPickerButton=Επιλογή…
vaultOptions.mount.mountPoint.directoryPickerTitle=Επιλέξτε ένα άδειο φάκελο
vaultOptions.mount.mountPoint.directoryPickerTitle=Επιλέξτε έναν κατάλογο
## Master Key
vaultOptions.masterkey=Κωδικός πρόσβασης
vaultOptions.masterkey.changePasswordBtn=Αλλαγή κωδικού πρόσβασης
+51 -15
View File
@@ -123,12 +123,14 @@ unlock.success.description=¡Desbloqueo de "%s" exitoso! Su bóveda ahora es acc
unlock.success.rememberChoice=Recordar opción y no mostrar de nuevo
unlock.success.revealBtn=Revelar unidad
## Failure
unlock.error.message=No se puede desbloquear la bóveda
### Invalid Mount Point
unlock.error.invalidMountPoint.notExisting=El punto de montaje "%s"no es un directorio, no está vacío o no existe.
unlock.error.invalidMountPoint.existing=El punto de montaje "%s" ya existe o falta la carpeta padre.
unlock.error.invalidMountPoint.driveLetterOccupied=La letra de unidad "%s" ya está en uso.
unlock.error.customPath.message=No se puede montar la bóveda en la ruta personalizada
unlock.error.customPath.description.notSupported=Si desea seguir usando la ruta personalizada, vaya a las preferencias y seleccione un tipo de volumen que lo admita. De lo contrario, vaya a las opciones de la bóveda y elija un punto de montaje compatible.
unlock.error.customPath.description.notExists=La ruta de montaje personalizada no existe. Créela en su sistema de archivos local o cámbiela en las opciones de la bóveda.
unlock.error.customPath.description.generic=Seleccionó una ruta de montaje personalizada para esta bóveda, pero falló al usarla con el mensaje: %s
## Hub
hub.noKeychain.message=No se puede acceder a la clave del dispositivo
hub.noKeychain.description=Para desbloquear las bóvedas de Hub, se requiere una clave de dispositivo que se asegura con un llavero. Para continuar, habilite "%s" y seleccione un llavero en las preferencias.
hub.noKeychain.openBtn=Abrir preferencias
### Waiting
hub.auth.message=Esperando la autenticación…
hub.auth.description=Debe ser redirigido automáticamente a la página de inicio de sesión.
@@ -169,8 +171,13 @@ lock.fail.description=No se pudo bloquear la bóveda "%s". Asegúrese de que el
# Migration
migration.title=Actualizar bóveda
## Start
migration.start.prompt=La bóveda "%s" necesita ser actualizada a un formato más nuevo. Antes de continuar, asegúrese de que no haya ninguna sincronización pendiente afectando esta bóveda.
migration.start.confirm=Sí, mi bóveda está sincronizada
migration.start.header=Actualizar bóveda
migration.start.text=Para abrir la bóveda "%s" en esta versión nueva de Cryptomator, la bóveda necesita actualizarse a un formato más reciente. Antes de hacer esto, debe saber lo siguiente:
migration.start.remarkUndone=Esta actualización no puede deshacerse.
migration.start.remarkVersions=Las versiones más antiguas de Cryptomator no podrán abrir la bóveda actualizada.
migration.start.remarkCanRun=Debe asegurarse de que todos los dispositivos desde los que accede a la bóveda puedan ejecutar esta versión de Cryptomator.
migration.start.remarkSynced=Debe asegurarse de que su bóveda esté completamente sincronizada en este dispositivo y en sus otros dispositivos antes de actualizarla.
migration.start.confirm=He leído y entendido la información anterior
## Run
migration.run.enterPassword=Ingresar la contraseña para "%s"
migration.run.startMigrationBtn=Migrar bóveda
@@ -218,8 +225,25 @@ health.check.detail.checkFinished=La comprobación terminó con éxito.
health.check.detail.checkFinishedAndFound=La comprobación terminó de ejecutarse. Revise los resultados.
health.check.detail.checkFailed=La comprobación terminó debido a un error.
health.check.detail.checkCancelled=La comprobación se canceló.
health.check.detail.listFilters.label=Filtro
health.check.detail.fixAllSpecificBtn=Reparar todo del tipo
health.check.exportBtn=Exportar informe
## Result view
health.result.severityFilter.all=Gravedad - Todos
health.result.severityFilter.good=Buena
health.result.severityFilter.info=Info
health.result.severityFilter.warn=Advertencia
health.result.severityFilter.crit=Crítica
health.result.severityTip.good=Gravedad: Buena\nEstructura normal de la bóveda.
health.result.severityTip.info=Gravedad: Info\nEstructura de la bóveda intacta, reparación sugerida.
health.result.severityTip.warn=Gravedad: Advertencia\nEstructura de la bóveda corrompida, reparación recomendada.
health.result.severityTip.crit=Gravedad: Crítica\nEstructura de la bóveda corrupta, pérdida de datos determinada.
health.result.fixStateFilter.all=Reparar estado - Todo
health.result.fixStateFilter.fixable=Reparable
health.result.fixStateFilter.notFixable=Irreparable
health.result.fixStateFilter.fixing=Reparando…
health.result.fixStateFilter.fixed=Reparado
health.result.fixStateFilter.fixFailed=Error de reparación
## Fix Application
health.fix.fixBtn=Reparar
health.fix.successTip=Reparación exitosa
@@ -251,9 +275,15 @@ preferences.interface.showMinimizeButton=Mostrar botón minimizar
preferences.interface.showTrayIcon=Mostrar ícono de bandeja (requiere reiniciar)
## Volume
preferences.volume=Unidad virtual
preferences.volume.type=Tipo de volumen
preferences.volume.webdav.port=Puerto WebDAV
preferences.volume.webdav.scheme=Esquema WebDAV
preferences.volume.type=Tipo de volumen (requiere reiniciar)
preferences.volume.type.automatic=Automático
preferences.volume.tcp.port=Puerto TCP
preferences.volume.supportedFeatures=El tipo de volumen elegido admite las siguientes funciones:
preferences.volume.feature.mountAuto=Selección automática del punto de montaje
preferences.volume.feature.mountToDir=Directorio personalizado como punto de montaje
preferences.volume.feature.mountToDriveLetter=Letra de unidad como punto de montaje
preferences.volume.feature.mountFlags=Opciones de montaje personalizadas
preferences.volume.feature.readOnly=Montaje de solo lectura
## Updates
preferences.updates=Actualizaciones
preferences.updates.currentVersion=Versión actual: %s
@@ -302,6 +332,8 @@ stats.encr.total.data.gib=Datos cifrados: %.1f GiB
stats.write.accessCount=Total de escrituras: %d
## Accesses
stats.access.current=Accesos: %d
stats.access.total=Accesos totales: %d
# Main Window
@@ -310,9 +342,6 @@ main.minimizeBtn.tooltip=Minimizar
main.preferencesBtn.tooltip=Preferencias
main.debugModeEnabled.tooltip=Modo de depuración activado
main.supporterCertificateMissing.tooltip=Por favor, considere donar
## Drag 'n' Drop
main.dropZone.dropVault=Añadir esta bóveda
main.dropZone.unknownDragboardContent=Si desea añadir una bóveda, arrástrela a esta ventana
## Vault List
main.vaultlist.emptyList.onboardingInstruction=Haga clic aquí para añadir una bóveda
main.vaultlist.contextMenu.remove=Eliminar…
@@ -335,6 +364,7 @@ main.vaultDetail.passwordSavedInKeychain=Contraseña guardada
main.vaultDetail.unlockedStatus=DESBLOQUEADO
main.vaultDetail.accessLocation=El contenido de la bóveda es accesible aquí:
main.vaultDetail.revealBtn=Revelar unidad
main.vaultDetail.copyUri=Copiar URI
main.vaultDetail.lockBtn=Bloquear
main.vaultDetail.bytesPerSecondRead=Lectura:
main.vaultDetail.bytesPerSecondWritten=Escritura:
@@ -342,6 +372,10 @@ main.vaultDetail.throughput.idle=inactivo
main.vaultDetail.throughput.kbps=%.1f kiB/s
main.vaultDetail.throughput.mbps=%.1f MiB/s
main.vaultDetail.stats=Estadísticas de la bóveda
main.vaultDetail.locateEncryptedFileBtn=Ubicar archivo cifrado
main.vaultDetail.locateEncryptedFileBtn.tooltip=Elija un archivo de su bóveda para ubicar su contraparte cifrada
main.vaultDetail.encryptedPathsCopied=¡Rutas copiadas al portapapeles!
main.vaultDetail.filePickerTitle=Seleccionar archivo dentro de la bóveda
### Missing
main.vaultDetail.missing.info=Cryptomator no pudo encontrar una bóveda en esta ruta.
main.vaultDetail.missing.recheck=Volver a comprobar
@@ -380,15 +414,17 @@ vaultOptions.general.startHealthCheckBtn=Iniciar comprobación de estado
## Mount
vaultOptions.mount=Montaje
vaultOptions.mount.info=Las opciones dependen del tipo de volumen seleccionado.
vaultOptions.mount.linkToPreferences=Abrir preferencias de unidad virtual
vaultOptions.mount.readonly=Sólo lectura
vaultOptions.mount.customMountFlags=Opciones de montaje personalizadas
vaultOptions.mount.winDriveLetterOccupied=ocupado
vaultOptions.mount.mountPoint=Punto de montaje
vaultOptions.mount.mountPoint.auto=Escoger automáticamente una ubicación adecuada
vaultOptions.mount.mountPoint.driveLetter=Usar letra de unidad asignada
vaultOptions.mount.mountPoint.custom=Ruta personalizada
vaultOptions.mount.mountPoint.custom=Usar directorio seleccionado
vaultOptions.mount.mountPoint.directoryPickerButton=Elegir…
vaultOptions.mount.mountPoint.directoryPickerTitle=Elegir un directorio vacío
vaultOptions.mount.mountPoint.directoryPickerTitle=Seleccionar un directorio
## Master Key
vaultOptions.masterkey=Contraseña
vaultOptions.masterkey.changePasswordBtn=Cambiar contraseña
+23 -2
View File
@@ -4,15 +4,22 @@
## Button
generic.button.apply=درخواست
generic.button.back=بازگشت
generic.button.cancel=انصراف
generic.button.change=تغییر
generic.button.choose=انتخاب کنید…
generic.button.close=ببند
generic.button.copy=کپی
generic.button.copied=کپی شد!
generic.button.done=انجام شده
generic.button.next=بعدی
generic.button.print=چاپ
# Error
error.message=خطایی رخ داده است
error.technicalDetails=جزئیات:
# Defaults
defaults.vault.vaultName=گاوصندوق
# Tray Menu
traymenu.showMainWindow=نشان
@@ -22,13 +29,24 @@ traymenu.vault.lock=قفل
traymenu.vault.reveal=ظاهر
# Add Vault Wizard
addvaultwizard.title=اضافه کردن گاوصندوق
## Welcome
addvaultwizard.welcome.newButton=ساخت گاوصندوق جدید
addvaultwizard.welcome.existingButton=باز کردن گاوصندوق موجود
## New
### Name
addvaultwizard.new.nameInstruction=یک نام برای گاوصندوق انتخاب کنید
addvaultwizard.new.namePrompt=نام گاوصندوق
### Location
addvaultwizard.new.locationLabel=مکان ذخیره‌سازی
addvaultwizard.new.directoryPickerLabel=مکان سفارشی
addvaultwizard.new.directoryPickerButton=انتخاب کنید…
addvaultwizard.new.fileAlreadyExists=در حال حاضر یک فایل یا پوشه با همین نام وجود دارد
addvaultwizard.new.validCharacters.numbers=اعداد
### Password
### Information
## Existing
addvaultwizard.existing.chooseBtn=انتخاب کنید…
## Success
# Remove Vault
@@ -42,7 +60,6 @@ unlock.unlockBtn=بازکردن قفل
## Select
## Success
## Failure
### Invalid Mount Point
## Hub
### Waiting
### Receive Key
@@ -55,6 +72,7 @@ unlock.unlockBtn=بازکردن قفل
# Lock
## Force
lock.forced.retryBtn=تلاش مجدد
## Failure
# Migration
@@ -90,10 +108,11 @@ unlock.unlockBtn=بازکردن قفل
# Main Window
main.closeBtn.tooltip=ببند
main.supporterCertificateMissing.tooltip=لطفا کمک مالی در نظر بگیرند
## Drag 'n' Drop
## Vault List
main.vaultlist.contextMenu.lock=قفل
main.vaultlist.addVaultBtn=اضافه کردن گاوصندوق
## Vault Detail
### Welcome
### Locked
@@ -107,8 +126,10 @@ main.vaultDetail.lockBtn=قفل
# Vault Options
## General
vaultOptions.general.vaultName=نام گاوصندوق
## Mount
vaultOptions.mount.mountPoint.directoryPickerButton=انتخاب کنید…
## Master Key
@@ -66,7 +66,6 @@ unlock.unlockBtn=I-unlock
## Select
## Success
## Failure
### Invalid Mount Point
## Hub
### Waiting
### Receive Key
@@ -120,7 +119,6 @@ preferences.interface.theme.light=Light
# Main Window
main.closeBtn.tooltip=Isara
main.preferencesBtn.tooltip=Mga Kagustuhan
## Drag 'n' Drop
## Vault List
main.vaultlist.contextMenu.lock=I-lock
main.vaultlist.addVaultBtn=Magdagdag ng Vault
+42 -27
View File
@@ -82,7 +82,7 @@ addvault.new.readme.accessLocation.2=Ceci est le chemin d'accès de votre coffre
addvault.new.readme.accessLocation.3=Tous les fichiers ajoutés à ce volume seront chiffrés par Cryptomator. Vous pouvez l'utiliser comme n'importe quel lecteur/répertoire. Ceci est seulement une vue déchiffrée de son contenu, vos fichiers restent chiffrés dans votre disque dur en permanence.
addvault.new.readme.accessLocation.4=Vous pouvez supprimer ce fichier.
## Existing
addvaultwizard.existing.instruction=Choisissez le fichier "vault.cryptomator" de votre volume existant. Si seul le fichier "masterkey.cryptomator" est présent, sélectionnez celui-là.
addvaultwizard.existing.instruction=Choisissez le fichier « vault.cryptomator » de votre volume existant. Si seul le fichier « masterkey.cryptomator » est présent, sélectionnez celui-là.
addvaultwizard.existing.chooseBtn=Choisir...
addvaultwizard.existing.filePickerTitle=Sélectionnez le fichier correspondant au volume chiffré
addvaultwizard.existing.filePickerMimeDesc=Coffre-fort Cryptomator
@@ -104,7 +104,7 @@ changepassword.finalConfirmation=Je comprends que je ne pourrai pas récupérer
# Forget Password
forgetPassword.title=Mot de passe oublié
forgetPassword.message=Oublier le mot de passe enregistré ?
forgetPassword.description=Cela supprimera le mot de passe enregistré de cet espace chiffré de votre trousseau système.
forgetPassword.description=Le mot de passe enregistré pour ce coffre sera supprimé de votre trousseau.
forgetPassword.confirmBtn=Oublier le mot de passe
# Unlock
@@ -123,12 +123,14 @@ unlock.success.description=“%s” déverrouillé ! Le contenu de votre espace
unlock.success.rememberChoice=Se souvenir de mon choix et ne plus me le demander
unlock.success.revealBtn=Révéler le lecteur
## Failure
unlock.error.message=Impossible de déverrouiller l'espace chiffré
### Invalid Mount Point
unlock.error.invalidMountPoint.notExisting=Le point de montage «%s» n'est pas un répertoire, n'est pas vide ou n'existe pas.
unlock.error.invalidMountPoint.existing=Le point de montage/le répertoire existe déjà ou le répertoire parent est manquant: %s
unlock.error.invalidMountPoint.driveLetterOccupied=Le lecteur "%s" est déjà utilisé.
unlock.error.customPath.message=Impossible de monter le coffre vers le chemin personnalisé
unlock.error.customPath.description.notSupported=Si vous souhaitez continuer à utiliser le chemin personnalisé, veuillez aller dans les préférences et sélectionner un type de volume qui le supporte. Sinon, allez dans les options du coffre et choisissez un point de montage pris en charge.
unlock.error.customPath.description.notExists=Le chemin de montage personnalisé n'existe pas. Créez le dans votre système de fichiers local ou modifiez-le dans les options du coffre.
unlock.error.customPath.description.generic=Vous avez sélectionné un chemin de montage personnalisé pour ce coffre, mais son utilisation a échoué avec le message : %s
## Hub
hub.noKeychain.message=Impossible d'accéder à la clé du périphérique
hub.noKeychain.description=Le déverrouillage des coffres Hub nécessite une clé de périphérique sécurisée à l'aide d'un trousseau. Pour continuer, activez « %s » et sélectionnez un trousseau dans les préférences.
hub.noKeychain.openBtn=Ouvrir les préférences
### Waiting
hub.auth.message=Authentification en cours…
hub.auth.description=Vous devriez automatiquement être redirigé vers la page de connexion.
@@ -163,14 +165,19 @@ lock.forced.description=Le verrouillage de «%s» a été bloqué par des opéra
lock.forced.retryBtn=Réessayer
lock.forced.forceBtn=Forcer le verrouillage
## Failure
lock.fail.message=Le verrouillage de l'espace chiffré a échoué
lock.fail.message=Le verrouillage du volume chiffré a échoué
lock.fail.description=L'espace chiffré "%s" n'a pas pu être verrouillé. Assurez-vous que le travail non sauvegardé est sauvegardé ailleurs et que les opérations importantes de lecture/écriture sont bien terminées. Pour fermer l'espace chiffré, tuez le processus Cryptomator.
# Migration
migration.title=Mettre à jour le coffre
## Start
migration.start.prompt=Le coffre “%s” doit être mis à jour. Assurez-vous quaucune synchronisation nest en cours sur ce coffre avant de continuer.
migration.start.confirm=Oui, mon coffre est bien synchronisé
migration.start.header=Mettre le coffre à jour
migration.start.text=Afin d'ouvrir votre coffre "%s" dans cette nouvelle version de Cryptomator, le coffre doit être mis à jour vers un format plus récent. Avant de faire cela, vous devriez savoir ce qui suit :
migration.start.remarkUndone=Cette mise à niveau ne peut pas être annulée.
migration.start.remarkVersions=Les versions plus anciennes de Cryptomator ne pourront pas ouvrir le coffre mis à jour.
migration.start.remarkCanRun=Vous devez vous assurer que chaque appareil à partir duquel vous accédez au coffre peut exécuter cette version de Cryptomator.
migration.start.remarkSynced=Vous devez vous assurer que votre coffre est entièrement synchronisé sur cet appareil, et sur vos autres appareils, avant de le mettre à niveau.
migration.start.confirm=J'ai lu et compris les informations ci-dessus
## Run
migration.run.enterPassword=Entrez le mot de passe pour %s
migration.run.startMigrationBtn=Migrer le coffre
@@ -219,13 +226,11 @@ health.check.detail.checkFinishedAndFound=Le test est terminé. Veuillez vérifi
health.check.detail.checkFailed=La vérification s'est arrêtée en raison d'une erreur.
health.check.detail.checkCancelled=Vérification annulée.
health.check.detail.listFilters.label=Filtre
health.check.detail.listFilters.severity=Gravité
health.check.detail.listFilters.fixState=Corriger l'état
health.check.detail.fixAllSpecificBtn=Corriger tout le type
health.check.exportBtn=Exporter le rapport
## Result view
health.result.severityFilter.all=Gravité - Tous
health.result.severityFilter.good=Satisfaisant
health.result.severityFilter.good=Bon
health.result.severityFilter.info=Information
health.result.severityFilter.warn=Avertissement
health.result.severityFilter.crit=Critique
@@ -270,9 +275,15 @@ preferences.interface.showMinimizeButton=Afficher le bouton Réduire
preferences.interface.showTrayIcon=Montrer l'icône de service (redémarrage nécessaire)
## Volume
preferences.volume=Disque virtuel
preferences.volume.type=Type de volume
preferences.volume.webdav.port=port WebDav
preferences.volume.webdav.scheme=Schéma WebDAV
preferences.volume.type=Type de volume (nécessite un redémarrage)
preferences.volume.type.automatic=Automatique
preferences.volume.tcp.port=Port TCP
preferences.volume.supportedFeatures=Le type de volume choisi prend en charge les fonctionnalités suivantes :
preferences.volume.feature.mountAuto=Sélection automatique de point de montage
preferences.volume.feature.mountToDir=Répertoire personnalisé comme point de montage
preferences.volume.feature.mountToDriveLetter=Lettre du lecteur comme point de montage
preferences.volume.feature.mountFlags=Options de montage personnalisées
preferences.volume.feature.readOnly=Montage en lecture seule
## Updates
preferences.updates=Mises à jour
preferences.updates.currentVersion=Version actuelle : “%s”
@@ -331,9 +342,6 @@ main.minimizeBtn.tooltip=Réduire
main.preferencesBtn.tooltip=Préférences
main.debugModeEnabled.tooltip=Le mode débogage est activé
main.supporterCertificateMissing.tooltip=Merci d'envisager un don
## Drag 'n' Drop
main.dropZone.dropVault=Ajouter ce volume chiffré
main.dropZone.unknownDragboardContent=Si vous voulez ajouter un volume chiffré, faites-le glisser dans cette fenêtre
## Vault List
main.vaultlist.emptyList.onboardingInstruction=Cliquez ici pour ajouter un volume chiffré
main.vaultlist.contextMenu.remove=Retirer…
@@ -356,6 +364,7 @@ main.vaultDetail.passwordSavedInKeychain=Mot de passe enregistré
main.vaultDetail.unlockedStatus=DÉVERROUILLÉ
main.vaultDetail.accessLocation=Le contenu de votre coffre est accessible ici :
main.vaultDetail.revealBtn=Afficher le lecteur
main.vaultDetail.copyUri=Copier lURI
main.vaultDetail.lockBtn=Verrouiller
main.vaultDetail.bytesPerSecondRead=Lecture :
main.vaultDetail.bytesPerSecondWritten=Écriture:
@@ -363,6 +372,10 @@ main.vaultDetail.throughput.idle=inactif
main.vaultDetail.throughput.kbps=%.1f Ko/s
main.vaultDetail.throughput.mbps=%.1f Mo/s
main.vaultDetail.stats=Statistiques du volume chiffré
main.vaultDetail.locateEncryptedFileBtn=Localiser le fichier chiffré
main.vaultDetail.locateEncryptedFileBtn.tooltip=Choisissez un fichier dans votre coffre pour localiser sa version chiffrée
main.vaultDetail.encryptedPathsCopied=Chemins d'accès copiés dans le presse-papier !
main.vaultDetail.filePickerTitle=Sélectionner le fichier dans le coffre
### Missing
main.vaultDetail.missing.info=Cryptomator n'a pas pu trouver de volume chiffré dans ce chemin d'accès.
main.vaultDetail.missing.recheck=Revérifier
@@ -401,20 +414,22 @@ vaultOptions.general.startHealthCheckBtn=Commencer la vérification de l'état
## Mount
vaultOptions.mount=Montage
vaultOptions.mount.info=Les options dépendent du type de volume sélectionné.
vaultOptions.mount.linkToPreferences=Ouvrir les préférences du lecteur virtuel
vaultOptions.mount.readonly=Lecture seule
vaultOptions.mount.customMountFlags=Paramètres personnalisés de montage
vaultOptions.mount.winDriveLetterOccupied=occupé
vaultOptions.mount.mountPoint=Point de montage
vaultOptions.mount.mountPoint.auto=Choisir automatiquement un emplacement approprié
vaultOptions.mount.mountPoint.driveLetter=Utiliser la lettre du lecteur assignée
vaultOptions.mount.mountPoint.custom=Chemin personnalisé
vaultOptions.mount.mountPoint.custom=Utiliser le répertoire choisi
vaultOptions.mount.mountPoint.directoryPickerButton=Choisir...
vaultOptions.mount.mountPoint.directoryPickerTitle=Choisir un répertoire vide
vaultOptions.mount.mountPoint.directoryPickerTitle=Choisissez un dossier
## Master Key
vaultOptions.masterkey=Mot de passe
vaultOptions.masterkey.changePasswordBtn=Modifier le mot de passe
vaultOptions.masterkey.forgetSavedPasswordBtn=Oublier le mot de passe enregistré
vaultOptions.masterkey.recoveryKeyExplanation=Une clé de récupération est votre seul moyen de rétablir l'accès à un volume chiffré, si vous perdez votre mot de passe.
vaultOptions.masterkey.recoveryKeyExplanation=Une clé de récupération est le seul moyen de rétablir l'accès à un volume chiffré si vous en perdez le mot de passe.
vaultOptions.masterkey.showRecoveryKeyBtn=Afficher la clé de récupération
vaultOptions.masterkey.recoverPasswordBtn=Réinitialiser le mot de passe
@@ -425,7 +440,7 @@ recoveryKey.display.title=Montrer la clé de récupération
recoveryKey.create.message=Mot de passe requis
recoveryKey.create.description=Entrer le mot de passe de "%s" pour afficher sa clé de récupération.
recoveryKey.display.description=La clé de récupération suivante peut être utilisée pour restaurer l'accès à "%s " :
recoveryKey.display.StorageHints=Gardez-la dans un endroit sûr, par ex. :\n • Stockez-la en utilisant un gestionnaire de mot de passe\n • Enregistrez-la sur une clé USB\n • Imprimez-la
recoveryKey.display.StorageHints=Gardez-la dans un endroit sûr, par ex. :\n • Stockez-la en utilisant un gestionnaire de mots de passe\n • Enregistrez-la sur une clé USB\n • Imprimez-la
## Reset Password
### Enter Recovery Key
recoveryKey.recover.title=Réinitialiser le mot de passe
@@ -439,7 +454,7 @@ recoveryKey.recover.resetSuccess.message=Réinitialisation du mot de passe réus
recoveryKey.recover.resetSuccess.description=Vous pouvez déverrouiller votre coffre avec le nouveau mot de passe.
# New Password
newPassword.promptText=Entrer un nouveau mot de passe
newPassword.promptText=Entrez un nouveau mot de passe
newPassword.reenterPassword=Confirmez le nouveau mot de passe
newPassword.passwordsMatch=Mots de passe identiques !
newPassword.passwordsDoNotMatch=Les mots de passe ne sont pas identiques
@@ -452,11 +467,11 @@ passwordStrength.messageLabel.4=Très fort
# Quit
quit.title=Quitter lapplication
quit.message=Il y a des espaces chiffrés déverrouillés
quit.description=Veuillez confirmer que vous voulez quitter. Cryptomator verrouillera préventivement tous les espaces chiffrés déverrouillés pour éviter la perte de données.
quit.message=Il y a des volumes chiffrés déverrouillés
quit.description=Veuillez confirmer la fermeture. Les volumes ouverts seront verrouillés afin d'éviter toute perte de données.
quit.lockAndQuitBtn=Verrouiller et quitter
# Forced Quit
quit.forced.message=Certains coffres n'ont pas pu être verrouillés
quit.forced.description=Le verrouillage des coffres a été bloqué par des opérations en attente ou des fichiers ouverts. Vous pouvez forcer le verrouillage des coffres restants, mais l'interruption d'E/S peut entraîner la perte de données non enregistrées.
quit.forced.forceAndQuitBtn=Forcer et Quitter
quit.forced.forceAndQuitBtn=Forcer la fermeture
@@ -41,7 +41,6 @@ error.message=Produciuse un erro
## Select
## Success
## Failure
### Invalid Mount Point
## Hub
### Waiting
### Receive Key
@@ -91,7 +90,6 @@ lock.forced.retryBtn=Tentar de novo
# Main Window
main.closeBtn.tooltip=Pechar
## Drag 'n' Drop
## Vault List
## Vault Detail
### Welcome
+15 -7
View File
@@ -123,15 +123,22 @@ unlock.success.description=הנעילה ל-"%s" בוטלה בהצלחה! הכס
unlock.success.rememberChoice=זכור בחירה, אל תראה שוב
unlock.success.revealBtn=חשוף את הכונן
## Failure
unlock.error.message=לא מתאפשר לבטל נעילת הכספת
### Invalid Mount Point
## Hub
hub.noKeychain.message=לא ניתן לגשת למפתח המכשיר
### Waiting
hub.auth.message=ממתין לאימות…
### Receive Key
### Register Device
hub.register.nameLabel=שם מכשיר
hub.register.occupiedMsg=שם זה נמצא כבר בשימוש
hub.register.registerBtn=אישור
### Registration Success
hub.registerSuccess.message=שם המכשיר
### Registration Failed
hub.registerFailed.message=הגדרת שם למכשיר נכשלה
### Unauthorized
hub.unauthorized.message=הגישה נדחתה
hub.unauthorized.description=המכשיר שלך טרם אושר לגשת לכספת הזאת. יש לבקש אישור גישה מבעל הכספת.
### License Exceeded
@@ -146,7 +153,7 @@ lock.fail.message=נעילת הכספת נשכלה.
# Migration
migration.title=שדרג הכספת
## Start
migration.start.confirm=כן, הכספת שלי מסונכרנת במלואה
migration.start.header=שדרג הכספת
## Run
migration.run.enterPassword=הכנס/י סיסמה עבור "%s"
migration.run.startMigrationBtn=העבר הכספת
@@ -205,7 +212,7 @@ preferences.interface.interfaceOrientation.rtl=מימין לשמאל
preferences.interface.showMinimizeButton=הצג כפתור מזעור
## Volume
preferences.volume=כונן וירטואלי
preferences.volume.webdav.port=יציאה WebDAV
preferences.volume.type.automatic=אוטומטי
## Updates
preferences.updates=עדכונים
## Contribution
@@ -235,7 +242,6 @@ stats.read.total.data.none=מידע שנקרא: -
main.closeBtn.tooltip=סגור
main.preferencesBtn.tooltip=העדפות
main.supporterCertificateMissing.tooltip=תרומתך תתקבל בברכה
## Drag 'n' Drop
## Vault List
main.vaultlist.contextMenu.lock=נעילה
main.vaultlist.contextMenu.unlockNow=בטל נעילה כעת
@@ -248,6 +254,10 @@ main.vaultDetail.unlockNowBtn=בטל נעילה כעת
### Unlocked
main.vaultDetail.revealBtn=חשוף את הכונן
main.vaultDetail.lockBtn=נעילה
main.vaultDetail.locateEncryptedFileBtn=מצא קבצים מוצפנים
main.vaultDetail.locateEncryptedFileBtn.tooltip=בחר קובץ מהכספת שלך על מנת לאתר את הקובץ התואם המוצפן
main.vaultDetail.encryptedPathsCopied=הנתיבים הועתקו ללוח!
main.vaultDetail.filePickerTitle=בחר קובץ בתוך הכספת
### Missing
### Needs Migration
main.vaultDetail.migrateButton=שדרג הכספת
@@ -271,9 +281,7 @@ vaultOptions.general.actionAfterUnlock.reveal=חשוף את הכונן
vaultOptions.mount.readonly=קריאה בלבד
vaultOptions.mount.winDriveLetterOccupied=בשימוש
vaultOptions.mount.mountPoint=נקודת עיגון
vaultOptions.mount.mountPoint.custom=תיקייה מותאמת אישית
vaultOptions.mount.mountPoint.directoryPickerButton=בחר...
vaultOptions.mount.mountPoint.directoryPickerTitle=בחירת ספרייה ריקה
## Master Key
vaultOptions.masterkey=סיסמה
vaultOptions.masterkey.changePasswordBtn=שנה סיסמה
+21 -5
View File
@@ -80,8 +80,10 @@ addvault.new.readme.accessLocation.3=इस वॉल्यूम में क
addvault.new.readme.accessLocation.4=आप इस फाइल को बेझिझक डिलीट कर सकते हैं।
## Existing
addvaultwizard.existing.chooseBtn=चुनें…
addvaultwizard.existing.filePickerTitle=तिजोरी फ़ाइल चुनें
addvaultwizard.existing.filePickerMimeDesc=क्रिप्टोमेटर वॉल्ट
## Success
addvaultwizard.success.nextStepsInstructions="%s" नामक तिजोरी शामिल हो गई।\n तिजोरी में प्रवेश या कुछ सम्मिलित करने के लिए आपको इसे खोलना होगा। वैकल्पिक रूप से आप इसे बाद में कभी भी खोल सकते हैं।
addvaultwizard.success.unlockNow=अब अनलॉक करें
# Remove Vault
@@ -112,8 +114,6 @@ unlock.success.message=अनलॉक सफल हुआ
unlock.success.rememberChoice=विकल्प याद रखें, दोबारा ना दिखाएं
unlock.success.revealBtn=फोल्डर खोलें
## Failure
unlock.error.message=वॉल्ट को अनलॉक करना असफल हुआ
### Invalid Mount Point
## Hub
### Waiting
### Receive Key
@@ -125,6 +125,7 @@ hub.register.registerBtn=पुष्टि करें
### Registration Success
### Registration Failed
### Unauthorized
hub.unauthorized.message=प्रवेश अस्वीकृत
### License Exceeded
@@ -132,14 +133,17 @@ hub.register.registerBtn=पुष्टि करें
## Force
lock.forced.message=लॉक करना विफल हुआ
lock.forced.retryBtn=पुन: प्रयास करें
lock.forced.forceBtn=जबर्दस्ती बंद करें
## Failure
lock.fail.message=लॉक करना विफल
# Migration
migration.title=वाउल्ट को अपग्रेड करें
## Start
migration.start.header=वाउल्ट को अपग्रेड करें
## Run
migration.run.enterPassword="%s" का पासवर्ड दर्ज करें:
migration.run.startMigrationBtn=तिजोरी स्थानांतरित करें
migration.run.progressHint=इसमें थोड़ा समय लग सकता है...
## Success
migration.success.unlockNow=अब अनलॉक करें
@@ -148,10 +152,18 @@ migration.success.unlockNow=अब अनलॉक करें
# Health Check
## Start
health.intro.header=स्वास्थ्य जाँच
health.intro.remarkFix=सभी समस्याओं को ठीक नहीं किया जा सकता।
## Start Failure
## Check Selection
## Detail view
health.check.detail.listFilters.label=छांटे
## Result view
health.result.severityFilter.all=गंभीरता - सारे
health.result.severityFilter.good=कुशल
health.result.severityFilter.info=सूचना
health.result.severityFilter.warn=चेतावनी
health.result.severityFilter.crit=गंभीर
## Fix Application
# Preferences
@@ -164,10 +176,17 @@ preferences.general.autoStart=क्रिप्टोमेटर को सि
preferences.interface.theme.automatic=ऑटोमैटिक
preferences.interface.theme.dark=डार्क
preferences.interface.theme.light=लाइट
preferences.interface.language=भाषा (पुनः प्रारंभ आवश्यक)
preferences.interface.language.auto=सिस्टम निर्धारित
preferences.interface.interfaceOrientation.ltr=बाएं से दाएं
preferences.interface.interfaceOrientation.rtl=दाएं से बाएं
## Volume
preferences.volume.type.automatic=ऑटोमैटिक
## Updates
preferences.updates=नवीनीकरण
preferences.updates.currentVersion=वर्तमान संस्करण: %s
preferences.updates.checkNowBtn=अभी जाँचें
preferences.updates.updateAvailable=संस्करण %s की तरफ नवीनीकरण उपलब्ध है।
## Contribution
preferences.contribute=हमें सपोर्ट करें
#<-- Add entries for donations and code/translation/documentation contribution -->
@@ -185,7 +204,6 @@ preferences.contribute=हमें सपोर्ट करें
main.closeBtn.tooltip=बंद करें
main.preferencesBtn.tooltip=प्राथमिकताएं
main.supporterCertificateMissing.tooltip=कृपया दान पर विचार करें।
## Drag 'n' Drop
## Vault List
main.vaultlist.emptyList.onboardingInstruction=वॉल्ट को डालने के लिए यहाँ क्लिक करें।
main.vaultlist.contextMenu.remove=हटाएँ...
@@ -231,9 +249,7 @@ vaultOptions.mount.winDriveLetterOccupied=इसका इस्तेमाल
vaultOptions.mount.mountPoint=माउंट पॉइंट
vaultOptions.mount.mountPoint.auto=स्वचालित रूप से एक उपयुक्त स्थान चुनें
vaultOptions.mount.mountPoint.driveLetter=नियुक्त किए गए ड्राइव अक्षर का उपयोग करें
vaultOptions.mount.mountPoint.custom=अपने पसंद की जगह
vaultOptions.mount.mountPoint.directoryPickerButton=चुनें…
vaultOptions.mount.mountPoint.directoryPickerTitle=कोई खाली जगह चुने
## Master Key
vaultOptions.masterkey=पासवर्ड
vaultOptions.masterkey.changePasswordBtn=पासवर्ड बदलें
+3 -15
View File
@@ -113,11 +113,6 @@ unlock.success.description=Uspješno otključan "%s"! Vaš trezor je sada dostup
unlock.success.rememberChoice=Zapamti izbor, ne prikazuj ovo više
unlock.success.revealBtn=Otkrij pogon
## Failure
unlock.error.message=Nije moguće otključati trezor
### Invalid Mount Point
unlock.error.invalidMountPoint.notExisting=Točka montiranja "%s" nije mapa, nije prazna ili ne postoji.
unlock.error.invalidMountPoint.existing=Točka montiranja "%s" već postoji ili nedostaje nadređena mapa.
unlock.error.invalidMountPoint.driveLetterOccupied=Slovna oznaka pogona "%s" se već koristi.
## Hub
### Waiting
### Receive Key
@@ -142,8 +137,8 @@ lock.fail.description=Trezor "%s" ne može se zaključati. Osigurajte da je nepo
# Migration
migration.title=Nadogradi trezor
## Start
migration.start.prompt=Vaš trezor "%s" treba nadograditi na noviji format. Prije nastavka, osigurajte da nema sinkronizacija u tijeku koje mogu utjecati na njega.
migration.start.confirm=Da, moj trezor je u cijelosti sinkroniziran
migration.start.header=Nadogradi trezor
migration.start.confirm=Pročitao/la sam i razumijem gore-navedene informacije
## Run
migration.run.enterPassword=Unesite lozinku za "%s"
migration.run.startMigrationBtn=Nadogradi trezor
@@ -223,9 +218,7 @@ preferences.interface.showMinimizeButton=Prikaži dugme za smanjivanje
preferences.interface.showTrayIcon=Pokaži ikonu u traci (zahtjeva ponovno pokretanje)
## Volume
preferences.volume=Virtualni pogon
preferences.volume.type=Tip volumena
preferences.volume.webdav.port=WebDAV port
preferences.volume.webdav.scheme=WebDAV shema
preferences.volume.type.automatic=Automatski
## Updates
preferences.updates=Ažuriranja
preferences.updates.currentVersion=Trenutna verzija: %s
@@ -282,9 +275,6 @@ main.minimizeBtn.tooltip=Smanji
main.preferencesBtn.tooltip=Postavke
main.debugModeEnabled.tooltip=Način otklanjanja pogrešaka je omogućen
main.supporterCertificateMissing.tooltip=Molimo razmislite o doniranju
## Drag 'n' Drop
main.dropZone.dropVault=Dodaj ovaj trezor
main.dropZone.unknownDragboardContent=Ako želite dodati trezor, povucite ga u ovaj prozor
## Vault List
main.vaultlist.emptyList.onboardingInstruction=Pritisnite ovdje da biste dodali trezor
main.vaultlist.contextMenu.remove=Ukloni…
@@ -358,9 +348,7 @@ vaultOptions.mount.winDriveLetterOccupied=zauzeto
vaultOptions.mount.mountPoint=Točka montiranja
vaultOptions.mount.mountPoint.auto=Automatski odaberi prikladnu lokaciju
vaultOptions.mount.mountPoint.driveLetter=Koristi dodijeljeno slovo pogona
vaultOptions.mount.mountPoint.custom=Prilagođeni put
vaultOptions.mount.mountPoint.directoryPickerButton=Odaberite…
vaultOptions.mount.mountPoint.directoryPickerTitle=Odaberi praznu mapu
## Master Key
vaultOptions.masterkey=Lozinka
vaultOptions.masterkey.changePasswordBtn=Promijeni lozinku
+3 -15
View File
@@ -111,11 +111,6 @@ unlock.success.description="%s" sikreresen feloldásra került! Mostmár hozzáf
unlock.success.rememberChoice=Jegyezze meg a választást és ne mutassa többet
unlock.success.revealBtn=Széf megjelenítése
## Failure
unlock.error.message=Nem lehet feloldani a széfet
### Invalid Mount Point
unlock.error.invalidMountPoint.notExisting=A csatolási pont "%s" nem egy könyvtár, nem üres vagy nem létezik.
unlock.error.invalidMountPoint.existing=A csatolási pont "%s" már létezik vagy a already exists or szülőmappa hiányzik.
unlock.error.invalidMountPoint.driveLetterOccupied=A "%s" meghajtó betűjel már használat alatt van.
## Hub
### Waiting
### Receive Key
@@ -139,8 +134,8 @@ lock.fail.description=A "%s" tárolót nem lehetett zárolni. Győződjön meg a
# Migration
migration.title=Széf frissítése
## Start
migration.start.prompt=A "%s" széf formátuma frissítésre szorul. A folytatás előtt győződjön meg arról, hogy nincs függőben lévő szinkronizálás, amely befolyásolja ezt a széfet.
migration.start.confirm=Igen, a széfem teljes mértékben szinkronizálva van
migration.start.header=Széf frissítése
migration.start.confirm=Elolvastam és megértettem a fenti információkat
## Run
migration.run.enterPassword=Írja be a jelszót a következőhöz Enter the password for "%s"
migration.run.startMigrationBtn=Széf frissítése
@@ -220,9 +215,7 @@ preferences.interface.showMinimizeButton=Kicsinyítés ikon megjelenítése
preferences.interface.showTrayIcon=Tálca ikon megjelenítése (újraindítás szükséges)
## Volume
preferences.volume=Virtuális meghajtó
preferences.volume.type=Kötet tipusa
preferences.volume.webdav.port=WebDAV port
preferences.volume.webdav.scheme=WebDAV vázlat
preferences.volume.type.automatic=Automatikus
## Updates
preferences.updates=Frissítések
preferences.updates.currentVersion=Jelenlegi verzió: %s
@@ -279,9 +272,6 @@ main.minimizeBtn.tooltip=Minimalizálás
main.preferencesBtn.tooltip=Beállítások
main.debugModeEnabled.tooltip=A hibakeresési mód aktiválva van
main.supporterCertificateMissing.tooltip=Kérjük, fontolja meg az adományozást
## Drag 'n' Drop
main.dropZone.dropVault=Adja hozzá ezt a széfet
main.dropZone.unknownDragboardContent=Ha egy széfet szeretne hozzáadni, akkor húzza át erre az ablakra.
## Vault List
main.vaultlist.emptyList.onboardingInstruction=Kattintson ide egy széf hozzáadásához
main.vaultlist.contextMenu.remove=Eltávolítás…
@@ -355,9 +345,7 @@ vaultOptions.mount.winDriveLetterOccupied=foglalt
vaultOptions.mount.mountPoint=Csatolási pont
vaultOptions.mount.mountPoint.auto=Válasszon egy megfelelő helyet automatikusan
vaultOptions.mount.mountPoint.driveLetter=Használja a kiválasztott meghajtó betűjelét
vaultOptions.mount.mountPoint.custom=Egyedi útvonal
vaultOptions.mount.mountPoint.directoryPickerButton=Kiválaszt…
vaultOptions.mount.mountPoint.directoryPickerTitle=Válasszon egy üres könyvtárat
## Master Key
vaultOptions.masterkey=Jelszó
vaultOptions.masterkey.changePasswordBtn=Jelszó megváltoztatása
+3 -15
View File
@@ -113,11 +113,6 @@ unlock.success.description="%s" berhasil dibuka! Vault Anda sekarang dapat diaks
unlock.success.rememberChoice=Ingat pilihan saya, jangan perlihatkan lagi
unlock.success.revealBtn=Tampilkan Drive
## Failure
unlock.error.message=Tidak dapat membuka vault
### Invalid Mount Point
unlock.error.invalidMountPoint.notExisting=Mount point "%s" bukanlah sebuah direktori, tidak sedang kosong, atau bahkan tidak ada sama sekali.
unlock.error.invalidMountPoint.existing=Mount point "%s" sudah ada atau folder induknya tidak ditemukan.
unlock.error.invalidMountPoint.driveLetterOccupied=Drive Letter "%s" sedang digunakan.
## Hub
### Waiting
### Receive Key
@@ -142,8 +137,8 @@ lock.fail.description=Vault "%s" tidak dapat dikunci. Pastikan bahwa file yang b
# Migration
migration.title=Tingkatkan Vault
## Start
migration.start.prompt=Vault "%s" Anda perlu diperbarui ke format yang baru. Sebelum melanjutkan, pastikan tidak ada sinkronisasi dalam antrian ataupun yang masih berjalan yang dapat berdampak pada vault ini.
migration.start.confirm=Ya, vault saya sepenuhnya tersinkronisasi
migration.start.header=Tingkatkan Vault
migration.start.confirm=Saya telah membaca dan memahami informasi di atas
## Run
migration.run.enterPassword=Masukkan kata sandi untuk "%s"
migration.run.startMigrationBtn=Pindahkan Vault
@@ -223,9 +218,7 @@ preferences.interface.showMinimizeButton=Tampilkan tombol perkecil
preferences.interface.showTrayIcon=Tampilkan ikon tray (aplikasi perlu dimuat ulang)
## Volume
preferences.volume=Drive Virtual
preferences.volume.type=Jenis Volume
preferences.volume.webdav.port=Port WebDAV
preferences.volume.webdav.scheme=Skema WebDAV
preferences.volume.type.automatic=Otomatis
## Updates
preferences.updates=Pembaharuan
preferences.updates.currentVersion=Versi Saat Ini: %s
@@ -282,9 +275,6 @@ main.minimizeBtn.tooltip=Perkecil
main.preferencesBtn.tooltip=Preferensi
main.debugModeEnabled.tooltip=Mode Debug diaktifkan
main.supporterCertificateMissing.tooltip=Tolong pertimbangkan untuk melakukan donasi
## Drag 'n' Drop
main.dropZone.dropVault=Tambah vault ini
main.dropZone.unknownDragboardContent=Jika Anda ingin menambahkan vault, seret ke jendela ini
## Vault List
main.vaultlist.emptyList.onboardingInstruction=Klik di sini untuk menambahkan vault
main.vaultlist.contextMenu.remove=Hapus…
@@ -358,9 +348,7 @@ vaultOptions.mount.winDriveLetterOccupied=terpakai
vaultOptions.mount.mountPoint=Titik Pasang
vaultOptions.mount.mountPoint.auto=Secara otomatis memilih lokasi yang sesuai
vaultOptions.mount.mountPoint.driveLetter=Gunakan drive letter yang sudah ditetapkan
vaultOptions.mount.mountPoint.custom=Path khusus
vaultOptions.mount.mountPoint.directoryPickerButton=Pilih…
vaultOptions.mount.mountPoint.directoryPickerTitle=Pilih direktori kosong
## Master Key
vaultOptions.masterkey=Kata Sandi
vaultOptions.masterkey.changePasswordBtn=Ubah Kata Sandi
+51 -15
View File
@@ -123,12 +123,14 @@ unlock.success.description="%s" sbloccato correttamente! La tua cassaforte è or
unlock.success.rememberChoice=Ricorda la scelta, non mostrarmelo più
unlock.success.revealBtn=Rivela l'Unità
## Failure
unlock.error.message=Impossibile sbloccare la cassaforte
### Invalid Mount Point
unlock.error.invalidMountPoint.notExisting=Il punto di montaggio "%s" non è una cartella, non è vuoto o non esiste.
unlock.error.invalidMountPoint.existing=Il punto di montaggio "%s" esiste già o la cartella madre è mancante.
unlock.error.invalidMountPoint.driveLetterOccupied=La lettera di unità "%s" è già in uso.
unlock.error.customPath.message=Impossibile montare la cassaforte sul percorso personalizzato
unlock.error.customPath.description.notSupported=Se desideri continuare a utilizzare il percorso personalizzato, vai alle preferenze e seleziona un tipo di volume che lo supporta. Altrimenti, vai alle opzioni della cassaforte e scegli un punto di montaggio supportato.
unlock.error.customPath.description.notExists=Il percorso di mount personalizzato non esiste. Crealo nel tuo file system locale o cambialo nelle opzioni della cassaforte.
unlock.error.customPath.description.generic=Hai selezionato un percorso di montaggio personalizzato per questa cassaforte, ma il suo utilizzo è fallito col messaggio: %s
## Hub
hub.noKeychain.message=Impossibile accedere alla chiave del dispositivo
hub.noKeychain.description=Per sbloccare le casseforti Hub, è necessaria una chiave del dispositivo, che è protetta tramite un portachiavi. Per procedere, abilita "%s" e seleziona un portachiavi nelle preferenze.
hub.noKeychain.openBtn=Apri Preferenze
### Waiting
hub.auth.message=In attesa di autenticazione…
hub.auth.description=Dovresti essere reindirizzato automaticamente alla pagina di login.
@@ -169,8 +171,13 @@ lock.fail.description=Impossibile bloccare la cassaforte "%s". Assicurati che il
# Migration
migration.title=Aggiorna la Cassaforte
## Start
migration.start.prompt=La tua cassaforte "%s" dev'esser aggiornata a un formato più recente. Prima di procedere, assicurati che non ci sia alcuna sincronizzazione in sospeso relativa a questa cassaforte.
migration.start.confirm=Sì, la mia cassaforte è completamente sincronizzata
migration.start.header=Aggiorna la Cassaforte
migration.start.text=Per poter aprire il tuo deposito "%s" in questa nuova versione di Cryptomator, la cassaforte deve essere aggiornata a un formato più recente. Prima di farlo, dovresti sapere quanto segue:
migration.start.remarkUndone=Questo aggiornamento non può essere annullato.
migration.start.remarkVersions=Le versioni più vecchie di Cryptomator non saranno in grado di aprire la cassaforte aggiornata.
migration.start.remarkCanRun=Devi assicurarti che ogni dispositivo da cui accedi alla cassaforte possa eseguire questa versione di Cryptomator.
migration.start.remarkSynced=Devi assicurarti che la tua cassaforte sia completamente sincronizzata su questo dispositivo e sugli altri dispositivi prima di aggiornarlo.
migration.start.confirm=Ho letto e compreso le informazioni suddette
## Run
migration.run.enterPassword=Inserisci la password per "%s"
migration.run.startMigrationBtn=Migra la Cassaforte
@@ -218,8 +225,25 @@ health.check.detail.checkFinished=Il controllo è terminato correttamente.
health.check.detail.checkFinishedAndFound=Il controllo è terminato. Sei pregato di revisionare i risultati.
health.check.detail.checkFailed=Il controllo è terminato a causa di un errore.
health.check.detail.checkCancelled=Il controllo è stato annullato.
health.check.detail.listFilters.label=Filtri
health.check.detail.fixAllSpecificBtn=Correggi tutto di tipo
health.check.exportBtn=Esporta il Rapporto
## Result view
health.result.severityFilter.all=Gravità - Tutto
health.result.severityFilter.good=Buona
health.result.severityFilter.info=Informazione
health.result.severityFilter.warn=Avviso
health.result.severityFilter.crit=Critica
health.result.severityTip.good=Gravità: Buona\nStruttura della Cassaforte normale.
health.result.severityTip.info=Gravità: Info\nStruttura della Cassaforte intatta, correzione suggerita.
health.result.severityTip.warn=Gravità: Avviso\nStruttura della Cassaforte corrotta, correzione altamente consigliata.
health.result.severityTip.crit=Gravità: Critica\nStruttura della Cassaforte corrotta, perdita di dati determinata.
health.result.fixStateFilter.all=Indice di riparabilità - tutti
health.result.fixStateFilter.fixable=Riparabile
health.result.fixStateFilter.notFixable=Irreparabile
health.result.fixStateFilter.fixing=Correzione…
health.result.fixStateFilter.fixed=Riparato
health.result.fixStateFilter.fixFailed=Riparazione fallita
## Fix Application
health.fix.fixBtn=Correggi
health.fix.successTip=Correzione riuscita
@@ -251,9 +275,15 @@ preferences.interface.showMinimizeButton=Mostra il pulsante minimizza
preferences.interface.showTrayIcon=Mostra l'icona della barra d'applicazioni (richiede il riavvio)
## Volume
preferences.volume=Unità Virtuale
preferences.volume.type=Tipo di Volume
preferences.volume.webdav.port=Porta WebDAV
preferences.volume.webdav.scheme=Schema WebDAV
preferences.volume.type=Tipo di volume (richiede riavvio)
preferences.volume.type.automatic=Automatico
preferences.volume.tcp.port=Porta TCP
preferences.volume.supportedFeatures=Il tipo di volume scelto supporta le seguenti caratteristiche:
preferences.volume.feature.mountAuto=Selezione automatica del punto di montaggio
preferences.volume.feature.mountToDir=Directory personalizzata come punto di montaggio
preferences.volume.feature.mountToDriveLetter=Lettera dispositivo come punto di montaggio
preferences.volume.feature.mountFlags=Opzioni di montaggio personalizzate
preferences.volume.feature.readOnly=Montaggio di sola lettura
## Updates
preferences.updates=Aggiornamenti
preferences.updates.currentVersion=Versione Corrente: %s
@@ -302,6 +332,8 @@ stats.encr.total.data.gib=Dati crittografati: %.1f GiB
stats.write.accessCount=Scritture totali: %d
## Accesses
stats.access.current=Accesso: %d
stats.access.total=Accesso totale: %d
# Main Window
@@ -310,9 +342,6 @@ main.minimizeBtn.tooltip=Minimizza
main.preferencesBtn.tooltip=Preferenze
main.debugModeEnabled.tooltip=La modalità di debug è abilitata
main.supporterCertificateMissing.tooltip=Per favore, considera le donazioni
## Drag 'n' Drop
main.dropZone.dropVault=Aggiungi questa cassaforte
main.dropZone.unknownDragboardContent=Se desideri aggiungere una cassaforte, trascinala a questa finestra
## Vault List
main.vaultlist.emptyList.onboardingInstruction=Clicca qui per aggiungere una cassaforte
main.vaultlist.contextMenu.remove=Rimuovi…
@@ -335,6 +364,7 @@ main.vaultDetail.passwordSavedInKeychain=Password salvata
main.vaultDetail.unlockedStatus=SBLOCCATA
main.vaultDetail.accessLocation=I contenuti della tua cassaforte sono accessibili qui:
main.vaultDetail.revealBtn=Rivela Unità
main.vaultDetail.copyUri=Copia URI
main.vaultDetail.lockBtn=Blocca
main.vaultDetail.bytesPerSecondRead=Lettura:
main.vaultDetail.bytesPerSecondWritten=Scrittura:
@@ -342,6 +372,10 @@ main.vaultDetail.throughput.idle=inattivo
main.vaultDetail.throughput.kbps=%.1f kiB/s
main.vaultDetail.throughput.mbps=%.1f MiB/s
main.vaultDetail.stats=Statistiche della Cassaforte
main.vaultDetail.locateEncryptedFileBtn=Individua File Crittografato
main.vaultDetail.locateEncryptedFileBtn.tooltip=Scegli un file dalla cassaforte per individuare la controparte cifrata
main.vaultDetail.encryptedPathsCopied=Percorsi copiati negli Appunti!
main.vaultDetail.filePickerTitle=Seleziona File Nella Cassaforte
### Missing
main.vaultDetail.missing.info=Cryptomator non è riuscito a trovare una cassaforte in questo percorso.
main.vaultDetail.missing.recheck=Ricontrolla
@@ -380,15 +414,17 @@ vaultOptions.general.startHealthCheckBtn=Avvia il Controllo della Salute
## Mount
vaultOptions.mount=Montaggio
vaultOptions.mount.info=Le opzioni dipendono dal tipo di volume selezionato.
vaultOptions.mount.linkToPreferences=Apri le preferenze dell'unità virtuale
vaultOptions.mount.readonly=Sola Lettura
vaultOptions.mount.customMountFlags=Flag di Montaggio Personalizzati
vaultOptions.mount.winDriveLetterOccupied=occupato
vaultOptions.mount.mountPoint=Punto di Montaggio
vaultOptions.mount.mountPoint.auto=Scegli automaticamente una posizione idonea
vaultOptions.mount.mountPoint.driveLetter=Usa la lettera del drive assegnata
vaultOptions.mount.mountPoint.custom=Percorso personalizzato
vaultOptions.mount.mountPoint.custom=Usa la directory scelta
vaultOptions.mount.mountPoint.directoryPickerButton=Scegli…
vaultOptions.mount.mountPoint.directoryPickerTitle=Scegli una directory vuota
vaultOptions.mount.mountPoint.directoryPickerTitle=Scegli una directory
## Master Key
vaultOptions.masterkey=Password
vaultOptions.masterkey.changePasswordBtn=Modifica password
+51 -25
View File
@@ -26,7 +26,7 @@ defaults.vault.vaultName=金庫
# Tray Menu
traymenu.showMainWindow=表示
traymenu.showPreferencesWindow=設定
traymenu.showPreferencesWindow=環境設定
traymenu.lockAllVaults=すべて施錠
traymenu.quitApplication=終了
traymenu.vault.unlock=解錠
@@ -116,19 +116,20 @@ unlock.unlockBtn=解錠
unlock.chooseMasterkey.message=Masterkey ファイルが見つかりません
unlock.chooseMasterkey.description=必要な場所にこの金庫の masterkey ファイルがありませんでした。ファイルを手動で選択してください。
unlock.chooseMasterkey.filePickerTitle=Masterkey ファイルを選択
unlock.chooseMasterkey.filePickerMimeDesc=Cryptomatorのマスターキー
unlock.chooseMasterkey.filePickerMimeDesc=Cryptomator のマスターキー
## Success
unlock.success.message=解錠に成功しました
unlock.success.description="%s" の解錠に成功しました! 仮想ドライブから金庫にアクセス可能です。
unlock.success.rememberChoice=選択を記憶させて、再度表示しない
unlock.success.revealBtn=金庫内を表示
unlock.success.revealBtn=ドライブを表示
## Failure
unlock.error.message=金庫の解錠に失敗
### Invalid Mount Point
unlock.error.invalidMountPoint.notExisting=マウントポイントが空のディレクトリか存在していません: %s
unlock.error.invalidMountPoint.existing=マウント ポイント "%s" が既に存在するか、親フォルダーがありません。
unlock.error.invalidMountPoint.driveLetterOccupied=ドライブレター「%s」は既に使用されています。
unlock.error.customPath.message=カスタム パスに金庫をマウントできません
unlock.error.customPath.description.notSupported=カスタム パスを使い続けたい場合、環境設定に移動してサポートしているボリューム タイプを選択してください。もしくは、金庫のオプションに移動してサポートされるマウント ポイントを選択してください。
unlock.error.customPath.description.notExists=カスタム マウント パスが存在していません。ローカル ファイルシステムで作成するか、金庫のオプションで変更を加えてください。
## Hub
hub.noKeychain.message=デバイス キーにアクセスできません
hub.noKeychain.description=ハブ金庫を解錠するには、キーチェーンが保護するデバイス キーが必要です。続行するには、"%s" を有効にし環境設定からキーチェーンを選択します。
hub.noKeychain.openBtn=環境設定を開く
### Waiting
hub.auth.message=認証を待機中…
hub.auth.description=ログイン ページに自動的にリダイレクトされます。
@@ -169,8 +170,10 @@ lock.fail.description=金庫 "%s" を施錠できませんでした。保存さ
# Migration
migration.title=金庫をアップグレード
## Start
migration.start.prompt="%s" を新しいフォーマットに更新する必要があります。続行する前に、この金庫に影響する保留中の同期がないことをご確認ください。
migration.start.confirm=はい。同期が完了しています
migration.start.header=金庫をアップグレード
migration.start.remarkUndone=このアップグレードは取り消すことができません。
migration.start.remarkVersions=古い Cryptomator では、アップグレードされた金庫を開くことができなくなります。
migration.start.confirm=上記の情報を理解しました。
## Run
migration.run.enterPassword="%s" のパスワードを入力してください
migration.run.startMigrationBtn=金庫を移行
@@ -218,21 +221,38 @@ health.check.detail.checkFinished=チェックが正常に終了しました。
health.check.detail.checkFinishedAndFound=実行中のチェックが終了しました。結果を確認してください。
health.check.detail.checkFailed=エラーが発生したためチェックを終了しました。
health.check.detail.checkCancelled=チェックがキャンセルされました。
health.check.detail.listFilters.label=フィルター
health.check.detail.fixAllSpecificBtn=すべての種類を修正する
health.check.exportBtn=結果をエクスポート
## Result view
health.result.severityFilter.all=深刻度 - すべて
health.result.severityFilter.good=適正
health.result.severityFilter.info=情報
health.result.severityFilter.warn=警告
health.result.severityFilter.crit=深刻
health.result.severityTip.good=深刻度: \t適正\n金庫の構造は適正です。
health.result.severityTip.info=深刻度: 情報\n金庫の構造に損失はありませんが、修正が提案されます。
health.result.severityTip.warn=深刻度: 警告\n金庫の構造が破損しており、修正が強く推奨されます。
health.result.severityTip.crit=深刻度: 深刻\n金庫の構造が破損しており、データを損失しています。
health.result.fixStateFilter.all=修正状態 - すべて
health.result.fixStateFilter.fixable=修正可能
health.result.fixStateFilter.notFixable=修正不可
health.result.fixStateFilter.fixing=修正中...
health.result.fixStateFilter.fixed=修正済み
health.result.fixStateFilter.fixFailed=修正に失敗
## Fix Application
health.fix.fixBtn=修正
health.fix.successTip=正常に修正されました
health.fix.failTip=修正に失敗しました。詳細はログを参照してください。
# Preferences
preferences.title=設定
preferences.title=環境設定
## General
preferences.general=基本設定
preferences.general.startHidden=Cryptomator を開始したときウィンドウを隠す
preferences.general.autoCloseVaults=アプリケーションを終了するときに自動的に開いている金庫を施錠する
preferences.general.debugLogging=ログを有効にする
preferences.general.debugDirectory=ログファイルを表示
preferences.general.debugDirectory=ログ ファイルを表示
preferences.general.autoStart=システム開始時に Cryptomator を起動する
preferences.general.keychainBackend=次を利用してパスワードを保存する
## Interface
@@ -251,9 +271,11 @@ preferences.interface.showMinimizeButton=最小化ボタンを表示
preferences.interface.showTrayIcon=トレイアイコンを表示 (再起動が必要)
## Volume
preferences.volume=仮想ドライブ
preferences.volume.type=マウント方法
preferences.volume.webdav.port=WebDAV ポート
preferences.volume.webdav.scheme=WebDAV スキーム
preferences.volume.type=ボリューム タイプ (再起動が必要)
preferences.volume.type.automatic=自動
preferences.volume.tcp.port=TCP ポート
preferences.volume.feature.mountFlags=カスタム マウント オプション
preferences.volume.feature.readOnly=読み取り専用マウント
## Updates
preferences.updates=更新
preferences.updates.currentVersion=現在のバージョン: %s
@@ -302,19 +324,18 @@ stats.encr.total.data.gib=暗号化済みデータ: %.1f GiB
stats.write.accessCount=合計書き込み: %d
## Accesses
stats.access.current=アクセス: %d
stats.access.total=合計アクセス: %d
# Main Window
main.closeBtn.tooltip=閉じる
main.minimizeBtn.tooltip=最小化
main.preferencesBtn.tooltip=設定
main.preferencesBtn.tooltip=環境設定
main.debugModeEnabled.tooltip=デバッグモードが有効です
main.supporterCertificateMissing.tooltip=寄付をお願いします
## Drag 'n' Drop
main.dropZone.dropVault=この金庫を追加
main.dropZone.unknownDragboardContent=このウィンドウにドラッグして、金庫を追加
## Vault List
main.vaultlist.emptyList.onboardingInstruction=ここをクリックして金庫を追加
main.vaultlist.emptyList.onboardingInstruction=ここをクリックして金庫を追加します
main.vaultlist.contextMenu.remove=削除...
main.vaultlist.contextMenu.lock=施錠
main.vaultlist.contextMenu.unlock=解錠...
@@ -335,6 +356,7 @@ main.vaultDetail.passwordSavedInKeychain=パスワードを保存しました
main.vaultDetail.unlockedStatus=解錠済み
main.vaultDetail.accessLocation=金庫の内容はこちらからアクセスできます:
main.vaultDetail.revealBtn=ドライブを表示
main.vaultDetail.copyUri=URI をコピー
main.vaultDetail.lockBtn=施錠
main.vaultDetail.bytesPerSecondRead=読み取り:
main.vaultDetail.bytesPerSecondWritten=書き込み:
@@ -342,6 +364,9 @@ main.vaultDetail.throughput.idle=アイドル
main.vaultDetail.throughput.kbps=%.1f kiB/s
main.vaultDetail.throughput.mbps=%.1f MiB/s
main.vaultDetail.stats=金庫の統計情報
main.vaultDetail.locateEncryptedFileBtn=暗号化されたファイルの場所
main.vaultDetail.locateEncryptedFileBtn.tooltip=暗号化された金庫のファイルを選択してください
main.vaultDetail.encryptedPathsCopied=パスをクリップボードにコピーしました!
### Missing
main.vaultDetail.missing.info=Cryptomator はこの場所に金庫を見つけることができませんでした。
main.vaultDetail.missing.recheck=再確認
@@ -371,7 +396,7 @@ vaultOptions.general=基本設定
vaultOptions.general.vaultName=金庫の名前
vaultOptions.general.autoLock.lockAfterTimePart1=アイドル時に施錠する
vaultOptions.general.autoLock.lockAfterTimePart2=
vaultOptions.general.unlockAfterStartup=Cryptomatorの起動時に金庫を解錠する
vaultOptions.general.unlockAfterStartup=Cryptomator の起動時に金庫を解錠する
vaultOptions.general.actionAfterUnlock=解錠に成功したあと
vaultOptions.general.actionAfterUnlock.ignore=何もしない
vaultOptions.general.actionAfterUnlock.reveal=ドライブを表示
@@ -380,20 +405,21 @@ vaultOptions.general.startHealthCheckBtn=正常性チェックを開始
## Mount
vaultOptions.mount=マウント
vaultOptions.mount.linkToPreferences=仮想ドライブの環境設定を開く
vaultOptions.mount.readonly=読み取り専用
vaultOptions.mount.customMountFlags=カスタム マウント フラグ
vaultOptions.mount.winDriveLetterOccupied=使用中
vaultOptions.mount.mountPoint=マウントポイント
vaultOptions.mount.mountPoint=マウント ポイント
vaultOptions.mount.mountPoint.auto=自動的に適切な場所を選択する
vaultOptions.mount.mountPoint.driveLetter=割り当てられるドライブ文字を使う
vaultOptions.mount.mountPoint.custom=カスタムパス
vaultOptions.mount.mountPoint.custom=選択したディレクトリを使う
vaultOptions.mount.mountPoint.directoryPickerButton=選択...
vaultOptions.mount.mountPoint.directoryPickerTitle=空のディレクトリを選択してください
vaultOptions.mount.mountPoint.directoryPickerTitle=ディレクトリを選択
## Master Key
vaultOptions.masterkey=パスワード
vaultOptions.masterkey.changePasswordBtn=パスワードの変更
vaultOptions.masterkey.forgetSavedPasswordBtn=保存したパスワードを削除する
vaultOptions.masterkey.recoveryKeyExplanation=回復キーはパスワードを忘れてしまった場合、金庫へのアクセスを回復する唯一の手段です。
vaultOptions.masterkey.recoveryKeyExplanation=回復キーはパスワードを忘れてしまった場合でも、金庫へのアクセスを回復する唯一の手段です。
vaultOptions.masterkey.showRecoveryKeyBtn=回復キーを表示
vaultOptions.masterkey.recoverPasswordBtn=パスワードをリセット
+3 -15
View File
@@ -111,11 +111,6 @@ unlock.success.description="%s"이(가) 성공적으로 잠금해제되었습니
unlock.success.rememberChoice=선택 기억함, 다시 묻지 않음
unlock.success.revealBtn=드라이브 표시
## Failure
unlock.error.message=Vault 잠금을 해제 할 수 없습니다.
### Invalid Mount Point
unlock.error.invalidMountPoint.notExisting=구성지점이 존재하지 않거나 빈 디렉터리가 아닙니다: %s
unlock.error.invalidMountPoint.existing=구성지점/폴더가 이미 존재하거나 부모 폴더가 없습니다: %s
unlock.error.invalidMountPoint.driveLetterOccupied="%s"는 이미 사용중인 드라이브 문자입니다
## Hub
### Waiting
### Receive Key
@@ -138,8 +133,8 @@ lock.fail.description="%s" Vault를 잠글 수 없습니다. 저장되지 않은
# Migration
migration.title=Vault 업그레이드
## Start
migration.start.prompt="%s" vault는 새로운 포멧으로 업데이트가 필요합니다. 작업 전, 이 Vault에 영향을 줄만한 동기화가 보류중인지 확인하여 주십시요.
migration.start.confirm=네, 이 Vault는 동기화가 완전히 된 상태입니다.
migration.start.header=Vault 업그레이드
migration.start.confirm=나는 위 정보를 읽고 정말 이해했습니다.
## Run
migration.run.enterPassword="%s"의 비밀번호를 입력하십시요.
migration.run.startMigrationBtn=Vault 마이그레이션
@@ -213,9 +208,7 @@ preferences.interface.showMinimizeButton=최소화 버튼 표시
preferences.interface.showTrayIcon=트레이 아이콘 보기 (재시작 필요)
## Volume
preferences.volume=가상 드라이브
preferences.volume.type=볼륨 유형
preferences.volume.webdav.port=WebDAV 포트
preferences.volume.webdav.scheme=WebDAV 스킴
preferences.volume.type.automatic=자동
## Updates
preferences.updates=업데이트
preferences.updates.currentVersion=현재 버전: %s
@@ -272,9 +265,6 @@ main.minimizeBtn.tooltip=최소화
main.preferencesBtn.tooltip=환경설정
main.debugModeEnabled.tooltip=디버그 모드가 활성화됨.
main.supporterCertificateMissing.tooltip=기부를 부탁드립니다.
## Drag 'n' Drop
main.dropZone.dropVault=이 Vault를 추가
main.dropZone.unknownDragboardContent=Vault를 추가하려면, 이 창에 드래그 하십시요.
## Vault List
main.vaultlist.emptyList.onboardingInstruction=Vault를 추가하기 위해 이곳을 클릭합니다.
main.vaultlist.contextMenu.remove=제거...
@@ -345,9 +335,7 @@ vaultOptions.mount.winDriveLetterOccupied=사용됨
vaultOptions.mount.mountPoint=마운트 지점
vaultOptions.mount.mountPoint.auto=자동으로 적합한 위치를 선택
vaultOptions.mount.mountPoint.driveLetter=드라이브 문자를 지정하여 사용
vaultOptions.mount.mountPoint.custom=사용자 지정 경로
vaultOptions.mount.mountPoint.directoryPickerButton=선택
vaultOptions.mount.mountPoint.directoryPickerTitle=빈 디렉터리를 선택
## Master Key
vaultOptions.masterkey=비밀번호
vaultOptions.masterkey.changePasswordBtn=비밀번호 변경
+1 -11
View File
@@ -106,7 +106,6 @@ unlock.chooseMasterkey.filePickerTitle=Atlasīt galveno atslēgas datni
## Success
unlock.success.revealBtn=Atklāt disku
## Failure
### Invalid Mount Point
## Hub
### Waiting
### Receive Key
@@ -126,8 +125,7 @@ hub.register.registerBtn=Apstiprināt
# Migration
migration.title=Jaunināt glabātuvi
## Start
migration.start.prompt=Jūsu "%s" glabātuvi nepieciešams atjaunināt uz jaunu formātu. Pirms turpiniet, pārliecinieties, ka nav aktīva šīs glabātuves sinhronizācija.
migration.start.confirm=Jā, mana glabātuve ir pilnībā sinhronizēta
migration.start.header=Jaunināt glabātuvi
## Run
migration.run.enterPassword=Ievadiet "%s" paroli
migration.run.startMigrationBtn=Migrēt glabātuvi
@@ -163,9 +161,6 @@ preferences.interface.theme.dark=Tumšs
preferences.interface.theme.light=Gaišs
## Volume
preferences.volume=Virtuāls disks
preferences.volume.type=Sējuma tips
preferences.volume.webdav.port=WebDAV ports
preferences.volume.webdav.scheme=WebDAV shēma
## Updates
preferences.updates=Atjauninājumi
preferences.updates.currentVersion=Pašreizējā versija: %s
@@ -190,9 +185,6 @@ main.closeBtn.tooltip=Aizvērt
main.minimizeBtn.tooltip=Minimizēt
main.preferencesBtn.tooltip=Iestatījumi
main.supporterCertificateMissing.tooltip=Lūdzu apsveriet iespēju ziedot
## Drag 'n' Drop
main.dropZone.dropVault=Pievienot šo glabātuvi
main.dropZone.unknownDragboardContent=Ja jūs vēlaties pievienot glabātuvi, velciet to uz šo logu
## Vault List
main.vaultlist.emptyList.onboardingInstruction=Spied šeit, lai pievienotu glabātuvi
main.vaultlist.contextMenu.lock=Aizslēgt
@@ -247,9 +239,7 @@ vaultOptions.mount.winDriveLetterOccupied=aizņemts
vaultOptions.mount.mountPoint=Montēšanas vieta
vaultOptions.mount.mountPoint.auto=Automātiski izvēlieties piemērotu vietu
vaultOptions.mount.mountPoint.driveLetter=Izmantot piešķirtu diska burtu
vaultOptions.mount.mountPoint.custom=Pielāgots ceļš
vaultOptions.mount.mountPoint.directoryPickerButton=Izvēlies...
vaultOptions.mount.mountPoint.directoryPickerTitle=Izvēlies tukšu mapi
## Master Key
vaultOptions.masterkey=Parole
vaultOptions.masterkey.changePasswordBtn=Mainīt paroli
@@ -29,7 +29,6 @@
## Select
## Success
## Failure
### Invalid Mount Point
## Hub
### Waiting
### Receive Key
@@ -78,7 +77,6 @@ hub.register.registerBtn=Потврди
# Main Window
## Drag 'n' Drop
## Vault List
## Vault Detail
### Welcome
+53 -17
View File
@@ -123,12 +123,14 @@ unlock.success.description=Vellykket opplåsing av "%s"! Hvelvet ditt er nå til
unlock.success.rememberChoice=Husk valget - ikke vis dette igjen
unlock.success.revealBtn=Gjør enheten synlig
## Failure
unlock.error.message=Klarer ikke å låse opp hvelvet
### Invalid Mount Point
unlock.error.invalidMountPoint.notExisting=Monteringspunktet "%s" er enten ikke en mappe, ikke tom eller eksisterer ikke.
unlock.error.invalidMountPoint.existing=Monteringspunktet "%s" finnes enten allerede eller at overordnet mappe mangler.
unlock.error.invalidMountPoint.driveLetterOccupied=Stasjonsbokstav "%s" er allerede i bruk.
unlock.error.customPath.message=Kan ikke montere hvelvet til egendefinert sti
unlock.error.customPath.description.notSupported=Hvis du vil fortsette å bruke den egendefinerte stien, gå til innstillingene og velg en enhetstype som støtter den. Gå ellers til hvelvalternativene og velg et støttet monteringspunkt.
unlock.error.customPath.description.notExists=Egendefinert monteringssti eksisterer ikke. Enten opprett den i ditt lokale filsystem eller endre den i hvelvvalgene.
unlock.error.customPath.description.generic=Du har valgt en egendefinert monterings sti for dette hvelvet, men ved bruk av den mislyktes med meldingen: %s
## Hub
hub.noKeychain.message=Får ikke tilgang til enhetsnøkkel
hub.noKeychain.description=For å låse opp Hub-hvelv er det nødvendig med en enhetsnøkkel som er sikret med en nøkkelring. For å fortsette, aktiver "%s" og velg en nøkkelring i innstillingene.
hub.noKeychain.openBtn=Åpne innstillinger
### Waiting
hub.auth.message=Venter på autentisering…
hub.auth.description=Du burde bli automatisk videresendt til innloggingssiden.
@@ -169,8 +171,13 @@ lock.fail.description=Hvelvet "%s" kunne ikke låses. Forsikre deg om at ulagred
# Migration
migration.title=Oppgrader hvelv
## Start
migration.start.prompt=Hvelvet ditt "%s" må oppdateres til et nyere format. Før du fortsetter må du forsikre deg om at det ikke er ventende synkronisering som kan påvirke dette hvelvet.
migration.start.confirm=Ja, hvelvet mitt er fullstendig synkronisert
migration.start.header=Oppgrader hvelv
migration.start.text=For å åpne hvelvet ditt "%s" i denne nye versjonen av Cryptomator, må hvelvet oppgraderes til et nyere format. Før du gjør dette, bør du vite følgende:
migration.start.remarkUndone=Denne oppgraderingen kan ikke angres.
migration.start.remarkVersions=Eldre versjoner av Cryptomator kan ikke åpne det oppgraderte hvelvet.
migration.start.remarkCanRun=Alle enheter som du har tilgang til hvelvet fra, må kunne kjøre denne versjonen av Cryptomator.
migration.start.remarkSynced=Du må være sikker på at hvelvet ditt er fullstendig synkronisert på både denne og dine andre enheter før du oppgraderer det.
migration.start.confirm=Jeg har lest og forstått informasjonen ovenfor
## Run
migration.run.enterPassword=Skriv inn passordet for "%s"
migration.run.startMigrationBtn=Oppgrader hvelv
@@ -218,8 +225,25 @@ health.check.detail.checkFinished=Helsesjekken ble fullført vellyket.
health.check.detail.checkFinishedAndFound=Helsesjekken er ferdig å kjøre. Vennligst se resultatene.
health.check.detail.checkFailed=Helsesjekken avsluttet på grunn av en feil.
health.check.detail.checkCancelled=Helsesjekken ble avbrutt.
health.check.detail.listFilters.label=Filter
health.check.detail.fixAllSpecificBtn=Fiks alt av type
health.check.exportBtn=Eksporter rapport
## Result view
health.result.severityFilter.all=Alvorlighetsgrad Alle
health.result.severityFilter.good=Bra
health.result.severityFilter.info=Info
health.result.severityFilter.warn=Advarsel
health.result.severityFilter.crit=Kritisk
health.result.severityTip.good=Alvorlighet: Godt\nNormal hvelv struktur.
health.result.severityTip.info=Alvorlighet: Info\nhvelvstrukturen intakt, fiks foreslått.
health.result.severityTip.warn=Alvorlighet: Advarsel\nhvelvstrukturen skadet, fiks høyt anbefalt.
health.result.severityTip.crit=Alvorlighet: Kritisk\nhvelvsstrukturen skadet, data tap bestemt.
health.result.fixStateFilter.all=Feilretting status - alle
health.result.fixStateFilter.fixable=Feilrettbar
health.result.fixStateFilter.notFixable=Ikke feilrettbar
health.result.fixStateFilter.fixing=Retter…
health.result.fixStateFilter.fixed=Rettet
health.result.fixStateFilter.fixFailed=Feilretting feilet
## Fix Application
health.fix.fixBtn=Reparer
health.fix.successTip=Vellykket reparering
@@ -247,13 +271,19 @@ preferences.interface.language.auto=Systemstandard
preferences.interface.interfaceOrientation=Grensesnittorientering
preferences.interface.interfaceOrientation.ltr=Fra venstre til høyre
preferences.interface.interfaceOrientation.rtl=Fra høyre til venstre
preferences.interface.showMinimizeButton=Vis minimer knapp
preferences.interface.showMinimizeButton=Vis minimer-knapp
preferences.interface.showTrayIcon=Vis verktøykasseikon (krever omstart)
## Volume
preferences.volume=Virtuell enhet
preferences.volume.type=Volumtype
preferences.volume.webdav.port=WebDAV-port
preferences.volume.webdav.scheme=WebDAV-ordning
preferences.volume.type=Volumtype (krever omstart)
preferences.volume.type.automatic=Automatisk
preferences.volume.tcp.port=TCP Port
preferences.volume.supportedFeatures=Valgt volumtype støtter følgende funksjoner:
preferences.volume.feature.mountAuto=Valg av automatisk monteringspunkt
preferences.volume.feature.mountToDir=Egendefinert mappe som monteringspunkt
preferences.volume.feature.mountToDriveLetter=Drevbokstav som monteringspunkt
preferences.volume.feature.mountFlags=Tilpassede monteringsparametre
preferences.volume.feature.readOnly=Skrivebeskyttet montering
## Updates
preferences.updates=Oppdateringer
preferences.updates.currentVersion=Gjeldende versjon: %s
@@ -263,7 +293,7 @@ preferences.updates.updateAvailable=Oppdatering til versjon %s er tilgjengelig.
## Contribution
preferences.contribute=Støtt oss
preferences.contribute.registeredFor=Supporter sertifikat registrert for %s
preferences.contribute.noCertificate=Støtt Cryptomator og motta et supporter sertifikat. Det er som en lisensnøkkel, men for fantastiske mennesker som bruker fri programvare. ;-)
preferences.contribute.noCertificate=Støtt Cryptomator og motta et supporter-sertifikat. Det er som en lisensnøkkel, men for fantastiske mennesker som bruker fri programvare. ;-)
preferences.contribute.getCertificate=Har du ikke en allerede? Lær hvordan du kan skaffe den.
preferences.contribute.promptText=Lim inn supporter sertifikatkoden her
#<-- Add entries for donations and code/translation/documentation contribution -->
@@ -302,6 +332,8 @@ stats.encr.total.data.gib=Data kryptert: %.1f GiB
stats.write.accessCount=Skrivninger totalt: %d
## Accesses
stats.access.current=Tilgang: %d
stats.access.total=Antall tilganger: %d
# Main Window
@@ -310,9 +342,6 @@ main.minimizeBtn.tooltip=Minimer
main.preferencesBtn.tooltip=Innstillinger
main.debugModeEnabled.tooltip=Feilsøkingsmodus er aktivert
main.supporterCertificateMissing.tooltip=Gjerne vurdér en donasjon
## Drag 'n' Drop
main.dropZone.dropVault=Legg til dette hvelvet
main.dropZone.unknownDragboardContent=Hvis du vil legge til et hvelv, kan du dra det til dette vinduet
## Vault List
main.vaultlist.emptyList.onboardingInstruction=Klikk her for å legge til et hvelv
main.vaultlist.contextMenu.remove=Fjern…
@@ -335,6 +364,7 @@ main.vaultDetail.passwordSavedInKeychain=Passordet er lagret
main.vaultDetail.unlockedStatus=ULÅST
main.vaultDetail.accessLocation=Innholdet i hvelvet ditt er tilgjengelig her:
main.vaultDetail.revealBtn=Gjør enheten synlig
main.vaultDetail.copyUri=Kopier URI
main.vaultDetail.lockBtn=Lås
main.vaultDetail.bytesPerSecondRead=Lesehastighet:
main.vaultDetail.bytesPerSecondWritten=Skriv:
@@ -342,6 +372,10 @@ main.vaultDetail.throughput.idle=inaktiv
main.vaultDetail.throughput.kbps=%.1f kiB/s
main.vaultDetail.throughput.mbps=%.1f MiB/s
main.vaultDetail.stats=Hvelvstatistikk
main.vaultDetail.locateEncryptedFileBtn=Finn kryptert fil
main.vaultDetail.locateEncryptedFileBtn.tooltip=Velg en fil fra hvelvet ditt for å finne den krypterte motparten
main.vaultDetail.encryptedPathsCopied=Stier kopiert til utklippstavlen!
main.vaultDetail.filePickerTitle=Velg Fil I Hvelvet
### Missing
main.vaultDetail.missing.info=Cryptomator kunne ikke finne et hvelv på denne søkestien.
main.vaultDetail.missing.recheck=Kontroller igjen
@@ -380,15 +414,17 @@ vaultOptions.general.startHealthCheckBtn=Start helsesjekk
## Mount
vaultOptions.mount=Montering
vaultOptions.mount.info=Alternativer avhenger av den valgte volumtypen.
vaultOptions.mount.linkToPreferences=Åpne virtuelle driv-innstillinger
vaultOptions.mount.readonly=Skrivebeskyttet
vaultOptions.mount.customMountFlags=Tilpassede moteringsparametre
vaultOptions.mount.winDriveLetterOccupied=opptatt
vaultOptions.mount.mountPoint=Monteringspunkt
vaultOptions.mount.mountPoint.auto=Velg et passende sted automatisk
vaultOptions.mount.mountPoint.driveLetter=Bruk tildelt enhetsbokstav
vaultOptions.mount.mountPoint.custom=Tilpasset søkesti
vaultOptions.mount.mountPoint.custom=Bruk valgt mappe
vaultOptions.mount.mountPoint.directoryPickerButton=Velg…
vaultOptions.mount.mountPoint.directoryPickerTitle=Velg en tom mappe
vaultOptions.mount.mountPoint.directoryPickerTitle=Velg en mappe
## Master Key
vaultOptions.masterkey=Passord
vaultOptions.masterkey.changePasswordBtn=Endre passord

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