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 id: volume-type
attributes: attributes:
label: Volume Type label: Volume Type
description: What is selected under Settings → Virtual Drive? description: What volume type is selected under Settings → Virtual Drive?
multiple: true value: |
options: - WinFsp
- FUSE - WinFsp (Local Drive)
- Dokany - FUSE-T
- WebDAV - macFUSE
- WebDAV (Windows Explorer)
- WebDAV (AppleScript)
- WebDAV (gio)
- WebDAV (HTTP Address)
- Dokany (1.5)
validations: validations:
required: false required: true
- type: textarea - type: textarea
id: reproduction-steps id: reproduction-steps
attributes: attributes:
+3 -10
View File
@@ -16,7 +16,7 @@ jobs:
get-version: get-version:
uses: ./.github/workflows/get-version.yml uses: ./.github/workflows/get-version.yml
with: with:
version: ${{ github.event.inputs.version }} version: ${{ inputs.version }}
build: build:
name: Build AppImage name: Build AppImage
@@ -47,7 +47,6 @@ jobs:
- name: Patch target dir - name: Patch target dir
run: | run: |
cp LICENSE.txt target cp LICENSE.txt target
cp dist/linux/launcher.sh target
cp target/cryptomator-*.jar target/mods cp target/cryptomator-*.jar target/mods
- name: Run jlink - name: Run jlink
run: > run: >
@@ -55,7 +54,7 @@ jobs:
--verbose --verbose
--output runtime --output runtime
--module-path "${JAVA_HOME}/jmods" --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 --strip-native-commands
--no-header-files --no-header-files
--no-man-pages --no-man-pages
@@ -78,7 +77,7 @@ jobs:
--dest appdir --dest appdir
--name Cryptomator --name Cryptomator
--vendor "Skymatic GmbH" --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 }}" --app-version "${{ needs.get-version.outputs.semVerNum }}.${{ needs.get-version.outputs.revNum }}"
--java-options "--enable-preview" --java-options "--enable-preview"
--java-options "--enable-native-access=org.cryptomator.jfuse.linux.amd64,org.cryptomator.jfuse.linux.aarch64" --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/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 usr/share/applications/org.cryptomator.Cryptomator.desktop Cryptomator.AppDir/Cryptomator.desktop
ln -s bin/cryptomator.sh Cryptomator.AppDir/AppRun 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 - name: Download AppImageKit
run: | run: |
curl -L https://github.com/AppImage/AppImageKit/releases/download/13/appimagetool-x86_64.AppImage -o appimagetool.AppImage 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 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 - name: Ensure major jfx version in pom and in jmods is the same
run: | 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_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#*@}
JMOD_VERSION_AARCH64=${JMOD_VERSION_AARCH64%%.*} JMOD_VERSION_AARCH64=${JMOD_VERSION_AARCH64%%.*}
POM_JFX_VERSION=$(mvn help:evaluate "-Dexpression=javafx.version" -q -DforceStdout) POM_JFX_VERSION=$(mvn help:evaluate "-Dexpression=javafx.version" -q -DforceStdout)
@@ -148,11 +148,8 @@ jobs:
echo "TAG_NAME=${REF##*/}" >> $GITHUB_ENV echo "TAG_NAME=${REF##*/}" >> $GITHUB_ENV
- name: Publish Debian package on GitHub Releases - name: Publish Debian package on GitHub Releases
if: startsWith(inputs.ref, 'refs/tags/') if: startsWith(inputs.ref, 'refs/tags/')
uses: softprops/action-gh-release@v1 env:
with: GITHUB_TOKEN: ${{ secrets.CRYPTOBOT_RELEASE_TOKEN }}
fail_on_unmatched_files: true run: |
tag_name: ${{ github.env.TAG_NAME }} artifacts=$(ls | grep cryptomator*.deb)
token: ${{ secrets.CRYPTOBOT_RELEASE_TOKEN }} gh release upload ${{ env.TAG_NAME }} $artifacts
files: |
cryptomator_*_amd64.deb
cryptomator_*.asc
+3 -3
View File
@@ -16,7 +16,7 @@ jobs:
get-version: get-version:
uses: ./.github/workflows/get-version.yml uses: ./.github/workflows/get-version.yml
with: with:
version: ${{ github.event.inputs.version }} version: ${{ inputs.version }}
build: build:
name: Build Cryptomator.app for ${{ matrix.output-suffix }} name: Build Cryptomator.app for ${{ matrix.output-suffix }}
@@ -61,7 +61,6 @@ jobs:
- name: Patch target dir - name: Patch target dir
run: | run: |
cp LICENSE.txt target cp LICENSE.txt target
cp dist/mac/launcher.sh target
cp target/cryptomator-*.jar target/mods cp target/cryptomator-*.jar target/mods
- name: Run jlink - name: Run jlink
run: > run: >
@@ -87,7 +86,7 @@ jobs:
--dest appdir --dest appdir
--name Cryptomator --name Cryptomator
--vendor "Skymatic GmbH" --vendor "Skymatic GmbH"
--copyright "(C) 2016 - 2022 Skymatic GmbH" --copyright "(C) 2016 - 2023 Skymatic GmbH"
--app-version "${{ needs.get-version.outputs.semVerNum }}" --app-version "${{ needs.get-version.outputs.semVerNum }}"
--java-options "--enable-preview" --java-options "--enable-preview"
--java-options "--enable-native-access=org.cryptomator.jfuse.mac" --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.p12Path=\"~/Library/Application Support/Cryptomator/key.p12\""
--java-options "-Dcryptomator.ipcSocketPath=\"~/Library/Application Support/Cryptomator/ipc.socket\"" --java-options "-Dcryptomator.ipcSocketPath=\"~/Library/Application Support/Cryptomator/ipc.socket\""
--java-options "-Dcryptomator.integrationsMac.keychainServiceName=\"Cryptomator\"" --java-options "-Dcryptomator.integrationsMac.keychainServiceName=\"Cryptomator\""
--java-options "-Dcryptomator.mountPointsDir=\"~/Cryptomator\""
--java-options "-Dcryptomator.showTrayIcon=true" --java-options "-Dcryptomator.showTrayIcon=true"
--java-options "-Dcryptomator.buildNumber=\"dmg-${{ needs.get-version.outputs.revNum }}\"" --java-options "-Dcryptomator.buildNumber=\"dmg-${{ needs.get-version.outputs.revNum }}\""
--mac-package-identifier org.cryptomator --mac-package-identifier org.cryptomator
+12 -6
View File
@@ -22,7 +22,7 @@ jobs:
get-version: get-version:
uses: ./.github/workflows/get-version.yml uses: ./.github/workflows/get-version.yml
with: with:
version: ${{ github.event.inputs.version }} version: ${{ inputs.version }}
build-msi: build-msi:
name: Build .msi Installer name: Build .msi Installer
@@ -55,7 +55,6 @@ jobs:
- name: Patch target dir - name: Patch target dir
run: | run: |
cp LICENSE.txt target cp LICENSE.txt target
cp dist/linux/launcher.sh target
cp target/cryptomator-*.jar target/mods cp target/cryptomator-*.jar target/mods
- name: Run jlink - name: Run jlink
run: > run: >
@@ -81,7 +80,7 @@ jobs:
--dest appdir --dest appdir
--name Cryptomator --name Cryptomator
--vendor "Skymatic GmbH" --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 }}" --app-version "${{ needs.get-version.outputs.semVerNum }}.${{ needs.get-version.outputs.revNum }}"
--java-options "--enable-preview" --java-options "--enable-preview"
--java-options "--enable-native-access=org.cryptomator.jfuse.win" --java-options "--enable-native-access=org.cryptomator.jfuse.win"
@@ -118,6 +117,9 @@ jobs:
- name: Fix permissions - name: Fix permissions
run: attrib -r appdir/Cryptomator/Cryptomator.exe run: attrib -r appdir/Cryptomator/Cryptomator.exe
shell: pwsh 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 - name: Codesign
uses: skymatic/code-sign-action@v2 uses: skymatic/code-sign-action@v2
with: with:
@@ -128,6 +130,10 @@ jobs:
timestampUrl: 'http://timestamp.digicert.com' timestampUrl: 'http://timestamp.digicert.com'
folder: appdir/Cryptomator folder: appdir/Cryptomator
recursive: true 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 - name: Generate license for MSI
run: > run: >
mvn -B license:add-third-party mvn -B license:add-third-party
@@ -149,8 +155,8 @@ jobs:
--dest installer --dest installer
--name Cryptomator --name Cryptomator
--vendor "Skymatic GmbH" --vendor "Skymatic GmbH"
--copyright "(C) 2016 - 2022 Skymatic GmbH" --copyright "(C) 2016 - 2023 Skymatic GmbH"
--app-version "${{ needs.get-version.outputs.semVerNum }}" --app-version "${{ needs.get-version.outputs.semVerNum }}.${{ needs.get-version.outputs.revNum}}"
--win-menu --win-menu
--win-dir-chooser --win-dir-chooser
--win-shortcut-prompt --win-shortcut-prompt
@@ -247,7 +253,7 @@ jobs:
-out dist/win/bundle/ -out dist/win/bundle/
-dBundleVersion="${{ needs.get-version.outputs.semVerNum }}.${{ needs.get-version.outputs.revNum }}" -dBundleVersion="${{ needs.get-version.outputs.semVerNum }}.${{ needs.get-version.outputs.revNum }}"
-dBundleVendor="Skymatic GmbH" -dBundleVendor="Skymatic GmbH"
-dBundleCopyright="(C) 2016 - 2022 Skymatic GmbH" -dBundleCopyright="(C) 2016 - 2023 Skymatic GmbH"
-dAboutUrl="https://cryptomator.org" -dAboutUrl="https://cryptomator.org"
-dHelpUrl="https://cryptomator.org/contact" -dHelpUrl="https://cryptomator.org/contact"
-dUpdateUrl="https://cryptomator.org/downloads/" -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> <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://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.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> </tr>
</tbody> </tbody>
</table> </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) VERSION=$(mvn -f ../../../pom.xml help:evaluate -Dexpression=project.version -q -DforceStdout)
SEMVER_STR=${VERSION} SEMVER_STR=${VERSION}
mvn -f ../../../pom.xml versions:set -DnewVersion=${SEMVER_STR}
# compile # 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 cp ../../../target/cryptomator-*.jar ../../../target/mods
# add runtime # add runtime
${JAVA_HOME}/bin/jlink \ ${JAVA_HOME}/bin/jlink \
--verbose \
--output runtime \ --output runtime \
--module-path "${JAVA_HOME}/jmods" \ --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 \ --strip-native-commands \
--no-header-files \ --no-header-files \
--no-man-pages \ --no-man-pages \
@@ -27,7 +32,7 @@ ${JAVA_HOME}/bin/jlink \
--compress=1 --compress=1
# create app dir # 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 \ ${JAVA_HOME}/bin/jpackage \
--verbose \ --verbose \
--type app-image \ --type app-image \
@@ -35,12 +40,12 @@ ${JAVA_HOME}/bin/jpackage \
--input ../../../target/libs \ --input ../../../target/libs \
--module-path ../../../target/mods \ --module-path ../../../target/mods \
--module org.cryptomator.desktop/org.cryptomator.launcher.Cryptomator \ --module org.cryptomator.desktop/org.cryptomator.launcher.Cryptomator \
--dest . \ --dest appdir \
--name Cryptomator \ --name Cryptomator \
--vendor "Skymatic GmbH" \ --vendor "Skymatic GmbH" \
--copyright "(C) 2016 - 2022 Skymatic GmbH" \
--java-options "--enable-preview" \ --java-options "--enable-preview" \
--java-options "--enable-native-access=org.cryptomator.jfuse.linux.amd64,org.cryptomator.jfuse.linux.aarch64" \ --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 "-Xss5m" \
--java-options "-Xmx256m" \ --java-options "-Xmx256m" \
--app-version "${VERSION}.${REVISION_NO}" \ --app-version "${VERSION}.${REVISION_NO}" \
@@ -48,6 +53,7 @@ ${JAVA_HOME}/bin/jpackage \
--java-options "-Dcryptomator.logDir=\"~/.local/share/Cryptomator/logs\"" \ --java-options "-Dcryptomator.logDir=\"~/.local/share/Cryptomator/logs\"" \
--java-options "-Dcryptomator.pluginDir=\"~/.local/share/Cryptomator/plugins\"" \ --java-options "-Dcryptomator.pluginDir=\"~/.local/share/Cryptomator/plugins\"" \
--java-options "-Dcryptomator.settingsPath=\"~/.config/Cryptomator/settings.json:~/.Cryptomator/settings.json\"" \ --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.ipcSocketPath=\"~/.config/Cryptomator/ipc.socket\"" \
--java-options "-Dcryptomator.mountPointsDir=\"~/.local/share/Cryptomator/mnt\"" \ --java-options "-Dcryptomator.mountPointsDir=\"~/.local/share/Cryptomator/mnt\"" \
--java-options "-Dcryptomator.showTrayIcon=false" \ --java-options "-Dcryptomator.showTrayIcon=false" \
@@ -56,9 +62,8 @@ ${JAVA_HOME}/bin/jpackage \
--resource-dir ../resources --resource-dir ../resources
# transform AppDir # transform AppDir
mv Cryptomator Cryptomator.AppDir mv appdir/Cryptomator Cryptomator.AppDir
cp -r resources/AppDir/* 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 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.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 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 usr/share/applications/org.cryptomator.Cryptomator.desktop Cryptomator.AppDir/Cryptomator.desktop
ln -s bin/cryptomator.sh Cryptomator.AppDir/AppRun 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 # load AppImageTool
curl -L https://github.com/AppImage/AppImageKit/releases/download/13/appimagetool-x86_64.AppImage -o /tmp/appimagetool.AppImage curl -L https://github.com/AppImage/AppImageKit/releases/download/13/appimagetool-x86_64.AppImage -o /tmp/appimagetool.AppImage
chmod +x /tmp/appimagetool.AppImage chmod +x /tmp/appimagetool.AppImage
@@ -85,5 +84,11 @@ chmod +x /tmp/appimagetool.AppImage
# create AppImage # create AppImage
/tmp/appimagetool.AppImage \ /tmp/appimagetool.AppImage \
Cryptomator.AppDir \ 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' -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 $?` GTK3_PRESENT=`pacman -Qi gtk3 &> /dev/null; echo $?`
fi 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 if [ "$GTK2_PRESENT" -eq 0 ] && [ "$GTK3_PRESENT" -ne 0 ]; then
bin/Cryptomator-gtk2 $@ bin/Cryptomator-gtk2 $@
else else
@@ -66,6 +66,7 @@
</content_rating> </content_rating>
<releases> <releases>
<release date="2022-12-14" version="1.6.17"/>
<release date="2022-12-06" version="1.6.16"/> <release date="2022-12-06" version="1.6.16"/>
<release date="2022-10-06" version="1.6.15"/> <release date="2022-10-06" version="1.6.15"/>
<release date="2022-08-31" version="1.6.14"/> <release date="2022-08-31" version="1.6.14"/>
+1 -1
View File
@@ -12,7 +12,7 @@ Package: cryptomator
Architecture: any Architecture: any
Section: utils Section: utils
Priority: optional 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 Recommends: gvfs-backends, gvfs-fuse, gnome-keyring
XB-AppName: Cryptomator XB-AppName: Cryptomator
XB-Category: Utility;Security;FileTools; XB-Category: Utility;Security;FileTools;
+2 -2
View File
@@ -4,11 +4,11 @@ Upstream-Contact: Cryptomator <info@cryptomator.org>
Source: https://cryptomator.org Source: https://cryptomator.org
Files: * Files: *
Copyright: 2016-2022 Skymatic GmbH Copyright: 2016-2023 Skymatic GmbH
License: GPL-3+ License: GPL-3+
Files: debian/org.cryptomator.Cryptomator.appdata.xml Files: debian/org.cryptomator.Cryptomator.appdata.xml
Copyright: 2016-2022 Skymatic GmbH Copyright: 2016-2023 Skymatic GmbH
License: FSFAP License: FSFAP
License: GPL-3+ License: GPL-3+
-1
View File
@@ -1,5 +1,4 @@
cryptomator usr/lib cryptomator usr/lib
debian/cryptomator.sh usr/lib/cryptomator/bin
common/org.cryptomator.Cryptomator.desktop usr/share/applications common/org.cryptomator.Cryptomator.desktop usr/share/applications
common/org.cryptomator.Cryptomator.svg usr/share/icons/hicolor/scalable/apps common/org.cryptomator.Cryptomator.svg usr/share/icons/hicolor/scalable/apps
common/org.cryptomator.Cryptomator256.png usr/share/icons/hicolor/256x256/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 \ $(JAVA_HOME)/bin/jlink \
--output runtime \ --output runtime \
--module-path "${JMODS_PATH}" \ --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 \ --strip-native-commands \
--no-header-files \ --no-header-files \
--no-man-pages \ --no-man-pages \
@@ -42,9 +42,9 @@ override_dh_auto_build:
--dest . \ --dest . \
--name cryptomator \ --name cryptomator \
--vendor "Skymatic GmbH" \ --vendor "Skymatic GmbH" \
--copyright "(C) 2016 - 2022 Skymatic GmbH" \
--java-options "--enable-preview" \ --java-options "--enable-preview" \
--java-options "--enable-native-access=org.cryptomator.jfuse.linux.amd64,org.cryptomator.jfuse.linux.aarch64" \ --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 "-Xss5m" \
--java-options "-Xmx256m" \ --java-options "-Xmx256m" \
--java-options "-Dfile.encoding=\"utf-8\"" \ --java-options "-Dfile.encoding=\"utf-8\"" \
@@ -60,10 +60,3 @@ override_dh_auto_build:
--app-version "${VERSION_NUM}.${REVISION_NUM}" \ --app-version "${VERSION_NUM}.${REVISION_NUM}" \
--resource-dir resources \ --resource-dir resources \
--verbose --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 # set variables
APP_NAME="Cryptomator" APP_NAME="Cryptomator"
VENDOR="Skymatic GmbH" VENDOR="Skymatic GmbH"
COPYRIGHT_YEARS="2016 - 2022" COPYRIGHT_YEARS="2016 - 2023"
PACKAGE_IDENTIFIER="org.cryptomator" PACKAGE_IDENTIFIER="org.cryptomator"
MAIN_JAR_GLOB="cryptomator-*.jar" MAIN_JAR_GLOB="cryptomator-*.jar"
MODULE_AND_MAIN_CLASS="org.cryptomator.desktop/org.cryptomator.launcher.Cryptomator" 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.ipcSocketPath=\"~/Library/Application Support/${APP_NAME}/ipc.socket\"" \
--java-options "-Dcryptomator.p12Path=\"~/Library/Application Support/${APP_NAME}/key.p12\"" \ --java-options "-Dcryptomator.p12Path=\"~/Library/Application Support/${APP_NAME}/key.p12\"" \
--java-options "-Dcryptomator.integrationsMac.keychainServiceName=\"${APP_NAME}\"" \ --java-options "-Dcryptomator.integrationsMac.keychainServiceName=\"${APP_NAME}\"" \
--java-options "-Dcryptomator.mountPointsDir=\"~/${APP_NAME}\"" \
--java-options "-Dcryptomator.showTrayIcon=true" \ --java-options "-Dcryptomator.showTrayIcon=true" \
--java-options "-Dcryptomator.buildNumber=\"dmg-${REVISION_NO}\"" \ --java-options "-Dcryptomator.buildNumber=\"dmg-${REVISION_NO}\"" \
--mac-package-identifier ${PACKAGE_IDENTIFIER} \ --mac-package-identifier ${PACKAGE_IDENTIFIER} \
Binary file not shown.
+1 -1
View File
@@ -17,7 +17,7 @@
\f1\b0 \ \f1\b0 \
\ \
\f0\b \'a9 2016 \'96 2022 Skymatic GmbH \f0\b \'a9 2016 \'96 2023 Skymatic GmbH
\f1\b0 \ \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.\ 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 ` --name $AppName `
--vendor $Vendor ` --vendor $Vendor `
--copyright $copyright ` --copyright $copyright `
--app-version "$semVerNo" ` --app-version "$semVerNo.$revisionNo" `
--win-menu ` --win-menu `
--win-dir-chooser ` --win-dir-chooser `
--win-shortcut-prompt ` --win-shortcut-prompt `
+1 -1
View File
@@ -10,7 +10,7 @@
\vieww12000\viewh15840\viewkind0 \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 \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 \par
\b\'a9 2016 \'96 2022 Skymatic GmbH \b0\par \b\'a9 2016 \'96 2023 Skymatic GmbH \b0\par
\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 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 \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)" /> <Control Id="Title" Type="Text" X="135" Y="20" Width="220" Height="60" Transparent="yes" NoPrefix="yes" Text="!(loc.ExitDialogTitle)" />
<!-- TODO: localize? --> <!-- TODO: localize? -->
<Control Id="Suggestion" Type="Text" X="135" Y="100" Width="220" Height="60" Transparent="yes" NoPrefix="yes"> <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>
<Control Id="WinFsp" Type="Hyperlink" X="140" Y="125" Width="220" Height="60" Transparent="yes"> <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> <Text><![CDATA[WinFsp (<a href="https://winfsp.dev/">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>
</Control> </Control>
</Dialog> </Dialog>
+1 -1
View File
@@ -10,7 +10,7 @@
\vieww12000\viewh15840\viewkind0 \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 \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 \par
\b\'a9 2016 \'96 2022 Skymatic GmbH \b0\par \b\'a9 2016 \'96 2023 Skymatic GmbH \b0\par
\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 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 \par
+8 -4
View File
@@ -54,7 +54,7 @@
Property="JP_UPGRADABLE_FOUND" Property="JP_UPGRADABLE_FOUND"
Maximum="$(var.JpAppVersion)" Maximum="$(var.JpAppVersion)"
MigrateFeatures="yes" MigrateFeatures="yes"
IncludeMaximum="$(var.JpUpgradeVersionOnlyDetectUpgrade)" /> IncludeMaximum="yes" /> <!-- TODO: check if this needs to be set to yes-->
<UpgradeVersion <UpgradeVersion
OnlyDetect="$(var.JpUpgradeVersionOnlyDetectDowngrade)" OnlyDetect="$(var.JpUpgradeVersionOnlyDetectDowngrade)"
Property="JP_DOWNGRADABLE_FOUND" Property="JP_DOWNGRADABLE_FOUND"
@@ -132,6 +132,9 @@
<!-- WebDAV patches --> <!-- WebDAV patches -->
<CustomAction Id="PatchWebDAV" Impersonate="no" ExeCommand="[INSTALLDIR]patchWebDAV.bat" Directory="INSTALLDIR" Execute="deferred" Return="asyncWait" /> <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 --> <!-- Running App detection and exit -->
<Property Id="FOUNDRUNNINGAPP" Admin="yes"/> <Property Id="FOUNDRUNNINGAPP" Admin="yes"/>
<util:CloseApplication <util:CloseApplication
@@ -140,11 +143,11 @@
CloseMessage="no" CloseMessage="no"
RebootPrompt="no" RebootPrompt="no"
PromptToContinue="yes" 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" Property="FOUNDRUNNINGAPP"
> >
</util:CloseApplication> </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 ?> <?ifdef JpIcon ?>
<Property Id="ARPPRODUCTICON" Value="JpARPPRODUCTICON"/> <Property Id="ARPPRODUCTICON" Value="JpARPPRODUCTICON"/>
@@ -179,9 +182,10 @@
<Custom Action="WixCloseApplications" Before="InstallValidate"></Custom> <Custom Action="WixCloseApplications" Before="InstallValidate"></Custom>
<Custom Action="FailOnRunningApp" After="WixCloseApplications" >FOUNDRUNNINGAPP</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="PatchWebDAV" After="InstallFiles">NOT Installed OR REINSTALL</Custom>
<Custom Action="V170MigrateSettings" After="InstallFiles">NOT Installed OR REINSTALL</Custom>
</InstallExecuteSequence> </InstallExecuteSequence>
<WixVariable Id="WixUIBannerBmp" Value="$(env.JP_WIXWIZARD_RESOURCES)\banner.bmp" /> <WixVariable Id="WixUIBannerBmp" Value="$(env.JP_WIXWIZARD_RESOURCES)\banner.bmp" />
+19 -12
View File
@@ -3,7 +3,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>org.cryptomator</groupId> <groupId>org.cryptomator</groupId>
<artifactId>cryptomator</artifactId> <artifactId>cryptomator</artifactId>
<version>1.7.0</version> <version>1.7.0-SNAPSHOT</version>
<name>Cryptomator Desktop App</name> <name>Cryptomator Desktop App</name>
<organization> <organization>
@@ -24,18 +24,19 @@
<project.jdk.version>19</project.jdk.version> <project.jdk.version>19</project.jdk.version>
<!-- Group IDs of jars that need to stay on the class path for now --> <!-- 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 --> <!-- Once hypfvieh, swiesend, purejava and integrations-linux have module-info, remove them-->
<nonModularGroupIds>com.github.jnr,org.ow2.asm,org.apache.jackrabbit,org.apache.httpcomponents,de.swiesend,org.purejava,com.github.hypfvieh</nonModularGroupIds> <nonModularGroupIds>org.ow2.asm,org.apache.jackrabbit,org.apache.httpcomponents,de.swiesend,org.purejava,com.github.hypfvieh</nonModularGroupIds>
<!-- cryptomator dependencies --> <!-- cryptomator dependencies -->
<cryptomator.cryptofs.version>2.5.3</cryptomator.cryptofs.version> <cryptomator.cryptolib.version>2.1.1</cryptomator.cryptolib.version>
<cryptomator.integrations.version>1.2.0-beta2</cryptomator.integrations.version> <cryptomator.cryptofs.version>2.6.1</cryptomator.cryptofs.version>
<cryptomator.integrations.win.version>1.1.2</cryptomator.integrations.win.version> <cryptomator.integrations.version>1.2.0-beta4</cryptomator.integrations.version>
<cryptomator.integrations.mac.version>1.1.2</cryptomator.integrations.mac.version> <cryptomator.integrations.win.version>1.2.0-beta3</cryptomator.integrations.win.version>
<cryptomator.integrations.linux.version>1.1.0</cryptomator.integrations.linux.version> <cryptomator.integrations.mac.version>1.2.0-beta2</cryptomator.integrations.mac.version>
<cryptomator.fuse.version>2.0.0-beta2</cryptomator.fuse.version> <cryptomator.integrations.linux.version>1.2.0-beta2</cryptomator.integrations.linux.version>
<cryptomator.dokany.version>2.0.0-beta1</cryptomator.dokany.version> <cryptomator.fuse.version>2.0.0-beta5</cryptomator.fuse.version>
<cryptomator.webdav.version>2.0.0-beta1</cryptomator.webdav.version> <cryptomator.dokany.version>2.0.0-beta2</cryptomator.dokany.version>
<cryptomator.webdav.version>2.0.0-beta5</cryptomator.webdav.version>
<!-- 3rd party dependencies --> <!-- 3rd party dependencies -->
<commons-lang3.version>3.12.0</commons-lang3.version> <commons-lang3.version>3.12.0</commons-lang3.version>
@@ -58,12 +59,18 @@
<!-- build-time dependencies --> <!-- build-time dependencies -->
<jetbrains.annotations.version>23.0.0</jetbrains.annotations.version> <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> <jacoco.version>0.8.8</jacoco.version>
</properties> </properties>
<dependencies> <dependencies>
<!-- Cryptomator Libs --> <!-- 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> <dependency>
<groupId>org.cryptomator</groupId> <groupId>org.cryptomator</groupId>
<artifactId>cryptofs</artifactId> <artifactId>cryptofs</artifactId>
@@ -16,6 +16,7 @@ import org.cryptomator.common.settings.SettingsProvider;
import org.cryptomator.common.vaults.VaultComponent; import org.cryptomator.common.vaults.VaultComponent;
import org.cryptomator.common.vaults.VaultListModule; import org.cryptomator.common.vaults.VaultListModule;
import org.cryptomator.cryptolib.common.MasterkeyFileAccess; import org.cryptomator.cryptolib.common.MasterkeyFileAccess;
import org.cryptomator.integrations.revealpath.RevealPathService;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@@ -26,6 +27,7 @@ import java.net.InetSocketAddress;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom; import java.security.SecureRandom;
import java.util.Comparator; import java.util.Comparator;
import java.util.Optional;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.SynchronousQueue; import java.util.concurrent.SynchronousQueue;
@@ -83,6 +85,13 @@ public abstract class CommonsModule {
return new SemVerComparator(); return new SemVerComparator();
} }
@Provides
@Singleton
static Optional<RevealPathService> provideRevealPathService() {
return RevealPathService.get().findFirst();
}
@Provides @Provides
@Singleton @Singleton
static Settings provideSettings(SettingsProvider settingsProvider) { 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 org.cryptomator.integrations.mount.MountService;
import javax.inject.Singleton; import javax.inject.Singleton;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.value.ObservableValue; import javafx.beans.value.ObservableValue;
import java.util.List; import java.util.List;
@@ -18,13 +19,33 @@ public class MountModule {
return MountService.get().toList(); return MountService.get().toList();
} }
//currently not used, because macFUSE and FUSE-T cannot be used in the same JVM
/*
@Provides @Provides
@Singleton @Singleton
static ObservableValue<MountService> provideMountService(Settings settings, List<MountService> serviceImpls) { static ObservableValue<ActualMountService> provideMountService(Settings settings, List<MountService> serviceImpls) {
return settings.mountService().map(desiredServiceImpl -> { var fallbackProvider = serviceImpls.stream().findFirst().orElse(null);
var fallbackProvider = serviceImpls.stream().findFirst().orElse(null); return ObservableUtil.mapWithDefault(settings.mountService(), //
return serviceImpls.stream().filter(serviceImpl -> serviceImpl.getClass().getName().equals(desiredServiceImpl)).findAny().orElse(fallbackProvider); 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 { private P384KeyPair createAndStoreNewKeyPair(char[] passphrase, Path p12File) throws IOException {
var keyPair = P384KeyPair.generate(); 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); LOG.debug("Store new device key to {}", p12File);
keyPair.store(p12File, passphrase); keyPair.store(p12File, passphrase);
return keyPair; return keyPair;
@@ -9,6 +9,7 @@ import com.google.gson.TypeAdapter;
import com.google.gson.stream.JsonReader; import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonToken; import com.google.gson.stream.JsonToken;
import com.google.gson.stream.JsonWriter; import com.google.gson.stream.JsonWriter;
import org.apache.commons.lang3.SystemUtils;
import org.cryptomator.common.Environment; import org.cryptomator.common.Environment;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@@ -36,6 +37,7 @@ public class SettingsJsonAdapter extends TypeAdapter<Settings> {
@Override @Override
public void write(JsonWriter out, Settings value) throws IOException { public void write(JsonWriter out, Settings value) throws IOException {
out.beginObject(); out.beginObject();
out.name("lastWrittenByVersion").value(env.getAppVersion()+env.getBuildNumber().map("-"::concat).orElse(""));
out.name("directories"); out.name("directories");
writeVaultSettingsArray(out, value.getDirectories()); writeVaultSettingsArray(out, value.getDirectories());
out.name("askedForUpdateCheck").value(value.askedForUpdateCheck().get()); out.name("askedForUpdateCheck").value(value.askedForUpdateCheck().get());
@@ -73,7 +75,9 @@ public class SettingsJsonAdapter extends TypeAdapter<Settings> {
@Override @Override
public Settings read(JsonReader in) throws IOException { public Settings read(JsonReader in) throws IOException {
Settings settings = new Settings(env); Settings settings = new Settings(env);
//1.6.x legacy
String volumeImpl = null;
//legacy end
in.beginObject(); in.beginObject();
while (in.hasNext()) { while (in.hasNext()) {
String name = in.nextName(); String name = in.nextName();
@@ -105,18 +109,49 @@ public class SettingsJsonAdapter extends TypeAdapter<Settings> {
settings.mountService().set(in.nextString()); settings.mountService().set(in.nextString());
} }
} }
//1.6.x legacy
case "preferredVolumeImpl" -> volumeImpl = in.nextString();
//legacy end
default -> { default -> {
LOG.warn("Unsupported vault setting found in JSON: {}", name); LOG.warn("Unsupported vault setting found in JSON: {}", name);
in.skipValue(); in.skipValue();
} }
} }
} }
in.endObject(); in.endObject();
//1.6.x legacy
if (volumeImpl != null) {
settings.mountService().set(convertLegacyVolumeImplToMountService(volumeImpl));
}
//legacy end
return settings; 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) { private UiTheme parseUiTheme(String uiThemeName) {
try { try {
return UiTheme.valueOf(uiThemeName.toUpperCase()); 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 unlockAfterStartup = new SimpleBooleanProperty(DEFAULT_UNLOCK_AFTER_STARTUP);
private final BooleanProperty revealAfterMount = new SimpleBooleanProperty(DEFAULT_REVEAL_AFTER_MOUNT); private final BooleanProperty revealAfterMount = new SimpleBooleanProperty(DEFAULT_REVEAL_AFTER_MOUNT);
private final BooleanProperty usesReadOnlyMode = new SimpleBooleanProperty(DEFAULT_USES_READONLY_MODE); 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 IntegerProperty maxCleartextFilenameLength = new SimpleIntegerProperty(DEFAULT_MAX_CLEARTEXT_FILENAME_LENGTH);
private final ObjectProperty<WhenUnlocked> actionAfterUnlock = new SimpleObjectProperty<>(DEFAULT_ACTION_AFTER_UNLOCK); private final ObjectProperty<WhenUnlocked> actionAfterUnlock = new SimpleObjectProperty<>(DEFAULT_ACTION_AFTER_UNLOCK);
private final BooleanProperty autoLockWhenIdle = new SimpleBooleanProperty(DEFAULT_AUTOLOCK_WHEN_IDLE); private final BooleanProperty autoLockWhenIdle = new SimpleBooleanProperty(DEFAULT_AUTOLOCK_WHEN_IDLE);
@@ -38,8 +38,6 @@ class VaultSettingsJsonAdapter {
out.endObject(); out.endObject();
} }
//TODO: usesCustomMountPath, customMountPath and winDriveLetter removed
// -> migration required
public VaultSettings read(JsonReader in) throws IOException { public VaultSettings read(JsonReader in) throws IOException {
String id = null; String id = null;
String path = null; String path = null;
@@ -55,6 +53,12 @@ class VaultSettingsJsonAdapter {
boolean autoLockWhenIdle = VaultSettings.DEFAULT_AUTOLOCK_WHEN_IDLE; boolean autoLockWhenIdle = VaultSettings.DEFAULT_AUTOLOCK_WHEN_IDLE;
int autoLockIdleSeconds = VaultSettings.DEFAULT_AUTOLOCK_IDLE_SECONDS; int autoLockIdleSeconds = VaultSettings.DEFAULT_AUTOLOCK_IDLE_SECONDS;
//legacy from 1.6.x
boolean useCustomMountPath = false;
String customMountPath = "";
String winDriveLetter = "";
//legacy end
in.beginObject(); in.beginObject();
while (in.hasNext()) { while (in.hasNext()) {
String name = in.nextName(); String name = in.nextName();
@@ -78,6 +82,11 @@ class VaultSettingsJsonAdapter {
case "actionAfterUnlock" -> actionAfterUnlock = parseActionAfterUnlock(in.nextString()); case "actionAfterUnlock" -> actionAfterUnlock = parseActionAfterUnlock(in.nextString());
case "autoLockWhenIdle" -> autoLockWhenIdle = in.nextBoolean(); case "autoLockWhenIdle" -> autoLockWhenIdle = in.nextBoolean();
case "autoLockIdleSeconds" -> autoLockIdleSeconds = in.nextInt(); 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 -> { default -> {
LOG.warn("Unsupported vault setting found in JSON: {}", name); LOG.warn("Unsupported vault setting found in JSON: {}", name);
in.skipValue(); in.skipValue();
@@ -102,6 +111,13 @@ class VaultSettingsJsonAdapter {
vaultSettings.autoLockWhenIdle().set(autoLockWhenIdle); vaultSettings.autoLockWhenIdle().set(autoLockWhenIdle);
vaultSettings.autoLockIdleSeconds().set(autoLockIdleSeconds); vaultSettings.autoLockIdleSeconds().set(autoLockIdleSeconds);
vaultSettings.mountPoint().set(mountPoint); 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; 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; package org.cryptomator.common.vaults;
import com.google.common.base.Strings;
import org.apache.commons.lang3.SystemUtils; import org.apache.commons.lang3.SystemUtils;
import org.cryptomator.common.Constants; 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.mount.WindowsDriveLetters;
import org.cryptomator.common.settings.Settings;
import org.cryptomator.common.settings.VaultSettings; import org.cryptomator.common.settings.VaultSettings;
import org.cryptomator.cryptofs.CryptoFileSystem; import org.cryptomator.cryptofs.CryptoFileSystem;
import org.cryptomator.cryptofs.CryptoFileSystemProperties; 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.CryptoException;
import org.cryptomator.cryptolib.api.MasterkeyLoader; import org.cryptomator.cryptolib.api.MasterkeyLoader;
import org.cryptomator.cryptolib.api.MasterkeyLoadingFailedException; 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.MountFailedException;
import org.cryptomator.integrations.mount.MountService;
import org.cryptomator.integrations.mount.Mountpoint; import org.cryptomator.integrations.mount.Mountpoint;
import org.cryptomator.integrations.mount.UnmountFailedException; import org.cryptomator.integrations.mount.UnmountFailedException;
import org.slf4j.Logger; import org.slf4j.Logger;
@@ -44,9 +38,7 @@ import javafx.beans.property.BooleanProperty;
import javafx.beans.property.ObjectProperty; import javafx.beans.property.ObjectProperty;
import javafx.beans.property.ReadOnlyStringProperty; import javafx.beans.property.ReadOnlyStringProperty;
import javafx.beans.property.SimpleBooleanProperty; import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.value.ObservableValue;
import java.io.IOException; import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.util.EnumSet; import java.util.EnumSet;
@@ -54,11 +46,6 @@ import java.util.Objects;
import java.util.Set; import java.util.Set;
import java.util.concurrent.atomic.AtomicReference; 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 @PerVault
public class Vault { public class Vault {
@@ -66,14 +53,10 @@ public class Vault {
private static final Path HOME_DIR = Paths.get(SystemUtils.USER_HOME); private static final Path HOME_DIR = Paths.get(SystemUtils.USER_HOME);
private static final int UNLIMITED_FILENAME_LENGTH = Integer.MAX_VALUE; private static final int UNLIMITED_FILENAME_LENGTH = Integer.MAX_VALUE;
private final Environment env;
private final Settings settings;
private final VaultSettings vaultSettings; private final VaultSettings vaultSettings;
private final AtomicReference<CryptoFileSystem> cryptoFileSystem; private final AtomicReference<CryptoFileSystem> cryptoFileSystem;
private final VaultState state; private final VaultState state;
private final ObjectProperty<Exception> lastKnownException; private final ObjectProperty<Exception> lastKnownException;
private final ObservableValue<MountService> mountService;
private final ObservableValue<String> defaultMountFlags;
private final VaultConfigCache configCache; private final VaultConfigCache configCache;
private final VaultStats stats; private final VaultStats stats;
private final StringBinding displayablePath; private final StringBinding displayablePath;
@@ -84,22 +67,18 @@ public class Vault {
private final BooleanBinding needsMigration; private final BooleanBinding needsMigration;
private final BooleanBinding unknownError; private final BooleanBinding unknownError;
private final ObjectBinding<Mountpoint> mountPoint; private final ObjectBinding<Mountpoint> mountPoint;
private final WindowsDriveLetters windowsDriveLetters; private final Mounter mounter;
private final BooleanProperty showingStats; private final BooleanProperty showingStats;
private AtomicReference<MountHandle> mountHandle = new AtomicReference<>(null); private AtomicReference<Mounter.MountHandle> mountHandle = new AtomicReference<>(null);
@Inject @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) { Vault(VaultSettings vaultSettings, VaultConfigCache configCache, AtomicReference<CryptoFileSystem> cryptoFileSystem, VaultState state, @Named("lastKnownException") ObjectProperty<Exception> lastKnownException, VaultStats stats, WindowsDriveLetters windowsDriveLetters, Mounter mounter) {
this.env = env;
this.settings = settings;
this.vaultSettings = vaultSettings; this.vaultSettings = vaultSettings;
this.configCache = configCache; this.configCache = configCache;
this.cryptoFileSystem = cryptoFileSystem; this.cryptoFileSystem = cryptoFileSystem;
this.state = state; this.state = state;
this.lastKnownException = lastKnownException; this.lastKnownException = lastKnownException;
this.mountService = mountService;
this.defaultMountFlags = mountService.map(MountService::getDefaultMountFlags);
this.stats = stats; this.stats = stats;
this.displayablePath = Bindings.createStringBinding(this::getDisplayablePath, vaultSettings.path()); this.displayablePath = Bindings.createStringBinding(this::getDisplayablePath, vaultSettings.path());
this.locked = Bindings.createBooleanBinding(this::isLocked, state); this.locked = Bindings.createBooleanBinding(this::isLocked, state);
@@ -109,7 +88,7 @@ public class Vault {
this.needsMigration = Bindings.createBooleanBinding(this::isNeedsMigration, state); this.needsMigration = Bindings.createBooleanBinding(this::isNeedsMigration, state);
this.unknownError = Bindings.createBooleanBinding(this::isUnknownError, state); this.unknownError = Bindings.createBooleanBinding(this::isUnknownError, state);
this.mountPoint = Bindings.createObjectBinding(this::getMountPoint, state); this.mountPoint = Bindings.createObjectBinding(this::getMountPoint, state);
this.windowsDriveLetters = windowsDriveLetters; this.mounter = mounter;
this.showingStats = new SimpleBooleanProperty(false); 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 { public synchronized void unlock(MasterkeyLoader keyLoader) throws CryptoException, IOException, MountFailedException {
if (cryptoFileSystem.get() != null) { if (cryptoFileSystem.get() != null) {
throw new IllegalStateException("Already unlocked."); throw new IllegalStateException("Already unlocked.");
@@ -207,8 +147,7 @@ public class Vault {
try { try {
cryptoFileSystem.set(fs); cryptoFileSystem.set(fs);
var rootPath = fs.getRootDirectories().iterator().next(); var rootPath = fs.getRootDirectories().iterator().next();
var supportsForcedUnmount = mountService.getValue().hasCapability(MountCapability.UNMOUNT_FORCED); var mountHandle = mounter.mount(vaultSettings, rootPath);
var mountHandle = new MountHandle(prepareMount(rootPath).mount(), supportsForcedUnmount);
success = this.mountHandle.compareAndSet(null, mountHandle); success = this.mountHandle.compareAndSet(null, mountHandle);
} finally { } finally {
if (!success) { if (!success) {
@@ -217,7 +156,6 @@ public class Vault {
} }
} }
public synchronized void lock(boolean forced) throws UnmountFailedException, IOException { public synchronized void lock(boolean forced) throws UnmountFailedException, IOException {
var mountHandle = this.mountHandle.get(); var mountHandle = this.mountHandle.get();
if (mountHandle == null) { if (mountHandle == null) {
@@ -225,14 +163,15 @@ public class Vault {
return; return;
} }
if (forced && mountHandle.supportsUnmountForced) { if (forced && mountHandle.supportsUnmountForced()) {
mountHandle.mount.unmountForced(); mountHandle.mountObj().unmountForced();
} else { } else {
mountHandle.mount.unmount(); mountHandle.mountObj().unmount();
} }
try { try {
mountHandle.mount.close(); mountHandle.mountObj().close();
mountHandle.specialCleanup().run();
} finally { } finally {
destroyCryptoFileSystem(); destroyCryptoFileSystem();
} }
@@ -327,7 +266,7 @@ public class Vault {
public Mountpoint getMountPoint() { public Mountpoint getMountPoint() {
var handle = mountHandle.get(); var handle = mountHandle.get();
return handle == null ? null : handle.mount.getMountpoint(); return handle == null ? null : handle.mountObj().getMountpoint();
} }
public StringBinding displayablePathProperty() { public StringBinding displayablePathProperty() {
@@ -375,35 +314,26 @@ public class Vault {
return vaultSettings.path().getValue(); return vaultSettings.path().getValue();
} }
public boolean isHavingCustomMountFlags() { /**
return !Strings.isNullOrEmpty(vaultSettings.mountFlags().get()); * Gets from the cleartext path its ciphertext counterpart.
} * The cleartext path has to start from the vault root (by starting with "/").
*
public ObservableValue<String> defaultMountFlagsProperty() { * @return Local os path to the ciphertext resource
return defaultMountFlags; * @throws IOException if an I/O error occurs
} */
public Path getCiphertextPath(String cleartextPath) throws IOException {
public String getDefaultMountFlags() { if (!cleartextPath.startsWith("/")) {
return defaultMountFlags.getValue(); throw new IllegalArgumentException("Input path must be absolute from vault root by starting with \"/\".");
}
public String getEffectiveMountFlags() {
String mountFlags = vaultSettings.mountFlags().get();
if (Strings.isNullOrEmpty(mountFlags)) {
return ""; //TODO: should the provider provide dem defaults??
} else {
return mountFlags;
} }
var fs = cryptoFileSystem.get();
var cryptoPath = fs.getPath(cleartextPath);
return fs.getCiphertextPath(cryptoPath);
} }
public VaultConfigCache getVaultConfigCache() { public VaultConfigCache getVaultConfigCache() {
return configCache; return configCache;
} }
public void setCustomMountFlags(String mountFlags) {
vaultSettings.mountFlags().set(mountFlags);
}
public String getId() { public String getId() {
return vaultSettings.getId(); return vaultSettings.getId();
} }
@@ -426,15 +356,12 @@ public class Vault {
} }
} }
/* TODO: reactivate/ needed at all?
public boolean supportsForcedUnmount() { 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(upgrade);
upgrades.addAppender(file); upgrades.addAppender(file);
upgrades.setAdditive(false); 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; return ExecutionStatus.DO_NOT_INVOKE_NEXT_IF_ANY;
} }
@@ -176,7 +176,7 @@ public class CreateNewVaultPasswordController implements FxController {
// 2. initialize vault: // 2. initialize vault:
try { try {
MasterkeyLoader loader = ignored -> masterkey.copy(); 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); CryptoFileSystemProvider.initialize(path, fsProps, DEFAULT_KEY_ID);
// 3. write vault-internal readme file: // 3. write vault-internal readme file:
@@ -13,6 +13,7 @@ public enum FxmlFile {
FORGET_PASSWORD("/fxml/forget_password.fxml"), // FORGET_PASSWORD("/fxml/forget_password.fxml"), //
HEALTH_START("/fxml/health_start.fxml"), // HEALTH_START("/fxml/health_start.fxml"), //
HEALTH_CHECK_LIST("/fxml/health_check_list.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_AUTH_FLOW("/fxml/hub_auth_flow.fxml"), //
HUB_LICENSE_EXCEEDED("/fxml/hub_license_exceeded.fxml"), // HUB_LICENSE_EXCEEDED("/fxml/hub_license_exceeded.fxml"), //
HUB_RECEIVE_KEY("/fxml/hub_receive_key.fxml"), // HUB_RECEIVE_KEY("/fxml/hub_receive_key.fxml"), //
@@ -25,6 +25,7 @@ public enum FontAwesome5Icon {
EYE_SLASH("\uF070"), // EYE_SLASH("\uF070"), //
FAST_FORWARD("\uF050"), // FAST_FORWARD("\uF050"), //
FILE("\uF15B"), // FILE("\uF15B"), //
FILE_DOWNLOAD("\uF56D"), //
FILE_IMPORT("\uF56F"), // FILE_IMPORT("\uF56F"), //
FOLDER_OPEN("\uF07C"), // FOLDER_OPEN("\uF07C"), //
FUNNEL("\uF0B0"), // FUNNEL("\uF0B0"), //
@@ -41,6 +42,7 @@ public enum FontAwesome5Icon {
PLUS("\uF067"), // PLUS("\uF067"), //
PRINT("\uF02F"), // PRINT("\uF02F"), //
QUESTION("\uF128"), // QUESTION("\uF128"), //
QUESTION_CIRCLE("\uf059"), //
REDO("\uF01E"), // REDO("\uF01E"), //
SEARCH("\uF002"), // SEARCH("\uF002"), //
SPINNER("\uF110"), // SPINNER("\uF110"), //
@@ -87,6 +87,13 @@ public abstract class HubKeyLoadingModule {
@StringKey(HubKeyLoadingStrategy.SCHEME_HUB_HTTPS) @StringKey(HubKeyLoadingStrategy.SCHEME_HUB_HTTPS)
abstract KeyLoadingStrategy bindHubKeyLoadingStrategyToHubHttps(HubKeyLoadingStrategy strategy); 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 @Provides
@FxmlScene(FxmlFile.HUB_AUTH_FLOW) @FxmlScene(FxmlFile.HUB_AUTH_FLOW)
@KeyLoadingScoped @KeyLoadingScoped
@@ -136,6 +143,11 @@ public abstract class HubKeyLoadingModule {
return fxmlLoaders.createScene(FxmlFile.HUB_UNAUTHORIZED_DEVICE); return fxmlLoaders.createScene(FxmlFile.HUB_UNAUTHORIZED_DEVICE);
} }
@Binds
@IntoMap
@FxControllerKey(NoKeychainController.class)
abstract FxController bindNoKeychainController(NoKeychainController controller);
@Binds @Binds
@IntoMap @IntoMap
@FxControllerKey(AuthFlowController.class) @FxControllerKey(AuthFlowController.class)
@@ -3,6 +3,8 @@ package org.cryptomator.ui.keyloading.hub;
import com.google.common.base.Preconditions; import com.google.common.base.Preconditions;
import com.nimbusds.jose.JWEObject; import com.nimbusds.jose.JWEObject;
import dagger.Lazy; import dagger.Lazy;
import org.cryptomator.common.keychain.KeychainManager;
import org.cryptomator.common.keychain.NoKeychainAccessProviderException;
import org.cryptomator.common.settings.DeviceKey; import org.cryptomator.common.settings.DeviceKey;
import org.cryptomator.cryptolib.api.Masterkey; import org.cryptomator.cryptolib.api.Masterkey;
import org.cryptomator.cryptolib.api.MasterkeyLoadingFailedException; import org.cryptomator.cryptolib.api.MasterkeyLoadingFailedException;
@@ -31,15 +33,19 @@ public class HubKeyLoadingStrategy implements KeyLoadingStrategy {
static final String SCHEME_HUB_HTTPS = SCHEME_PREFIX + "https"; static final String SCHEME_HUB_HTTPS = SCHEME_PREFIX + "https";
private final Stage window; private final Stage window;
private final KeychainManager keychainManager;
private final Lazy<Scene> authFlowScene; private final Lazy<Scene> authFlowScene;
private final Lazy<Scene> noKeychainScene;
private final CompletableFuture<JWEObject> result; private final CompletableFuture<JWEObject> result;
private final DeviceKey deviceKey; private final DeviceKey deviceKey;
@Inject @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.window = window;
this.keychainManager = keychainManager;
window.setTitle(windowTitle); window.setTitle(windowTitle);
this.authFlowScene = authFlowScene; this.authFlowScene = authFlowScene;
this.noKeychainScene = noKeychainScene;
this.result = result; this.result = result;
this.deviceKey = deviceKey; this.deviceKey = deviceKey;
} }
@@ -48,9 +54,16 @@ public class HubKeyLoadingStrategy implements KeyLoadingStrategy {
public Masterkey loadKey(URI keyId) throws MasterkeyLoadingFailedException { public Masterkey loadKey(URI keyId) throws MasterkeyLoadingFailedException {
Preconditions.checkArgument(keyId.getScheme().startsWith(SCHEME_PREFIX)); Preconditions.checkArgument(keyId.getScheme().startsWith(SCHEME_PREFIX));
try { try {
startAuthFlow(); if (!keychainManager.isSupported()) {
throw new NoKeychainAccessProviderException();
}
var keypair = deviceKey.get();
showWindow(authFlowScene);
var jwe = result.get(); 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) { } catch (DeviceKey.DeviceKeyRetrievalException e) {
throw new MasterkeyLoadingFailedException("Failed to load keypair", e); throw new MasterkeyLoadingFailedException("Failed to load keypair", e);
} catch (CancellationException e) { } catch (CancellationException e) {
@@ -63,9 +76,9 @@ public class HubKeyLoadingStrategy implements KeyLoadingStrategy {
} }
} }
private void startAuthFlow() { private void showWindow(Lazy<Scene> scene) {
Platform.runLater(() -> { Platform.runLater(() -> {
window.setScene(authFlowScene.get()); window.setScene(scene.get());
window.show(); window.show();
Window owner = window.getOwner(); Window owner = window.getOwner();
if (owner != null) { 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() { 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.apache.commons.lang3.SystemUtils;
import org.cryptomator.common.vaults.Vault; import org.cryptomator.common.vaults.Vault;
import org.cryptomator.common.vaults.VaultListManager; 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.common.FxController;
import org.cryptomator.ui.wrongfilealert.WrongFileAlertComponent;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import javax.inject.Inject; import javax.inject.Inject;
import javafx.beans.Observable; import javafx.beans.Observable;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.ObjectProperty; import javafx.beans.property.ObjectProperty;
import javafx.beans.property.ReadOnlyObjectProperty; import javafx.beans.property.ReadOnlyObjectProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.fxml.FXML; import javafx.fxml.FXML;
import javafx.scene.input.DragEvent;
import javafx.scene.input.TransferMode;
import javafx.scene.layout.StackPane; import javafx.scene.layout.StackPane;
import javafx.stage.Stage; 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 @MainWindowScoped
public class MainWindowController implements FxController { public class MainWindowController implements FxController {
@@ -37,28 +21,19 @@ public class MainWindowController implements FxController {
private static final Logger LOG = LoggerFactory.getLogger(MainWindowController.class); private static final Logger LOG = LoggerFactory.getLogger(MainWindowController.class);
private final Stage window; private final Stage window;
private final VaultListManager vaultListManager;
private final ReadOnlyObjectProperty<Vault> selectedVault; 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; public StackPane root;
@Inject @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.window = window;
this.vaultListManager = vaultListManager;
this.selectedVault = selectedVault; this.selectedVault = selectedVault;
this.wrongFileAlert = wrongFileAlert;
} }
@FXML @FXML
public void initialize() { public void initialize() {
LOG.trace("init MainWindowController"); 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) { if (SystemUtils.IS_OS_WINDOWS) {
root.getStyleClass().add("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; package org.cryptomator.ui.mainwindow;
import com.google.common.base.Preconditions;
import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader; import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache; import com.google.common.cache.LoadingCache;
import com.tobiasdiez.easybind.EasyBind;
import org.cryptomator.common.vaults.Vault; import org.cryptomator.common.vaults.Vault;
import org.cryptomator.common.vaults.VaultState;
import org.cryptomator.integrations.mount.Mountpoint; 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.FxController;
import org.cryptomator.ui.common.VaultService; import org.cryptomator.ui.common.VaultService;
import org.cryptomator.ui.fxapp.FxApplicationWindows; import org.cryptomator.ui.fxapp.FxApplicationWindows;
import org.cryptomator.ui.stats.VaultStatisticsComponent; 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 javax.inject.Inject;
import javafx.beans.binding.Bindings; import javafx.application.Platform;
import javafx.beans.binding.BooleanBinding; import javafx.beans.property.BooleanProperty;
import javafx.beans.binding.StringBinding;
import javafx.beans.property.ObjectProperty; import javafx.beans.property.ObjectProperty;
import javafx.beans.property.ReadOnlyObjectProperty; import javafx.beans.property.ReadOnlyObjectProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.value.ObservableValue; import javafx.beans.value.ObservableValue;
import javafx.fxml.FXML; 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 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.Optional;
import java.util.ResourceBundle;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
@MainWindowScoped @MainWindowScoped
public class VaultDetailUnlockedController implements FxController { 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 ReadOnlyObjectProperty<Vault> vault;
private final FxApplicationWindows appWindows; private final FxApplicationWindows appWindows;
private final VaultService vaultService; private final VaultService vaultService;
private final WrongFileAlertComponent.Builder wrongFileAlert;
private final Stage mainWindow; private final Stage mainWindow;
private final Optional<RevealPathService> revealPathService;
private final ResourceBundle resourceBundle;
private final LoadingCache<Vault, VaultStatisticsComponent> vaultStats; private final LoadingCache<Vault, VaultStatisticsComponent> vaultStats;
private final VaultStatisticsComponent.Builder vaultStatsBuilder; private final VaultStatisticsComponent.Builder vaultStatsBuilder;
private final ObservableValue<Mountpoint> mountPoint;
private final ObservableValue<Boolean> accessibleViaPath; private final ObservableValue<Boolean> accessibleViaPath;
private final ObservableValue<Boolean> accessibleViaUri; 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 @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.vault = vault;
this.appWindows = appWindows; this.appWindows = appWindows;
this.vaultService = vaultService; this.vaultService = vaultService;
this.wrongFileAlert = wrongFileAlert;
this.mainWindow = mainWindow; this.mainWindow = mainWindow;
this.revealPathService = revealPathService;
this.resourceBundle = resourceBundle;
this.vaultStats = CacheBuilder.newBuilder().weakValues().build(CacheLoader.from(this::buildVaultStats)); this.vaultStats = CacheBuilder.newBuilder().weakValues().build(CacheLoader.from(this::buildVaultStats));
this.vaultStatsBuilder = vaultStatsBuilder; this.vaultStatsBuilder = vaultStatsBuilder;
this.mountPoint = vault.flatMap(Vault::mountPointProperty); var mp = vault.flatMap(Vault::mountPointProperty);
this.accessibleViaPath = mountPoint.map(m -> m instanceof Mountpoint.WithPath).orElse(false); this.accessibleViaPath = mp.map(m -> m instanceof Mountpoint.WithPath).orElse(false);
this.accessibleViaUri = mountPoint.map(m -> m instanceof Mountpoint.WithUri).orElse(false); this.accessibleViaUri = mp.map(m -> m instanceof Mountpoint.WithUri).orElse(false);
this.mountUri = mountPoint.map(Mountpoint::uri).map(URI::toASCIIString).orElse(""); 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) { private VaultStatisticsComponent buildVaultStats(Vault vault) {
@@ -62,7 +128,9 @@ public class VaultDetailUnlockedController implements FxController {
@FXML @FXML
public void copyMountUri() { public void copyMountUri() {
// TODO ClipboardContent clipboardContent = new ClipboardContent();
clipboardContent.putString(mountPoint.getValue());
Clipboard.getSystemClipboard().setContent(clipboardContent);
} }
@FXML @FXML
@@ -75,6 +143,69 @@ public class VaultDetailUnlockedController implements FxController {
vaultStats.getUnchecked(vault.get()).showVaultStatisticsWindow(); 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 */ /* Getter/Setter */
public ReadOnlyObjectProperty<Vault> vaultProperty() { public ReadOnlyObjectProperty<Vault> vaultProperty() {
@@ -101,13 +232,19 @@ public class VaultDetailUnlockedController implements FxController {
return accessibleViaUri.getValue(); return accessibleViaUri.getValue();
} }
public ObservableValue<String> mountUriProperty() { public ObservableValue<String> mountPointProperty() {
return mountUri; return mountPoint;
} }
public String getMountUri() { public String getMountPoint() {
return mountUri.getValue(); 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.apache.commons.lang3.SystemUtils;
import org.cryptomator.common.vaults.Vault; import org.cryptomator.common.vaults.Vault;
import org.cryptomator.common.vaults.VaultListManager; 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.addvaultwizard.AddVaultWizardComponent;
import org.cryptomator.ui.common.FxController; import org.cryptomator.ui.common.FxController;
import org.cryptomator.ui.removevault.RemoveVaultComponent; import org.cryptomator.ui.removevault.RemoveVaultComponent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.inject.Inject; import javax.inject.Inject;
import javafx.beans.binding.Bindings; import javafx.beans.binding.Bindings;
import javafx.beans.binding.BooleanBinding; import javafx.beans.binding.BooleanBinding;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.ObjectProperty; import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.value.ObservableValue; import javafx.beans.value.ObservableValue;
import javafx.collections.ListChangeListener; import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList; import javafx.collections.ObservableList;
import javafx.fxml.FXML; import javafx.fxml.FXML;
import javafx.scene.control.ListView; import javafx.scene.control.ListView;
import javafx.scene.input.ContextMenuEvent; import javafx.scene.input.ContextMenuEvent;
import javafx.scene.input.DragEvent;
import javafx.scene.input.KeyCode; import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent; import javafx.scene.input.KeyEvent;
import javafx.scene.input.MouseEvent; import javafx.scene.input.MouseEvent;
import javafx.scene.input.TransferMode;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage; import javafx.stage.Stage;
import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.util.EnumSet; 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.ERROR;
import static org.cryptomator.common.vaults.VaultState.Value.LOCKED; import static org.cryptomator.common.vaults.VaultState.Value.LOCKED;
import static org.cryptomator.common.vaults.VaultState.Value.MISSING; import static org.cryptomator.common.vaults.VaultState.Value.MISSING;
@@ -31,6 +48,7 @@ import static org.cryptomator.common.vaults.VaultState.Value.NEEDS_MIGRATION;
@MainWindowScoped @MainWindowScoped
public class VaultListController implements FxController { public class VaultListController implements FxController {
private static final Logger LOG = LoggerFactory.getLogger(VaultListController.class);
private final Stage mainWindow; private final Stage mainWindow;
private final ObservableList<Vault> vaults; private final ObservableList<Vault> vaults;
@@ -39,17 +57,21 @@ public class VaultListController implements FxController {
private final AddVaultWizardComponent.Builder addVaultWizard; private final AddVaultWizardComponent.Builder addVaultWizard;
private final BooleanBinding emptyVaultList; private final BooleanBinding emptyVaultList;
private final RemoveVaultComponent.Builder removeVaultDialogue; private final RemoveVaultComponent.Builder removeVaultDialogue;
private final VaultListManager vaultListManager;
private final BooleanProperty draggingVaultOver = new SimpleBooleanProperty();
public ListView<Vault> vaultList; public ListView<Vault> vaultList;
public StackPane root;
@Inject @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.mainWindow = mainWindow;
this.vaults = vaults; this.vaults = vaults;
this.selectedVault = selectedVault; this.selectedVault = selectedVault;
this.cellFactory = cellFactory; this.cellFactory = cellFactory;
this.addVaultWizard = addVaultWizard; this.addVaultWizard = addVaultWizard;
this.removeVaultDialogue = removeVaultDialogue; this.removeVaultDialogue = removeVaultDialogue;
this.vaultListManager = vaultListManager;
this.emptyVaultList = Bindings.isEmpty(vaults); this.emptyVaultList = Bindings.isEmpty(vaults);
@@ -100,6 +122,11 @@ public class VaultListController implements FxController {
keyEvent.consume(); keyEvent.consume();
} }
}); });
root.setOnDragEntered(this::handleDragEvent);
root.setOnDragOver(this::handleDragEvent);
root.setOnDragDropped(this::handleDragEvent);
root.setOnDragExited(this::handleDragEvent);
} }
private void deselect(MouseEvent released) { 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 // Getter and Setter
public BooleanBinding emptyVaultListProperty() { public BooleanBinding emptyVaultListProperty() {
@@ -138,4 +206,13 @@ public class VaultListController implements FxController {
return emptyVaultList.get(); return emptyVaultList.get();
} }
public BooleanProperty draggingVaultOverProperty() {
return draggingVaultOver;
}
public boolean isDraggingVaultOver() {
return draggingVaultOver.get();
}
} }
@@ -1,11 +1,14 @@
package org.cryptomator.ui.preferences; package org.cryptomator.ui.preferences;
import dagger.Lazy;
import org.cryptomator.common.ObservableUtil;
import org.cryptomator.common.settings.Settings; import org.cryptomator.common.settings.Settings;
import org.cryptomator.integrations.mount.MountCapability; import org.cryptomator.integrations.mount.MountCapability;
import org.cryptomator.integrations.mount.MountService; import org.cryptomator.integrations.mount.MountService;
import org.cryptomator.ui.common.FxController; import org.cryptomator.ui.common.FxController;
import javax.inject.Inject; import javax.inject.Inject;
import javafx.application.Application;
import javafx.beans.binding.Bindings; import javafx.beans.binding.Bindings;
import javafx.beans.binding.BooleanExpression; import javafx.beans.binding.BooleanExpression;
import javafx.beans.value.ObservableValue; import javafx.beans.value.ObservableValue;
@@ -14,39 +17,58 @@ import javafx.scene.control.ChoiceBox;
import javafx.scene.control.TextField; import javafx.scene.control.TextField;
import javafx.util.StringConverter; import javafx.util.StringConverter;
import java.util.List; 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 @PreferencesScoped
public class VolumePreferencesController implements FxController { 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 Settings settings;
private final ObservableValue<MountService> selectedMountService; private final ObservableValue<MountService> selectedMountService;
private final ResourceBundle resourceBundle;
private final BooleanExpression loopbackPortSupported; 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; private final List<MountService> mountProviders;
public ChoiceBox<MountService> volumeTypeChoiceBox; public ChoiceBox<MountService> volumeTypeChoiceBox;
public TextField loopbackPortField; public TextField loopbackPortField;
public Button loopbackPortApplyButton; public Button loopbackPortApplyButton;
@Inject @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.settings = settings;
this.application = application;
this.mountProviders = mountProviders; 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.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() { public void initialize() {
volumeTypeChoiceBox.getItems().add(null);
volumeTypeChoiceBox.getItems().addAll(mountProviders); volumeTypeChoiceBox.getItems().addAll(mountProviders);
volumeTypeChoiceBox.setConverter(new MountServiceConverter()); volumeTypeChoiceBox.setConverter(new MountServiceConverter());
volumeTypeChoiceBox.getSelectionModel().select(selectedMountService.getValue()); boolean autoSelected = settings.mountService().get() == null;
volumeTypeChoiceBox.valueProperty().addListener((observableValue, oldProvide, newProvider) -> settings.mountService().set(newProvider.getClass().getName())); 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())); loopbackPortField.setText(String.valueOf(settings.port().get()));
loopbackPortApplyButton.visibleProperty().bind(settings.port().asString().isNotEqualTo(loopbackPortField.textProperty())); loopbackPortApplyButton.visibleProperty().bind(settings.port().asString().isNotEqualTo(loopbackPortField.textProperty()));
loopbackPortApplyButton.disableProperty().bind(Bindings.createBooleanBinding(this::validateLoopbackPort, loopbackPortField.textProperty()).not()); loopbackPortApplyButton.disableProperty().bind(Bindings.createBooleanBinding(this::validateLoopbackPort, loopbackPortField.textProperty()).not());
} }
private boolean validateLoopbackPort() { private boolean validateLoopbackPort() {
@@ -75,13 +97,49 @@ public class VolumePreferencesController implements FxController {
return loopbackPortSupported.get(); 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 */ /* Helpers */
private static class MountServiceConverter extends StringConverter<MountService> { private class MountServiceConverter extends StringConverter<MountService> {
@Override @Override
public String toString(MountService provider) { 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 @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 @Override
public void showTrayIcon(byte[] rawImageData, Runnable defaultAction, String tooltip) throws TrayMenuException { public void showTrayIcon(byte[] imageData, Runnable defaultAction, String tooltip) throws TrayMenuException {
var image = Toolkit.getDefaultToolkit().createImage(rawImageData); var image = Toolkit.getDefaultToolkit().createImage(imageData);
trayIcon = new TrayIcon(image, tooltip, menu); trayIcon = new TrayIcon(image, tooltip, menu);
trayIcon.setImageAutoSize(true); 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 @Override
public void updateTrayMenu(List<TrayMenuItem> items) { public void updateTrayMenu(List<TrayMenuItem> items) {
menu.removeAll(); menu.removeAll();
@@ -67,7 +76,7 @@ public class AwtTrayMenuController implements TrayMenuController {
Preconditions.checkNotNull(this.trayIcon); Preconditions.checkNotNull(this.trayIcon);
this.trayIcon.addMouseListener(new MouseAdapter() { this.trayIcon.addMouseListener(new MouseAdapter() {
@Override @Override
public void mouseClicked(MouseEvent e) { public void mousePressed(MouseEvent e) {
listener.run(); listener.run();
} }
}); });
@@ -33,7 +33,9 @@ public class TrayMenuBuilder {
private static final Logger LOG = LoggerFactory.getLogger(TrayMenuBuilder.class); 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_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 ResourceBundle resourceBundle;
private final VaultService vaultService; private final VaultService vaultService;
@@ -62,8 +64,8 @@ public class TrayMenuBuilder {
v.displayNameProperty().addListener(this::vaultListChanged); v.displayNameProperty().addListener(this::vaultListChanged);
}); });
try (var image = getClass().getResourceAsStream(SystemUtils.IS_OS_MAC_OSX ? TRAY_ICON_MAC : TRAY_ICON)) { try {
trayMenu.showTrayIcon(image.readAllBytes(), this::showMainWindow, "Cryptomator"); trayMenu.showTrayIcon(getAppropriateTrayIconImage(), this::showMainWindow, "Cryptomator");
trayMenu.onBeforeOpenMenu(() -> { trayMenu.onBeforeOpenMenu(() -> {
for (Vault vault : vaults) { for (Vault vault : vaults) {
VaultListManager.redetermineVaultState(vault); VaultListManager.redetermineVaultState(vault);
@@ -71,8 +73,6 @@ public class TrayMenuBuilder {
}); });
rebuildMenu(); rebuildMenu();
initialized = true; initialized = true;
} catch (IOException e) {
throw new UncheckedIOException("Failed to load embedded resource", e);
} catch (TrayMenuException e) { } catch (TrayMenuException e) {
LOG.error("Adding tray icon failed", e); LOG.error("Adding tray icon failed", e);
} }
@@ -84,6 +84,7 @@ public class TrayMenuBuilder {
private void vaultListChanged(@SuppressWarnings("unused") Observable observable) { private void vaultListChanged(@SuppressWarnings("unused") Observable observable) {
assert Platform.isFxApplicationThread(); assert Platform.isFxApplicationThread();
trayMenu.updateTrayIcon(getAppropriateTrayIconImage());
rebuildMenu(); rebuildMenu();
} }
@@ -154,4 +155,22 @@ public class TrayMenuBuilder {
appWindows.showPreferencesWindow(SelectedPreferencesTab.ANY); 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; 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.common.vaults.Vault;
import org.cryptomator.ui.common.FxController; 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 javax.inject.Inject;
import javafx.fxml.FXML; import javafx.fxml.FXML;
import javafx.stage.Stage; 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. //At the current point in time only the CustomMountPointChooser may cause this window to be shown.
@UnlockScoped @UnlockScoped
@@ -13,11 +20,32 @@ public class UnlockInvalidMountPointController implements FxController {
private final Stage window; private final Stage window;
private final Vault vault; private final Vault vault;
private final AtomicReference<Throwable> unlockException;
private final FxApplicationWindows appWindows;
private final ResourceBundle resourceBundle;
public FormattedLabel dialogDescription;
@Inject @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.window = window;
this.vault = vault; 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 @FXML
@@ -25,4 +53,10 @@ public class UnlockInvalidMountPointController implements FxController {
window.close(); 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 javafx.stage.Stage;
import java.util.Map; import java.util.Map;
import java.util.ResourceBundle; import java.util.ResourceBundle;
import java.util.concurrent.atomic.AtomicReference;
@Module(subcomponents = {KeyLoadingComponent.class}) @Module(subcomponents = {KeyLoadingComponent.class})
abstract class UnlockModule { abstract class UnlockModule {
@@ -57,6 +58,13 @@ abstract class UnlockModule {
return compBuilder.vault(vault).window(window).build().keyloadingStrategy(); return compBuilder.vault(vault).window(window).build().keyloadingStrategy();
} }
@Provides
@UnlockWindow
@UnlockScoped
static AtomicReference<Throwable> unlockException() {
return new AtomicReference<>();
}
@Provides @Provides
@FxmlScene(FxmlFile.UNLOCK_SUCCESS) @FxmlScene(FxmlFile.UNLOCK_SUCCESS)
@UnlockScoped @UnlockScoped
@@ -2,6 +2,7 @@ package org.cryptomator.ui.unlock;
import com.google.common.base.Throwables; import com.google.common.base.Throwables;
import dagger.Lazy; import dagger.Lazy;
import org.cryptomator.common.mount.IllegalMountPointException;
import org.cryptomator.common.vaults.Vault; import org.cryptomator.common.vaults.Vault;
import org.cryptomator.common.vaults.VaultState; import org.cryptomator.common.vaults.VaultState;
import org.cryptomator.cryptolib.api.CryptoException; import org.cryptomator.cryptolib.api.CryptoException;
@@ -20,6 +21,7 @@ import javafx.concurrent.Task;
import javafx.scene.Scene; import javafx.scene.Scene;
import javafx.stage.Stage; import javafx.stage.Stage;
import java.io.IOException; import java.io.IOException;
import java.util.concurrent.atomic.AtomicReference;
/** /**
* A multi-step task that consists of background activities as well as user interaction. * 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 Lazy<Scene> invalidMountPointScene;
private final FxApplicationWindows appWindows; private final FxApplicationWindows appWindows;
private final KeyLoadingStrategy keyLoadingStrategy; private final KeyLoadingStrategy keyLoadingStrategy;
private final AtomicReference<Throwable> unlockFailedException;
@Inject @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.window = window;
this.vault = vault; this.vault = vault;
this.vaultService = vaultService; this.vaultService = vaultService;
@@ -48,6 +51,7 @@ public class UnlockWorkflow extends Task<Boolean> {
this.invalidMountPointScene = invalidMountPointScene; this.invalidMountPointScene = invalidMountPointScene;
this.appWindows = appWindows; this.appWindows = appWindows;
this.keyLoadingStrategy = keyLoadingStrategy; this.keyLoadingStrategy = keyLoadingStrategy;
this.unlockFailedException = unlockFailedException;
} }
@Override @Override
@@ -67,13 +71,15 @@ public class UnlockWorkflow extends Task<Boolean> {
} catch (Exception e) { } catch (Exception e) {
Throwables.propagateIfPossible(e, IOException.class); Throwables.propagateIfPossible(e, IOException.class);
Throwables.propagateIfPossible(e, CryptoException.class); Throwables.propagateIfPossible(e, CryptoException.class);
Throwables.propagateIfPossible(e, IllegalMountPointException.class);
Throwables.propagateIfPossible(e, MountFailedException.class); Throwables.propagateIfPossible(e, MountFailedException.class);
throw new IllegalStateException("unexpected exception type", e); throw new IllegalStateException("unexpected exception type", e);
} }
} }
private void showInvalidMountPointScene() { private void handleIllegalMountPointError(IllegalMountPointException impe) {
Platform.runLater(() -> { Platform.runLater(() -> {
unlockFailedException.set(impe);
window.setScene(invalidMountPointScene.get()); window.setScene(invalidMountPointScene.get());
window.show(); window.show();
}); });
@@ -107,7 +113,11 @@ public class UnlockWorkflow extends Task<Boolean> {
protected void failed() { protected void failed() {
LOG.info("Unlock of '{}' failed.", vault.getDisplayName()); LOG.info("Unlock of '{}' failed.", vault.getDisplayName());
Throwable throwable = super.getException(); 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); vault.stateProperty().transition(VaultState.Value.PROCESSING, VaultState.Value.LOCKED);
} }
@@ -1,11 +1,14 @@
package org.cryptomator.ui.vaultoptions; 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.mount.WindowsDriveLetters;
import org.cryptomator.common.settings.VaultSettings;
import org.cryptomator.common.vaults.Vault; import org.cryptomator.common.vaults.Vault;
import org.cryptomator.integrations.mount.MountCapability; import org.cryptomator.integrations.mount.MountCapability;
import org.cryptomator.integrations.mount.MountService;
import org.cryptomator.ui.common.FxController; import org.cryptomator.ui.common.FxController;
import org.cryptomator.ui.fxapp.FxApplicationWindows;
import org.cryptomator.ui.preferences.SelectedPreferencesTab;
import javax.inject.Inject; import javax.inject.Inject;
import javafx.beans.value.ObservableValue; import javafx.beans.value.ObservableValue;
@@ -30,16 +33,17 @@ import java.util.Set;
public class MountOptionsController implements FxController { public class MountOptionsController implements FxController {
private final Stage window; private final Stage window;
private final Vault vault; private final VaultSettings vaultSettings;
private final WindowsDriveLetters windowsDriveLetters; private final WindowsDriveLetters windowsDriveLetters;
private final ResourceBundle resourceBundle; private final ResourceBundle resourceBundle;
private final ObservableValue<String> defaultMountFlags;
private final ObservableValue<Boolean> mountpointDirSupported; private final ObservableValue<Boolean> mountpointDirSupported;
private final ObservableValue<Boolean> mountpointDriveLetterSupported; private final ObservableValue<Boolean> mountpointDriveLetterSupported;
private final ObservableValue<Boolean> readOnlySupported; private final ObservableValue<Boolean> readOnlySupported;
private final ObservableValue<Boolean> mountFlagsSupported; private final ObservableValue<Boolean> mountFlagsSupported;
private final ObservableValue<Path> driveLetter;
private final ObservableValue<String> directoryPath; private final ObservableValue<String> directoryPath;
private final FxApplicationWindows applicationWindows;
//-- FXML objects -- //-- FXML objects --
@@ -54,59 +58,75 @@ public class MountOptionsController implements FxController {
public ChoiceBox<Path> driveLetterSelection; public ChoiceBox<Path> driveLetterSelection;
@Inject @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.window = window;
this.vault = vault; this.vaultSettings = vault.getVaultSettings();
this.windowsDriveLetters = windowsDriveLetters; this.windowsDriveLetters = windowsDriveLetters;
this.resourceBundle = resourceBundle; this.resourceBundle = resourceBundle;
this.mountpointDirSupported = mountService.map(s -> s.hasCapability(MountCapability.MOUNT_TO_EXISTING_DIR) || s.hasCapability(MountCapability.MOUNT_WITHIN_EXISTING_PARENT)); this.defaultMountFlags = mountService.map(as -> {
this.mountpointDriveLetterSupported = mountService.map(s -> s.hasCapability(MountCapability.MOUNT_AS_DRIVE_LETTER)); if (as.service().hasCapability(MountCapability.MOUNT_FLAGS)) {
this.mountFlagsSupported = mountService.map(s -> s.hasCapability(MountCapability.MOUNT_FLAGS)); return as.service().getDefaultMountFlags();
this.readOnlySupported = mountService.map(s -> s.hasCapability(MountCapability.READ_ONLY)); } else {
this.driveLetter = vault.getVaultSettings().mountPoint().map(p -> isDriveLetter(p) ? p : null); 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.directoryPath = vault.getVaultSettings().mountPoint().map(p -> isDriveLetter(p) ? null : p.toString());
this.applicationWindows = applicationWindows;
} }
@FXML @FXML
public void initialize() { public void initialize() {
// readonly: // readonly:
readOnlyCheckbox.selectedProperty().bindBidirectional(vault.getVaultSettings().usesReadOnlyMode()); readOnlyCheckbox.selectedProperty().bindBidirectional(vaultSettings.usesReadOnlyMode());
// custom mount flags: // custom mount flags:
mountFlagsField.disableProperty().bind(customMountFlagsCheckbox.selectedProperty().not()); mountFlagsField.disableProperty().bind(customMountFlagsCheckbox.selectedProperty().not());
customMountFlagsCheckbox.setSelected(vault.isHavingCustomMountFlags()); customMountFlagsCheckbox.setSelected(!Strings.isNullOrEmpty(vaultSettings.mountFlags().getValue()));
toggleUseCustomMountFlags();
//driveLetter choice box //driveLetter choice box
driveLetterSelection.getItems().addAll(windowsDriveLetters.getAll()); driveLetterSelection.getItems().addAll(windowsDriveLetters.getAll());
driveLetterSelection.setConverter(new WinDriveLetterLabelConverter(windowsDriveLetters, resourceBundle)); driveLetterSelection.setConverter(new WinDriveLetterLabelConverter(windowsDriveLetters, resourceBundle));
driveLetterSelection.setOnShowing(event -> driveLetterSelection.setConverter(new WinDriveLetterLabelConverter(windowsDriveLetters, resourceBundle))); //TODO: does this work?
//mountPoint toggle group //mountPoint toggle group
var mountPoint = vault.getVaultSettings().getMountPoint(); var mountPoint = vaultSettings.getMountPoint();
if (mountPoint == null) { if (mountPoint == null) {
//prepare and select auto //prepare and select auto
mountPointToggleGroup.selectToggle(mountPointAutoBtn); mountPointToggleGroup.selectToggle(mountPointAutoBtn);
} else if (mountPoint.getParent() == null && isDriveLetter(mountPoint)) { } else if (mountPoint.getParent() == null && isDriveLetter(mountPoint)) {
//prepare and select drive letter //prepare and select drive letter
mountPointToggleGroup.selectToggle(mountPointDriveLetterBtn); mountPointToggleGroup.selectToggle(mountPointDriveLetterBtn);
} else if (driveLetterSelection.getValue() == null) { driveLetterSelection.valueProperty().bindBidirectional(vaultSettings.mountPoint());
} else {
//prepare and select dir //prepare and select dir
mountPointToggleGroup.selectToggle(mountPointDirBtn); mountPointToggleGroup.selectToggle(mountPointDirBtn);
} }
mountPointToggleGroup.selectedToggleProperty().addListener(this::selectedToggleChanged); mountPointToggleGroup.selectedToggleProperty().addListener(this::selectedToggleChanged);
} }
@FXML
public void openVolumePreferences() {
applicationWindows.showPreferencesWindow(SelectedPreferencesTab.VOLUME);
}
@FXML @FXML
public void toggleUseCustomMountFlags() { public void toggleUseCustomMountFlags() {
if (customMountFlagsCheckbox.isSelected()) { if (customMountFlagsCheckbox.isSelected()) {
readOnlyCheckbox.setSelected(false); // to prevent invalid states readOnlyCheckbox.setSelected(false); // to prevent invalid states
mountFlagsField.textProperty().unbind(); mountFlagsField.textProperty().unbind();
vault.setCustomMountFlags(vault.defaultMountFlagsProperty().getValue()); var mountFlags = vaultSettings.mountFlags().get();
mountFlagsField.textProperty().bindBidirectional(vault.getVaultSettings().mountFlags()); if (mountFlags == null || mountFlags.isBlank()) {
vaultSettings.mountFlags().set(defaultMountFlags.getValue());
}
mountFlagsField.textProperty().bindBidirectional(vaultSettings.mountFlags());
} else { } else {
mountFlagsField.textProperty().unbindBidirectional(vault.getVaultSettings().mountFlags()); mountFlagsField.textProperty().unbindBidirectional(vaultSettings.mountFlags());
vault.setCustomMountFlags(null); vaultSettings.mountFlags().set(null);
mountFlagsField.textProperty().bind(vault.defaultMountFlagsProperty()); mountFlagsField.textProperty().bind(defaultMountFlags);
} }
} }
@@ -114,7 +134,7 @@ public class MountOptionsController implements FxController {
public void chooseCustomMountPoint() { public void chooseCustomMountPoint() {
try { try {
Path chosenPath = chooseCustomMountPointInternal(); Path chosenPath = chooseCustomMountPointInternal();
vault.getVaultSettings().mountPoint().set(chosenPath); vaultSettings.mountPoint().set(chosenPath);
} catch (NoDirSelectedException e) { } catch (NoDirSelectedException e) {
//no-op //no-op
} }
@@ -131,7 +151,7 @@ public class MountOptionsController implements FxController {
DirectoryChooser directoryChooser = new DirectoryChooser(); DirectoryChooser directoryChooser = new DirectoryChooser();
directoryChooser.setTitle(resourceBundle.getString("vaultOptions.mount.mountPoint.directoryPickerTitle")); directoryChooser.setTitle(resourceBundle.getString("vaultOptions.mount.mountPoint.directoryPickerTitle"));
try { 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")); var initialDir = mp != null && !isDriveLetter(mp) ? mp : Path.of(System.getProperty("user.home"));
if (Files.isDirectory(initialDir)) { if (Files.isDirectory(initialDir)) {
@@ -149,27 +169,30 @@ public class MountOptionsController implements FxController {
} }
private void selectedToggleChanged(ObservableValue<? extends Toggle> observable, Toggle oldToggle, Toggle newToggle) { private void selectedToggleChanged(ObservableValue<? extends Toggle> observable, Toggle oldToggle, Toggle newToggle) {
Path mountPointToBe = null; //Remark: the mountpoint corresponding to the newToggle must be null, otherwise it would not be new!
try { driveLetterSelection.valueProperty().unbindBidirectional(vaultSettings.mountPoint());
//Remark: the mountpoint corresponding to the newToggle must be null, otherwise it would not be new! if (mountPointDriveLetterBtn.equals(newToggle)) {
if (mountPointDriveLetterBtn.equals(newToggle)) { vaultSettings.mountPoint().set(windowsDriveLetters.getFirstDesiredAvailable().orElse(windowsDriveLetters.getAll().stream().findAny().get()));
mountPointToBe = driveLetterSelection.getItems().get(0); driveLetterSelection.valueProperty().bindBidirectional(vaultSettings.mountPoint());
} else if (mountPointDirBtn.equals(newToggle)) { } else if (mountPointDirBtn.equals(newToggle)) {
mountPointToBe = chooseCustomMountPointInternal(); try {
} vaultSettings.mountPoint().set(chooseCustomMountPointInternal());
vault.getVaultSettings().mountPoint().set(mountPointToBe); } catch (NoDirSelectedException e) {
} catch (NoDirSelectedException e) { if (oldToggle != null && !mountPointDirBtn.equals(oldToggle)) {
if (!mountPointDirBtn.equals(oldToggle)) { mountPointToggleGroup.selectToggle(oldToggle);
mountPointToggleGroup.selectToggle(oldToggle); } else {
mountPointToggleGroup.selectToggle(mountPointAutoBtn);
}
} }
} else {
vaultSettings.mountPoint().set(null);
} }
} }
private boolean isDriveLetter(Path mountPoint) { private boolean isDriveLetter(Path mountPoint) {
if (mountPoint != null) { if (mountPoint != null) {
var s = mountPoint.toString(); var s = mountPoint.toString();
return s.length() == 3 && mountPoint.toString().endsWith(":\\"); return s.length() == 3 && s.endsWith(":\\");
} }
return false; return false;
} }
@@ -237,21 +260,13 @@ public class MountOptionsController implements FxController {
} }
public ObservableValue<Boolean> readOnlySupportedProperty() { public ObservableValue<Boolean> readOnlySupportedProperty() {
return mountpointDriveLetterSupported; return readOnlySupported;
} }
public boolean isReadOnlySupported() { public boolean isReadOnlySupported() {
return readOnlySupported.getValue(); return readOnlySupported.getValue();
} }
public ObservableValue<Path> driveLetterProperty() {
return driveLetter;
}
public Path getDriveLetter() {
return driveLetter.getValue();
}
public ObservableValue<String> directoryPathProperty() { public ObservableValue<String> directoryPathProperty() {
return directoryPath; return directoryPath;
} }
@@ -259,5 +274,4 @@ public class MountOptionsController implements FxController {
public String getDirectoryPath() { public String getDirectoryPath() {
return directoryPath.getValue(); 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); -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 * * TabPane *
@@ -884,3 +874,51 @@
-fx-fill: linear-gradient(to bottom, PRIMARY, transparent); -fx-fill: linear-gradient(to bottom, PRIMARY, transparent);
-fx-stroke: 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); -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 * * TabPane *
@@ -883,3 +873,51 @@
-fx-fill: linear-gradient(to bottom, PRIMARY, transparent); -fx-fill: linear-gradient(to bottom, PRIMARY, transparent);
-fx-stroke: 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"?> <?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.control.SplitPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.Region?>
<?import javafx.scene.layout.StackPane?> <?import javafx.scene.layout.StackPane?>
<?import javafx.scene.layout.VBox?> <?import javafx.scene.layout.VBox?>
<StackPane xmlns:fx="http://javafx.com/fxml" <StackPane xmlns:fx="http://javafx.com/fxml"
@@ -14,24 +10,10 @@
styleClass="main-window"> styleClass="main-window">
<VBox minWidth="650"> <VBox minWidth="650">
<fx:include source="main_window_title.fxml" VBox.vgrow="NEVER"/> <fx:include source="main_window_title.fxml" VBox.vgrow="NEVER"/>
<StackPane VBox.vgrow="ALWAYS"> <SplitPane dividerPositions="0.33" orientation="HORIZONTAL" VBox.vgrow="ALWAYS">
<SplitPane dividerPositions="0.33" orientation="HORIZONTAL"> <fx:include source="vault_list.fxml" SplitPane.resizableWithParent="false"/>
<fx:include source="vault_list.fxml" SplitPane.resizableWithParent="false"/> <fx:include source="vault_detail.fxml" SplitPane.resizableWithParent="true"/>
<fx:include source="vault_detail.fxml" SplitPane.resizableWithParent="true"/> </SplitPane>
</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>
</VBox> </VBox>
<fx:include source="main_window_resize.fxml"/> <fx:include source="main_window_resize.fxml"/>
</StackPane> </StackPane>
+46 -8
View File
@@ -6,16 +6,20 @@
<?import javafx.scene.control.Button?> <?import javafx.scene.control.Button?>
<?import javafx.scene.control.ButtonBar?> <?import javafx.scene.control.ButtonBar?>
<?import javafx.scene.control.CheckBox?> <?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.HBox?>
<?import javafx.scene.layout.StackPane?> <?import javafx.scene.layout.StackPane?>
<?import javafx.scene.layout.Region?>
<?import javafx.scene.layout.RowConstraints?>
<?import javafx.scene.layout.VBox?> <?import javafx.scene.layout.VBox?>
<?import javafx.scene.shape.Circle?> <?import javafx.scene.shape.Circle?>
<VBox xmlns:fx="http://javafx.com/fxml" <VBox xmlns:fx="http://javafx.com/fxml"
xmlns="http://javafx.com/javafx" xmlns="http://javafx.com/javafx"
fx:controller="org.cryptomator.ui.migration.MigrationStartController" fx:controller="org.cryptomator.ui.migration.MigrationStartController"
minWidth="400" prefWidth="580"
maxWidth="400" prefHeight="350"
minHeight="145"
spacing="12"> spacing="12">
<padding> <padding>
<Insets topRightBottomLeft="12"/> <Insets topRightBottomLeft="12"/>
@@ -23,13 +27,47 @@
<children> <children>
<HBox spacing="12" alignment="CENTER_LEFT" VBox.vgrow="ALWAYS"> <HBox spacing="12" alignment="CENTER_LEFT" VBox.vgrow="ALWAYS">
<StackPane alignment="CENTER" HBox.hgrow="NEVER"> <StackPane alignment="CENTER" HBox.hgrow="NEVER">
<Circle styleClass="glyph-icon-primary" radius="24"/> <padding>
<FontAwesome5IconView styleClass="glyph-icon-white" glyph="FILE_IMPORT" glyphSize="24"/> <Insets left="12"/>
</padding>
<Circle styleClass="glyph-icon-primary" radius="48"/>
<FontAwesome5IconView styleClass="glyph-icon-white" glyph="FILE_IMPORT" glyphSize="48"/>
</StackPane> </StackPane>
<VBox spacing="6" HBox.hgrow="ALWAYS"> <VBox HBox.hgrow="ALWAYS" alignment="CENTER">
<FormattedLabel format="%migration.start.prompt" arg1="${controller.vault.displayName}" wrapText="true"/> <padding>
<CheckBox fx:id="confirmSyncDone" text="%migration.start.confirm"/> <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> </VBox>
</HBox> </HBox>
@@ -22,7 +22,7 @@
</ImageView> </ImageView>
<VBox spacing="3" HBox.hgrow="ALWAYS" alignment="CENTER_LEFT"> <VBox spacing="3" HBox.hgrow="ALWAYS" alignment="CENTER_LEFT">
<FormattedLabel styleClass="label-extra-large" format="Cryptomator %s" arg1="${controller.fullApplicationVersion}"/> <FormattedLabel styleClass="label-extra-large" format="Cryptomator %s" arg1="${controller.fullApplicationVersion}"/>
<Label text="© 2016 2022 Skymatic GmbH"/> <Label text="© 2016 2023 Skymatic GmbH"/>
</VBox> </VBox>
</HBox> </HBox>
@@ -1,12 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<?import org.cryptomator.ui.controls.FontAwesome5IconView?>
<?import org.cryptomator.ui.controls.NumericTextField?> <?import org.cryptomator.ui.controls.NumericTextField?>
<?import javafx.geometry.Insets?> <?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?> <?import javafx.scene.control.Button?>
<?import javafx.scene.control.ChoiceBox?> <?import javafx.scene.control.ChoiceBox?>
<?import javafx.scene.control.Hyperlink?>
<?import javafx.scene.control.Label?> <?import javafx.scene.control.Label?>
<?import javafx.scene.control.Separator?>
<?import javafx.scene.layout.HBox?> <?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.VBox?> <?import javafx.scene.layout.VBox?>
<?import javafx.scene.control.Tooltip?>
<VBox xmlns:fx="http://javafx.com/fxml" <VBox xmlns:fx="http://javafx.com/fxml"
xmlns="http://javafx.com/javafx" xmlns="http://javafx.com/javafx"
fx:controller="org.cryptomator.ui.preferences.VolumePreferencesController" fx:controller="org.cryptomator.ui.preferences.VolumePreferencesController"
@@ -18,12 +22,51 @@
<HBox spacing="12" alignment="CENTER_LEFT"> <HBox spacing="12" alignment="CENTER_LEFT">
<Label text="%preferences.volume.type"/> <Label text="%preferences.volume.type"/>
<ChoiceBox fx:id="volumeTypeChoiceBox"/> <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>
<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"/> <Label text="%preferences.volume.tcp.port"/>
<NumericTextField fx:id="loopbackPortField"/> <NumericTextField fx:id="loopbackPortField"/>
<Button text="%generic.button.apply" fx:id="loopbackPortApplyButton" onAction="#doChangeLoopbackPort"/> <Button text="%generic.button.apply" fx:id="loopbackPortApplyButton" onAction="#doChangeLoopbackPort"/>
</HBox> </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> </children>
</VBox> </VBox>
@@ -34,16 +34,19 @@
</StackPane> </StackPane>
</Group> </Group>
<VBox HBox.hgrow="ALWAYS"> <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> <padding>
<Insets bottom="6" top="6"/> <Insets bottom="6" top="6"/>
</padding> </padding>
</Label> </Label>
<FormattedLabel fx:id="dialogDescription" wrapText="true" textAlignment="LEFT"/>
<Region VBox.vgrow="ALWAYS" minHeight="18"/> <Region VBox.vgrow="ALWAYS" minHeight="18"/>
<ButtonBar buttonMinWidth="120" buttonOrder="+C"> <ButtonBar buttonMinWidth="120" buttonOrder="+CI">
<buttons> <buttons>
<Button text="%generic.button.cancel" ButtonBar.buttonData="CANCEL_CLOSE" cancelButton="true" onAction="#close"/> <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> </buttons>
</ButtonBar> </ButtonBar>
</VBox> </VBox>
@@ -2,10 +2,11 @@
<?import org.cryptomator.ui.controls.ThroughputLabel?> <?import org.cryptomator.ui.controls.ThroughputLabel?>
<?import javafx.scene.control.Button?> <?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?> <?import javafx.scene.control.Label?>
<?import javafx.scene.control.Tooltip?>
<?import javafx.scene.layout.HBox?> <?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.Region?> <?import javafx.scene.layout.Region?>
<?import javafx.scene.layout.VBox?> <?import javafx.scene.layout.VBox?>
<?import javafx.scene.control.Tooltip?>
<?import javafx.geometry.Insets?>
<VBox xmlns:fx="http://javafx.com/fxml" <VBox xmlns:fx="http://javafx.com/fxml"
xmlns="http://javafx.com/javafx" xmlns="http://javafx.com/javafx"
fx:controller="org.cryptomator.ui.mainwindow.VaultDetailUnlockedController" fx:controller="org.cryptomator.ui.mainwindow.VaultDetailUnlockedController"
@@ -18,6 +19,7 @@
<FontAwesome5IconView glyph="HDD" glyphSize="24"/> <FontAwesome5IconView glyph="HDD" glyphSize="24"/>
<VBox spacing="4" alignment="CENTER_LEFT"> <VBox spacing="4" alignment="CENTER_LEFT">
<Label text="%main.vaultDetail.revealBtn"/> <Label text="%main.vaultDetail.revealBtn"/>
<Label styleClass="label-extra-small" text="${controller.mountPoint}" textOverrun="CENTER_ELLIPSIS"/>
</VBox> </VBox>
</HBox> </HBox>
</graphic> </graphic>
@@ -27,8 +29,8 @@
<HBox spacing="12" alignment="CENTER"> <HBox spacing="12" alignment="CENTER">
<FontAwesome5IconView glyph="LINK" glyphSize="24"/> <FontAwesome5IconView glyph="LINK" glyphSize="24"/>
<VBox spacing="4" alignment="CENTER_LEFT"> <VBox spacing="4" alignment="CENTER_LEFT">
<Label text="%generic.button.copy"/> <!-- TODO --> <Label text="%main.vaultDetail.copyUri"/>
<Label styleClass="label-extra-small" text="${controller.mountUri}" textOverrun="CENTER_ELLIPSIS"/> <Label styleClass="label-extra-small" text="${controller.mountPoint}" textOverrun="CENTER_ELLIPSIS"/>
</VBox> </VBox>
</HBox> </HBox>
</graphic> </graphic>
@@ -41,7 +43,28 @@
<Region VBox.vgrow="ALWAYS"/> <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"> <Button text="%main.vaultDetail.stats" minWidth="120" onAction="#showVaultStatistics" contentDisplay="BOTTOM">
<graphic> <graphic>
<VBox spacing="6"> <VBox spacing="6">
+26 -22
View File
@@ -8,25 +8,29 @@
<?import javafx.scene.layout.StackPane?> <?import javafx.scene.layout.StackPane?>
<?import javafx.scene.layout.VBox?> <?import javafx.scene.layout.VBox?>
<?import javafx.scene.shape.Arc?> <?import javafx.scene.shape.Arc?>
<VBox xmlns:fx="http://javafx.com/fxml" <StackPane xmlns:fx="http://javafx.com/fxml"
xmlns="http://javafx.com/javafx" xmlns="http://javafx.com/javafx"
fx:controller="org.cryptomator.ui.mainwindow.VaultListController" fx:id="root"
minWidth="206"> fx:controller="org.cryptomator.ui.mainwindow.VaultListController"
<StackPane VBox.vgrow="ALWAYS"> minWidth="206">
<ListView fx:id="vaultList" editable="true" fixedCellSize="60"> <VBox>
<contextMenu> <StackPane VBox.vgrow="ALWAYS">
<fx:include source="vault_list_contextmenu.fxml"/> <ListView fx:id="vaultList" editable="true" fixedCellSize="60">
</contextMenu> <contextMenu>
</ListView> <fx:include source="vault_list_contextmenu.fxml"/>
<VBox visible="${controller.emptyVaultList}" spacing="6" alignment="CENTER"> </contextMenu>
<Region VBox.vgrow="ALWAYS"/> </ListView>
<Label VBox.vgrow="NEVER" text="%main.vaultlist.emptyList.onboardingInstruction" textAlignment="CENTER" wrapText="true"/> <VBox visible="${controller.emptyVaultList}" spacing="6" alignment="CENTER">
<Arc VBox.vgrow="NEVER" styleClass="onboarding-overlay-arc" type="OPEN" centerX="50" centerY="0" radiusY="100" radiusX="50" startAngle="0" length="-60" strokeWidth="1"/> <Region VBox.vgrow="ALWAYS"/>
</VBox> <Label VBox.vgrow="NEVER" text="%main.vaultlist.emptyList.onboardingInstruction" textAlignment="CENTER" wrapText="true"/>
</StackPane> <Arc VBox.vgrow="NEVER" styleClass="onboarding-overlay-arc" type="OPEN" centerX="50" centerY="0" radiusY="100" radiusX="50" startAngle="0" length="-60" strokeWidth="1"/>
<Button styleClass="toolbar-button" text="%main.vaultlist.addVaultBtn" onAction="#didClickAddVault" alignment="BASELINE_CENTER" maxWidth="Infinity"> </VBox>
<graphic> </StackPane>
<FontAwesome5IconView glyph="PLUS"/> <Button styleClass="toolbar-button" text="%main.vaultlist.addVaultBtn" onAction="#didClickAddVault" alignment="BASELINE_CENTER" maxWidth="Infinity">
</graphic> <graphic>
</Button> <FontAwesome5IconView glyph="PLUS"/>
</VBox> </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.Button?>
<?import javafx.scene.control.CheckBox?> <?import javafx.scene.control.CheckBox?>
<?import javafx.scene.control.ChoiceBox?> <?import javafx.scene.control.ChoiceBox?>
<?import javafx.scene.control.Hyperlink?>
<?import javafx.scene.control.Label?> <?import javafx.scene.control.Label?>
<?import javafx.scene.control.RadioButton?> <?import javafx.scene.control.RadioButton?>
<?import javafx.scene.control.TextField?> <?import javafx.scene.control.TextField?>
<?import javafx.scene.control.ToggleGroup?> <?import javafx.scene.control.ToggleGroup?>
<?import javafx.scene.layout.HBox?> <?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.VBox?> <?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Text?>
<?import javafx.scene.text.TextFlow?>
<VBox xmlns:fx="http://javafx.com/fxml" <VBox xmlns:fx="http://javafx.com/fxml"
xmlns="http://javafx.com/javafx" xmlns="http://javafx.com/javafx"
fx:controller="org.cryptomator.ui.vaultoptions.MountOptionsController" fx:controller="org.cryptomator.ui.vaultoptions.MountOptionsController"
@@ -22,7 +25,11 @@
<Insets topRightBottomLeft="12"/> <Insets topRightBottomLeft="12"/>
</padding> </padding>
<children> <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}"/> <CheckBox fx:id="readOnlyCheckbox" text="%vaultOptions.mount.readonly" visible="${controller.readOnlySupported}" managed="${controller.readOnlySupported}"/>
<VBox visible="${controller.mountFlagsSupported}" managed="${controller.mountFlagsSupported}"> <VBox visible="${controller.mountFlagsSupported}" managed="${controller.mountFlagsSupported}">
@@ -44,22 +51,24 @@
<HBox spacing="6" visible="${controller.mountpointDriveLetterSupported}" managed="${controller.mountpointDriveLetterSupported}"> <HBox spacing="6" visible="${controller.mountpointDriveLetterSupported}" managed="${controller.mountpointDriveLetterSupported}">
<RadioButton toggleGroup="${mountPointToggleGroup}" fx:id="mountPointDriveLetterBtn" text="%vaultOptions.mount.mountPoint.driveLetter"/> <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>
<HBox spacing="6" alignment="CENTER_LEFT" visible="${controller.mountpointDirSupported}" managed="${controller.mountpointDirSupported}"> <VBox spacing="6" visible="${controller.mountpointDirSupported}" managed="${controller.mountpointDirSupported}">
<RadioButton toggleGroup="${mountPointToggleGroup}" fx:id="mountPointDirBtn" text="%vaultOptions.mount.mountPoint.custom"/> <HBox spacing="6" alignment="CENTER_LEFT">
<Button text="%vaultOptions.mount.mountPoint.directoryPickerButton" onAction="#chooseCustomMountPoint" contentDisplay="LEFT" disable="${!mountPointDirBtn.selected}"> <RadioButton toggleGroup="${mountPointToggleGroup}" fx:id="mountPointDirBtn" text="%vaultOptions.mount.mountPoint.custom"/>
<graphic> <Button text="%vaultOptions.mount.mountPoint.directoryPickerButton" onAction="#chooseCustomMountPoint" contentDisplay="LEFT" disable="${!mountPointDirBtn.selected}">
<FontAwesome5IconView glyph="FOLDER_OPEN" glyphSize="15"/> <graphic>
</graphic> <FontAwesome5IconView glyph="FOLDER_OPEN" glyphSize="15"/>
</Button> </graphic>
</HBox> </Button>
<TextField fx:id="directoryPathField" text="${controller.directoryPath}" visible="${mountPointDirBtn.selected}" managed="${mountPointDirBtn.managed}" maxWidth="Infinity" editable="false" > </HBox>
<VBox.margin> <TextField fx:id="directoryPathField" text="${controller.directoryPath}" visible="${mountPointDirBtn.selected}" managed="${mountPointDirBtn.managed}" maxWidth="Infinity" editable="false">
<Insets left="24"/> <VBox.margin>
</VBox.margin> <Insets left="24"/>
</TextField> </VBox.margin>
</TextField>
</VBox>
</children> </children>
</VBox> </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.rememberChoice=Remember my choice, don't ask again
unlock.success.revealBtn=Reveal Drive unlock.success.revealBtn=Reveal Drive
## Failure ## Failure
unlock.error.message=Unable to unlock vault unlock.error.customPath.message=Unable to mount vault to custom path
### Invalid Mount Point 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.invalidMountPoint.notExisting=Mount point "%s" is not a directory, not empty or does not exist. 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.invalidMountPoint.existing=Mount point "%s" already exists or parent folder is missing. unlock.error.customPath.description.generic=You have selected a custom mount path for this vault, but using it failed with the message: %s
unlock.error.invalidMountPoint.driveLetterOccupied=Drive Letter "%s" is already in use.
## Hub ## 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 ### Waiting
hub.auth.message=Waiting for authentication… hub.auth.message=Waiting for authentication…
hub.auth.description=You should automatically be redirected to the login page. 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
migration.title=Upgrade Vault migration.title=Upgrade Vault
## Start ## 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.header=Upgrade Vault
migration.start.confirm=Yes, my vault is fully synced 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 ## Run
migration.run.enterPassword=Enter the password for "%s" migration.run.enterPassword=Enter the password for "%s"
migration.run.startMigrationBtn=Migrate Vault migration.run.startMigrationBtn=Migrate Vault
@@ -269,8 +276,16 @@ preferences.interface.showMinimizeButton=Show minimize button
preferences.interface.showTrayIcon=Show tray icon (requires restart) preferences.interface.showTrayIcon=Show tray icon (requires restart)
## Volume ## Volume
preferences.volume=Virtual Drive 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.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 ## Updates
preferences.updates=Updates preferences.updates=Updates
preferences.updates.currentVersion=Current Version: %s preferences.updates.currentVersion=Current Version: %s
@@ -329,9 +344,6 @@ main.minimizeBtn.tooltip=Minimize
main.preferencesBtn.tooltip=Preferences main.preferencesBtn.tooltip=Preferences
main.debugModeEnabled.tooltip=Debug mode is enabled main.debugModeEnabled.tooltip=Debug mode is enabled
main.supporterCertificateMissing.tooltip=Please consider donating 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 ## Vault List
main.vaultlist.emptyList.onboardingInstruction=Click here to add a vault main.vaultlist.emptyList.onboardingInstruction=Click here to add a vault
main.vaultlist.contextMenu.remove=Remove… main.vaultlist.contextMenu.remove=Remove…
@@ -354,6 +366,7 @@ main.vaultDetail.passwordSavedInKeychain=Password saved
main.vaultDetail.unlockedStatus=UNLOCKED main.vaultDetail.unlockedStatus=UNLOCKED
main.vaultDetail.accessLocation=Your vault's contents are accessible here: main.vaultDetail.accessLocation=Your vault's contents are accessible here:
main.vaultDetail.revealBtn=Reveal Drive main.vaultDetail.revealBtn=Reveal Drive
main.vaultDetail.copyUri=Copy URI
main.vaultDetail.lockBtn=Lock main.vaultDetail.lockBtn=Lock
main.vaultDetail.bytesPerSecondRead=Read: main.vaultDetail.bytesPerSecondRead=Read:
main.vaultDetail.bytesPerSecondWritten=Write: main.vaultDetail.bytesPerSecondWritten=Write:
@@ -361,6 +374,10 @@ main.vaultDetail.throughput.idle=idle
main.vaultDetail.throughput.kbps=%.1f kiB/s main.vaultDetail.throughput.kbps=%.1f kiB/s
main.vaultDetail.throughput.mbps=%.1f MiB/s main.vaultDetail.throughput.mbps=%.1f MiB/s
main.vaultDetail.stats=Vault Statistics 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 ### Missing
main.vaultDetail.missing.info=Cryptomator could not find a vault at this path. main.vaultDetail.missing.info=Cryptomator could not find a vault at this path.
main.vaultDetail.missing.recheck=Recheck main.vaultDetail.missing.recheck=Recheck
@@ -399,6 +416,8 @@ vaultOptions.general.startHealthCheckBtn=Start Health Check
## Mount ## Mount
vaultOptions.mount=Mounting 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.readonly=Read-only
vaultOptions.mount.customMountFlags=Custom mount flags vaultOptions.mount.customMountFlags=Custom mount flags
vaultOptions.mount.winDriveLetterOccupied=occupied vaultOptions.mount.winDriveLetterOccupied=occupied
+11 -14
View File
@@ -103,10 +103,6 @@ unlock.success.description=تم فتح "%s" بنجاح! يمكنك الآن ال
unlock.success.rememberChoice=تذكر اختياري ولا تظهر هذا مرة أخرى unlock.success.rememberChoice=تذكر اختياري ولا تظهر هذا مرة أخرى
unlock.success.revealBtn=اظهار القرص unlock.success.revealBtn=اظهار القرص
## Failure ## Failure
unlock.error.message=غير قادر على فتح الخزنة
### Invalid Mount Point
unlock.error.invalidMountPoint.notExisting=نقطة التحميل ليست مجلد فارغ أو غير موجودة: %s
unlock.error.invalidMountPoint.existing=نقطة/مجلد التحميل موجود بالفعل أو المجلد الأصل مفقود: %s
## Hub ## Hub
### Waiting ### Waiting
### Receive Key ### Receive Key
@@ -129,8 +125,13 @@ lock.fail.description=فشل عملية قفل %s". تأكد من حفظ الع
# Migration # Migration
migration.title=ترقية الحافظة migration.title=ترقية الحافظة
## Start ## Start
migration.start.prompt=يجب تحديث المخزن الخاص بك "%s" إلى تنسيق أحدث. قبل المتابعة، يجب التأكد من عدم وجود مزامنة معلقة على هذا المخزن. migration.start.header=ترقية الخزنة
migration.start.confirm=نعم, محفظتي متزامنة بالكامل migration.start.text=من أجل فتح الخزنة الخاصة بك "%s" في هذا الإصدار الجديد من Cryptomator، يجب ترقية الخزنة إلى تنسيق جديد. وقبل القيام بذلك، ينبغي أن تعرف ما يلي:
migration.start.remarkUndone=هذه الترقية لا يمكن التراجع عنها.
migration.start.remarkVersions=لن تكون الإصدارات القديمة من Cryptomator قادرة على فتح الخزنة التي تم ترقيتها.
migration.start.remarkCanRun=يجب أن تكون متأكداً من أن كل جهاز تريد ان تستخدم الخزنة عليه يمكن تشغيل هذا الإصدار من Cryptomter.
migration.start.remarkSynced=يجب أن تكون متأكداً من أن خزنتك قد تمت مزامنتها بالكامل على هذا الجهاز، وعلى الأجهزة الأخرى الخاصة بك، قبل ترقيتها.
migration.start.confirm=لقد قرأت وفهمت المعلومات الواردة أعلاه
## Run ## Run
migration.run.enterPassword=أدخل كلمة المرور لـ "%s" migration.run.enterPassword=أدخل كلمة المرور لـ "%s"
migration.run.startMigrationBtn=ترقية الحافظة migration.run.startMigrationBtn=ترقية الحافظة
@@ -172,9 +173,6 @@ preferences.interface.theme.dark=مظلم (أسود)
preferences.interface.theme.light=فاتح (أبيض) preferences.interface.theme.light=فاتح (أبيض)
## Volume ## Volume
preferences.volume=القرص الإفتراضي preferences.volume=القرص الإفتراضي
preferences.volume.type=‮نوع المجلد
preferences.volume.webdav.port=منفذ WebDav
preferences.volume.webdav.scheme=مخطط WebDAV
## Updates ## Updates
preferences.updates=تحديثات preferences.updates=تحديثات
preferences.updates.currentVersion=الإصدار الحالي: %s preferences.updates.currentVersion=الإصدار الحالي: %s
@@ -210,9 +208,6 @@ main.minimizeBtn.tooltip=تصغير
main.preferencesBtn.tooltip=تفضيلات main.preferencesBtn.tooltip=تفضيلات
main.debugModeEnabled.tooltip=تم تمكين وضع التصحيح main.debugModeEnabled.tooltip=تم تمكين وضع التصحيح
main.supporterCertificateMissing.tooltip=يرجى النظر في تقديم تبرعات main.supporterCertificateMissing.tooltip=يرجى النظر في تقديم تبرعات
## Drag 'n' Drop
main.dropZone.dropVault=أضف هذا المخزن
main.dropZone.unknownDragboardContent=إذا كنت ترغب في إضافة مخزن، قم بسحبه إلى هذه النافذة
## Vault List ## Vault List
main.vaultlist.emptyList.onboardingInstruction=انقر هنا لإضافة خزنة main.vaultlist.emptyList.onboardingInstruction=انقر هنا لإضافة خزنة
main.vaultlist.contextMenu.remove=حذف… main.vaultlist.contextMenu.remove=حذف…
@@ -242,6 +237,10 @@ main.vaultDetail.throughput.idle=خمول
main.vaultDetail.throughput.kbps=%.1f كيلوبايت/ث main.vaultDetail.throughput.kbps=%.1f كيلوبايت/ث
main.vaultDetail.throughput.mbps=%.1f ميجابايت/ث main.vaultDetail.throughput.mbps=%.1f ميجابايت/ث
main.vaultDetail.stats=إحصائيات الخزنة main.vaultDetail.stats=إحصائيات الخزنة
main.vaultDetail.locateEncryptedFileBtn=تحديد موقع الملف المشفر
main.vaultDetail.locateEncryptedFileBtn.tooltip=اختر ملف من خزانتك لتحديد مكان نظيره المشفر
main.vaultDetail.encryptedPathsCopied=تم نسخ مسارات الملفات إلى الحافظة!
main.vaultDetail.filePickerTitle=إختر الملف من الخزنة
### Missing ### Missing
main.vaultDetail.missing.info=لم يتمكن Cryptomator من العثور على خزنة في هذا المسار. main.vaultDetail.missing.info=لم يتمكن Cryptomator من العثور على خزنة في هذا المسار.
main.vaultDetail.missing.recheck=إعادة الفحص main.vaultDetail.missing.recheck=إعادة الفحص
@@ -280,9 +279,7 @@ vaultOptions.mount.winDriveLetterOccupied=مشغول
vaultOptions.mount.mountPoint=موقع التحميل الوهمي vaultOptions.mount.mountPoint=موقع التحميل الوهمي
vaultOptions.mount.mountPoint.auto=اختيار موقع مناسب تلقائياً vaultOptions.mount.mountPoint.auto=اختيار موقع مناسب تلقائياً
vaultOptions.mount.mountPoint.driveLetter=استخدام دالة قرص معين vaultOptions.mount.mountPoint.driveLetter=استخدام دالة قرص معين
vaultOptions.mount.mountPoint.custom=مسار مخصص
vaultOptions.mount.mountPoint.directoryPickerButton=اختر… vaultOptions.mount.mountPoint.directoryPickerButton=اختر…
vaultOptions.mount.mountPoint.directoryPickerTitle=اختر مجلد فارغ
## Master Key ## Master Key
vaultOptions.masterkey=كلمة المرور vaultOptions.masterkey=كلمة المرور
vaultOptions.masterkey.changePasswordBtn=تغيير كلمة المرور vaultOptions.masterkey.changePasswordBtn=تغيير كلمة المرور
+2 -15
View File
@@ -123,11 +123,6 @@ unlock.success.description=Змест скарбніцы "%s" цяпер дас
unlock.success.rememberChoice=Запомні мой выбар і больш не пытай unlock.success.rememberChoice=Запомні мой выбар і больш не пытай
unlock.success.revealBtn=Паказаць дыск unlock.success.revealBtn=Паказаць дыск
## Failure ## Failure
unlock.error.message=Немагчыма разамкнуць скарбніцу
### Invalid Mount Point
unlock.error.invalidMountPoint.notExisting=Пункт мантажу "%s" не з'яўляецца пустой тэчкаю альбо ўвогуле не існуе.
unlock.error.invalidMountPoint.existing=Пункт мантажу "%s" ужо існуе альбо адсутнічае бацькоўская тэчка.
unlock.error.invalidMountPoint.driveLetterOccupied=Дыскавая літара "%s" ужо выкарыстоўваецца.
## Hub ## Hub
### Waiting ### Waiting
hub.auth.message=Чаканне спраўджання… hub.auth.message=Чаканне спраўджання…
@@ -168,8 +163,7 @@ lock.fail.description=Скарбніцу "%s" не мажліва замкнуц
# Migration # Migration
migration.title=Абнавіць скарбніцу migration.title=Абнавіць скарбніцу
## Start ## Start
migration.start.prompt=Тваю скарбніцу "%s" неабходна абнавіць у новы фармат. Перад тым, як пачаць, запэўніся, што не адбываецца працэсу сінхранавання, які можа ўздзейнічаць на скарбніцу. migration.start.header=Абнавіць скарбніцу
migration.start.confirm=Так, мая скарбніца цалкам сінхранавана
## Run ## Run
migration.run.enterPassword=Увядзіце пароль да "%s" migration.run.enterPassword=Увядзіце пароль да "%s"
migration.run.startMigrationBtn=Перамясціць скарбніцу migration.run.startMigrationBtn=Перамясціць скарбніцу
@@ -233,9 +227,7 @@ preferences.interface.showMinimizeButton=Паказаць кнопку згор
preferences.interface.showTrayIcon=Паказваць іконку на інфармацыйнай панэлі (спатрэбіцца перазапуск) preferences.interface.showTrayIcon=Паказваць іконку на інфармацыйнай панэлі (спатрэбіцца перазапуск)
## Volume ## Volume
preferences.volume=Віртуальны дыск preferences.volume=Віртуальны дыск
preferences.volume.type=Тып тому preferences.volume.type.automatic=Аўтаматычна
preferences.volume.webdav.port=Порт WebDAV
preferences.volume.webdav.scheme=Схема WebDAV
## Updates ## Updates
preferences.updates=Абнаўленні preferences.updates=Абнаўленні
preferences.updates.currentVersion=Бягучая версія: %s preferences.updates.currentVersion=Бягучая версія: %s
@@ -288,9 +280,6 @@ main.minimizeBtn.tooltip=Згарнуць
main.preferencesBtn.tooltip=Налады main.preferencesBtn.tooltip=Налады
main.debugModeEnabled.tooltip=Функццыя дыягназавання выключана main.debugModeEnabled.tooltip=Функццыя дыягназавання выключана
main.supporterCertificateMissing.tooltip=Калі ласка, падумай пра ахвяраванне main.supporterCertificateMissing.tooltip=Калі ласка, падумай пра ахвяраванне
## Drag 'n' Drop
main.dropZone.dropVault=Дадаць гэтую скарбніцу
main.dropZone.unknownDragboardContent=Калі ты хочаш дадаць скарбніцу, перацягні яе ў гэтае акно
## Vault List ## Vault List
main.vaultlist.emptyList.onboardingInstruction=Пстрыкні тут, каб дадаць скарбніцу main.vaultlist.emptyList.onboardingInstruction=Пстрыкні тут, каб дадаць скарбніцу
main.vaultlist.contextMenu.remove=Выдаліць… main.vaultlist.contextMenu.remove=Выдаліць…
@@ -361,9 +350,7 @@ vaultOptions.mount.winDriveLetterOccupied=занята
vaultOptions.mount.mountPoint=Пункт мантажавання vaultOptions.mount.mountPoint=Пункт мантажавання
vaultOptions.mount.mountPoint.auto=Аўтаматычны выбар пасуючага месцазнаходжання vaultOptions.mount.mountPoint.auto=Аўтаматычны выбар пасуючага месцазнаходжання
vaultOptions.mount.mountPoint.driveLetter=Назначыць літару для дыску vaultOptions.mount.mountPoint.driveLetter=Назначыць літару для дыску
vaultOptions.mount.mountPoint.custom=Уласная сцежка
vaultOptions.mount.mountPoint.directoryPickerButton=Абраць… vaultOptions.mount.mountPoint.directoryPickerButton=Абраць…
vaultOptions.mount.mountPoint.directoryPickerTitle=Абяры парожнюю тэчку
## Master Key ## Master Key
vaultOptions.masterkey=Пароль vaultOptions.masterkey=Пароль
vaultOptions.masterkey.changePasswordBtn=Змяніць пароль vaultOptions.masterkey.changePasswordBtn=Змяніць пароль
@@ -44,11 +44,19 @@ addvaultwizard.new.namePrompt=ভোল্ট এর নাম
addvaultwizard.new.locationInstruction=ভোল্ট এর এনক্রিপ্টেড ফাইলগুলো ক্রিপ্টোমেটর কোথায় সংরক্ষণ করবে? addvaultwizard.new.locationInstruction=ভোল্ট এর এনক্রিপ্টেড ফাইলগুলো ক্রিপ্টোমেটর কোথায় সংরক্ষণ করবে?
addvaultwizard.new.locationLabel=স্টোরেজ লোকেশন addvaultwizard.new.locationLabel=স্টোরেজ লোকেশন
addvaultwizard.new.locationPrompt= addvaultwizard.new.locationPrompt=
addvaultwizard.new.directoryPickerLabel=স্বনির্বাচিত লোকেশন
addvaultwizard.new.directoryPickerButton=নির্বাচন করুন… addvaultwizard.new.directoryPickerButton=নির্বাচন করুন…
addvaultwizard.new.directoryPickerTitle=ডিরেক্টরি নির্বাচন addvaultwizard.new.directoryPickerTitle=ডিরেক্টরি নির্বাচন
addvaultwizard.new.fileAlreadyExists=ভোল্টের নামে একটি ফাইল অথবা ডিরেক্টরি ইতিমধ্যে বিদ্যমান
addvaultwizard.new.locationDoesNotExist=নিদিষ্ট করা পথে একটি ডিরেক্টরি বিদ্যমান নয় অথবা প্রবেশ করা যাচ্ছে না addvaultwizard.new.locationDoesNotExist=নিদিষ্ট করা পথে একটি ডিরেক্টরি বিদ্যমান নয় অথবা প্রবেশ করা যাচ্ছে না
addvaultwizard.new.locationIsNotWritable=নিদিষ্ট করা পথে কোনো কিছু পরিবর্তন করার অনুমতি নেই addvaultwizard.new.locationIsNotWritable=নিদিষ্ট করা পথে কোনো কিছু পরিবর্তন করার অনুমতি নেই
addvaultwizard.new.locationIsOk=আপনার ভোল্টের জন্য উপযুক্ত ঠিকানা 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 ### Password
addvaultwizard.new.createVaultBtn=ভোল্ট তৈরি করুন addvaultwizard.new.createVaultBtn=ভোল্ট তৈরি করুন
addvaultwizard.new.generateRecoveryKeyChoice=পাসওয়ার্ড ছাড়া আপনি আপনার তথ্যগুলো ব্যবহার করতে পারবেন না. তাই আপনি কি একটি পুনরুদ্ধার চাবি চান যদি আপনি পাসওয়ার্ড হারিয়ে ফেলেন? addvaultwizard.new.generateRecoveryKeyChoice=পাসওয়ার্ড ছাড়া আপনি আপনার তথ্যগুলো ব্যবহার করতে পারবেন না. তাই আপনি কি একটি পুনরুদ্ধার চাবি চান যদি আপনি পাসওয়ার্ড হারিয়ে ফেলেন?
@@ -79,7 +87,6 @@ unlock.unlockBtn=আনলক করুন
## Select ## Select
## Success ## Success
## Failure ## Failure
### Invalid Mount Point
## Hub ## Hub
### Waiting ### Waiting
### Receive Key ### Receive Key
@@ -130,7 +137,6 @@ lock.forced.retryBtn=পুনরায় চেষ্টা করুন
# Main Window # Main Window
main.closeBtn.tooltip=বন্ধ করুন main.closeBtn.tooltip=বন্ধ করুন
## Drag 'n' Drop
## Vault List ## Vault List
main.vaultlist.contextMenu.lock=লক করুন main.vaultlist.contextMenu.lock=লক করুন
main.vaultlist.addVaultBtn=ভোল্ট যুক্ত করুন 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.rememberChoice=Zapamtite izbor, ne pokazujte ovo ponovo
unlock.success.revealBtn=Otkrij pogon unlock.success.revealBtn=Otkrij pogon
## Failure ## 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 ## Hub
### Waiting ### Waiting
### Receive Key ### Receive Key
@@ -128,8 +124,7 @@ lock.fail.description=Sef "%s" nije moguće zaključati. Osigurajte da je nespre
# Migration # Migration
migration.title=Nadogradi sef migration.title=Nadogradi sef
## Start ## 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.header=Nadogradi sef
migration.start.confirm=Da, moj sef je u potpunosti sinhroniziran
## Run ## Run
migration.run.enterPassword=Unesite lozinku za "%s" migration.run.enterPassword=Unesite lozinku za "%s"
migration.run.startMigrationBtn=Nadogradi sef migration.run.startMigrationBtn=Nadogradi sef
@@ -171,9 +166,6 @@ preferences.interface.theme.dark=Tamno
preferences.interface.theme.light=Svijetlo preferences.interface.theme.light=Svijetlo
## Volume ## Volume
preferences.volume=Virtuelni pogon preferences.volume=Virtuelni pogon
preferences.volume.type=Tip volumena
preferences.volume.webdav.port=WebDAV Port
preferences.volume.webdav.scheme=WebDAV Scheme
## Updates ## Updates
preferences.updates=Ažuriranja preferences.updates=Ažuriranja
preferences.updates.currentVersion=Trenutna verzija: %s preferences.updates.currentVersion=Trenutna verzija: %s
@@ -225,9 +217,6 @@ main.minimizeBtn.tooltip=Minimiziraj
main.preferencesBtn.tooltip=Postavke main.preferencesBtn.tooltip=Postavke
main.debugModeEnabled.tooltip=Omogućen je mod otklanjanja pogrešaka main.debugModeEnabled.tooltip=Omogućen je mod otklanjanja pogrešaka
main.supporterCertificateMissing.tooltip=Molimo razmislite o doniranju 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 ## Vault List
main.vaultlist.emptyList.onboardingInstruction=Kliknite ovdje da dodate sef main.vaultlist.emptyList.onboardingInstruction=Kliknite ovdje da dodate sef
main.vaultlist.contextMenu.remove=Ukloni… main.vaultlist.contextMenu.remove=Ukloni…
@@ -295,9 +284,7 @@ vaultOptions.mount.winDriveLetterOccupied=zauzeto
vaultOptions.mount.mountPoint=Tačka povezivanja vaultOptions.mount.mountPoint=Tačka povezivanja
vaultOptions.mount.mountPoint.auto=Automatski odaberi pogodnu lokaciju vaultOptions.mount.mountPoint.auto=Automatski odaberi pogodnu lokaciju
vaultOptions.mount.mountPoint.driveLetter=Koristi dodjeljeno slovo (oznaku) diska vaultOptions.mount.mountPoint.driveLetter=Koristi dodjeljeno slovo (oznaku) diska
vaultOptions.mount.mountPoint.custom=Prilagođena adresa
vaultOptions.mount.mountPoint.directoryPickerButton=Odaberi… vaultOptions.mount.mountPoint.directoryPickerButton=Odaberi…
vaultOptions.mount.mountPoint.directoryPickerTitle=Izaberi praznu mapu
## Master Key ## Master Key
vaultOptions.masterkey=Šifra vaultOptions.masterkey=Šifra
vaultOptions.masterkey.changePasswordBtn=Promjeni lozinku vaultOptions.masterkey.changePasswordBtn=Promjeni lozinku
+48 -21
View File
@@ -15,10 +15,10 @@ generic.button.next=Següent
generic.button.print=Imprimeix generic.button.print=Imprimeix
# Error # 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.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.lookup=Cerca aquest error
error.hyperlink.report=Notifica un error error.hyperlink.report=Notifica aquest error
error.technicalDetails=Detalls: error.technicalDetails=Detalls:
# Defaults # 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.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.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.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.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.storageLocation.10=Si us cal ajuda, llegiu la documentació: %s
addvault.new.readme.accessLocation.fileName=BENVINGUTS.rtf 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.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.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.filePickerTitle=Seleccioneu el fitxer de Clau Mestra
unlock.chooseMasterkey.filePickerMimeDesc=La clau mestra de Cryptomator
## Success ## Success
unlock.success.message=Desbloqueig satisfactori 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.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.rememberChoice=Recorda l'elecció. No ho tornis a mostrar.
unlock.success.revealBtn=Mostra la unitat unlock.success.revealBtn=Mostra la unitat
## Failure ## Failure
unlock.error.message=No ha estat possible desblocar la caixa forta unlock.error.customPath.message=No es pot muntar la caixa forta en la ruta personalitzada
### Invalid Mount Point 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.invalidMountPoint.notExisting=El punt de muntatge no és un directori buit, o no existeix: %s 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.invalidMountPoint.existing=El punt de muntatge o la carpeta ja existeix, o no es pot accedir al directori superior: %s unlock.error.customPath.description.generic=Ha seleccionat una ruta personalitzada on muntar la caixa forta, però ha fallat amb aquest missatge: %s
unlock.error.invalidMountPoint.driveLetterOccupied=La unitat o arxiu "%s" ja està en ús.
## Hub ## 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 ### Waiting
hub.auth.message=Sestà esperant lautenticació… hub.auth.message=Sestà esperant lautenticació…
hub.auth.description=Hauríeu de ser redirigits a la pàgina d'accés. 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. hub.auth.loginLink=No heu estat redirigit? Feu clic aquí per a obrir-la.
### Receive Key ### Receive Key
hub.receive.message=S'està processant la resposta… 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 ### Register Device
hub.register.message=Cal un nom de dispositiu 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.nameLabel=Nom del dispositiu
hub.register.occupiedMsg=El nom ja està en ús hub.register.occupiedMsg=El nom ja està en ús
hub.register.registerBtn=Confirma hub.register.registerBtn=Confirma
### Registration Success ### 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. hub.registerSuccess.description=Per a accedir a la caixa forta, el vostre dispositiu ha de ser autoritzat pel propietari de la caixa.
### Registration Failed ### 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 ### Unauthorized
hub.unauthorized.message=Accés denegat 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. hub.unauthorized.description=El vostre dispositiu no ha estat encara autoritzat a accedir a aquesta caixa forta. Demaneu autorització al propietari.
### License Exceeded ### 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 # Lock
@@ -161,8 +171,13 @@ lock.fail.description=La caixa forta "%s" no s'ha pogut blocar. Assegureu-vos qu
# Migration # Migration
migration.title=Actualitza la caixa forta migration.title=Actualitza la caixa forta
## Start ## 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.header=Actualitza la caixa forta
migration.start.confirm=Sí, la meua caixa forta està completament sicronitzada 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 ## Run
migration.run.enterPassword=Introduïu la contrasenya per a "%s" migration.run.enterPassword=Introduïu la contrasenya per a "%s"
migration.run.startMigrationBtn=Migrar la caixa forta 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.checkFailed=La comprovació ha acabat a causa d'un error.
health.check.detail.checkCancelled=S'ha cancel·lat la prova. health.check.detail.checkCancelled=S'ha cancel·lat la prova.
health.check.detail.listFilters.label=Filtre 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.detail.fixAllSpecificBtn=Qualsevol reparació
health.check.exportBtn=Exporta informe health.check.exportBtn=Exporta informe
## Result view ## Result view
@@ -221,6 +234,10 @@ health.result.severityFilter.good=Bé
health.result.severityFilter.info=Info health.result.severityFilter.info=Info
health.result.severityFilter.warn=Avís health.result.severityFilter.warn=Avís
health.result.severityFilter.crit=Crític 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.all=Estat de reparació - Tot
health.result.fixStateFilter.fixable=Es pot arreglar health.result.fixStateFilter.fixable=Es pot arreglar
health.result.fixStateFilter.notFixable=No 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) preferences.interface.showTrayIcon=Mostra la icona en la barra (cal reiniciar)
## Volume ## Volume
preferences.volume=Unitat virtual preferences.volume=Unitat virtual
preferences.volume.type=Tipus de volum preferences.volume.type=Tipus de volum (requereix reiniciar)
preferences.volume.webdav.port=Port WebDAV preferences.volume.type.automatic=Automàtic
preferences.volume.webdav.scheme=Esquema WebDAV 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 ## Updates
preferences.updates=Actualitzacions preferences.updates=Actualitzacions
preferences.updates.currentVersion=Versió actual: %s preferences.updates.currentVersion=Versió actual: %s
@@ -319,9 +342,6 @@ main.minimizeBtn.tooltip=Minimitza
main.preferencesBtn.tooltip=Preferències main.preferencesBtn.tooltip=Preferències
main.debugModeEnabled.tooltip=Mode depuració activat main.debugModeEnabled.tooltip=Mode depuració activat
main.supporterCertificateMissing.tooltip=Si us plau, considereu fer una donació 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 ## Vault List
main.vaultlist.emptyList.onboardingInstruction=Feu clic aquí per afegir una caixa forta main.vaultlist.emptyList.onboardingInstruction=Feu clic aquí per afegir una caixa forta
main.vaultlist.contextMenu.remove=Elimina… main.vaultlist.contextMenu.remove=Elimina…
@@ -344,6 +364,7 @@ main.vaultDetail.passwordSavedInKeychain=Contrasenya desada
main.vaultDetail.unlockedStatus=DESBLOQUEJADA main.vaultDetail.unlockedStatus=DESBLOQUEJADA
main.vaultDetail.accessLocation=Els continguts de la vostra caixa forta són accessibles aquí: main.vaultDetail.accessLocation=Els continguts de la vostra caixa forta són accessibles aquí:
main.vaultDetail.revealBtn=Mostra la unitat main.vaultDetail.revealBtn=Mostra la unitat
main.vaultDetail.copyUri=Copiar URI
main.vaultDetail.lockBtn=Bloqueja main.vaultDetail.lockBtn=Bloqueja
main.vaultDetail.bytesPerSecondRead=Lectura: main.vaultDetail.bytesPerSecondRead=Lectura:
main.vaultDetail.bytesPerSecondWritten=Escriu: main.vaultDetail.bytesPerSecondWritten=Escriu:
@@ -351,8 +372,12 @@ main.vaultDetail.throughput.idle=inactiu
main.vaultDetail.throughput.kbps=%.1f kiB/s main.vaultDetail.throughput.kbps=%.1f kiB/s
main.vaultDetail.throughput.mbps=%.1f MiB/s main.vaultDetail.throughput.mbps=%.1f MiB/s
main.vaultDetail.stats=Estadístiques de la caixa forta 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 ### 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.recheck=Torna a comprovar
main.vaultDetail.missing.remove=Eliminar de la llista de la caixa forta… main.vaultDetail.missing.remove=Eliminar de la llista de la caixa forta…
main.vaultDetail.missing.changeLocation=Canvia la localització 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 ## Mount
vaultOptions.mount=Muntatge 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.readonly=Només lectura
vaultOptions.mount.customMountFlags=Senyaladors de muntatge personalitzats vaultOptions.mount.customMountFlags=Senyaladors de muntatge personalitzats
vaultOptions.mount.winDriveLetterOccupied=ocupat vaultOptions.mount.winDriveLetterOccupied=ocupat
vaultOptions.mount.mountPoint=Punt de muntatge vaultOptions.mount.mountPoint=Punt de muntatge
vaultOptions.mount.mountPoint.auto=Tria automàticament una ubicació adequada vaultOptions.mount.mountPoint.auto=Tria automàticament una ubicació adequada
vaultOptions.mount.mountPoint.driveLetter=Utilitza la lletra de la unitat assignada 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.directoryPickerButton=Trieu…
vaultOptions.mount.mountPoint.directoryPickerTitle=Esculliu un directori buit vaultOptions.mount.mountPoint.directoryPickerTitle=Triï un directori
## Master Key ## Master Key
vaultOptions.masterkey=Contrasenya vaultOptions.masterkey=Contrasenya
vaultOptions.masterkey.changePasswordBtn=Canvi de 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.locationDoesNotExist=Složka v zadané cestě neexistuje nebo není přístupná
addvaultwizard.new.locationIsNotWritable=Není možné zapisovat na zadané cestě addvaultwizard.new.locationIsNotWritable=Není možné zapisovat na zadané cestě
addvaultwizard.new.locationIsOk=Vhodné umístění pro váš trezor 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 ### Password
addvaultwizard.new.createVaultBtn=Vytvořit trezor 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? 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 # Remove Vault
removeVault.title=Odstranit trezor 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.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 removeVault.confirmBtn=Odstranit trezor
@@ -96,6 +103,7 @@ changepassword.finalConfirmation=Chápu, že pokud zapomenu své heslo, nebudu m
# Forget Password # Forget Password
forgetPassword.title=Zapomenout heslo forgetPassword.title=Zapomenout heslo
forgetPassword.message=Zapomenout uložené heslo?
forgetPassword.description=Toto smaže uložené heslo pro tento trezor. forgetPassword.description=Toto smaže uložené heslo pro tento trezor.
forgetPassword.confirmBtn=Zapomenout heslo forgetPassword.confirmBtn=Zapomenout heslo
@@ -105,28 +113,37 @@ unlock.passwordPrompt=Zadejte heslo pro "%s":
unlock.savePassword=Zapamatovat heslo unlock.savePassword=Zapamatovat heslo
unlock.unlockBtn=Odemknout unlock.unlockBtn=Odemknout
## Select ## 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.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.filePickerTitle=Vyberte soubor s hlavním klíčem
unlock.chooseMasterkey.filePickerMimeDesc=Hlavní klíč Cryptomatoru unlock.chooseMasterkey.filePickerMimeDesc=Hlavní klíč Cryptomatoru
## Success ## 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.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.rememberChoice=Pamatovat si volbu, nezobrazovat to znovu
unlock.success.revealBtn=Zobrazit jednotku unlock.success.revealBtn=Zobrazit jednotku
## Failure ## 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
hub.noKeychain.openBtn=Otevřít předvolby
### Waiting ### Waiting
hub.auth.message=Čekání na ověření…
### Receive Key ### Receive Key
### Register Device ### 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 hub.register.registerBtn=Potvrdit
### Registration Success ### 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 ### Registration Failed
hub.registerFailed.message=Pojmenování zařízení se nezdařilo
### Unauthorized ### 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 ### 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 # Lock
@@ -142,8 +159,13 @@ lock.fail.description=Trezor "%s" nelze uzamknout. Ujistěte se, že je neulože
# Migration # Migration
migration.title=Upgrade trezoru migration.title=Upgrade trezoru
## Start ## 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.header=Upgrade trezoru
migration.start.confirm=Ano, můj trezor je plně synchronizován. 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 ## Run
migration.run.enterPassword=Zadejte heslo pro "%s" migration.run.enterPassword=Zadejte heslo pro "%s"
migration.run.startMigrationBtn=Migrovat trezor 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.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.checkFailed=Kontrola byla ukončena z důvodu chyby.
health.check.detail.checkCancelled=Kontrola byla zrušena. 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 health.check.exportBtn=Exportovat sestavu
## Result view ## 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 ## Fix Application
health.fix.fixBtn=Opravit health.fix.fixBtn=Opravit
health.fix.successTip=Oprava byla úspěšná 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) preferences.interface.showTrayIcon=Zobrazit ikonu v liště (vyžaduje restart)
## Volume ## Volume
preferences.volume=Virtuální jednotky preferences.volume=Virtuální jednotky
preferences.volume.type=Typ připojení preferences.volume.type.automatic=Automatické
preferences.volume.webdav.port=WebDAV Port
preferences.volume.webdav.scheme=WebDAV schéma
## Updates ## Updates
preferences.updates=Aktualizace preferences.updates=Aktualizace
preferences.updates.currentVersion=Aktuální verze: %s 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 stats.write.accessCount=Celkem zapsáno: %d
## Accesses ## Accesses
stats.access.current=Přístup: %d
stats.access.total=Přístup celkem: %d
# Main Window # Main Window
@@ -282,9 +311,6 @@ main.minimizeBtn.tooltip=Minimalizovat
main.preferencesBtn.tooltip=Nastavení main.preferencesBtn.tooltip=Nastavení
main.debugModeEnabled.tooltip=Režim ladění je povolen main.debugModeEnabled.tooltip=Režim ladění je povolen
main.supporterCertificateMissing.tooltip=Prosím, zvažte darování 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 ## Vault List
main.vaultlist.emptyList.onboardingInstruction=Klikněte zde pro přidání nového trezoru main.vaultlist.emptyList.onboardingInstruction=Klikněte zde pro přidání nového trezoru
main.vaultlist.contextMenu.remove=Odstranit… main.vaultlist.contextMenu.remove=Odstranit…
@@ -358,28 +384,31 @@ vaultOptions.mount.winDriveLetterOccupied=obsazeno
vaultOptions.mount.mountPoint=Přípojný bod vaultOptions.mount.mountPoint=Přípojný bod
vaultOptions.mount.mountPoint.auto=Automaticky vybrat vhodné místo vaultOptions.mount.mountPoint.auto=Automaticky vybrat vhodné místo
vaultOptions.mount.mountPoint.driveLetter=Použít zvolenou jednotku vaultOptions.mount.mountPoint.driveLetter=Použít zvolenou jednotku
vaultOptions.mount.mountPoint.custom=Vlastní cesta
vaultOptions.mount.mountPoint.directoryPickerButton=Vybrat... vaultOptions.mount.mountPoint.directoryPickerButton=Vybrat...
vaultOptions.mount.mountPoint.directoryPickerTitle=Vyberte prázdný adresář
## Master Key ## Master Key
vaultOptions.masterkey=Heslo vaultOptions.masterkey=Heslo
vaultOptions.masterkey.changePasswordBtn=Změnit heslo vaultOptions.masterkey.changePasswordBtn=Změnit heslo
vaultOptions.masterkey.forgetSavedPasswordBtn=Zapomenout uložené 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.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.showRecoveryKeyBtn=Zobrazit klíč k obnově
vaultOptions.masterkey.recoverPasswordBtn=Resetovat heslo
# Recovery Key # Recovery Key
## Display 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.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.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 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 ## Reset Password
### Enter Recovery Key ### Enter Recovery Key
recoveryKey.recover.title=Resetovat heslo
recoveryKey.recover.prompt=Zadejte váš obnovovací klíč pro "%s": recoveryKey.recover.prompt=Zadejte váš obnovovací klíč pro "%s":
recoveryKey.recover.validKey=Toto je platný obnovovací klíč recoveryKey.recover.validKey=Toto je platný obnovovací klíč
recoveryKey.printout.heading=Obnovovací klíč Cryptomator\n"%s"\n recoveryKey.printout.heading=Obnovovací klíč Cryptomator\n"%s"\n
### Reset Password ### Reset Password
recoveryKey.recover.resetBtn=Resetovat
### Recovery Key Password Reset Success ### Recovery Key Password Reset Success
# New Password # New Password
@@ -395,6 +424,7 @@ passwordStrength.messageLabel.3=silné
passwordStrength.messageLabel.4=velmi silné passwordStrength.messageLabel.4=velmi silné
# Quit # Quit
quit.title=Ukončit aplikaci
quit.lockAndQuitBtn=Uzamknout a zavřít quit.lockAndQuitBtn=Uzamknout a zavřít
# Forced Quit # 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.rememberChoice=Husk mit valg. Spørg ikke igen
unlock.success.revealBtn=Vis drev unlock.success.revealBtn=Vis drev
## Failure ## 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
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 ### Waiting
hub.auth.message=Afventer godkendelse… hub.auth.message=Afventer godkendelse…
hub.auth.description=Du burde automatisk blive omdirigeret til login-siden. 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
migration.title=Opgradér boks migration.title=Opgradér boks
## Start ## 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.header=Opgradér boks
migration.start.confirm=Ja. Min boks er fuldt synkroniseret 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 ## Run
migration.run.enterPassword=Indtast adgangskoden for "%s" migration.run.enterPassword=Indtast adgangskoden for "%s"
migration.run.startMigrationBtn=Migrér boks 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.checkFinishedAndFound=Kontrolproceduren er kørt færdig. Gennemse venligst resultatet.
health.check.detail.checkFailed=Kontrolproceduren blev afbrudt af en fejl. health.check.detail.checkFailed=Kontrolproceduren blev afbrudt af en fejl.
health.check.detail.checkCancelled=Kontrolproceduren blev annulleret. 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 health.check.exportBtn=Eksportér rapport
## Result view ## 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 ## Fix Application
health.fix.fixBtn=Reparér health.fix.fixBtn=Reparér
health.fix.successTip=Repareret 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) preferences.interface.showTrayIcon=Vis ikon i system-bakken (kræver genstart)
## Volume ## Volume
preferences.volume=Virtuelt drev preferences.volume=Virtuelt drev
preferences.volume.type=Drev-type preferences.volume.type.automatic=Automatisk
preferences.volume.webdav.port=WebDAV port
preferences.volume.webdav.scheme=WebDAV skema
## Updates ## Updates
preferences.updates=Opdateringer preferences.updates=Opdateringer
preferences.updates.currentVersion=Nuværende version: %s 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 stats.write.accessCount=Totalt antal skrivninger: %d
## Accesses ## Accesses
stats.access.current=Adgang: %d
stats.access.total=Samlede adgang: %d
# Main Window # Main Window
@@ -310,9 +330,6 @@ main.minimizeBtn.tooltip=Minimér
main.preferencesBtn.tooltip=Præferencer main.preferencesBtn.tooltip=Præferencer
main.debugModeEnabled.tooltip=Fejlfindingstilstand er aktiveret main.debugModeEnabled.tooltip=Fejlfindingstilstand er aktiveret
main.supporterCertificateMissing.tooltip=Overvej venligst at donere 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 ## Vault List
main.vaultlist.emptyList.onboardingInstruction=Klik her for at tilføje en boks main.vaultlist.emptyList.onboardingInstruction=Klik her for at tilføje en boks
main.vaultlist.contextMenu.remove=Fjern… main.vaultlist.contextMenu.remove=Fjern…
@@ -386,9 +403,7 @@ vaultOptions.mount.winDriveLetterOccupied=optaget
vaultOptions.mount.mountPoint=Monterings-sted vaultOptions.mount.mountPoint=Monterings-sted
vaultOptions.mount.mountPoint.auto=Vælg automatisk en passende placering vaultOptions.mount.mountPoint.auto=Vælg automatisk en passende placering
vaultOptions.mount.mountPoint.driveLetter=Brug et ledigt drevbogstav vaultOptions.mount.mountPoint.driveLetter=Brug et ledigt drevbogstav
vaultOptions.mount.mountPoint.custom=Brugerdefineret sti
vaultOptions.mount.mountPoint.directoryPickerButton=Vælg… vaultOptions.mount.mountPoint.directoryPickerButton=Vælg…
vaultOptions.mount.mountPoint.directoryPickerTitle=Vælg en tom mappe
## Master Key ## Master Key
vaultOptions.masterkey=Adgangskode vaultOptions.masterkey=Adgangskode
vaultOptions.masterkey.changePasswordBtn=Skift adgangskode vaultOptions.masterkey.changePasswordBtn=Skift adgangskode
+23 -28
View File
@@ -93,7 +93,7 @@ addvaultwizard.success.unlockNow=Jetzt entsperren
# Remove Vault # Remove Vault
removeVault.title=„%s“ entfernen removeVault.title=„%s“ entfernen
removeVault.message=Tresor 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 removeVault.confirmBtn=Tresor entfernen
# Change Password # 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.rememberChoice=Auswahl merken und nicht mehr fragen
unlock.success.revealBtn=Laufwerk anzeigen unlock.success.revealBtn=Laufwerk anzeigen
## Failure ## 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
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 ### Waiting
hub.auth.message=Warten auf Authentifizierung … hub.auth.message=Warten auf Authentifizierung …
hub.auth.description=Du solltest automatisch zur Anmeldeseite weitergeleitet werden. 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. 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 ### License Exceeded
hub.licenseExceeded.message=Lizenz überschritten 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 # Lock
@@ -169,8 +167,13 @@ lock.fail.description=Der Tresor „%s“ konnte nicht gesperrt werden. Stelle s
# Migration # Migration
migration.title=Tresor upgraden migration.title=Tresor upgraden
## Start ## 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.header=Tresor upgraden
migration.start.confirm=Ja, mein Tresor ist vollständig synchronisiert 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 ## Run
migration.run.enterPassword=Gib das Passwort für „%s“ ein migration.run.enterPassword=Gib das Passwort für „%s“ ein
migration.run.startMigrationBtn=Tresor migrieren 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.checkFailed=Die Prüfung wurde wegen eines Fehlers abgebrochen.
health.check.detail.checkCancelled=Die Prüfung wurde abgebrochen. health.check.detail.checkCancelled=Die Prüfung wurde abgebrochen.
health.check.detail.listFilters.label=Filter health.check.detail.listFilters.label=Filter
health.check.detail.listFilters.severity=Schweregrad health.check.detail.fixAllSpecificBtn=Alle dieses Typs reparieren
health.check.detail.listFilters.fixState=Fix Status
health.check.detail.fixAllSpecificBtn=Behebe alle mit Status
health.check.exportBtn=Bericht exportieren health.check.exportBtn=Bericht exportieren
## Result view ## Result view
health.result.severityFilter.all=Schweregrad - Alle health.result.severityFilter.all=Schweregrad - Alle
@@ -230,14 +231,15 @@ health.result.severityFilter.info=Info
health.result.severityFilter.warn=Warnung health.result.severityFilter.warn=Warnung
health.result.severityFilter.crit=Kritisch health.result.severityFilter.crit=Kritisch
health.result.severityTip.good=Schweregrad: Gut\nNormale Tresorstruktur. health.result.severityTip.good=Schweregrad: Gut\nNormale Tresorstruktur.
health.result.severityTip.info=Schweregrad: Info\nTresorstruktur intakt, Beheben empfohlen. health.result.severityTip.info=Schweregrad: Info\nTresorstruktur intakt, Reparatur empfohlen.
health.result.severityTip.warn=Schweregrad: Warnung\nTresorstruktur beschädigt, Beheben dringend empfohlen. health.result.severityTip.warn=Schweregrad: Warnung\nTresorstruktur beschädigt, Reparatur dringend empfohlen.
health.result.severityTip.crit=Schweregrad: Kritisch\nTresorstruktur beschädigt, Datenverlust möglich. health.result.severityTip.crit=Schweregrad: Kritisch\nTresorstruktur beschädigt, Datenverlust festgestellt.
health.result.fixStateFilter.all=Fix-Status - Alle health.result.fixStateFilter.all=Reparaturstatus - Alle
health.result.fixStateFilter.fixable=Fixierbar health.result.fixStateFilter.fixable=Reparabel
health.result.fixStateFilter.notFixable=Nicht behebbar health.result.fixStateFilter.notFixable=Irreparabel
health.result.fixStateFilter.fixed=Behoben health.result.fixStateFilter.fixing=Wird repariert …
health.result.fixStateFilter.fixFailed=Fix fehlgeschlagen health.result.fixStateFilter.fixed=Repariert
health.result.fixStateFilter.fixFailed=Reparatur gescheitert
## Fix Application ## Fix Application
health.fix.fixBtn=Beheben health.fix.fixBtn=Beheben
health.fix.successTip=Fehlerbehebung erfolgreich 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) preferences.interface.showTrayIcon=Symbol im Infobereich anzeigen (Neustart erforderlich)
## Volume ## Volume
preferences.volume=Tresorlaufwerk preferences.volume=Tresorlaufwerk
preferences.volume.type=Laufwerkstyp preferences.volume.type.automatic=Automatisch
preferences.volume.webdav.port=WebDAV-Port
preferences.volume.webdav.scheme=WebDAV-Schema
## Updates ## Updates
preferences.updates=Updates preferences.updates=Updates
preferences.updates.currentVersion=Aktuelle Version: %s preferences.updates.currentVersion=Aktuelle Version: %s
@@ -330,9 +330,6 @@ main.minimizeBtn.tooltip=Minimieren
main.preferencesBtn.tooltip=Einstellungen main.preferencesBtn.tooltip=Einstellungen
main.debugModeEnabled.tooltip=Diagnosemodus ist aktiviert main.debugModeEnabled.tooltip=Diagnosemodus ist aktiviert
main.supporterCertificateMissing.tooltip=Zieh bitte eine Spende in Betracht 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 ## Vault List
main.vaultlist.emptyList.onboardingInstruction=Klicke hier, um einen Tresor hinzuzufügen main.vaultlist.emptyList.onboardingInstruction=Klicke hier, um einen Tresor hinzuzufügen
main.vaultlist.contextMenu.remove=Entfernen … main.vaultlist.contextMenu.remove=Entfernen …
@@ -406,9 +403,7 @@ vaultOptions.mount.winDriveLetterOccupied=belegt
vaultOptions.mount.mountPoint=Einhängepunkt vaultOptions.mount.mountPoint=Einhängepunkt
vaultOptions.mount.mountPoint.auto=Automatisch einen geeigneten Ort auswählen vaultOptions.mount.mountPoint.auto=Automatisch einen geeigneten Ort auswählen
vaultOptions.mount.mountPoint.driveLetter=Laufwerksbuchstaben zuweisen vaultOptions.mount.mountPoint.driveLetter=Laufwerksbuchstaben zuweisen
vaultOptions.mount.mountPoint.custom=Eigener Pfad
vaultOptions.mount.mountPoint.directoryPickerButton=Durchsuchen … vaultOptions.mount.mountPoint.directoryPickerButton=Durchsuchen …
vaultOptions.mount.mountPoint.directoryPickerTitle=Wähle ein leeres Verzeichnis
## Master Key ## Master Key
vaultOptions.masterkey=Passwort vaultOptions.masterkey=Passwort
vaultOptions.masterkey.changePasswordBtn=Passwort ändern vaultOptions.masterkey.changePasswordBtn=Passwort ändern
+51 -15
View File
@@ -123,12 +123,14 @@ unlock.success.description=Το περιεχόμενο στην κρύπτη "%s
unlock.success.rememberChoice=Απομνημόνευση επιλογής, μη ρωτήσεις ξανά unlock.success.rememberChoice=Απομνημόνευση επιλογής, μη ρωτήσεις ξανά
unlock.success.revealBtn=Αποκάλυψη εικονικού δίσκου unlock.success.revealBtn=Αποκάλυψη εικονικού δίσκου
## Failure ## Failure
unlock.error.message=Αδυναμία ξεκλειδώματος κρύπτης unlock.error.customPath.message=Αδυναμία προσάρτησης της κρύπτης στην προσαρμοσμένη διαδρομή
### Invalid Mount Point unlock.error.customPath.description.notSupported=Εάν θέλετε να συνεχίσετε να χρησιμοποιείτε την προσαρμοσμένη διαδρομή, μεταβείτε στις προτιμήσεις και επιλέξτε έναν τύπο τόμου που την υποστηρίζει. Διαφορετικά, μεταβείτε στις επιλογές της κρύπτης και επιλέξτε ένα υποστηριζόμενο σημείο προσάρτησης.
unlock.error.invalidMountPoint.notExisting=Το σημείο προσάρτησης δεν είναι κενός φάκελος ή δεν υπάρχει: %s unlock.error.customPath.description.notExists=Η προσαρμοσμένη διαδρομή προσάρτησης δεν υπάρχει. Είτε δημιουργήστε την στο τοπικό σύστημα αρχείων σας είτε αλλάξτε την στις επιλογές κρύπτης.
unlock.error.invalidMountPoint.existing=Το σημείο/φάκελος προσάρτησης υπάρχει ήδη ή ο γονικός φάκελος λείπει: %s unlock.error.customPath.description.generic=Έχετε επιλέξει μια προσαρμοσμένη διαδρομή προσάρτησης για αυτή την κρύπτη, αλλά η χρήση της απέτυχε με το μήνυμα: %s
unlock.error.invalidMountPoint.driveLetterOccupied=Το Γράμμα Δίσκου "%s" χρησιμοποιείται ήδη.
## Hub ## Hub
hub.noKeychain.message=Δεν είναι δυνατή η πρόσβαση στο κλειδί της συσκευής
hub.noKeychain.description=Για να ξεκλειδώσετε τις κρύπτες Hub, απαιτείται ένα κλειδί συσκευής, το οποίο ασφαλίζεται με χρήση μπρελόκ. Για να συνεχίσετε, ενεργοποιήστε το "%s" και επιλέξτε ένα keychain στις προτιμήσεις.
hub.noKeychain.openBtn=Άνοιγμα Προτιμήσεων
### Waiting ### Waiting
hub.auth.message=Αναμονή για επαλήθευση… hub.auth.message=Αναμονή για επαλήθευση…
hub.auth.description=Θα πρέπει να ανακατευθυνθείτε αυτόματα στη σελίδα σύνδεσης. hub.auth.description=Θα πρέπει να ανακατευθυνθείτε αυτόματα στη σελίδα σύνδεσης.
@@ -169,8 +171,13 @@ lock.fail.description=Η κρυπτη "%s" δεν ήταν δυνατό να κ
# Migration # Migration
migration.title=Αναβάθμιση Vault migration.title=Αναβάθμιση Vault
## Start ## Start
migration.start.prompt=Το vault "%s" πρέπει να αναβαθμιστεί σε νεότερο format. Προτού προχωρήσετε, σιγουρευτείτε πως δεν εκτελούνται εργασίες συγχρονισμού που μπορεί να επηρεάσουν το vault. migration.start.header=Αναβάθμιση Κρύπτης
migration.start.confirm=Ναι, το vault μου είναι πλήρως συγχρονισμένο migration.start.text=Για να ανοίξετε την κρύπτη σας "%s" σε αυτήν τη νέα έκδοση του Cryptomator, η κρύπτη πρέπει να αναβαθμιστεί σε νεότερη μορφή. Πριν το κάνετε αυτό, θα πρέπει να γνωρίζετε τα εξής:
migration.start.remarkUndone=Αυτή η αναβάθμιση δεν μπορεί να αναιρεθεί.
migration.start.remarkVersions=Οι παλαιότερες εκδόσεις του Cryptomator δεν θα μπορούν να ανοίξουν την αναβαθμισμένη κρύπτη.
migration.start.remarkCanRun=Πρέπει να είστε βέβαιοι ότι κάθε συσκευή από την οποία αποκτάτε πρόσβαση στην κρύπτη μπορεί να εκτελέσει αυτήν την έκδοση του Cryptomator.
migration.start.remarkSynced=Πρέπει να βεβαιωθείτε ότι η κρύπτη σας είναι πλήρως συγχρονισμένη σε αυτήν τη συσκευή και σε άλλες συσκευές σας, προτού την αναβαθμίσετε.
migration.start.confirm=Έχω διαβάσει και κατανοήσει τις παραπάνω πληροφορίες
## Run ## Run
migration.run.enterPassword=Εισάγετε τον κωδικό για "%s" migration.run.enterPassword=Εισάγετε τον κωδικό για "%s"
migration.run.startMigrationBtn=Ενσωμάτωση Vault migration.run.startMigrationBtn=Ενσωμάτωση Vault
@@ -218,8 +225,25 @@ health.check.detail.checkFinished=Ο έλεγχος ολοκληρώθηκε μ
health.check.detail.checkFinishedAndFound=Ο έλεγχος σταμάτησε να εκτελείται. Παρακαλώ εξετάστε τα αποτελέσματα. health.check.detail.checkFinishedAndFound=Ο έλεγχος σταμάτησε να εκτελείται. Παρακαλώ εξετάστε τα αποτελέσματα.
health.check.detail.checkFailed=Ο έλεγχος τερματίστηκε λόγω σφάλματος. health.check.detail.checkFailed=Ο έλεγχος τερματίστηκε λόγω σφάλματος.
health.check.detail.checkCancelled=Ο έλεγχος ακυρώθηκε. health.check.detail.checkCancelled=Ο έλεγχος ακυρώθηκε.
health.check.detail.listFilters.label=Φίλτρο
health.check.detail.fixAllSpecificBtn=Επισκευή όλων των τύπων
health.check.exportBtn=Εξαγωγή Αναφοράς health.check.exportBtn=Εξαγωγή Αναφοράς
## Result view ## 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 ## Fix Application
health.fix.fixBtn=Επιδιόρθωση health.fix.fixBtn=Επιδιόρθωση
health.fix.successTip=Επιτυχής επιδιόρθωση health.fix.successTip=Επιτυχής επιδιόρθωση
@@ -251,9 +275,15 @@ preferences.interface.showMinimizeButton=Εμφάνιση κουμπιού ελ
preferences.interface.showTrayIcon=Εμφάνιση εικονιδίου tray (απαιτεί επανεκκίνηση) preferences.interface.showTrayIcon=Εμφάνιση εικονιδίου tray (απαιτεί επανεκκίνηση)
## Volume ## Volume
preferences.volume=Εικονικός δίσκος preferences.volume=Εικονικός δίσκος
preferences.volume.type=Τύπος τόμου preferences.volume.type=Τύπος Τόμου (απαιτείται επανεκκίνηση)
preferences.volume.webdav.port=Θύρα WebDAV preferences.volume.type.automatic=Αυτόματα
preferences.volume.webdav.scheme=Σχήμα WebDAV 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 ## Updates
preferences.updates=Ενημερώσεις preferences.updates=Ενημερώσεις
preferences.updates.currentVersion=Τρέχουσα έκδοση: %s preferences.updates.currentVersion=Τρέχουσα έκδοση: %s
@@ -302,6 +332,8 @@ stats.encr.total.data.gib=Δεδομένα που κρυπτογραφήθηκα
stats.write.accessCount=Συνολικές εγγραφές: %d stats.write.accessCount=Συνολικές εγγραφές: %d
## Accesses ## Accesses
stats.access.current=Πρόσβαση: %d
stats.access.total=Συνολική πρόσβαση: %d
# Main Window # Main Window
@@ -310,9 +342,6 @@ main.minimizeBtn.tooltip=Ελαχιστοποίηση
main.preferencesBtn.tooltip=Προτιμήσεις main.preferencesBtn.tooltip=Προτιμήσεις
main.debugModeEnabled.tooltip=Έχει ενεργοποιηθεί η λειτουργία αποσφαλμάτωσης main.debugModeEnabled.tooltip=Έχει ενεργοποιηθεί η λειτουργία αποσφαλμάτωσης
main.supporterCertificateMissing.tooltip=Παρακαλούμε σκεφτείτε να κάνετε δωρεά main.supporterCertificateMissing.tooltip=Παρακαλούμε σκεφτείτε να κάνετε δωρεά
## Drag 'n' Drop
main.dropZone.dropVault=Προσθήκη vault
main.dropZone.unknownDragboardContent=Αν θέλετε να προσθέσετε ένα vault, σύρετε το σε αυτό το παράθυρο
## Vault List ## Vault List
main.vaultlist.emptyList.onboardingInstruction=Κάντε κλικ εδώ για να προσθέσετε ένα vault main.vaultlist.emptyList.onboardingInstruction=Κάντε κλικ εδώ για να προσθέσετε ένα vault
main.vaultlist.contextMenu.remove=Αφαίρεση… main.vaultlist.contextMenu.remove=Αφαίρεση…
@@ -335,6 +364,7 @@ main.vaultDetail.passwordSavedInKeychain=Ο κωδικός αποθηκεύτη
main.vaultDetail.unlockedStatus=ΞΕΚΛΕΙΔΩΜΕΝΟ main.vaultDetail.unlockedStatus=ΞΕΚΛΕΙΔΩΜΕΝΟ
main.vaultDetail.accessLocation=Τα δεδομένα του vault σας είναι διαθέσιμα εδώ: main.vaultDetail.accessLocation=Τα δεδομένα του vault σας είναι διαθέσιμα εδώ:
main.vaultDetail.revealBtn=Αποκάλυψη εικονικού δίσκου main.vaultDetail.revealBtn=Αποκάλυψη εικονικού δίσκου
main.vaultDetail.copyUri=Αντιγραφή URI
main.vaultDetail.lockBtn=Κλείδωμα main.vaultDetail.lockBtn=Κλείδωμα
main.vaultDetail.bytesPerSecondRead=Ανάγνωση: main.vaultDetail.bytesPerSecondRead=Ανάγνωση:
main.vaultDetail.bytesPerSecondWritten=Εγγραφή: main.vaultDetail.bytesPerSecondWritten=Εγγραφή:
@@ -342,6 +372,10 @@ main.vaultDetail.throughput.idle=σε αδράνεια
main.vaultDetail.throughput.kbps=%.1f kiB/s main.vaultDetail.throughput.kbps=%.1f kiB/s
main.vaultDetail.throughput.mbps=%.1f MiB/s main.vaultDetail.throughput.mbps=%.1f MiB/s
main.vaultDetail.stats=Στατιστικά Vault main.vaultDetail.stats=Στατιστικά Vault
main.vaultDetail.locateEncryptedFileBtn=Εντοπισμός Κρυπτογραφημένου Αρχείου
main.vaultDetail.locateEncryptedFileBtn.tooltip=Επιλέξτε ένα αρχείο από την κρύπτη σας για να εντοπίσετε το κρυπτογραφημένο αντίστοιχο
main.vaultDetail.encryptedPathsCopied=Οι Διαδρομές Αντιγράφηκαν στο Πρόχειρο!
main.vaultDetail.filePickerTitle=Επιλογή Αρχείου Μέσα Στην Κρύπτη
### Missing ### Missing
main.vaultDetail.missing.info=Cryptomator δεν βρήκε vault σε αυτόν τον κατάλογο. main.vaultDetail.missing.info=Cryptomator δεν βρήκε vault σε αυτόν τον κατάλογο.
main.vaultDetail.missing.recheck=Επανέλεγχος main.vaultDetail.missing.recheck=Επανέλεγχος
@@ -380,15 +414,17 @@ vaultOptions.general.startHealthCheckBtn=Έναρξη ελέγχου Υγεία
## Mount ## Mount
vaultOptions.mount=Προσάρτηση vaultOptions.mount=Προσάρτηση
vaultOptions.mount.info=Οι επιλογές εξαρτώνται από τον επιλεγμένο τύπο τόμου.
vaultOptions.mount.linkToPreferences=Άνοιγμα προτιμήσεων εικονικής μονάδας δίσκου
vaultOptions.mount.readonly=Μόνο για ανάγνωση vaultOptions.mount.readonly=Μόνο για ανάγνωση
vaultOptions.mount.customMountFlags=Προσαρμοσμένες ετικέτες προσάρτησης vaultOptions.mount.customMountFlags=Προσαρμοσμένες ετικέτες προσάρτησης
vaultOptions.mount.winDriveLetterOccupied=κατειλημμένο vaultOptions.mount.winDriveLetterOccupied=κατειλημμένο
vaultOptions.mount.mountPoint=Σημείο προσάρτησης vaultOptions.mount.mountPoint=Σημείο προσάρτησης
vaultOptions.mount.mountPoint.auto=Επιλογή κατάλληλης τοποθεσίας αυτόματα vaultOptions.mount.mountPoint.auto=Επιλογή κατάλληλης τοποθεσίας αυτόματα
vaultOptions.mount.mountPoint.driveLetter=Χρήση επιλεγμένου γράμματος δίσκου vaultOptions.mount.mountPoint.driveLetter=Χρήση επιλεγμένου γράμματος δίσκου
vaultOptions.mount.mountPoint.custom=Προσαρμοσμένη διαδρομή vaultOptions.mount.mountPoint.custom=Χρήση επιλεγμένου καταλόγου
vaultOptions.mount.mountPoint.directoryPickerButton=Επιλογή… vaultOptions.mount.mountPoint.directoryPickerButton=Επιλογή…
vaultOptions.mount.mountPoint.directoryPickerTitle=Επιλέξτε ένα άδειο φάκελο vaultOptions.mount.mountPoint.directoryPickerTitle=Επιλέξτε έναν κατάλογο
## Master Key ## Master Key
vaultOptions.masterkey=Κωδικός πρόσβασης vaultOptions.masterkey=Κωδικός πρόσβασης
vaultOptions.masterkey.changePasswordBtn=Αλλαγή κωδικού πρόσβασης 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.rememberChoice=Recordar opción y no mostrar de nuevo
unlock.success.revealBtn=Revelar unidad unlock.success.revealBtn=Revelar unidad
## Failure ## Failure
unlock.error.message=No se puede desbloquear la bóveda unlock.error.customPath.message=No se puede montar la bóveda en la ruta personalizada
### Invalid Mount Point 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.invalidMountPoint.notExisting=El punto de montaje "%s"no es un directorio, no está vacío o no existe. 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.invalidMountPoint.existing=El punto de montaje "%s" ya existe o falta la carpeta padre. unlock.error.customPath.description.generic=Seleccionó una ruta de montaje personalizada para esta bóveda, pero falló al usarla con el mensaje: %s
unlock.error.invalidMountPoint.driveLetterOccupied=La letra de unidad "%s" ya está en uso.
## Hub ## 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 ### Waiting
hub.auth.message=Esperando la autenticación… hub.auth.message=Esperando la autenticación…
hub.auth.description=Debe ser redirigido automáticamente a la página de inicio de sesió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
migration.title=Actualizar bóveda migration.title=Actualizar bóveda
## Start ## 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.header=Actualizar bóveda
migration.start.confirm=Sí, mi bóveda está sincronizada 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 ## Run
migration.run.enterPassword=Ingresar la contraseña para "%s" migration.run.enterPassword=Ingresar la contraseña para "%s"
migration.run.startMigrationBtn=Migrar bóveda 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.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.checkFailed=La comprobación terminó debido a un error.
health.check.detail.checkCancelled=La comprobación se canceló. 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 health.check.exportBtn=Exportar informe
## Result view ## 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 ## Fix Application
health.fix.fixBtn=Reparar health.fix.fixBtn=Reparar
health.fix.successTip=Reparación exitosa 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) preferences.interface.showTrayIcon=Mostrar ícono de bandeja (requiere reiniciar)
## Volume ## Volume
preferences.volume=Unidad virtual preferences.volume=Unidad virtual
preferences.volume.type=Tipo de volumen preferences.volume.type=Tipo de volumen (requiere reiniciar)
preferences.volume.webdav.port=Puerto WebDAV preferences.volume.type.automatic=Automático
preferences.volume.webdav.scheme=Esquema WebDAV 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 ## Updates
preferences.updates=Actualizaciones preferences.updates=Actualizaciones
preferences.updates.currentVersion=Versión actual: %s 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 stats.write.accessCount=Total de escrituras: %d
## Accesses ## Accesses
stats.access.current=Accesos: %d
stats.access.total=Accesos totales: %d
# Main Window # Main Window
@@ -310,9 +342,6 @@ main.minimizeBtn.tooltip=Minimizar
main.preferencesBtn.tooltip=Preferencias main.preferencesBtn.tooltip=Preferencias
main.debugModeEnabled.tooltip=Modo de depuración activado main.debugModeEnabled.tooltip=Modo de depuración activado
main.supporterCertificateMissing.tooltip=Por favor, considere donar 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 ## Vault List
main.vaultlist.emptyList.onboardingInstruction=Haga clic aquí para añadir una bóveda main.vaultlist.emptyList.onboardingInstruction=Haga clic aquí para añadir una bóveda
main.vaultlist.contextMenu.remove=Eliminar… main.vaultlist.contextMenu.remove=Eliminar…
@@ -335,6 +364,7 @@ main.vaultDetail.passwordSavedInKeychain=Contraseña guardada
main.vaultDetail.unlockedStatus=DESBLOQUEADO main.vaultDetail.unlockedStatus=DESBLOQUEADO
main.vaultDetail.accessLocation=El contenido de la bóveda es accesible aquí: main.vaultDetail.accessLocation=El contenido de la bóveda es accesible aquí:
main.vaultDetail.revealBtn=Revelar unidad main.vaultDetail.revealBtn=Revelar unidad
main.vaultDetail.copyUri=Copiar URI
main.vaultDetail.lockBtn=Bloquear main.vaultDetail.lockBtn=Bloquear
main.vaultDetail.bytesPerSecondRead=Lectura: main.vaultDetail.bytesPerSecondRead=Lectura:
main.vaultDetail.bytesPerSecondWritten=Escritura: main.vaultDetail.bytesPerSecondWritten=Escritura:
@@ -342,6 +372,10 @@ main.vaultDetail.throughput.idle=inactivo
main.vaultDetail.throughput.kbps=%.1f kiB/s main.vaultDetail.throughput.kbps=%.1f kiB/s
main.vaultDetail.throughput.mbps=%.1f MiB/s main.vaultDetail.throughput.mbps=%.1f MiB/s
main.vaultDetail.stats=Estadísticas de la bóveda 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 ### Missing
main.vaultDetail.missing.info=Cryptomator no pudo encontrar una bóveda en esta ruta. main.vaultDetail.missing.info=Cryptomator no pudo encontrar una bóveda en esta ruta.
main.vaultDetail.missing.recheck=Volver a comprobar main.vaultDetail.missing.recheck=Volver a comprobar
@@ -380,15 +414,17 @@ vaultOptions.general.startHealthCheckBtn=Iniciar comprobación de estado
## Mount ## Mount
vaultOptions.mount=Montaje 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.readonly=Sólo lectura
vaultOptions.mount.customMountFlags=Opciones de montaje personalizadas vaultOptions.mount.customMountFlags=Opciones de montaje personalizadas
vaultOptions.mount.winDriveLetterOccupied=ocupado vaultOptions.mount.winDriveLetterOccupied=ocupado
vaultOptions.mount.mountPoint=Punto de montaje vaultOptions.mount.mountPoint=Punto de montaje
vaultOptions.mount.mountPoint.auto=Escoger automáticamente una ubicación adecuada vaultOptions.mount.mountPoint.auto=Escoger automáticamente una ubicación adecuada
vaultOptions.mount.mountPoint.driveLetter=Usar letra de unidad asignada 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.directoryPickerButton=Elegir…
vaultOptions.mount.mountPoint.directoryPickerTitle=Elegir un directorio vacío vaultOptions.mount.mountPoint.directoryPickerTitle=Seleccionar un directorio
## Master Key ## Master Key
vaultOptions.masterkey=Contraseña vaultOptions.masterkey=Contraseña
vaultOptions.masterkey.changePasswordBtn=Cambiar contraseña vaultOptions.masterkey.changePasswordBtn=Cambiar contraseña
+23 -2
View File
@@ -4,15 +4,22 @@
## Button ## Button
generic.button.apply=درخواست generic.button.apply=درخواست
generic.button.back=بازگشت generic.button.back=بازگشت
generic.button.cancel=انصراف
generic.button.change=تغییر generic.button.change=تغییر
generic.button.choose=انتخاب کنید…
generic.button.close=ببند
generic.button.copy=کپی generic.button.copy=کپی
generic.button.copied=کپی شد! generic.button.copied=کپی شد!
generic.button.done=انجام شده
generic.button.next=بعدی generic.button.next=بعدی
generic.button.print=چاپ generic.button.print=چاپ
# Error # Error
error.message=خطایی رخ داده است
error.technicalDetails=جزئیات:
# Defaults # Defaults
defaults.vault.vaultName=گاوصندوق
# Tray Menu # Tray Menu
traymenu.showMainWindow=نشان traymenu.showMainWindow=نشان
@@ -22,13 +29,24 @@ traymenu.vault.lock=قفل
traymenu.vault.reveal=ظاهر traymenu.vault.reveal=ظاهر
# Add Vault Wizard # Add Vault Wizard
addvaultwizard.title=اضافه کردن گاوصندوق
## Welcome ## Welcome
addvaultwizard.welcome.newButton=ساخت گاوصندوق جدید
addvaultwizard.welcome.existingButton=باز کردن گاوصندوق موجود
## New ## New
### Name ### Name
addvaultwizard.new.nameInstruction=یک نام برای گاوصندوق انتخاب کنید
addvaultwizard.new.namePrompt=نام گاوصندوق
### Location ### Location
addvaultwizard.new.locationLabel=مکان ذخیره‌سازی
addvaultwizard.new.directoryPickerLabel=مکان سفارشی
addvaultwizard.new.directoryPickerButton=انتخاب کنید…
addvaultwizard.new.fileAlreadyExists=در حال حاضر یک فایل یا پوشه با همین نام وجود دارد
addvaultwizard.new.validCharacters.numbers=اعداد
### Password ### Password
### Information ### Information
## Existing ## Existing
addvaultwizard.existing.chooseBtn=انتخاب کنید…
## Success ## Success
# Remove Vault # Remove Vault
@@ -42,7 +60,6 @@ unlock.unlockBtn=بازکردن قفل
## Select ## Select
## Success ## Success
## Failure ## Failure
### Invalid Mount Point
## Hub ## Hub
### Waiting ### Waiting
### Receive Key ### Receive Key
@@ -55,6 +72,7 @@ unlock.unlockBtn=بازکردن قفل
# Lock # Lock
## Force ## Force
lock.forced.retryBtn=تلاش مجدد
## Failure ## Failure
# Migration # Migration
@@ -90,10 +108,11 @@ unlock.unlockBtn=بازکردن قفل
# Main Window # Main Window
main.closeBtn.tooltip=ببند
main.supporterCertificateMissing.tooltip=لطفا کمک مالی در نظر بگیرند main.supporterCertificateMissing.tooltip=لطفا کمک مالی در نظر بگیرند
## Drag 'n' Drop
## Vault List ## Vault List
main.vaultlist.contextMenu.lock=قفل main.vaultlist.contextMenu.lock=قفل
main.vaultlist.addVaultBtn=اضافه کردن گاوصندوق
## Vault Detail ## Vault Detail
### Welcome ### Welcome
### Locked ### Locked
@@ -107,8 +126,10 @@ main.vaultDetail.lockBtn=قفل
# Vault Options # Vault Options
## General ## General
vaultOptions.general.vaultName=نام گاوصندوق
## Mount ## Mount
vaultOptions.mount.mountPoint.directoryPickerButton=انتخاب کنید…
## Master Key ## Master Key
@@ -66,7 +66,6 @@ unlock.unlockBtn=I-unlock
## Select ## Select
## Success ## Success
## Failure ## Failure
### Invalid Mount Point
## Hub ## Hub
### Waiting ### Waiting
### Receive Key ### Receive Key
@@ -120,7 +119,6 @@ preferences.interface.theme.light=Light
# Main Window # Main Window
main.closeBtn.tooltip=Isara main.closeBtn.tooltip=Isara
main.preferencesBtn.tooltip=Mga Kagustuhan main.preferencesBtn.tooltip=Mga Kagustuhan
## Drag 'n' Drop
## Vault List ## Vault List
main.vaultlist.contextMenu.lock=I-lock main.vaultlist.contextMenu.lock=I-lock
main.vaultlist.addVaultBtn=Magdagdag ng Vault 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.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. addvault.new.readme.accessLocation.4=Vous pouvez supprimer ce fichier.
## Existing ## 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.chooseBtn=Choisir...
addvaultwizard.existing.filePickerTitle=Sélectionnez le fichier correspondant au volume chiffré addvaultwizard.existing.filePickerTitle=Sélectionnez le fichier correspondant au volume chiffré
addvaultwizard.existing.filePickerMimeDesc=Coffre-fort Cryptomator addvaultwizard.existing.filePickerMimeDesc=Coffre-fort Cryptomator
@@ -104,7 +104,7 @@ changepassword.finalConfirmation=Je comprends que je ne pourrai pas récupérer
# Forget Password # Forget Password
forgetPassword.title=Mot de passe oublié forgetPassword.title=Mot de passe oublié
forgetPassword.message=Oublier le mot de passe enregistré ? 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 forgetPassword.confirmBtn=Oublier le mot de passe
# Unlock # 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.rememberChoice=Se souvenir de mon choix et ne plus me le demander
unlock.success.revealBtn=Révéler le lecteur unlock.success.revealBtn=Révéler le lecteur
## Failure ## Failure
unlock.error.message=Impossible de déverrouiller l'espace chiffré unlock.error.customPath.message=Impossible de monter le coffre vers le chemin personnalisé
### Invalid Mount Point 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.invalidMountPoint.notExisting=Le point de montage «%s» n'est pas un répertoire, n'est pas vide ou n'existe pas. 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.invalidMountPoint.existing=Le point de montage/le répertoire existe déjà ou le répertoire parent est manquant: %s 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
unlock.error.invalidMountPoint.driveLetterOccupied=Le lecteur "%s" est déjà utilisé.
## Hub ## 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 ### Waiting
hub.auth.message=Authentification en cours… hub.auth.message=Authentification en cours…
hub.auth.description=Vous devriez automatiquement être redirigé vers la page de connexion. 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.retryBtn=Réessayer
lock.forced.forceBtn=Forcer le verrouillage lock.forced.forceBtn=Forcer le verrouillage
## Failure ## 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. 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
migration.title=Mettre à jour le coffre migration.title=Mettre à jour le coffre
## Start ## 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.header=Mettre le coffre à jour
migration.start.confirm=Oui, mon coffre est bien synchronisé 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 ## Run
migration.run.enterPassword=Entrez le mot de passe pour %s migration.run.enterPassword=Entrez le mot de passe pour %s
migration.run.startMigrationBtn=Migrer le coffre 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.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.checkCancelled=Vérification annulée.
health.check.detail.listFilters.label=Filtre 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.detail.fixAllSpecificBtn=Corriger tout le type
health.check.exportBtn=Exporter le rapport health.check.exportBtn=Exporter le rapport
## Result view ## Result view
health.result.severityFilter.all=Gravité - Tous health.result.severityFilter.all=Gravité - Tous
health.result.severityFilter.good=Satisfaisant health.result.severityFilter.good=Bon
health.result.severityFilter.info=Information health.result.severityFilter.info=Information
health.result.severityFilter.warn=Avertissement health.result.severityFilter.warn=Avertissement
health.result.severityFilter.crit=Critique 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) preferences.interface.showTrayIcon=Montrer l'icône de service (redémarrage nécessaire)
## Volume ## Volume
preferences.volume=Disque virtuel preferences.volume=Disque virtuel
preferences.volume.type=Type de volume preferences.volume.type=Type de volume (nécessite un redémarrage)
preferences.volume.webdav.port=port WebDav preferences.volume.type.automatic=Automatique
preferences.volume.webdav.scheme=Schéma WebDAV 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 ## Updates
preferences.updates=Mises à jour preferences.updates=Mises à jour
preferences.updates.currentVersion=Version actuelle : “%s” preferences.updates.currentVersion=Version actuelle : “%s”
@@ -331,9 +342,6 @@ main.minimizeBtn.tooltip=Réduire
main.preferencesBtn.tooltip=Préférences main.preferencesBtn.tooltip=Préférences
main.debugModeEnabled.tooltip=Le mode débogage est activé main.debugModeEnabled.tooltip=Le mode débogage est activé
main.supporterCertificateMissing.tooltip=Merci d'envisager un don 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 ## Vault List
main.vaultlist.emptyList.onboardingInstruction=Cliquez ici pour ajouter un volume chiffré main.vaultlist.emptyList.onboardingInstruction=Cliquez ici pour ajouter un volume chiffré
main.vaultlist.contextMenu.remove=Retirer… main.vaultlist.contextMenu.remove=Retirer…
@@ -356,6 +364,7 @@ main.vaultDetail.passwordSavedInKeychain=Mot de passe enregistré
main.vaultDetail.unlockedStatus=DÉVERROUILLÉ main.vaultDetail.unlockedStatus=DÉVERROUILLÉ
main.vaultDetail.accessLocation=Le contenu de votre coffre est accessible ici : main.vaultDetail.accessLocation=Le contenu de votre coffre est accessible ici :
main.vaultDetail.revealBtn=Afficher le lecteur main.vaultDetail.revealBtn=Afficher le lecteur
main.vaultDetail.copyUri=Copier lURI
main.vaultDetail.lockBtn=Verrouiller main.vaultDetail.lockBtn=Verrouiller
main.vaultDetail.bytesPerSecondRead=Lecture : main.vaultDetail.bytesPerSecondRead=Lecture :
main.vaultDetail.bytesPerSecondWritten=Écriture: main.vaultDetail.bytesPerSecondWritten=Écriture:
@@ -363,6 +372,10 @@ main.vaultDetail.throughput.idle=inactif
main.vaultDetail.throughput.kbps=%.1f Ko/s main.vaultDetail.throughput.kbps=%.1f Ko/s
main.vaultDetail.throughput.mbps=%.1f Mo/s main.vaultDetail.throughput.mbps=%.1f Mo/s
main.vaultDetail.stats=Statistiques du volume chiffré 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 ### Missing
main.vaultDetail.missing.info=Cryptomator n'a pas pu trouver de volume chiffré dans ce chemin d'accès. 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 main.vaultDetail.missing.recheck=Revérifier
@@ -401,20 +414,22 @@ vaultOptions.general.startHealthCheckBtn=Commencer la vérification de l'état
## Mount ## Mount
vaultOptions.mount=Montage 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.readonly=Lecture seule
vaultOptions.mount.customMountFlags=Paramètres personnalisés de montage vaultOptions.mount.customMountFlags=Paramètres personnalisés de montage
vaultOptions.mount.winDriveLetterOccupied=occupé vaultOptions.mount.winDriveLetterOccupied=occupé
vaultOptions.mount.mountPoint=Point de montage vaultOptions.mount.mountPoint=Point de montage
vaultOptions.mount.mountPoint.auto=Choisir automatiquement un emplacement approprié vaultOptions.mount.mountPoint.auto=Choisir automatiquement un emplacement approprié
vaultOptions.mount.mountPoint.driveLetter=Utiliser la lettre du lecteur assignée 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.directoryPickerButton=Choisir...
vaultOptions.mount.mountPoint.directoryPickerTitle=Choisir un répertoire vide vaultOptions.mount.mountPoint.directoryPickerTitle=Choisissez un dossier
## Master Key ## Master Key
vaultOptions.masterkey=Mot de passe vaultOptions.masterkey=Mot de passe
vaultOptions.masterkey.changePasswordBtn=Modifier le mot de passe vaultOptions.masterkey.changePasswordBtn=Modifier le mot de passe
vaultOptions.masterkey.forgetSavedPasswordBtn=Oublier le mot de passe enregistré 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.showRecoveryKeyBtn=Afficher la clé de récupération
vaultOptions.masterkey.recoverPasswordBtn=Réinitialiser le mot de passe 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.message=Mot de passe requis
recoveryKey.create.description=Entrer le mot de passe de "%s" pour afficher sa clé de récupération. 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.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 ## Reset Password
### Enter Recovery Key ### Enter Recovery Key
recoveryKey.recover.title=Réinitialiser le mot de passe 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. recoveryKey.recover.resetSuccess.description=Vous pouvez déverrouiller votre coffre avec le nouveau mot de passe.
# New Password # 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.reenterPassword=Confirmez le nouveau mot de passe
newPassword.passwordsMatch=Mots de passe identiques ! newPassword.passwordsMatch=Mots de passe identiques !
newPassword.passwordsDoNotMatch=Les mots de passe ne sont pas identiques newPassword.passwordsDoNotMatch=Les mots de passe ne sont pas identiques
@@ -452,11 +467,11 @@ passwordStrength.messageLabel.4=Très fort
# Quit # Quit
quit.title=Quitter lapplication quit.title=Quitter lapplication
quit.message=Il y a des espaces chiffrés déverrouillés quit.message=Il y a des volumes 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.description=Veuillez confirmer la fermeture. Les volumes ouverts seront verrouillés afin d'éviter toute perte de données.
quit.lockAndQuitBtn=Verrouiller et quitter quit.lockAndQuitBtn=Verrouiller et quitter
# Forced Quit # Forced Quit
quit.forced.message=Certains coffres n'ont pas pu être verrouillés 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.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 ## Select
## Success ## Success
## Failure ## Failure
### Invalid Mount Point
## Hub ## Hub
### Waiting ### Waiting
### Receive Key ### Receive Key
@@ -91,7 +90,6 @@ lock.forced.retryBtn=Tentar de novo
# Main Window # Main Window
main.closeBtn.tooltip=Pechar main.closeBtn.tooltip=Pechar
## Drag 'n' Drop
## Vault List ## Vault List
## Vault Detail ## Vault Detail
### Welcome ### Welcome
+15 -7
View File
@@ -123,15 +123,22 @@ unlock.success.description=הנעילה ל-"%s" בוטלה בהצלחה! הכס
unlock.success.rememberChoice=זכור בחירה, אל תראה שוב unlock.success.rememberChoice=זכור בחירה, אל תראה שוב
unlock.success.revealBtn=חשוף את הכונן unlock.success.revealBtn=חשוף את הכונן
## Failure ## Failure
unlock.error.message=לא מתאפשר לבטל נעילת הכספת
### Invalid Mount Point
## Hub ## Hub
hub.noKeychain.message=לא ניתן לגשת למפתח המכשיר
### Waiting ### Waiting
hub.auth.message=ממתין לאימות…
### Receive Key ### Receive Key
### Register Device ### Register Device
hub.register.nameLabel=שם מכשיר
hub.register.occupiedMsg=שם זה נמצא כבר בשימוש
hub.register.registerBtn=אישור
### Registration Success ### Registration Success
hub.registerSuccess.message=שם המכשיר
### Registration Failed ### Registration Failed
hub.registerFailed.message=הגדרת שם למכשיר נכשלה
### Unauthorized ### Unauthorized
hub.unauthorized.message=הגישה נדחתה
hub.unauthorized.description=המכשיר שלך טרם אושר לגשת לכספת הזאת. יש לבקש אישור גישה מבעל הכספת.
### License Exceeded ### License Exceeded
@@ -146,7 +153,7 @@ lock.fail.message=נעילת הכספת נשכלה.
# Migration # Migration
migration.title=שדרג הכספת migration.title=שדרג הכספת
## Start ## Start
migration.start.confirm=כן, הכספת שלי מסונכרנת במלואה migration.start.header=שדרג הכספת
## Run ## Run
migration.run.enterPassword=הכנס/י סיסמה עבור "%s" migration.run.enterPassword=הכנס/י סיסמה עבור "%s"
migration.run.startMigrationBtn=העבר הכספת migration.run.startMigrationBtn=העבר הכספת
@@ -205,7 +212,7 @@ preferences.interface.interfaceOrientation.rtl=מימין לשמאל
preferences.interface.showMinimizeButton=הצג כפתור מזעור preferences.interface.showMinimizeButton=הצג כפתור מזעור
## Volume ## Volume
preferences.volume=כונן וירטואלי preferences.volume=כונן וירטואלי
preferences.volume.webdav.port=יציאה WebDAV preferences.volume.type.automatic=אוטומטי
## Updates ## Updates
preferences.updates=עדכונים preferences.updates=עדכונים
## Contribution ## Contribution
@@ -235,7 +242,6 @@ stats.read.total.data.none=מידע שנקרא: -
main.closeBtn.tooltip=סגור main.closeBtn.tooltip=סגור
main.preferencesBtn.tooltip=העדפות main.preferencesBtn.tooltip=העדפות
main.supporterCertificateMissing.tooltip=תרומתך תתקבל בברכה main.supporterCertificateMissing.tooltip=תרומתך תתקבל בברכה
## Drag 'n' Drop
## Vault List ## Vault List
main.vaultlist.contextMenu.lock=נעילה main.vaultlist.contextMenu.lock=נעילה
main.vaultlist.contextMenu.unlockNow=בטל נעילה כעת main.vaultlist.contextMenu.unlockNow=בטל נעילה כעת
@@ -248,6 +254,10 @@ main.vaultDetail.unlockNowBtn=בטל נעילה כעת
### Unlocked ### Unlocked
main.vaultDetail.revealBtn=חשוף את הכונן main.vaultDetail.revealBtn=חשוף את הכונן
main.vaultDetail.lockBtn=נעילה main.vaultDetail.lockBtn=נעילה
main.vaultDetail.locateEncryptedFileBtn=מצא קבצים מוצפנים
main.vaultDetail.locateEncryptedFileBtn.tooltip=בחר קובץ מהכספת שלך על מנת לאתר את הקובץ התואם המוצפן
main.vaultDetail.encryptedPathsCopied=הנתיבים הועתקו ללוח!
main.vaultDetail.filePickerTitle=בחר קובץ בתוך הכספת
### Missing ### Missing
### Needs Migration ### Needs Migration
main.vaultDetail.migrateButton=שדרג הכספת main.vaultDetail.migrateButton=שדרג הכספת
@@ -271,9 +281,7 @@ vaultOptions.general.actionAfterUnlock.reveal=חשוף את הכונן
vaultOptions.mount.readonly=קריאה בלבד vaultOptions.mount.readonly=קריאה בלבד
vaultOptions.mount.winDriveLetterOccupied=בשימוש vaultOptions.mount.winDriveLetterOccupied=בשימוש
vaultOptions.mount.mountPoint=נקודת עיגון vaultOptions.mount.mountPoint=נקודת עיגון
vaultOptions.mount.mountPoint.custom=תיקייה מותאמת אישית
vaultOptions.mount.mountPoint.directoryPickerButton=בחר... vaultOptions.mount.mountPoint.directoryPickerButton=בחר...
vaultOptions.mount.mountPoint.directoryPickerTitle=בחירת ספרייה ריקה
## Master Key ## Master Key
vaultOptions.masterkey=סיסמה vaultOptions.masterkey=סיסמה
vaultOptions.masterkey.changePasswordBtn=שנה סיסמה vaultOptions.masterkey.changePasswordBtn=שנה סיסמה
+21 -5
View File
@@ -80,8 +80,10 @@ addvault.new.readme.accessLocation.3=इस वॉल्यूम में क
addvault.new.readme.accessLocation.4=आप इस फाइल को बेझिझक डिलीट कर सकते हैं। addvault.new.readme.accessLocation.4=आप इस फाइल को बेझिझक डिलीट कर सकते हैं।
## Existing ## Existing
addvaultwizard.existing.chooseBtn=चुनें… addvaultwizard.existing.chooseBtn=चुनें…
addvaultwizard.existing.filePickerTitle=तिजोरी फ़ाइल चुनें
addvaultwizard.existing.filePickerMimeDesc=क्रिप्टोमेटर वॉल्ट addvaultwizard.existing.filePickerMimeDesc=क्रिप्टोमेटर वॉल्ट
## Success ## Success
addvaultwizard.success.nextStepsInstructions="%s" नामक तिजोरी शामिल हो गई।\n तिजोरी में प्रवेश या कुछ सम्मिलित करने के लिए आपको इसे खोलना होगा। वैकल्पिक रूप से आप इसे बाद में कभी भी खोल सकते हैं।
addvaultwizard.success.unlockNow=अब अनलॉक करें addvaultwizard.success.unlockNow=अब अनलॉक करें
# Remove Vault # Remove Vault
@@ -112,8 +114,6 @@ unlock.success.message=अनलॉक सफल हुआ
unlock.success.rememberChoice=विकल्प याद रखें, दोबारा ना दिखाएं unlock.success.rememberChoice=विकल्प याद रखें, दोबारा ना दिखाएं
unlock.success.revealBtn=फोल्डर खोलें unlock.success.revealBtn=फोल्डर खोलें
## Failure ## Failure
unlock.error.message=वॉल्ट को अनलॉक करना असफल हुआ
### Invalid Mount Point
## Hub ## Hub
### Waiting ### Waiting
### Receive Key ### Receive Key
@@ -125,6 +125,7 @@ hub.register.registerBtn=पुष्टि करें
### Registration Success ### Registration Success
### Registration Failed ### Registration Failed
### Unauthorized ### Unauthorized
hub.unauthorized.message=प्रवेश अस्वीकृत
### License Exceeded ### License Exceeded
@@ -132,14 +133,17 @@ hub.register.registerBtn=पुष्टि करें
## Force ## Force
lock.forced.message=लॉक करना विफल हुआ lock.forced.message=लॉक करना विफल हुआ
lock.forced.retryBtn=पुन: प्रयास करें lock.forced.retryBtn=पुन: प्रयास करें
lock.forced.forceBtn=जबर्दस्ती बंद करें
## Failure ## Failure
lock.fail.message=लॉक करना विफल lock.fail.message=लॉक करना विफल
# Migration # Migration
migration.title=वाउल्ट को अपग्रेड करें migration.title=वाउल्ट को अपग्रेड करें
## Start ## Start
migration.start.header=वाउल्ट को अपग्रेड करें
## Run ## Run
migration.run.enterPassword="%s" का पासवर्ड दर्ज करें: migration.run.enterPassword="%s" का पासवर्ड दर्ज करें:
migration.run.startMigrationBtn=तिजोरी स्थानांतरित करें
migration.run.progressHint=इसमें थोड़ा समय लग सकता है... migration.run.progressHint=इसमें थोड़ा समय लग सकता है...
## Success ## Success
migration.success.unlockNow=अब अनलॉक करें migration.success.unlockNow=अब अनलॉक करें
@@ -148,10 +152,18 @@ migration.success.unlockNow=अब अनलॉक करें
# Health Check # Health Check
## Start ## Start
health.intro.header=स्वास्थ्य जाँच
health.intro.remarkFix=सभी समस्याओं को ठीक नहीं किया जा सकता।
## Start Failure ## Start Failure
## Check Selection ## Check Selection
## Detail view ## Detail view
health.check.detail.listFilters.label=छांटे
## Result view ## Result view
health.result.severityFilter.all=गंभीरता - सारे
health.result.severityFilter.good=कुशल
health.result.severityFilter.info=सूचना
health.result.severityFilter.warn=चेतावनी
health.result.severityFilter.crit=गंभीर
## Fix Application ## Fix Application
# Preferences # Preferences
@@ -164,10 +176,17 @@ preferences.general.autoStart=क्रिप्टोमेटर को सि
preferences.interface.theme.automatic=ऑटोमैटिक preferences.interface.theme.automatic=ऑटोमैटिक
preferences.interface.theme.dark=डार्क preferences.interface.theme.dark=डार्क
preferences.interface.theme.light=लाइट preferences.interface.theme.light=लाइट
preferences.interface.language=भाषा (पुनः प्रारंभ आवश्यक)
preferences.interface.language.auto=सिस्टम निर्धारित
preferences.interface.interfaceOrientation.ltr=बाएं से दाएं preferences.interface.interfaceOrientation.ltr=बाएं से दाएं
preferences.interface.interfaceOrientation.rtl=दाएं से बाएं preferences.interface.interfaceOrientation.rtl=दाएं से बाएं
## Volume ## Volume
preferences.volume.type.automatic=ऑटोमैटिक
## Updates ## Updates
preferences.updates=नवीनीकरण
preferences.updates.currentVersion=वर्तमान संस्करण: %s
preferences.updates.checkNowBtn=अभी जाँचें
preferences.updates.updateAvailable=संस्करण %s की तरफ नवीनीकरण उपलब्ध है।
## Contribution ## Contribution
preferences.contribute=हमें सपोर्ट करें preferences.contribute=हमें सपोर्ट करें
#<-- Add entries for donations and code/translation/documentation contribution --> #<-- Add entries for donations and code/translation/documentation contribution -->
@@ -185,7 +204,6 @@ preferences.contribute=हमें सपोर्ट करें
main.closeBtn.tooltip=बंद करें main.closeBtn.tooltip=बंद करें
main.preferencesBtn.tooltip=प्राथमिकताएं main.preferencesBtn.tooltip=प्राथमिकताएं
main.supporterCertificateMissing.tooltip=कृपया दान पर विचार करें। main.supporterCertificateMissing.tooltip=कृपया दान पर विचार करें।
## Drag 'n' Drop
## Vault List ## Vault List
main.vaultlist.emptyList.onboardingInstruction=वॉल्ट को डालने के लिए यहाँ क्लिक करें। main.vaultlist.emptyList.onboardingInstruction=वॉल्ट को डालने के लिए यहाँ क्लिक करें।
main.vaultlist.contextMenu.remove=हटाएँ... main.vaultlist.contextMenu.remove=हटाएँ...
@@ -231,9 +249,7 @@ vaultOptions.mount.winDriveLetterOccupied=इसका इस्तेमाल
vaultOptions.mount.mountPoint=माउंट पॉइंट vaultOptions.mount.mountPoint=माउंट पॉइंट
vaultOptions.mount.mountPoint.auto=स्वचालित रूप से एक उपयुक्त स्थान चुनें vaultOptions.mount.mountPoint.auto=स्वचालित रूप से एक उपयुक्त स्थान चुनें
vaultOptions.mount.mountPoint.driveLetter=नियुक्त किए गए ड्राइव अक्षर का उपयोग करें vaultOptions.mount.mountPoint.driveLetter=नियुक्त किए गए ड्राइव अक्षर का उपयोग करें
vaultOptions.mount.mountPoint.custom=अपने पसंद की जगह
vaultOptions.mount.mountPoint.directoryPickerButton=चुनें… vaultOptions.mount.mountPoint.directoryPickerButton=चुनें…
vaultOptions.mount.mountPoint.directoryPickerTitle=कोई खाली जगह चुने
## Master Key ## Master Key
vaultOptions.masterkey=पासवर्ड vaultOptions.masterkey=पासवर्ड
vaultOptions.masterkey.changePasswordBtn=पासवर्ड बदलें 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.rememberChoice=Zapamti izbor, ne prikazuj ovo više
unlock.success.revealBtn=Otkrij pogon unlock.success.revealBtn=Otkrij pogon
## Failure ## 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 ## Hub
### Waiting ### Waiting
### Receive Key ### Receive Key
@@ -142,8 +137,8 @@ lock.fail.description=Trezor "%s" ne može se zaključati. Osigurajte da je nepo
# Migration # Migration
migration.title=Nadogradi trezor migration.title=Nadogradi trezor
## Start ## 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.header=Nadogradi trezor
migration.start.confirm=Da, moj trezor je u cijelosti sinkroniziran migration.start.confirm=Pročitao/la sam i razumijem gore-navedene informacije
## Run ## Run
migration.run.enterPassword=Unesite lozinku za "%s" migration.run.enterPassword=Unesite lozinku za "%s"
migration.run.startMigrationBtn=Nadogradi trezor 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) preferences.interface.showTrayIcon=Pokaži ikonu u traci (zahtjeva ponovno pokretanje)
## Volume ## Volume
preferences.volume=Virtualni pogon preferences.volume=Virtualni pogon
preferences.volume.type=Tip volumena preferences.volume.type.automatic=Automatski
preferences.volume.webdav.port=WebDAV port
preferences.volume.webdav.scheme=WebDAV shema
## Updates ## Updates
preferences.updates=Ažuriranja preferences.updates=Ažuriranja
preferences.updates.currentVersion=Trenutna verzija: %s preferences.updates.currentVersion=Trenutna verzija: %s
@@ -282,9 +275,6 @@ main.minimizeBtn.tooltip=Smanji
main.preferencesBtn.tooltip=Postavke main.preferencesBtn.tooltip=Postavke
main.debugModeEnabled.tooltip=Način otklanjanja pogrešaka je omogućen main.debugModeEnabled.tooltip=Način otklanjanja pogrešaka je omogućen
main.supporterCertificateMissing.tooltip=Molimo razmislite o doniranju 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 ## Vault List
main.vaultlist.emptyList.onboardingInstruction=Pritisnite ovdje da biste dodali trezor main.vaultlist.emptyList.onboardingInstruction=Pritisnite ovdje da biste dodali trezor
main.vaultlist.contextMenu.remove=Ukloni… main.vaultlist.contextMenu.remove=Ukloni…
@@ -358,9 +348,7 @@ vaultOptions.mount.winDriveLetterOccupied=zauzeto
vaultOptions.mount.mountPoint=Točka montiranja vaultOptions.mount.mountPoint=Točka montiranja
vaultOptions.mount.mountPoint.auto=Automatski odaberi prikladnu lokaciju vaultOptions.mount.mountPoint.auto=Automatski odaberi prikladnu lokaciju
vaultOptions.mount.mountPoint.driveLetter=Koristi dodijeljeno slovo pogona vaultOptions.mount.mountPoint.driveLetter=Koristi dodijeljeno slovo pogona
vaultOptions.mount.mountPoint.custom=Prilagođeni put
vaultOptions.mount.mountPoint.directoryPickerButton=Odaberite… vaultOptions.mount.mountPoint.directoryPickerButton=Odaberite…
vaultOptions.mount.mountPoint.directoryPickerTitle=Odaberi praznu mapu
## Master Key ## Master Key
vaultOptions.masterkey=Lozinka vaultOptions.masterkey=Lozinka
vaultOptions.masterkey.changePasswordBtn=Promijeni lozinku 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.rememberChoice=Jegyezze meg a választást és ne mutassa többet
unlock.success.revealBtn=Széf megjelenítése unlock.success.revealBtn=Széf megjelenítése
## Failure ## 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 ## Hub
### Waiting ### Waiting
### Receive Key ### 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
migration.title=Széf frissítése migration.title=Széf frissítése
## Start ## 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.header=Széf frissítése
migration.start.confirm=Igen, a széfem teljes mértékben szinkronizálva van migration.start.confirm=Elolvastam és megértettem a fenti információkat
## Run ## Run
migration.run.enterPassword=Írja be a jelszót a következőhöz Enter the password for "%s" 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 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) preferences.interface.showTrayIcon=Tálca ikon megjelenítése (újraindítás szükséges)
## Volume ## Volume
preferences.volume=Virtuális meghajtó preferences.volume=Virtuális meghajtó
preferences.volume.type=Kötet tipusa preferences.volume.type.automatic=Automatikus
preferences.volume.webdav.port=WebDAV port
preferences.volume.webdav.scheme=WebDAV vázlat
## Updates ## Updates
preferences.updates=Frissítések preferences.updates=Frissítések
preferences.updates.currentVersion=Jelenlegi verzió: %s preferences.updates.currentVersion=Jelenlegi verzió: %s
@@ -279,9 +272,6 @@ main.minimizeBtn.tooltip=Minimalizálás
main.preferencesBtn.tooltip=Beállítások main.preferencesBtn.tooltip=Beállítások
main.debugModeEnabled.tooltip=A hibakeresési mód aktiválva van main.debugModeEnabled.tooltip=A hibakeresési mód aktiválva van
main.supporterCertificateMissing.tooltip=Kérjük, fontolja meg az adományozást 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 ## Vault List
main.vaultlist.emptyList.onboardingInstruction=Kattintson ide egy széf hozzáadásához main.vaultlist.emptyList.onboardingInstruction=Kattintson ide egy széf hozzáadásához
main.vaultlist.contextMenu.remove=Eltávolítás… 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=Csatolási pont
vaultOptions.mount.mountPoint.auto=Válasszon egy megfelelő helyet automatikusan 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.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.directoryPickerButton=Kiválaszt…
vaultOptions.mount.mountPoint.directoryPickerTitle=Válasszon egy üres könyvtárat
## Master Key ## Master Key
vaultOptions.masterkey=Jelszó vaultOptions.masterkey=Jelszó
vaultOptions.masterkey.changePasswordBtn=Jelszó megváltoztatása 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.rememberChoice=Ingat pilihan saya, jangan perlihatkan lagi
unlock.success.revealBtn=Tampilkan Drive unlock.success.revealBtn=Tampilkan Drive
## Failure ## 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 ## Hub
### Waiting ### Waiting
### Receive Key ### Receive Key
@@ -142,8 +137,8 @@ lock.fail.description=Vault "%s" tidak dapat dikunci. Pastikan bahwa file yang b
# Migration # Migration
migration.title=Tingkatkan Vault migration.title=Tingkatkan Vault
## Start ## 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.header=Tingkatkan Vault
migration.start.confirm=Ya, vault saya sepenuhnya tersinkronisasi migration.start.confirm=Saya telah membaca dan memahami informasi di atas
## Run ## Run
migration.run.enterPassword=Masukkan kata sandi untuk "%s" migration.run.enterPassword=Masukkan kata sandi untuk "%s"
migration.run.startMigrationBtn=Pindahkan Vault 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) preferences.interface.showTrayIcon=Tampilkan ikon tray (aplikasi perlu dimuat ulang)
## Volume ## Volume
preferences.volume=Drive Virtual preferences.volume=Drive Virtual
preferences.volume.type=Jenis Volume preferences.volume.type.automatic=Otomatis
preferences.volume.webdav.port=Port WebDAV
preferences.volume.webdav.scheme=Skema WebDAV
## Updates ## Updates
preferences.updates=Pembaharuan preferences.updates=Pembaharuan
preferences.updates.currentVersion=Versi Saat Ini: %s preferences.updates.currentVersion=Versi Saat Ini: %s
@@ -282,9 +275,6 @@ main.minimizeBtn.tooltip=Perkecil
main.preferencesBtn.tooltip=Preferensi main.preferencesBtn.tooltip=Preferensi
main.debugModeEnabled.tooltip=Mode Debug diaktifkan main.debugModeEnabled.tooltip=Mode Debug diaktifkan
main.supporterCertificateMissing.tooltip=Tolong pertimbangkan untuk melakukan donasi 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 ## Vault List
main.vaultlist.emptyList.onboardingInstruction=Klik di sini untuk menambahkan vault main.vaultlist.emptyList.onboardingInstruction=Klik di sini untuk menambahkan vault
main.vaultlist.contextMenu.remove=Hapus… main.vaultlist.contextMenu.remove=Hapus…
@@ -358,9 +348,7 @@ vaultOptions.mount.winDriveLetterOccupied=terpakai
vaultOptions.mount.mountPoint=Titik Pasang vaultOptions.mount.mountPoint=Titik Pasang
vaultOptions.mount.mountPoint.auto=Secara otomatis memilih lokasi yang sesuai vaultOptions.mount.mountPoint.auto=Secara otomatis memilih lokasi yang sesuai
vaultOptions.mount.mountPoint.driveLetter=Gunakan drive letter yang sudah ditetapkan vaultOptions.mount.mountPoint.driveLetter=Gunakan drive letter yang sudah ditetapkan
vaultOptions.mount.mountPoint.custom=Path khusus
vaultOptions.mount.mountPoint.directoryPickerButton=Pilih… vaultOptions.mount.mountPoint.directoryPickerButton=Pilih…
vaultOptions.mount.mountPoint.directoryPickerTitle=Pilih direktori kosong
## Master Key ## Master Key
vaultOptions.masterkey=Kata Sandi vaultOptions.masterkey=Kata Sandi
vaultOptions.masterkey.changePasswordBtn=Ubah 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.rememberChoice=Ricorda la scelta, non mostrarmelo più
unlock.success.revealBtn=Rivela l'Unità unlock.success.revealBtn=Rivela l'Unità
## Failure ## Failure
unlock.error.message=Impossibile sbloccare la cassaforte unlock.error.customPath.message=Impossibile montare la cassaforte sul percorso personalizzato
### Invalid Mount Point 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.invalidMountPoint.notExisting=Il punto di montaggio "%s" non è una cartella, non è vuoto o non esiste. 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.invalidMountPoint.existing=Il punto di montaggio "%s" esiste già o la cartella madre è mancante. unlock.error.customPath.description.generic=Hai selezionato un percorso di montaggio personalizzato per questa cassaforte, ma il suo utilizzo è fallito col messaggio: %s
unlock.error.invalidMountPoint.driveLetterOccupied=La lettera di unità "%s" è già in uso.
## Hub ## 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 ### Waiting
hub.auth.message=In attesa di autenticazione… hub.auth.message=In attesa di autenticazione…
hub.auth.description=Dovresti essere reindirizzato automaticamente alla pagina di login. 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
migration.title=Aggiorna la Cassaforte migration.title=Aggiorna la Cassaforte
## Start ## 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.header=Aggiorna la Cassaforte
migration.start.confirm=Sì, la mia cassaforte è completamente sincronizzata 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 ## Run
migration.run.enterPassword=Inserisci la password per "%s" migration.run.enterPassword=Inserisci la password per "%s"
migration.run.startMigrationBtn=Migra la Cassaforte 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.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.checkFailed=Il controllo è terminato a causa di un errore.
health.check.detail.checkCancelled=Il controllo è stato annullato. 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 health.check.exportBtn=Esporta il Rapporto
## Result view ## 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 ## Fix Application
health.fix.fixBtn=Correggi health.fix.fixBtn=Correggi
health.fix.successTip=Correzione riuscita 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) preferences.interface.showTrayIcon=Mostra l'icona della barra d'applicazioni (richiede il riavvio)
## Volume ## Volume
preferences.volume=Unità Virtuale preferences.volume=Unità Virtuale
preferences.volume.type=Tipo di Volume preferences.volume.type=Tipo di volume (richiede riavvio)
preferences.volume.webdav.port=Porta WebDAV preferences.volume.type.automatic=Automatico
preferences.volume.webdav.scheme=Schema WebDAV 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 ## Updates
preferences.updates=Aggiornamenti preferences.updates=Aggiornamenti
preferences.updates.currentVersion=Versione Corrente: %s 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 stats.write.accessCount=Scritture totali: %d
## Accesses ## Accesses
stats.access.current=Accesso: %d
stats.access.total=Accesso totale: %d
# Main Window # Main Window
@@ -310,9 +342,6 @@ main.minimizeBtn.tooltip=Minimizza
main.preferencesBtn.tooltip=Preferenze main.preferencesBtn.tooltip=Preferenze
main.debugModeEnabled.tooltip=La modalità di debug è abilitata main.debugModeEnabled.tooltip=La modalità di debug è abilitata
main.supporterCertificateMissing.tooltip=Per favore, considera le donazioni 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 ## Vault List
main.vaultlist.emptyList.onboardingInstruction=Clicca qui per aggiungere una cassaforte main.vaultlist.emptyList.onboardingInstruction=Clicca qui per aggiungere una cassaforte
main.vaultlist.contextMenu.remove=Rimuovi… main.vaultlist.contextMenu.remove=Rimuovi…
@@ -335,6 +364,7 @@ main.vaultDetail.passwordSavedInKeychain=Password salvata
main.vaultDetail.unlockedStatus=SBLOCCATA main.vaultDetail.unlockedStatus=SBLOCCATA
main.vaultDetail.accessLocation=I contenuti della tua cassaforte sono accessibili qui: main.vaultDetail.accessLocation=I contenuti della tua cassaforte sono accessibili qui:
main.vaultDetail.revealBtn=Rivela Unità main.vaultDetail.revealBtn=Rivela Unità
main.vaultDetail.copyUri=Copia URI
main.vaultDetail.lockBtn=Blocca main.vaultDetail.lockBtn=Blocca
main.vaultDetail.bytesPerSecondRead=Lettura: main.vaultDetail.bytesPerSecondRead=Lettura:
main.vaultDetail.bytesPerSecondWritten=Scrittura: main.vaultDetail.bytesPerSecondWritten=Scrittura:
@@ -342,6 +372,10 @@ main.vaultDetail.throughput.idle=inattivo
main.vaultDetail.throughput.kbps=%.1f kiB/s main.vaultDetail.throughput.kbps=%.1f kiB/s
main.vaultDetail.throughput.mbps=%.1f MiB/s main.vaultDetail.throughput.mbps=%.1f MiB/s
main.vaultDetail.stats=Statistiche della Cassaforte 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 ### Missing
main.vaultDetail.missing.info=Cryptomator non è riuscito a trovare una cassaforte in questo percorso. main.vaultDetail.missing.info=Cryptomator non è riuscito a trovare una cassaforte in questo percorso.
main.vaultDetail.missing.recheck=Ricontrolla main.vaultDetail.missing.recheck=Ricontrolla
@@ -380,15 +414,17 @@ vaultOptions.general.startHealthCheckBtn=Avvia il Controllo della Salute
## Mount ## Mount
vaultOptions.mount=Montaggio 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.readonly=Sola Lettura
vaultOptions.mount.customMountFlags=Flag di Montaggio Personalizzati vaultOptions.mount.customMountFlags=Flag di Montaggio Personalizzati
vaultOptions.mount.winDriveLetterOccupied=occupato vaultOptions.mount.winDriveLetterOccupied=occupato
vaultOptions.mount.mountPoint=Punto di Montaggio vaultOptions.mount.mountPoint=Punto di Montaggio
vaultOptions.mount.mountPoint.auto=Scegli automaticamente una posizione idonea vaultOptions.mount.mountPoint.auto=Scegli automaticamente una posizione idonea
vaultOptions.mount.mountPoint.driveLetter=Usa la lettera del drive assegnata 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.directoryPickerButton=Scegli…
vaultOptions.mount.mountPoint.directoryPickerTitle=Scegli una directory vuota vaultOptions.mount.mountPoint.directoryPickerTitle=Scegli una directory
## Master Key ## Master Key
vaultOptions.masterkey=Password vaultOptions.masterkey=Password
vaultOptions.masterkey.changePasswordBtn=Modifica password vaultOptions.masterkey.changePasswordBtn=Modifica password
+51 -25
View File
@@ -26,7 +26,7 @@ defaults.vault.vaultName=金庫
# Tray Menu # Tray Menu
traymenu.showMainWindow=表示 traymenu.showMainWindow=表示
traymenu.showPreferencesWindow=設定 traymenu.showPreferencesWindow=環境設定
traymenu.lockAllVaults=すべて施錠 traymenu.lockAllVaults=すべて施錠
traymenu.quitApplication=終了 traymenu.quitApplication=終了
traymenu.vault.unlock=解錠 traymenu.vault.unlock=解錠
@@ -116,19 +116,20 @@ unlock.unlockBtn=解錠
unlock.chooseMasterkey.message=Masterkey ファイルが見つかりません unlock.chooseMasterkey.message=Masterkey ファイルが見つかりません
unlock.chooseMasterkey.description=必要な場所にこの金庫の masterkey ファイルがありませんでした。ファイルを手動で選択してください。 unlock.chooseMasterkey.description=必要な場所にこの金庫の masterkey ファイルがありませんでした。ファイルを手動で選択してください。
unlock.chooseMasterkey.filePickerTitle=Masterkey ファイルを選択 unlock.chooseMasterkey.filePickerTitle=Masterkey ファイルを選択
unlock.chooseMasterkey.filePickerMimeDesc=Cryptomatorのマスターキー unlock.chooseMasterkey.filePickerMimeDesc=Cryptomator のマスターキー
## Success ## Success
unlock.success.message=解錠に成功しました unlock.success.message=解錠に成功しました
unlock.success.description="%s" の解錠に成功しました! 仮想ドライブから金庫にアクセス可能です。 unlock.success.description="%s" の解錠に成功しました! 仮想ドライブから金庫にアクセス可能です。
unlock.success.rememberChoice=選択を記憶させて、再度表示しない unlock.success.rememberChoice=選択を記憶させて、再度表示しない
unlock.success.revealBtn=金庫内を表示 unlock.success.revealBtn=ドライブを表示
## Failure ## Failure
unlock.error.message=金庫の解錠に失敗 unlock.error.customPath.message=カスタム パスに金庫をマウントできません
### Invalid Mount Point unlock.error.customPath.description.notSupported=カスタム パスを使い続けたい場合、環境設定に移動してサポートしているボリューム タイプを選択してください。もしくは、金庫のオプションに移動してサポートされるマウント ポイントを選択してください。
unlock.error.invalidMountPoint.notExisting=マウントポイントが空のディレクトリか存在していません: %s unlock.error.customPath.description.notExists=カスタム マウント パスが存在していません。ローカル ファイルシステムで作成するか、金庫のオプションで変更を加えてください。
unlock.error.invalidMountPoint.existing=マウント ポイント "%s" が既に存在するか、親フォルダーがありません。
unlock.error.invalidMountPoint.driveLetterOccupied=ドライブレター「%s」は既に使用されています。
## Hub ## Hub
hub.noKeychain.message=デバイス キーにアクセスできません
hub.noKeychain.description=ハブ金庫を解錠するには、キーチェーンが保護するデバイス キーが必要です。続行するには、"%s" を有効にし環境設定からキーチェーンを選択します。
hub.noKeychain.openBtn=環境設定を開く
### Waiting ### Waiting
hub.auth.message=認証を待機中… hub.auth.message=認証を待機中…
hub.auth.description=ログイン ページに自動的にリダイレクトされます。 hub.auth.description=ログイン ページに自動的にリダイレクトされます。
@@ -169,8 +170,10 @@ lock.fail.description=金庫 "%s" を施錠できませんでした。保存さ
# Migration # Migration
migration.title=金庫をアップグレード migration.title=金庫をアップグレード
## Start ## Start
migration.start.prompt="%s" を新しいフォーマットに更新する必要があります。続行する前に、この金庫に影響する保留中の同期がないことをご確認ください。 migration.start.header=金庫をアップグレード
migration.start.confirm=はい。同期が完了しています migration.start.remarkUndone=このアップグレードは取り消すことができません。
migration.start.remarkVersions=古い Cryptomator では、アップグレードされた金庫を開くことができなくなります。
migration.start.confirm=上記の情報を理解しました。
## Run ## Run
migration.run.enterPassword="%s" のパスワードを入力してください migration.run.enterPassword="%s" のパスワードを入力してください
migration.run.startMigrationBtn=金庫を移行 migration.run.startMigrationBtn=金庫を移行
@@ -218,21 +221,38 @@ health.check.detail.checkFinished=チェックが正常に終了しました。
health.check.detail.checkFinishedAndFound=実行中のチェックが終了しました。結果を確認してください。 health.check.detail.checkFinishedAndFound=実行中のチェックが終了しました。結果を確認してください。
health.check.detail.checkFailed=エラーが発生したためチェックを終了しました。 health.check.detail.checkFailed=エラーが発生したためチェックを終了しました。
health.check.detail.checkCancelled=チェックがキャンセルされました。 health.check.detail.checkCancelled=チェックがキャンセルされました。
health.check.detail.listFilters.label=フィルター
health.check.detail.fixAllSpecificBtn=すべての種類を修正する
health.check.exportBtn=結果をエクスポート health.check.exportBtn=結果をエクスポート
## Result view ## 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 ## Fix Application
health.fix.fixBtn=修正 health.fix.fixBtn=修正
health.fix.successTip=正常に修正されました health.fix.successTip=正常に修正されました
health.fix.failTip=修正に失敗しました。詳細はログを参照してください。 health.fix.failTip=修正に失敗しました。詳細はログを参照してください。
# Preferences # Preferences
preferences.title=設定 preferences.title=環境設定
## General ## General
preferences.general=基本設定 preferences.general=基本設定
preferences.general.startHidden=Cryptomator を開始したときウィンドウを隠す preferences.general.startHidden=Cryptomator を開始したときウィンドウを隠す
preferences.general.autoCloseVaults=アプリケーションを終了するときに自動的に開いている金庫を施錠する preferences.general.autoCloseVaults=アプリケーションを終了するときに自動的に開いている金庫を施錠する
preferences.general.debugLogging=ログを有効にする preferences.general.debugLogging=ログを有効にする
preferences.general.debugDirectory=ログファイルを表示 preferences.general.debugDirectory=ログ ファイルを表示
preferences.general.autoStart=システム開始時に Cryptomator を起動する preferences.general.autoStart=システム開始時に Cryptomator を起動する
preferences.general.keychainBackend=次を利用してパスワードを保存する preferences.general.keychainBackend=次を利用してパスワードを保存する
## Interface ## Interface
@@ -251,9 +271,11 @@ preferences.interface.showMinimizeButton=最小化ボタンを表示
preferences.interface.showTrayIcon=トレイアイコンを表示 (再起動が必要) preferences.interface.showTrayIcon=トレイアイコンを表示 (再起動が必要)
## Volume ## Volume
preferences.volume=仮想ドライブ preferences.volume=仮想ドライブ
preferences.volume.type=マウント方法 preferences.volume.type=ボリューム タイプ (再起動が必要)
preferences.volume.webdav.port=WebDAV ポート preferences.volume.type.automatic=自動
preferences.volume.webdav.scheme=WebDAV スキーム preferences.volume.tcp.port=TCP ポート
preferences.volume.feature.mountFlags=カスタム マウント オプション
preferences.volume.feature.readOnly=読み取り専用マウント
## Updates ## Updates
preferences.updates=更新 preferences.updates=更新
preferences.updates.currentVersion=現在のバージョン: %s preferences.updates.currentVersion=現在のバージョン: %s
@@ -302,19 +324,18 @@ stats.encr.total.data.gib=暗号化済みデータ: %.1f GiB
stats.write.accessCount=合計書き込み: %d stats.write.accessCount=合計書き込み: %d
## Accesses ## Accesses
stats.access.current=アクセス: %d
stats.access.total=合計アクセス: %d
# Main Window # Main Window
main.closeBtn.tooltip=閉じる main.closeBtn.tooltip=閉じる
main.minimizeBtn.tooltip=最小化 main.minimizeBtn.tooltip=最小化
main.preferencesBtn.tooltip=設定 main.preferencesBtn.tooltip=環境設定
main.debugModeEnabled.tooltip=デバッグモードが有効です main.debugModeEnabled.tooltip=デバッグモードが有効です
main.supporterCertificateMissing.tooltip=寄付をお願いします main.supporterCertificateMissing.tooltip=寄付をお願いします
## Drag 'n' Drop
main.dropZone.dropVault=この金庫を追加
main.dropZone.unknownDragboardContent=このウィンドウにドラッグして、金庫を追加
## Vault List ## Vault List
main.vaultlist.emptyList.onboardingInstruction=ここをクリックして金庫を追加 main.vaultlist.emptyList.onboardingInstruction=ここをクリックして金庫を追加します
main.vaultlist.contextMenu.remove=削除... main.vaultlist.contextMenu.remove=削除...
main.vaultlist.contextMenu.lock=施錠 main.vaultlist.contextMenu.lock=施錠
main.vaultlist.contextMenu.unlock=解錠... main.vaultlist.contextMenu.unlock=解錠...
@@ -335,6 +356,7 @@ main.vaultDetail.passwordSavedInKeychain=パスワードを保存しました
main.vaultDetail.unlockedStatus=解錠済み main.vaultDetail.unlockedStatus=解錠済み
main.vaultDetail.accessLocation=金庫の内容はこちらからアクセスできます: main.vaultDetail.accessLocation=金庫の内容はこちらからアクセスできます:
main.vaultDetail.revealBtn=ドライブを表示 main.vaultDetail.revealBtn=ドライブを表示
main.vaultDetail.copyUri=URI をコピー
main.vaultDetail.lockBtn=施錠 main.vaultDetail.lockBtn=施錠
main.vaultDetail.bytesPerSecondRead=読み取り: main.vaultDetail.bytesPerSecondRead=読み取り:
main.vaultDetail.bytesPerSecondWritten=書き込み: main.vaultDetail.bytesPerSecondWritten=書き込み:
@@ -342,6 +364,9 @@ main.vaultDetail.throughput.idle=アイドル
main.vaultDetail.throughput.kbps=%.1f kiB/s main.vaultDetail.throughput.kbps=%.1f kiB/s
main.vaultDetail.throughput.mbps=%.1f MiB/s main.vaultDetail.throughput.mbps=%.1f MiB/s
main.vaultDetail.stats=金庫の統計情報 main.vaultDetail.stats=金庫の統計情報
main.vaultDetail.locateEncryptedFileBtn=暗号化されたファイルの場所
main.vaultDetail.locateEncryptedFileBtn.tooltip=暗号化された金庫のファイルを選択してください
main.vaultDetail.encryptedPathsCopied=パスをクリップボードにコピーしました!
### Missing ### Missing
main.vaultDetail.missing.info=Cryptomator はこの場所に金庫を見つけることができませんでした。 main.vaultDetail.missing.info=Cryptomator はこの場所に金庫を見つけることができませんでした。
main.vaultDetail.missing.recheck=再確認 main.vaultDetail.missing.recheck=再確認
@@ -371,7 +396,7 @@ vaultOptions.general=基本設定
vaultOptions.general.vaultName=金庫の名前 vaultOptions.general.vaultName=金庫の名前
vaultOptions.general.autoLock.lockAfterTimePart1=アイドル時に施錠する vaultOptions.general.autoLock.lockAfterTimePart1=アイドル時に施錠する
vaultOptions.general.autoLock.lockAfterTimePart2= vaultOptions.general.autoLock.lockAfterTimePart2=
vaultOptions.general.unlockAfterStartup=Cryptomatorの起動時に金庫を解錠する vaultOptions.general.unlockAfterStartup=Cryptomator の起動時に金庫を解錠する
vaultOptions.general.actionAfterUnlock=解錠に成功したあと vaultOptions.general.actionAfterUnlock=解錠に成功したあと
vaultOptions.general.actionAfterUnlock.ignore=何もしない vaultOptions.general.actionAfterUnlock.ignore=何もしない
vaultOptions.general.actionAfterUnlock.reveal=ドライブを表示 vaultOptions.general.actionAfterUnlock.reveal=ドライブを表示
@@ -380,20 +405,21 @@ vaultOptions.general.startHealthCheckBtn=正常性チェックを開始
## Mount ## Mount
vaultOptions.mount=マウント vaultOptions.mount=マウント
vaultOptions.mount.linkToPreferences=仮想ドライブの環境設定を開く
vaultOptions.mount.readonly=読み取り専用 vaultOptions.mount.readonly=読み取り専用
vaultOptions.mount.customMountFlags=カスタム マウント フラグ vaultOptions.mount.customMountFlags=カスタム マウント フラグ
vaultOptions.mount.winDriveLetterOccupied=使用中 vaultOptions.mount.winDriveLetterOccupied=使用中
vaultOptions.mount.mountPoint=マウントポイント vaultOptions.mount.mountPoint=マウント ポイント
vaultOptions.mount.mountPoint.auto=自動的に適切な場所を選択する vaultOptions.mount.mountPoint.auto=自動的に適切な場所を選択する
vaultOptions.mount.mountPoint.driveLetter=割り当てられるドライブ文字を使う vaultOptions.mount.mountPoint.driveLetter=割り当てられるドライブ文字を使う
vaultOptions.mount.mountPoint.custom=カスタムパス vaultOptions.mount.mountPoint.custom=選択したディレクトリを使う
vaultOptions.mount.mountPoint.directoryPickerButton=選択... vaultOptions.mount.mountPoint.directoryPickerButton=選択...
vaultOptions.mount.mountPoint.directoryPickerTitle=空のディレクトリを選択してください vaultOptions.mount.mountPoint.directoryPickerTitle=ディレクトリを選択
## Master Key ## Master Key
vaultOptions.masterkey=パスワード vaultOptions.masterkey=パスワード
vaultOptions.masterkey.changePasswordBtn=パスワードの変更 vaultOptions.masterkey.changePasswordBtn=パスワードの変更
vaultOptions.masterkey.forgetSavedPasswordBtn=保存したパスワードを削除する vaultOptions.masterkey.forgetSavedPasswordBtn=保存したパスワードを削除する
vaultOptions.masterkey.recoveryKeyExplanation=回復キーはパスワードを忘れてしまった場合、金庫へのアクセスを回復する唯一の手段です。 vaultOptions.masterkey.recoveryKeyExplanation=回復キーはパスワードを忘れてしまった場合でも、金庫へのアクセスを回復する唯一の手段です。
vaultOptions.masterkey.showRecoveryKeyBtn=回復キーを表示 vaultOptions.masterkey.showRecoveryKeyBtn=回復キーを表示
vaultOptions.masterkey.recoverPasswordBtn=パスワードをリセット vaultOptions.masterkey.recoverPasswordBtn=パスワードをリセット
+3 -15
View File
@@ -111,11 +111,6 @@ unlock.success.description="%s"이(가) 성공적으로 잠금해제되었습니
unlock.success.rememberChoice=선택 기억함, 다시 묻지 않음 unlock.success.rememberChoice=선택 기억함, 다시 묻지 않음
unlock.success.revealBtn=드라이브 표시 unlock.success.revealBtn=드라이브 표시
## Failure ## Failure
unlock.error.message=Vault 잠금을 해제 할 수 없습니다.
### Invalid Mount Point
unlock.error.invalidMountPoint.notExisting=구성지점이 존재하지 않거나 빈 디렉터리가 아닙니다: %s
unlock.error.invalidMountPoint.existing=구성지점/폴더가 이미 존재하거나 부모 폴더가 없습니다: %s
unlock.error.invalidMountPoint.driveLetterOccupied="%s"는 이미 사용중인 드라이브 문자입니다
## Hub ## Hub
### Waiting ### Waiting
### Receive Key ### Receive Key
@@ -138,8 +133,8 @@ lock.fail.description="%s" Vault를 잠글 수 없습니다. 저장되지 않은
# Migration # Migration
migration.title=Vault 업그레이드 migration.title=Vault 업그레이드
## Start ## Start
migration.start.prompt="%s" vault는 새로운 포멧으로 업데이트가 필요합니다. 작업 전, 이 Vault에 영향을 줄만한 동기화가 보류중인지 확인하여 주십시요. migration.start.header=Vault 업그레이드
migration.start.confirm=네, 이 Vault는 동기화가 완전히 된 상태입니다. migration.start.confirm=나는 위 정보를 읽고 정말 이해했습니다.
## Run ## Run
migration.run.enterPassword="%s"의 비밀번호를 입력하십시요. migration.run.enterPassword="%s"의 비밀번호를 입력하십시요.
migration.run.startMigrationBtn=Vault 마이그레이션 migration.run.startMigrationBtn=Vault 마이그레이션
@@ -213,9 +208,7 @@ preferences.interface.showMinimizeButton=최소화 버튼 표시
preferences.interface.showTrayIcon=트레이 아이콘 보기 (재시작 필요) preferences.interface.showTrayIcon=트레이 아이콘 보기 (재시작 필요)
## Volume ## Volume
preferences.volume=가상 드라이브 preferences.volume=가상 드라이브
preferences.volume.type=볼륨 유형 preferences.volume.type.automatic=자동
preferences.volume.webdav.port=WebDAV 포트
preferences.volume.webdav.scheme=WebDAV 스킴
## Updates ## Updates
preferences.updates=업데이트 preferences.updates=업데이트
preferences.updates.currentVersion=현재 버전: %s preferences.updates.currentVersion=현재 버전: %s
@@ -272,9 +265,6 @@ main.minimizeBtn.tooltip=최소화
main.preferencesBtn.tooltip=환경설정 main.preferencesBtn.tooltip=환경설정
main.debugModeEnabled.tooltip=디버그 모드가 활성화됨. main.debugModeEnabled.tooltip=디버그 모드가 활성화됨.
main.supporterCertificateMissing.tooltip=기부를 부탁드립니다. main.supporterCertificateMissing.tooltip=기부를 부탁드립니다.
## Drag 'n' Drop
main.dropZone.dropVault=이 Vault를 추가
main.dropZone.unknownDragboardContent=Vault를 추가하려면, 이 창에 드래그 하십시요.
## Vault List ## Vault List
main.vaultlist.emptyList.onboardingInstruction=Vault를 추가하기 위해 이곳을 클릭합니다. main.vaultlist.emptyList.onboardingInstruction=Vault를 추가하기 위해 이곳을 클릭합니다.
main.vaultlist.contextMenu.remove=제거... main.vaultlist.contextMenu.remove=제거...
@@ -345,9 +335,7 @@ vaultOptions.mount.winDriveLetterOccupied=사용됨
vaultOptions.mount.mountPoint=마운트 지점 vaultOptions.mount.mountPoint=마운트 지점
vaultOptions.mount.mountPoint.auto=자동으로 적합한 위치를 선택 vaultOptions.mount.mountPoint.auto=자동으로 적합한 위치를 선택
vaultOptions.mount.mountPoint.driveLetter=드라이브 문자를 지정하여 사용 vaultOptions.mount.mountPoint.driveLetter=드라이브 문자를 지정하여 사용
vaultOptions.mount.mountPoint.custom=사용자 지정 경로
vaultOptions.mount.mountPoint.directoryPickerButton=선택 vaultOptions.mount.mountPoint.directoryPickerButton=선택
vaultOptions.mount.mountPoint.directoryPickerTitle=빈 디렉터리를 선택
## Master Key ## Master Key
vaultOptions.masterkey=비밀번호 vaultOptions.masterkey=비밀번호
vaultOptions.masterkey.changePasswordBtn=비밀번호 변경 vaultOptions.masterkey.changePasswordBtn=비밀번호 변경
+1 -11
View File
@@ -106,7 +106,6 @@ unlock.chooseMasterkey.filePickerTitle=Atlasīt galveno atslēgas datni
## Success ## Success
unlock.success.revealBtn=Atklāt disku unlock.success.revealBtn=Atklāt disku
## Failure ## Failure
### Invalid Mount Point
## Hub ## Hub
### Waiting ### Waiting
### Receive Key ### Receive Key
@@ -126,8 +125,7 @@ hub.register.registerBtn=Apstiprināt
# Migration # Migration
migration.title=Jaunināt glabātuvi migration.title=Jaunināt glabātuvi
## Start ## 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.header=Jaunināt glabātuvi
migration.start.confirm=Jā, mana glabātuve ir pilnībā sinhronizēta
## Run ## Run
migration.run.enterPassword=Ievadiet "%s" paroli migration.run.enterPassword=Ievadiet "%s" paroli
migration.run.startMigrationBtn=Migrēt glabātuvi migration.run.startMigrationBtn=Migrēt glabātuvi
@@ -163,9 +161,6 @@ preferences.interface.theme.dark=Tumšs
preferences.interface.theme.light=Gaišs preferences.interface.theme.light=Gaišs
## Volume ## Volume
preferences.volume=Virtuāls disks 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 ## Updates
preferences.updates=Atjauninājumi preferences.updates=Atjauninājumi
preferences.updates.currentVersion=Pašreizējā versija: %s preferences.updates.currentVersion=Pašreizējā versija: %s
@@ -190,9 +185,6 @@ main.closeBtn.tooltip=Aizvērt
main.minimizeBtn.tooltip=Minimizēt main.minimizeBtn.tooltip=Minimizēt
main.preferencesBtn.tooltip=Iestatījumi main.preferencesBtn.tooltip=Iestatījumi
main.supporterCertificateMissing.tooltip=Lūdzu apsveriet iespēju ziedot 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 ## Vault List
main.vaultlist.emptyList.onboardingInstruction=Spied šeit, lai pievienotu glabātuvi main.vaultlist.emptyList.onboardingInstruction=Spied šeit, lai pievienotu glabātuvi
main.vaultlist.contextMenu.lock=Aizslēgt main.vaultlist.contextMenu.lock=Aizslēgt
@@ -247,9 +239,7 @@ vaultOptions.mount.winDriveLetterOccupied=aizņemts
vaultOptions.mount.mountPoint=Montēšanas vieta vaultOptions.mount.mountPoint=Montēšanas vieta
vaultOptions.mount.mountPoint.auto=Automātiski izvēlieties piemērotu vietu vaultOptions.mount.mountPoint.auto=Automātiski izvēlieties piemērotu vietu
vaultOptions.mount.mountPoint.driveLetter=Izmantot piešķirtu diska burtu 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.directoryPickerButton=Izvēlies...
vaultOptions.mount.mountPoint.directoryPickerTitle=Izvēlies tukšu mapi
## Master Key ## Master Key
vaultOptions.masterkey=Parole vaultOptions.masterkey=Parole
vaultOptions.masterkey.changePasswordBtn=Mainīt paroli vaultOptions.masterkey.changePasswordBtn=Mainīt paroli
@@ -29,7 +29,6 @@
## Select ## Select
## Success ## Success
## Failure ## Failure
### Invalid Mount Point
## Hub ## Hub
### Waiting ### Waiting
### Receive Key ### Receive Key
@@ -78,7 +77,6 @@ hub.register.registerBtn=Потврди
# Main Window # Main Window
## Drag 'n' Drop
## Vault List ## Vault List
## Vault Detail ## Vault Detail
### Welcome ### 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.rememberChoice=Husk valget - ikke vis dette igjen
unlock.success.revealBtn=Gjør enheten synlig unlock.success.revealBtn=Gjør enheten synlig
## Failure ## Failure
unlock.error.message=Klarer ikke å låse opp hvelvet unlock.error.customPath.message=Kan ikke montere hvelvet til egendefinert sti
### Invalid Mount Point 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.invalidMountPoint.notExisting=Monteringspunktet "%s" er enten ikke en mappe, ikke tom eller eksisterer ikke. unlock.error.customPath.description.notExists=Egendefinert monteringssti eksisterer ikke. Enten opprett den i ditt lokale filsystem eller endre den i hvelvvalgene.
unlock.error.invalidMountPoint.existing=Monteringspunktet "%s" finnes enten allerede eller at overordnet mappe mangler. unlock.error.customPath.description.generic=Du har valgt en egendefinert monterings sti for dette hvelvet, men ved bruk av den mislyktes med meldingen: %s
unlock.error.invalidMountPoint.driveLetterOccupied=Stasjonsbokstav "%s" er allerede i bruk.
## Hub ## 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 ### Waiting
hub.auth.message=Venter på autentisering… hub.auth.message=Venter på autentisering…
hub.auth.description=Du burde bli automatisk videresendt til innloggingssiden. 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
migration.title=Oppgrader hvelv migration.title=Oppgrader hvelv
## Start ## 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.header=Oppgrader hvelv
migration.start.confirm=Ja, hvelvet mitt er fullstendig synkronisert 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 ## Run
migration.run.enterPassword=Skriv inn passordet for "%s" migration.run.enterPassword=Skriv inn passordet for "%s"
migration.run.startMigrationBtn=Oppgrader hvelv 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.checkFinishedAndFound=Helsesjekken er ferdig å kjøre. Vennligst se resultatene.
health.check.detail.checkFailed=Helsesjekken avsluttet på grunn av en feil. health.check.detail.checkFailed=Helsesjekken avsluttet på grunn av en feil.
health.check.detail.checkCancelled=Helsesjekken ble avbrutt. 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 health.check.exportBtn=Eksporter rapport
## Result view ## 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 ## Fix Application
health.fix.fixBtn=Reparer health.fix.fixBtn=Reparer
health.fix.successTip=Vellykket reparering health.fix.successTip=Vellykket reparering
@@ -247,13 +271,19 @@ preferences.interface.language.auto=Systemstandard
preferences.interface.interfaceOrientation=Grensesnittorientering preferences.interface.interfaceOrientation=Grensesnittorientering
preferences.interface.interfaceOrientation.ltr=Fra venstre til høyre preferences.interface.interfaceOrientation.ltr=Fra venstre til høyre
preferences.interface.interfaceOrientation.rtl=Fra høyre til venstre 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) preferences.interface.showTrayIcon=Vis verktøykasseikon (krever omstart)
## Volume ## Volume
preferences.volume=Virtuell enhet preferences.volume=Virtuell enhet
preferences.volume.type=Volumtype preferences.volume.type=Volumtype (krever omstart)
preferences.volume.webdav.port=WebDAV-port preferences.volume.type.automatic=Automatisk
preferences.volume.webdav.scheme=WebDAV-ordning 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 ## Updates
preferences.updates=Oppdateringer preferences.updates=Oppdateringer
preferences.updates.currentVersion=Gjeldende versjon: %s preferences.updates.currentVersion=Gjeldende versjon: %s
@@ -263,7 +293,7 @@ preferences.updates.updateAvailable=Oppdatering til versjon %s er tilgjengelig.
## Contribution ## Contribution
preferences.contribute=Støtt oss preferences.contribute=Støtt oss
preferences.contribute.registeredFor=Supporter sertifikat registrert for %s 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.getCertificate=Har du ikke en allerede? Lær hvordan du kan skaffe den.
preferences.contribute.promptText=Lim inn supporter sertifikatkoden her preferences.contribute.promptText=Lim inn supporter sertifikatkoden her
#<-- Add entries for donations and code/translation/documentation contribution --> #<-- 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 stats.write.accessCount=Skrivninger totalt: %d
## Accesses ## Accesses
stats.access.current=Tilgang: %d
stats.access.total=Antall tilganger: %d
# Main Window # Main Window
@@ -310,9 +342,6 @@ main.minimizeBtn.tooltip=Minimer
main.preferencesBtn.tooltip=Innstillinger main.preferencesBtn.tooltip=Innstillinger
main.debugModeEnabled.tooltip=Feilsøkingsmodus er aktivert main.debugModeEnabled.tooltip=Feilsøkingsmodus er aktivert
main.supporterCertificateMissing.tooltip=Gjerne vurdér en donasjon 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 ## Vault List
main.vaultlist.emptyList.onboardingInstruction=Klikk her for å legge til et hvelv main.vaultlist.emptyList.onboardingInstruction=Klikk her for å legge til et hvelv
main.vaultlist.contextMenu.remove=Fjern… main.vaultlist.contextMenu.remove=Fjern…
@@ -335,6 +364,7 @@ main.vaultDetail.passwordSavedInKeychain=Passordet er lagret
main.vaultDetail.unlockedStatus=ULÅST main.vaultDetail.unlockedStatus=ULÅST
main.vaultDetail.accessLocation=Innholdet i hvelvet ditt er tilgjengelig her: main.vaultDetail.accessLocation=Innholdet i hvelvet ditt er tilgjengelig her:
main.vaultDetail.revealBtn=Gjør enheten synlig main.vaultDetail.revealBtn=Gjør enheten synlig
main.vaultDetail.copyUri=Kopier URI
main.vaultDetail.lockBtn=Lås main.vaultDetail.lockBtn=Lås
main.vaultDetail.bytesPerSecondRead=Lesehastighet: main.vaultDetail.bytesPerSecondRead=Lesehastighet:
main.vaultDetail.bytesPerSecondWritten=Skriv: main.vaultDetail.bytesPerSecondWritten=Skriv:
@@ -342,6 +372,10 @@ main.vaultDetail.throughput.idle=inaktiv
main.vaultDetail.throughput.kbps=%.1f kiB/s main.vaultDetail.throughput.kbps=%.1f kiB/s
main.vaultDetail.throughput.mbps=%.1f MiB/s main.vaultDetail.throughput.mbps=%.1f MiB/s
main.vaultDetail.stats=Hvelvstatistikk 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 ### Missing
main.vaultDetail.missing.info=Cryptomator kunne ikke finne et hvelv på denne søkestien. main.vaultDetail.missing.info=Cryptomator kunne ikke finne et hvelv på denne søkestien.
main.vaultDetail.missing.recheck=Kontroller igjen main.vaultDetail.missing.recheck=Kontroller igjen
@@ -380,15 +414,17 @@ vaultOptions.general.startHealthCheckBtn=Start helsesjekk
## Mount ## Mount
vaultOptions.mount=Montering 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.readonly=Skrivebeskyttet
vaultOptions.mount.customMountFlags=Tilpassede moteringsparametre vaultOptions.mount.customMountFlags=Tilpassede moteringsparametre
vaultOptions.mount.winDriveLetterOccupied=opptatt vaultOptions.mount.winDriveLetterOccupied=opptatt
vaultOptions.mount.mountPoint=Monteringspunkt vaultOptions.mount.mountPoint=Monteringspunkt
vaultOptions.mount.mountPoint.auto=Velg et passende sted automatisk vaultOptions.mount.mountPoint.auto=Velg et passende sted automatisk
vaultOptions.mount.mountPoint.driveLetter=Bruk tildelt enhetsbokstav 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.directoryPickerButton=Velg…
vaultOptions.mount.mountPoint.directoryPickerTitle=Velg en tom mappe vaultOptions.mount.mountPoint.directoryPickerTitle=Velg en mappe
## Master Key ## Master Key
vaultOptions.masterkey=Passord vaultOptions.masterkey=Passord
vaultOptions.masterkey.changePasswordBtn=Endre passord vaultOptions.masterkey.changePasswordBtn=Endre passord

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