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