mirror of
https://github.com/cryptomator/cryptomator.git
synced 2026-09-21 15:34:27 +00:00
Compare commits
61
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
04bdb2d8c4 | ||
|
|
f32d24c1c0 | ||
|
|
f4f093bb42 | ||
|
|
3f06460667 | ||
|
|
617f1bf2c9 | ||
|
|
02ad38f871 | ||
|
|
7a2944cbea | ||
|
|
4c47204f92 | ||
|
|
f052395a7f | ||
|
|
57be83b38d | ||
|
|
c2cd4f5bbf | ||
|
|
d3d57312ba | ||
|
|
593a64c9bd | ||
|
|
19dc4fb6ff | ||
|
|
81f45012f3 | ||
|
|
c59554f7bb | ||
|
|
11c66e8df7 | ||
|
|
c49bf0f146 | ||
|
|
e74bd91879 | ||
|
|
89d9249a08 | ||
|
|
013fff1223 | ||
|
|
fd9d27215e | ||
|
|
f91cc2374c | ||
|
|
48298bb161 | ||
|
|
7a1cd9026c | ||
|
|
754e53d8db | ||
|
|
c36f1bc8d0 | ||
|
|
7315b59a6d | ||
|
|
8a243a01aa | ||
|
|
9e4006cc89 | ||
|
|
26b69beb87 | ||
|
|
f95bf87a4b | ||
|
|
e854c7d189 | ||
|
|
8a434dcd96 | ||
|
|
6b7324723e | ||
|
|
0bdcb2b3be | ||
|
|
c3931d9d29 | ||
|
|
307825a339 | ||
|
|
093f0e8c94 | ||
|
|
c938c42c00 | ||
|
|
884c6f6bdd | ||
|
|
c5367db971 | ||
|
|
59560193ee | ||
|
|
a6b31e19b9 | ||
|
|
8a44115234 | ||
|
|
43a1f00bea | ||
|
|
3e458060bc | ||
|
|
4bb5a3f10d | ||
|
|
cdcd43a805 | ||
|
|
d5245009f4 | ||
|
|
8f4392711e | ||
|
|
79bb4a5215 | ||
|
|
2ce7fee06d | ||
|
|
99e9e92f10 | ||
|
|
8e6500d93f | ||
|
|
89ce99deaf | ||
|
|
510e134605 | ||
|
|
62b434f549 | ||
|
|
1f1e336d57 | ||
|
|
02186ca17a | ||
|
|
b0ed133e05 |
@@ -20,6 +20,10 @@
|
||||
|
||||
Translations are not managed directly in this repository. Instead, we use [Crowdin](https://translate.cryptomator.org/), which automatically synchronizes translations with this repository. If you want to help us with translations, please visit our translation project on Crowdin.
|
||||
|
||||
## Use of Generative AI
|
||||
|
||||
AI tools may assist your work, but every contribution must be fully understood, reviewed, and tested by you. Only submit changes you can clearly explain and justify. Unverified or low-quality AI output that wastes our time and resources will be closed without further review.
|
||||
|
||||
## Code of Conduct
|
||||
|
||||
Help us keep Cryptomator open and inclusive. Please read and follow our [Code of Conduct](https://github.com/cryptomator/cryptomator/blob/develop/.github/CODE_OF_CONDUCT.md).
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
name: 'Windows Code Signing'
|
||||
description: 'Sign files on Windows with the Azure Trusted Signing'
|
||||
inputs:
|
||||
base-dir:
|
||||
description: 'Absolute path to the base directory to search for files'
|
||||
required: true
|
||||
recursive:
|
||||
description: 'Whether to search recursively in subdirectories'
|
||||
required: false
|
||||
default: 'false'
|
||||
file-extensions:
|
||||
description: 'List of file extensions to sign, separated by comma'
|
||||
required: true
|
||||
default: 'exe,dll,ps1'
|
||||
description:
|
||||
description: 'Signature description'
|
||||
required: true
|
||||
default: 'Cryptomator'
|
||||
url:
|
||||
description: 'Signature URL'
|
||||
required: false
|
||||
default: 'https://cryptomator.org'
|
||||
append-signature:
|
||||
description: 'Whether to append the signature to existing signatures'
|
||||
required: false
|
||||
default: 'false'
|
||||
tenant-id:
|
||||
description: 'Azure Tenant ID'
|
||||
required: true
|
||||
client-id:
|
||||
description: 'Azure Client ID'
|
||||
required: true
|
||||
client-secret:
|
||||
description: 'Azure Client Secret'
|
||||
required: true
|
||||
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- name: Generate, mask, and output the input secrets
|
||||
id: set-secrets
|
||||
run: |
|
||||
echo "::add-mask::${{ inputs.tenant-id }}"
|
||||
echo "::add-mask::${{ inputs.client-id }}"
|
||||
echo "::add-mask::${{ inputs.client-secret }}"
|
||||
echo "tenant-id=${{ inputs.tenant-id }}" >> "$GITHUB_OUTPUT"
|
||||
echo "client-id=${{ inputs.client-id }}" >> "$GITHUB_OUTPUT"
|
||||
echo "client-secret=${{ inputs.client-secret }}" >> "$GITHUB_OUTPUT"
|
||||
shell: bash
|
||||
- name: Sign DLLs with Azure Trusted Signing
|
||||
uses: azure/trusted-signing-action@fc390cf8ed0f14e248a542af1d838388a47c7a7c # v0.5.10
|
||||
with:
|
||||
files-folder: ${{ inputs.base-dir }}
|
||||
files-folder-filter: ${{ inputs.file-extensions }}
|
||||
files-folder-recurse: ${{ inputs.recursive }}
|
||||
append-signature: ${{ inputs.append-signature }}
|
||||
description: ${{ inputs.description }}
|
||||
description-url: ${{ inputs.url }}
|
||||
azure-tenant-id: ${{ steps.set-secrets.outputs.tenant-id }}
|
||||
azure-client-id: ${{ steps.set-secrets.outputs.client-id }}
|
||||
azure-client-secret: ${{ steps.set-secrets.outputs.client-secret }}
|
||||
trusted-signing-account-name: cryptomatorSigning
|
||||
certificate-profile-name: production
|
||||
endpoint: https://weu.codesigning.azure.net/
|
||||
timestamp-rfc3161: http://timestamp.acs.microsoft.com
|
||||
timestamp-digest: SHA256
|
||||
exclude-environment-credential: false
|
||||
exclude-workload-identity-credential: true
|
||||
exclude-managed-identity-credential: true
|
||||
exclude-shared-token-cache-credential: true
|
||||
exclude-visual-studio-credential: true
|
||||
exclude-visual-studio-code-credential: true
|
||||
exclude-azure-cli-credential: true
|
||||
exclude-azure-powershell-credential: true
|
||||
exclude-azure-developer-cli-credential: true
|
||||
exclude-interactive-browser-credential: true
|
||||
@@ -19,7 +19,7 @@ on:
|
||||
|
||||
env:
|
||||
JAVA_DIST: 'temurin'
|
||||
JAVA_VERSION: '24.0.1+9'
|
||||
JAVA_VERSION: '25.0.1+8.0.LTS'
|
||||
|
||||
jobs:
|
||||
get-version:
|
||||
@@ -42,7 +42,7 @@ jobs:
|
||||
- os: ubuntu-24.04-arm
|
||||
appimage-suffix: aarch64
|
||||
openjfx-url: 'https://download2.gluonhq.com/openjfx/25/openjfx-25_linux-aarch64_bin-jmods.zip'
|
||||
openjfx-sha: '951c52481af0ec5885b06f1ebaa8a10da7e8ea23c5e1ef3e2f6f11fa1b3a7ce1'
|
||||
openjfx-sha: '9ad4ca7b769ca4ee6419f1e99143dd6ff812f8be4fddb46a7d7cacbeea148af4'
|
||||
steps:
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
- name: Setup Java
|
||||
|
||||
+16
-11
@@ -11,7 +11,7 @@ on:
|
||||
|
||||
env:
|
||||
JAVA_DIST: 'temurin'
|
||||
JAVA_VERSION: 24
|
||||
JAVA_VERSION: 25
|
||||
|
||||
defaults:
|
||||
run:
|
||||
@@ -56,21 +56,21 @@ jobs:
|
||||
token: ${{ secrets.CRYPTOBOT_RELEASE_TOKEN }}
|
||||
generate_release_notes: true
|
||||
body: |-
|
||||
:construction: Work in Progress
|
||||
> [!NOTE]
|
||||
> 🚧 Work in Progress 🚧
|
||||
>
|
||||
> Please be patient, the [builds are still running](https://github.com/cryptomator/cryptomator/actions). Binary packages can be found here in a few moments.
|
||||
|
||||
<!--REPLACE with auto-generated release notes (see below)
|
||||
### What's New 🎉
|
||||
|
||||
### Bugfixes 🐛
|
||||
|
||||
### Other Changes 📎
|
||||
END REPLACE-->
|
||||
|
||||
Feel free to also read our [CHANGELOG.md](https://github.com/cryptomator/cryptomator/blob/develop/CHANGELOG.md).
|
||||
|
||||
---
|
||||
|
||||
TODO FULL CHANGELOG
|
||||
|
||||
📜 List of closed issues is available [here](TODO)
|
||||
|
||||
---
|
||||
⏳ Please be patient, the builds are still [running](https://github.com/cryptomator/cryptomator/actions). New versions of Cryptomator can be found here in a few moments. ⏳
|
||||
|
||||
<!-- Don't forget to include the
|
||||
💾 SHA-256 checksums of release artifacts:
|
||||
@@ -78,4 +78,9 @@ jobs:
|
||||
```
|
||||
-->
|
||||
|
||||
As usual, the GPG signatures can be checked using [our public key `5811 7AFA 1F85 B3EE C154 677D 615D 449F E6E6 A235`](https://gist.github.com/cryptobot/211111cf092037490275f39d408f461a).
|
||||
> [!TIP]
|
||||
> You can verify the GPG signature of all assets using our public key: [`5811 7AFA 1F85 B3EE C154 677D 615D 449F E6E6 A235`](https://gist.github.com/cryptobot/211111cf092037490275f39d408f461a).
|
||||
|
||||
|
||||
|
||||
<!-- Auto-Generated Release Notes: -->
|
||||
|
||||
@@ -6,7 +6,7 @@ on:
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
JDK_VERSION: '24.0.1+9'
|
||||
JDK_VERSION: '25.0.1+8.0.LTS'
|
||||
JDK_VENDOR: temurin
|
||||
RUNTIME_VERSION_HELPER: >
|
||||
public class Test {
|
||||
@@ -23,7 +23,7 @@ jobs:
|
||||
JDK_MAJOR_VERSION: 'toBeFilled'
|
||||
steps:
|
||||
- name: Determine current major version
|
||||
run: echo 'JDK_MAJOR_VERSION=${{ env.JDK_VERSION }}'.substring(0,20) >> "$env:GITHUB_ENV"
|
||||
run: echo 'JDK_MAJOR_VERSION=${{ env.JDK_VERSION }}'.substring(0,2) >> "$env:GITHUB_ENV"
|
||||
shell: pwsh
|
||||
- name: Checkout latest JDK ${{ env.JDK_MAJOR_VERSION }}
|
||||
uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5.0.0
|
||||
|
||||
@@ -23,13 +23,12 @@ on:
|
||||
|
||||
env:
|
||||
JAVA_DIST: 'temurin'
|
||||
JAVA_VERSION: '24.0.1+9'
|
||||
COFFEELIBS_JDK: 24
|
||||
COFFEELIBS_JDK_VERSION: '24.0.1+9-0ppa3'
|
||||
JAVA_VERSION: '25.0.1+8.0.LTS'
|
||||
DEB_BUILD_DEPENDS: 'debhelper (>=10), openjdk-25-jdk (>= 25+36), libgtk-3-0 (>= 3.20.0), libxxf86vm1, libgl1'
|
||||
OPENJFX_JMODS_AMD64: 'https://download2.gluonhq.com/openjfx/25/openjfx-25_linux-x64_bin-jmods.zip'
|
||||
OPENJFX_JMODS_AMD64_HASH: '96e520f48610d8ffb94ca30face1f11ffe8a977ddc1c4ff80b1a9e9f048bd94e'
|
||||
OPENJFX_JMODS_AARCH64: 'https://download2.gluonhq.com/openjfx/25/openjfx-25_linux-aarch64_bin-jmods.zip'
|
||||
OPENJFX_JMODS_AARCH64_HASH: '951c52481af0ec5885b06f1ebaa8a10da7e8ea23c5e1ef3e2f6f11fa1b3a7ce1'
|
||||
OPENJFX_JMODS_AARCH64_HASH: '9ad4ca7b769ca4ee6419f1e99143dd6ff812f8be4fddb46a7d7cacbeea148af4'
|
||||
|
||||
jobs:
|
||||
get-version:
|
||||
@@ -55,9 +54,11 @@ jobs:
|
||||
fi
|
||||
- name: Install build tools
|
||||
run: |
|
||||
sudo add-apt-repository ppa:coffeelibs/openjdk
|
||||
sudo apt-get update
|
||||
sudo apt-get install debhelper devscripts dput coffeelibs-jdk-${{ env.COFFEELIBS_JDK }}=${{ env.COFFEELIBS_JDK_VERSION }}
|
||||
sudo apt-get install devscripts dput
|
||||
sudo apt-get satisfy "${DEB_BUILD_DEPENDS}"
|
||||
env:
|
||||
DEB_BUILD_DEPENDS: ${{ env.DEB_BUILD_DEPENDS }}
|
||||
- name: Setup Java
|
||||
uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5.0.0
|
||||
with:
|
||||
|
||||
@@ -11,7 +11,7 @@ jobs:
|
||||
with:
|
||||
runner-os: 'ubuntu-latest'
|
||||
java-distribution: 'temurin'
|
||||
java-version: 24
|
||||
java-version: 25
|
||||
secrets:
|
||||
nvd-api-key: ${{ secrets.NVD_API_KEY }}
|
||||
ossindex-username: ${{ secrets.OSSINDEX_USERNAME }}
|
||||
|
||||
@@ -23,7 +23,7 @@ on:
|
||||
|
||||
env:
|
||||
JAVA_DIST: 'temurin'
|
||||
JAVA_VERSION: 24
|
||||
JAVA_VERSION: 25
|
||||
|
||||
jobs:
|
||||
determine-version:
|
||||
|
||||
@@ -24,7 +24,7 @@ on:
|
||||
|
||||
env:
|
||||
JAVA_DIST: 'temurin'
|
||||
JAVA_VERSION: '24.0.1+9'
|
||||
JAVA_VERSION: '25.0.1+8.0.LTS'
|
||||
|
||||
jobs:
|
||||
get-version:
|
||||
@@ -136,6 +136,7 @@ jobs:
|
||||
--java-options "-Dcryptomator.integrationsMac.keychainServiceName=\"Cryptomator\""
|
||||
--java-options "-Dcryptomator.mountPointsDir=\"@{userhome}/Library/Application Support/Cryptomator/mnt\""
|
||||
--java-options "-Dcryptomator.showTrayIcon=true"
|
||||
--java-options "-Dcryptomator.updateMechanism=org.cryptomator.macos.update.DmgUpdateMechanism"
|
||||
--java-options "-Dcryptomator.buildNumber=\"dmg-${{ needs.get-version.outputs.revNum }}\""
|
||||
--mac-package-identifier org.cryptomator
|
||||
--resource-dir dist/mac/resources
|
||||
|
||||
@@ -22,7 +22,7 @@ on:
|
||||
|
||||
env:
|
||||
JAVA_DIST: 'temurin'
|
||||
JAVA_VERSION: '24.0.1+9'
|
||||
JAVA_VERSION: '25.0.1+8.0.LTS'
|
||||
|
||||
jobs:
|
||||
get-version:
|
||||
@@ -134,6 +134,7 @@ jobs:
|
||||
--java-options "-Dcryptomator.integrationsMac.keychainServiceName=\"Cryptomator\""
|
||||
--java-options "-Dcryptomator.mountPointsDir=\"@{userhome}/Library/Application Support/Cryptomator/mnt\""
|
||||
--java-options "-Dcryptomator.showTrayIcon=true"
|
||||
--java-options "-Dcryptomator.updateMechanism=org.cryptomator.macos.update.DmgUpdateMechanism"
|
||||
--java-options "-Dcryptomator.buildNumber=\"dmg-${{ needs.get-version.outputs.revNum }}\""
|
||||
--java-options "-XX:ErrorFile=/cryptomator/cryptomator_crash.log"
|
||||
--mac-package-identifier org.cryptomator
|
||||
|
||||
@@ -5,7 +5,7 @@ on:
|
||||
|
||||
env:
|
||||
JAVA_DIST: 'temurin'
|
||||
JAVA_VERSION: 24
|
||||
JAVA_VERSION: 25
|
||||
|
||||
defaults:
|
||||
run:
|
||||
|
||||
@@ -12,7 +12,7 @@ defaults:
|
||||
|
||||
env:
|
||||
JAVA_DIST: 'temurin'
|
||||
JAVA_VERSION: 23
|
||||
JAVA_VERSION: 25
|
||||
|
||||
jobs:
|
||||
check-preconditions:
|
||||
|
||||
@@ -8,10 +8,6 @@ on:
|
||||
version:
|
||||
description: 'Version'
|
||||
required: false
|
||||
isDebug:
|
||||
description: 'Build debug version with console output'
|
||||
type: boolean
|
||||
default: false
|
||||
sign:
|
||||
description: 'Sign binaries'
|
||||
required: false
|
||||
@@ -51,8 +47,8 @@ jobs:
|
||||
include:
|
||||
- arch: x64
|
||||
os: windows-latest
|
||||
java-dist: 'zulu'
|
||||
java-version: '24.0.1+9'
|
||||
java-dist: 'zulu' #cannot use temurin, see https://github.com/cryptomator/cryptomator/issues/3824#issuecomment-2829827427
|
||||
java-version: '25.0.1+8'
|
||||
java-package: 'jdk'
|
||||
steps:
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
@@ -192,6 +188,16 @@ jobs:
|
||||
New-Item -Path appdir/jpackage-jmod -ItemType Directory
|
||||
& $env:JAVA_HOME\bin\jmod.exe extract --dir jpackage-jmod "${env:JAVA_HOME}\jmods\jdk.jpackage.jmod"
|
||||
Get-ChildItem -Recurse -Path "jpackage-jmod" -File wixhelper.dll | Select-Object -Last 1 | Copy-Item -Destination "appdir"
|
||||
- name: Sign DLLs with Azure Trusted Signing
|
||||
if: inputs.sign || github.event_name == 'release'
|
||||
uses: ./.github/actions/win-sign-action
|
||||
with:
|
||||
base-dir: ${{ github.workspace }}\appdir
|
||||
recursive: true
|
||||
append-signature: true
|
||||
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
|
||||
client-id: ${{ secrets.AZURE_CLIENT_ID }}
|
||||
client-secret: ${{ secrets.AZURE_CLIENT_SECRET }}
|
||||
- name: Sign DLLs with Actalis CodeSigner
|
||||
if: inputs.sign || github.event_name == 'release'
|
||||
uses: skymatic/workflows/.github/actions/win-sign-action@450e322ff2214d0be0b079b63343c894f3ef735f # no specific version
|
||||
@@ -251,16 +257,16 @@ jobs:
|
||||
env:
|
||||
JP_WIXWIZARD_RESOURCES: ${{ github.workspace }}/dist/win/resources # requires abs path, used in resources/main.wxs
|
||||
JP_WIXHELPER_DIR: ${{ github.workspace }}\appdir
|
||||
- name: Sign msi with Actalis CodeSigner
|
||||
- name: Sign MSI with Azure Trusted Signing
|
||||
if: inputs.sign || github.event_name == 'release'
|
||||
uses: skymatic/workflows/.github/actions/win-sign-action@450e322ff2214d0be0b079b63343c894f3ef735f # no specific version
|
||||
uses: ./.github/actions/win-sign-action
|
||||
with:
|
||||
base-dir: 'installer'
|
||||
file-extensions: 'msi'
|
||||
sign-description: 'Cryptomator Installer'
|
||||
sign-url: 'https://cryptomator.org'
|
||||
username: ${{ secrets.WIN_CODESIGN_USERNAME }}
|
||||
password: ${{ secrets.WIN_CODESIGN_PW }}
|
||||
base-dir: ${{ github.workspace }}\installer
|
||||
file-extensions: msi
|
||||
description: 'Cryptomator Installer'
|
||||
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
|
||||
client-id: ${{ secrets.AZURE_CLIENT_ID }}
|
||||
client-secret: ${{ secrets.AZURE_CLIENT_SECRET }}
|
||||
- name: Add possible alpha/beta tags and architecture to installer name
|
||||
run: mv installer/Cryptomator-*.msi Cryptomator-${{ needs.get-version.outputs.semVerStr }}-${{ matrix.arch }}.msi
|
||||
- name: Create detached GPG signature with key 615D449FE6E6A235
|
||||
@@ -357,6 +363,17 @@ jobs:
|
||||
- name: Detach burn engine in preparation to sign
|
||||
run: >
|
||||
wix burn detach installer/unsigned/Cryptomator-Installer.exe -engine tmp/engine.exe
|
||||
- name: Sign WiX burn engine with Azure Trusted Signing
|
||||
if: inputs.sign || github.event_name == 'release'
|
||||
uses: ./.github/actions/win-sign-action
|
||||
with:
|
||||
base-dir: ${{ github.workspace }}\tmp
|
||||
file-extensions: exe
|
||||
append-signature: true
|
||||
description: 'Cryptomator Bundle Installer'
|
||||
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
|
||||
client-id: ${{ secrets.AZURE_CLIENT_ID }}
|
||||
client-secret: ${{ secrets.AZURE_CLIENT_SECRET }}
|
||||
- name: Sign burn engine with Actalis CodeSigner
|
||||
if: inputs.sign || github.event_name == 'release'
|
||||
uses: skymatic/workflows/.github/actions/win-sign-action@450e322ff2214d0be0b079b63343c894f3ef735f # no specific version
|
||||
@@ -370,6 +387,17 @@ jobs:
|
||||
- name: Reattach signed burn engine to installer
|
||||
run: >
|
||||
wix burn reattach installer/unsigned/Cryptomator-Installer.exe -engine tmp/engine.exe -o installer/Cryptomator-Installer.exe
|
||||
- name: Sign EXE installer with Azure Trusted Signing
|
||||
if: inputs.sign || github.event_name == 'release'
|
||||
uses: ./.github/actions/win-sign-action
|
||||
with:
|
||||
base-dir: ${{ github.workspace }}\installer
|
||||
file-extensions: exe
|
||||
append-signature: true
|
||||
description: 'Cryptomator Bundle Installer'
|
||||
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
|
||||
client-id: ${{ secrets.AZURE_CLIENT_ID }}
|
||||
client-secret: ${{ secrets.AZURE_CLIENT_SECRET }}
|
||||
- name: Sign installer with Actalis CodeSigner
|
||||
if: inputs.sign || github.event_name == 'release'
|
||||
uses: skymatic/workflows/.github/actions/win-sign-action@450e322ff2214d0be0b079b63343c894f3ef735f # no specific version
|
||||
|
||||
Generated
+11
-10
@@ -14,16 +14,15 @@
|
||||
<option name="dagger.fastInit" value="enabled" />
|
||||
<option name="dagger.formatGeneratedSource" value="enabled" />
|
||||
<processorPath useClasspath="false">
|
||||
<entry name="$MAVEN_REPOSITORY$/com/google/dagger/dagger-compiler/2.55/dagger-compiler-2.55.jar" />
|
||||
<entry name="$MAVEN_REPOSITORY$/com/google/dagger/dagger/2.55/dagger-2.55.jar" />
|
||||
<entry name="$MAVEN_REPOSITORY$/com/google/dagger/dagger-compiler/2.57.2/dagger-compiler-2.57.2.jar" />
|
||||
<entry name="$MAVEN_REPOSITORY$/com/google/dagger/dagger/2.57.2/dagger-2.57.2.jar" />
|
||||
<entry name="$MAVEN_REPOSITORY$/jakarta/inject/jakarta.inject-api/2.0.1/jakarta.inject-api-2.0.1.jar" />
|
||||
<entry name="$MAVEN_REPOSITORY$/javax/inject/javax.inject/1/javax.inject-1.jar" />
|
||||
<entry name="$MAVEN_REPOSITORY$/org/jspecify/jspecify/1.0.0/jspecify-1.0.0.jar" />
|
||||
<entry name="$MAVEN_REPOSITORY$/com/google/dagger/dagger-spi/2.55/dagger-spi-2.55.jar" />
|
||||
<entry name="$MAVEN_REPOSITORY$/com/google/dagger/dagger-spi/2.57.2/dagger-spi-2.57.2.jar" />
|
||||
<entry name="$MAVEN_REPOSITORY$/com/google/code/findbugs/jsr305/3.0.2/jsr305-3.0.2.jar" />
|
||||
<entry name="$MAVEN_REPOSITORY$/com/google/devtools/ksp/symbol-processing-api/2.0.21-1.0.28/symbol-processing-api-2.0.21-1.0.28.jar" />
|
||||
<entry name="$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib/2.0.21/kotlin-stdlib-2.0.21.jar" />
|
||||
<entry name="$MAVEN_REPOSITORY$/org/jetbrains/annotations/13.0/annotations-13.0.jar" />
|
||||
<entry name="$MAVEN_REPOSITORY$/com/google/devtools/ksp/symbol-processing-api/2.1.21-2.0.2/symbol-processing-api-2.1.21-2.0.2.jar" />
|
||||
<entry name="$MAVEN_REPOSITORY$/com/google/googlejavaformat/google-java-format/1.5/google-java-format-1.5.jar" />
|
||||
<entry name="$MAVEN_REPOSITORY$/com/google/errorprone/javac-shaded/9-dev-r4023-3/javac-shaded-9-dev-r4023-3.jar" />
|
||||
<entry name="$MAVEN_REPOSITORY$/com/google/guava/failureaccess/1.0.2/failureaccess-1.0.2.jar" />
|
||||
<entry name="$MAVEN_REPOSITORY$/com/google/guava/guava/33.0.0-jre/guava-33.0.0-jre.jar" />
|
||||
<entry name="$MAVEN_REPOSITORY$/com/google/guava/listenablefuture/9999.0-empty-to-avoid-conflict-with-guava/listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar" />
|
||||
@@ -31,14 +30,16 @@
|
||||
<entry name="$MAVEN_REPOSITORY$/com/google/errorprone/error_prone_annotations/2.23.0/error_prone_annotations-2.23.0.jar" />
|
||||
<entry name="$MAVEN_REPOSITORY$/com/google/j2objc/j2objc-annotations/2.8/j2objc-annotations-2.8.jar" />
|
||||
<entry name="$MAVEN_REPOSITORY$/com/squareup/javapoet/1.13.0/javapoet-1.13.0.jar" />
|
||||
<entry name="$MAVEN_REPOSITORY$/com/google/googlejavaformat/google-java-format/1.5/google-java-format-1.5.jar" />
|
||||
<entry name="$MAVEN_REPOSITORY$/com/google/errorprone/javac-shaded/9-dev-r4023-3/javac-shaded-9-dev-r4023-3.jar" />
|
||||
<entry name="$MAVEN_REPOSITORY$/com/squareup/kotlinpoet/1.11.0/kotlinpoet-1.11.0.jar" />
|
||||
<entry name="$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib-jdk8/1.6.10/kotlin-stdlib-jdk8-1.6.10.jar" />
|
||||
<entry name="$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib-jdk7/1.6.10/kotlin-stdlib-jdk7-1.6.10.jar" />
|
||||
<entry name="$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-reflect/1.6.10/kotlin-reflect-1.6.10.jar" />
|
||||
<entry name="$MAVEN_REPOSITORY$/javax/inject/javax.inject/1/javax.inject-1.jar" />
|
||||
<entry name="$MAVEN_REPOSITORY$/net/ltgt/gradle/incap/incap/0.2/incap-0.2.jar" />
|
||||
<entry name="$MAVEN_REPOSITORY$/org/checkerframework/checker-compat-qual/2.5.5/checker-compat-qual-2.5.5.jar" />
|
||||
<entry name="$MAVEN_REPOSITORY$/org/checkerframework/checker-compat-qual/2.5.3/checker-compat-qual-2.5.3.jar" />
|
||||
<entry name="$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-metadata-jvm/2.1.21/kotlin-metadata-jvm-2.1.21.jar" />
|
||||
<entry name="$MAVEN_REPOSITORY$/org/jetbrains/kotlin/kotlin-stdlib/2.1.21/kotlin-stdlib-2.1.21.jar" />
|
||||
<entry name="$MAVEN_REPOSITORY$/org/jetbrains/annotations/13.0/annotations-13.0.jar" />
|
||||
</processorPath>
|
||||
<module name="cryptomator" />
|
||||
</profile>
|
||||
|
||||
+3
-5
@@ -1,10 +1,8 @@
|
||||
<component name="InspectionProjectProfileManager">
|
||||
<profile version="1.0">
|
||||
<option name="myName" value="Project Default" />
|
||||
<inspection_tool class="SpellCheckingInspection" enabled="true" level="TYPO" enabled_by_default="true">
|
||||
<option name="processCode" value="true" />
|
||||
<option name="processLiterals" value="true" />
|
||||
<option name="processComments" value="true" />
|
||||
</inspection_tool>
|
||||
<inspection_tool class="Deprecation" enabled="true" level="WARNING" enabled_by_default="true" editorAttributes="DEPRECATED_ATTRIBUTES" />
|
||||
<inspection_tool class="MarkedForRemoval" enabled="true" level="WARNING" enabled_by_default="true" editorAttributes="MARKED_FOR_REMOVAL_ATTRIBUTES" />
|
||||
<inspection_tool class="RedundantScheduledForRemovalAnnotation" enabled="true" level="WARNING" enabled_by_default="true" editorAttributes="MARKED_FOR_REMOVAL_ATTRIBUTES" />
|
||||
</profile>
|
||||
</component>
|
||||
Generated
+1
-1
@@ -8,7 +8,7 @@
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_24" project-jdk-name="25" project-jdk-type="JavaSDK">
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_25" project-jdk-name="25" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/out" />
|
||||
</component>
|
||||
</project>
|
||||
+1
-1
@@ -5,7 +5,7 @@
|
||||
</envs>
|
||||
<option name="MAIN_CLASS_NAME" value="org.cryptomator.launcher.Cryptomator" />
|
||||
<module name="cryptomator" />
|
||||
<option name="VM_PARAMETERS" value="-Dapple.awt.enableTemplateImages=true -Dcryptomator.settingsPath="@{userhome}/Library/Application Support/Cryptomator/settings.json" -Dcryptomator.p12Path="@{userhome}/Library/Application Support/Cryptomator/key.p12" -Dcryptomator.ipcSocketPath="@{userhome}/Library/Application Support/Cryptomator/ipc.socket" -Dcryptomator.logDir="@{userhome}/Library/Logs/Cryptomator" -Dcryptomator.pluginDir="@{userhome}/Library/Application Support/Cryptomator/Plugins" -Dcryptomator.mountPointsDir="@{userhome}/Cryptomator" -Dcryptomator.showTrayIcon=true -Dcryptomator.integrationsMac.keychainServiceName=Cryptomator -Xss2m -Xmx512m -ea --enable-preview --enable-native-access=org.cryptomator.jfuse.mac,javafx.graphics" />
|
||||
<option name="VM_PARAMETERS" value="-Dapple.awt.enableTemplateImages=true -Dcryptomator.settingsPath="@{userhome}/Library/Application Support/Cryptomator/settings.json" -Dcryptomator.p12Path="@{userhome}/Library/Application Support/Cryptomator/key.p12" -Dcryptomator.ipcSocketPath="@{userhome}/Library/Application Support/Cryptomator/ipc.socket" -Dcryptomator.logDir="@{userhome}/Library/Logs/Cryptomator" -Dcryptomator.pluginDir="@{userhome}/Library/Application Support/Cryptomator/Plugins" -Dcryptomator.mountPointsDir="@{userhome}/Cryptomator" -Dcryptomator.showTrayIcon=true -Dcryptomator.integrationsMac.keychainServiceName=Cryptomator -Dcryptomator.updateMechanism=org.cryptomator.macos.update.DmgUpdateMechanism -Xss2m -Xmx512m -ea --enable-preview --enable-native-access=org.cryptomator.jfuse.mac,javafx.graphics" />
|
||||
<method v="2">
|
||||
<option name="Make" enabled="true" />
|
||||
</method>
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
# Changelog
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
||||
|
||||
The changelog starts with version 1.19.0.
|
||||
Changes to prior versions can be found on the [Github release page](https://github.com/cryptomator/cryptomator/releases).
|
||||
|
||||
## [Unreleased](https://github.com/cryptomator/cryptomator/compare/1.18.0...HEAD)
|
||||
|
||||
### Added
|
||||
* New Self-Update Mechanism (#3948)
|
||||
* Implemented `.dmg` update mechanism
|
||||
* Implemented Flatpak update mechanism
|
||||
|
||||
### Changed
|
||||
* Built using JDK 25 (#4031)
|
||||
* Modernized Templage for GitHub Releases
|
||||
@@ -83,6 +83,9 @@
|
||||
</content_rating>
|
||||
|
||||
<releases>
|
||||
<release date="2025-11-12" version="1.18.0">
|
||||
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.18.0</url>
|
||||
</release>
|
||||
<release date="2025-07-08" version="1.17.1">
|
||||
<url type="details">https://github.com/cryptomator/cryptomator/releases/1.17.1</url>
|
||||
</release>
|
||||
|
||||
Vendored
+1
-1
@@ -2,7 +2,7 @@ Source: cryptomator
|
||||
Maintainer: Cryptobot <releases@cryptomator.org>
|
||||
Section: utils
|
||||
Priority: optional
|
||||
Build-Depends: debhelper (>=10), coffeelibs-jdk-24 (>= 24.0.1+9-0ppa3), libgtk-3-0 (>= 3.20.0), libxxf86vm1, libgl1
|
||||
Build-Depends: debhelper (>=10), openjdk-25-jdk (>= 25+36), libgtk-3-0 (>= 3.20.0), libxxf86vm1, libgl1
|
||||
Standards-Version: 4.5.0
|
||||
Homepage: https://cryptomator.org
|
||||
Vcs-Git: https://github.com/cryptomator/cryptomator.git
|
||||
|
||||
Vendored
+2
-1
@@ -4,11 +4,12 @@
|
||||
# Uncomment this to turn on verbose mode.
|
||||
#export DH_VERBOSE=1
|
||||
|
||||
JAVA_HOME = /usr/lib/jvm/java-24-coffeelibs
|
||||
DEB_BUILD_ARCH ?= $(shell dpkg-architecture -qDEB_BUILD_ARCH)
|
||||
ifeq ($(DEB_BUILD_ARCH),amd64)
|
||||
JAVA_HOME = /usr/lib/jvm/java-25-openjdk-amd64
|
||||
JMODS_PATH = jmods/amd64:${JAVA_HOME}/jmods
|
||||
else ifeq ($(DEB_BUILD_ARCH),arm64)
|
||||
JAVA_HOME = /usr/lib/jvm/java-25-openjdk-arm64
|
||||
JMODS_PATH = jmods/aarch64:${JAVA_HOME}/jmods
|
||||
endif
|
||||
|
||||
|
||||
Vendored
+1
@@ -123,6 +123,7 @@ ${JAVA_HOME}/bin/jpackage \
|
||||
--java-options "-Dcryptomator.integrationsMac.keychainServiceName=\"${APP_NAME}\"" \
|
||||
--java-options "-Dcryptomator.mountPointsDir=\"@{userhome}/Library/Application Support${APP_NAME}/mnt\"" \
|
||||
--java-options "-Dcryptomator.showTrayIcon=true" \
|
||||
--java-options "-Dcryptomator.updateMechanism=org.cryptomator.macos.update.DmgUpdateMechanism" \
|
||||
--java-options "-Dcryptomator.buildNumber=\"dmg-${REVISION_NO}\"" \
|
||||
--mac-package-identifier ${PACKAGE_IDENTIFIER} \
|
||||
--resource-dir ../resources
|
||||
|
||||
+3
-3
@@ -1,6 +1,6 @@
|
||||
Apache License v2.0|Apache License, Version 2.0|The Apache Software License, Version 2.0|Apache 2.0|Apache Software License - Version 2.0|Apache-2.0
|
||||
MIT License|The MIT License (MIT)|The MIT License|MIT license
|
||||
LGPL 2.1|LGPL, version 2.1|GNU Lesser/Library General Public License version 2|GNU Lesser General Public License Version 2.1
|
||||
Apache License v2.0|Apache License, Version 2.0|The Apache License, Version 2.0|The Apache Software License, Version 2.0|Apache 2.0|Apache Software License - Version 2.0|Apache-2.0
|
||||
MIT License|MIT|The MIT License (MIT)|The MIT License|MIT license
|
||||
LGPL 2.1|LGPL, version 2.1|GNU Lesser/Library General Public License version 2|GNU Lesser General Public License Version 2.1|GNU Lesser General Public License
|
||||
GPLv2|GNU General Public License Version 2
|
||||
GPLv2+CE|CDDL + GPLv2 with classpath exception
|
||||
Eclipse Public License - Version 1.0|Eclipse Public License - v 1.0
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.cryptomator</groupId>
|
||||
<artifactId>cryptomator</artifactId>
|
||||
<version>1.18.0</version>
|
||||
<version>1.19.0</version>
|
||||
<name>Cryptomator Desktop App</name>
|
||||
|
||||
<organization>
|
||||
@@ -26,7 +26,7 @@
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.jdk.version>24</project.jdk.version>
|
||||
<project.jdk.version>25</project.jdk.version>
|
||||
|
||||
<!-- Group IDs of jars that need to stay on the class path for now -->
|
||||
<!-- remove them, as soon they got modularized or support is dropped (i.e., WebDAV) -->
|
||||
@@ -34,10 +34,10 @@
|
||||
|
||||
<!-- cryptomator dependencies -->
|
||||
<cryptomator.cryptofs.version>2.9.0</cryptomator.cryptofs.version>
|
||||
<cryptomator.integrations.version>1.7.0</cryptomator.integrations.version>
|
||||
<cryptomator.integrations.version>1.8.0-beta1</cryptomator.integrations.version>
|
||||
<cryptomator.integrations.win.version>1.5.1</cryptomator.integrations.win.version>
|
||||
<cryptomator.integrations.mac.version>1.4.1</cryptomator.integrations.mac.version>
|
||||
<cryptomator.integrations.linux.version>1.6.1</cryptomator.integrations.linux.version>
|
||||
<cryptomator.integrations.mac.version>1.5.0-beta2</cryptomator.integrations.mac.version>
|
||||
<cryptomator.integrations.linux.version>1.7.0-beta2</cryptomator.integrations.linux.version>
|
||||
<cryptomator.fuse.version>5.1.0</cryptomator.fuse.version>
|
||||
<cryptomator.webdav.version>3.0.0</cryptomator.webdav.version>
|
||||
|
||||
@@ -62,7 +62,7 @@
|
||||
<!-- build-time dependencies -->
|
||||
<jetbrains.annotations.version>26.0.2-1</jetbrains.annotations.version>
|
||||
<dependency-check.version>12.1.5</dependency-check.version>
|
||||
<jacoco.version>0.8.13</jacoco.version>
|
||||
<jacoco.version>0.8.14</jacoco.version>
|
||||
<license-generator.version>2.7.0</license-generator.version>
|
||||
<junit-tree-reporter.version>1.4.0</junit-tree-reporter.version>
|
||||
<mvn-compiler.version>3.14.1</mvn-compiler.version>
|
||||
@@ -75,6 +75,20 @@
|
||||
<surefire.jacoco.args></surefire.jacoco.args>
|
||||
</properties>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<name>Central Portal Snapshots</name>
|
||||
<id>central-portal-snapshots</id>
|
||||
<url>https://central.sonatype.com/repository/maven-snapshots/</url>
|
||||
<releases>
|
||||
<enabled>false</enabled>
|
||||
</releases>
|
||||
<snapshots>
|
||||
<enabled>true</enabled>
|
||||
</snapshots>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<dependencies>
|
||||
<!-- Cryptomator Libs -->
|
||||
<dependency>
|
||||
|
||||
@@ -50,12 +50,12 @@ open module org.cryptomator.desktop {
|
||||
requires io.github.coffeelibs.tinyoauth2client;
|
||||
requires org.slf4j;
|
||||
requires org.apache.commons.lang3;
|
||||
requires com.github.benmanes.caffeine;
|
||||
|
||||
/* dagger bs */
|
||||
requires jakarta.inject;
|
||||
requires static javax.inject;
|
||||
requires java.compiler;
|
||||
requires com.github.benmanes.caffeine;
|
||||
|
||||
uses org.cryptomator.common.locationpresets.LocationPresetsProvider;
|
||||
uses SSLContextProvider;
|
||||
|
||||
@@ -74,13 +74,6 @@ public abstract class CommonsModule {
|
||||
return new MasterkeyFileAccess(Constants.PEPPER, csprng);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
@Named("SemVer")
|
||||
static Comparator<String> providesSemVerComparator() {
|
||||
return new SemVerComparator();
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
static Optional<RevealPathService> provideRevealPathService() {
|
||||
|
||||
@@ -124,6 +124,15 @@ public class Environment {
|
||||
return Optional.ofNullable(System.getProperty(BUILD_NUMBER_PROP_NAME));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the app version concatenated with the build number (if defined).
|
||||
*
|
||||
* @return version string formatted like {@code 1.2.3-4567} or {@code 1.2.3} if no build number is defined.
|
||||
*/
|
||||
public String getAppVersionWithBuildNumber() {
|
||||
return getAppVersion() + getBuildNumber().map("-"::concat).orElse("");
|
||||
}
|
||||
|
||||
public Optional<Path> getPluginDir() {
|
||||
return getPath(PLUGIN_DIR_PROP_NAME);
|
||||
}
|
||||
|
||||
@@ -1,81 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2016, 2017 Sebastian Stenzel and others.
|
||||
* All rights reserved.
|
||||
* This program and the accompanying materials are made available under the terms of the accompanying LICENSE file.
|
||||
*
|
||||
* Contributors:
|
||||
* Sebastian Stenzel - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.cryptomator.common;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.util.Comparator;
|
||||
|
||||
/**
|
||||
* Compares version strings according to <a href="http://semver.org/spec/v2.0.0.html">SemVer 2.0.0</a>.
|
||||
*/
|
||||
public class SemVerComparator implements Comparator<String> {
|
||||
|
||||
private static final char VERSION_SEP = '.'; // http://semver.org/spec/v2.0.0.html#spec-item-2
|
||||
private static final String PRE_RELEASE_SEP = "-"; // http://semver.org/spec/v2.0.0.html#spec-item-9
|
||||
private static final String BUILD_SEP = "+"; // http://semver.org/spec/v2.0.0.html#spec-item-10
|
||||
|
||||
@Override
|
||||
public int compare(String version1, String version2) {
|
||||
// "Build metadata SHOULD be ignored when determining version precedence.
|
||||
// Thus two versions that differ only in the build metadata, have the same precedence."
|
||||
String v1WithoutBuildMetadata = StringUtils.substringBefore(version1, BUILD_SEP);
|
||||
String v2WithoutBuildMetadata = StringUtils.substringBefore(version2, BUILD_SEP);
|
||||
|
||||
if (v1WithoutBuildMetadata.equals(v2WithoutBuildMetadata)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
String v1MajorMinorPatch = StringUtils.substringBefore(v1WithoutBuildMetadata, PRE_RELEASE_SEP);
|
||||
String v2MajorMinorPatch = StringUtils.substringBefore(v2WithoutBuildMetadata, PRE_RELEASE_SEP);
|
||||
String v1PreReleaseVersion = StringUtils.substringAfter(v1WithoutBuildMetadata, PRE_RELEASE_SEP);
|
||||
String v2PreReleaseVersion = StringUtils.substringAfter(v2WithoutBuildMetadata, PRE_RELEASE_SEP);
|
||||
return compare(v1MajorMinorPatch, v1PreReleaseVersion, v2MajorMinorPatch, v2PreReleaseVersion);
|
||||
}
|
||||
|
||||
private int compare(String v1MajorMinorPatch, String v1PreReleaseVersion, String v2MajorMinorPatch, String v2PreReleaseVersion) {
|
||||
int comparisonResult = compareNumericallyThenLexicographically(v1MajorMinorPatch, v2MajorMinorPatch);
|
||||
if (comparisonResult == 0) {
|
||||
if (v1PreReleaseVersion.isEmpty()) {
|
||||
return 1; // 1.0.0 > 1.0.0-BETA
|
||||
} else if (v2PreReleaseVersion.isEmpty()) {
|
||||
return -1; // 1.0.0-BETA < 1.0.0
|
||||
} else {
|
||||
return compareNumericallyThenLexicographically(v1PreReleaseVersion, v2PreReleaseVersion);
|
||||
}
|
||||
} else {
|
||||
return comparisonResult;
|
||||
}
|
||||
}
|
||||
|
||||
private int compareNumericallyThenLexicographically(String version1, String version2) {
|
||||
final String[] vComps1 = StringUtils.split(version1, VERSION_SEP);
|
||||
final String[] vComps2 = StringUtils.split(version2, VERSION_SEP);
|
||||
final int commonCompCount = Math.min(vComps1.length, vComps2.length);
|
||||
|
||||
for (int i = 0; i < commonCompCount; i++) {
|
||||
int subversionComparisonResult = 0;
|
||||
try {
|
||||
final int v1 = Integer.parseInt(vComps1[i]);
|
||||
final int v2 = Integer.parseInt(vComps2[i]);
|
||||
subversionComparisonResult = v1 - v2;
|
||||
} catch (NumberFormatException ex) {
|
||||
// ok, lets compare this fragment lexicographically
|
||||
subversionComparisonResult = vComps1[i].compareTo(vComps2[i]);
|
||||
}
|
||||
if (subversionComparisonResult != 0) {
|
||||
return subversionComparisonResult;
|
||||
}
|
||||
}
|
||||
|
||||
// all in common so far? longest version string is considered the higher version:
|
||||
return vComps1.length - vComps2.length;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -25,10 +25,8 @@ import javafx.beans.property.StringProperty;
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.collections.ObservableList;
|
||||
import javafx.geometry.NodeOrientation;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.time.Instant;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class Settings {
|
||||
|
||||
@@ -53,6 +51,7 @@ public class Settings {
|
||||
static final String DEFAULT_USER_INTERFACE_ORIENTATION = NodeOrientation.LEFT_TO_RIGHT.name();
|
||||
public static final Instant DEFAULT_TIMESTAMP = Instant.parse("2000-01-01T00:00:00Z");
|
||||
|
||||
private final SettingsProvider provider;
|
||||
public final ObservableList<VaultSettings> directories;
|
||||
public final BooleanProperty startHidden;
|
||||
public final BooleanProperty autoCloseVaults;
|
||||
@@ -78,13 +77,12 @@ public class Settings {
|
||||
public final ObjectProperty<Instant> lastUpdateCheckReminder;
|
||||
public final ObjectProperty<Instant> lastSuccessfulUpdateCheck;
|
||||
public final ObjectProperty<Path> previouslyUsedVaultDirectory;
|
||||
public final StringProperty lastUpdateAttemptedByVersion;
|
||||
|
||||
private Consumer<Settings> saveCmd;
|
||||
|
||||
public static Settings create(Environment env) {
|
||||
public static Settings create(SettingsProvider provider, Environment env) {
|
||||
var defaults = new SettingsJson();
|
||||
defaults.showTrayIcon = env.showTrayIcon();
|
||||
return new Settings(defaults);
|
||||
return new Settings(provider, defaults);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -92,7 +90,8 @@ public class Settings {
|
||||
*
|
||||
* @param json The parsed settings.json
|
||||
*/
|
||||
Settings(SettingsJson json) {
|
||||
Settings(SettingsProvider provider, SettingsJson json) {
|
||||
this.provider = provider;
|
||||
this.directories = FXCollections.observableArrayList(VaultSettings::observables);
|
||||
this.startHidden = new SimpleBooleanProperty(this, "startHidden", json.startHidden);
|
||||
this.autoCloseVaults = new SimpleBooleanProperty(this, "autoCloseVaults", json.autoCloseVaults);
|
||||
@@ -118,6 +117,7 @@ public class Settings {
|
||||
this.lastUpdateCheckReminder = new SimpleObjectProperty<>(this, "lastUpdateCheckReminder", json.lastReminderForUpdateCheck);
|
||||
this.lastSuccessfulUpdateCheck = new SimpleObjectProperty<>(this, "lastSuccessfulUpdateCheck", json.lastSuccessfulUpdateCheck);
|
||||
this.previouslyUsedVaultDirectory = new SimpleObjectProperty<>(this, "previouslyUsedVaultDirectory", json.previouslyUsedVaultDirectory);
|
||||
this.lastUpdateAttemptedByVersion = new SimpleStringProperty(this, "lastUpdateAttemptedByVersion", json.lastUpdateAttemptedByVersion);
|
||||
|
||||
this.directories.addAll(json.directories.stream().map(VaultSettings::new).toList());
|
||||
|
||||
@@ -148,6 +148,7 @@ public class Settings {
|
||||
lastUpdateCheckReminder.addListener(this::somethingChanged);
|
||||
lastSuccessfulUpdateCheck.addListener(this::somethingChanged);
|
||||
previouslyUsedVaultDirectory.addListener(this::somethingChanged);
|
||||
lastUpdateAttemptedByVersion.addListener(this::somethingChanged);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@@ -210,6 +211,7 @@ public class Settings {
|
||||
json.lastReminderForUpdateCheck = lastUpdateCheckReminder.get();
|
||||
json.lastSuccessfulUpdateCheck = lastSuccessfulUpdateCheck.get();
|
||||
json.previouslyUsedVaultDirectory = previouslyUsedVaultDirectory.get();
|
||||
json.lastUpdateAttemptedByVersion = lastUpdateAttemptedByVersion.get();
|
||||
return json;
|
||||
}
|
||||
|
||||
@@ -222,20 +224,12 @@ public class Settings {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// TODO rename to setChangeListener
|
||||
void setSaveCmd(Consumer<Settings> saveCmd) {
|
||||
this.saveCmd = saveCmd;
|
||||
}
|
||||
|
||||
private void somethingChanged(@SuppressWarnings("unused") Observable observable) {
|
||||
this.save();
|
||||
provider.scheduleSave(this);
|
||||
}
|
||||
|
||||
void save() {
|
||||
if (saveCmd != null) {
|
||||
saveCmd.accept(this);
|
||||
}
|
||||
public void saveNow() {
|
||||
provider.saveNow(this);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -96,4 +96,7 @@ class SettingsJson {
|
||||
|
||||
@JsonProperty("previouslyUsedVaultDirectory")
|
||||
Path previouslyUsedVaultDirectory;
|
||||
|
||||
@JsonProperty("lastUpdateAttemptedByVersion")
|
||||
String lastUpdateAttemptedByVersion;
|
||||
}
|
||||
|
||||
@@ -26,7 +26,9 @@ import java.nio.file.NoSuchFileException;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.nio.file.StandardOpenOption;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
@@ -61,8 +63,7 @@ public class SettingsProvider implements Supplier<Settings> {
|
||||
Settings settings = env.getSettingsPath() //
|
||||
.flatMap(this::tryLoad) //
|
||||
.findFirst() //
|
||||
.orElseGet(() -> Settings.create(env));
|
||||
settings.setSaveCmd(this::scheduleSave);
|
||||
.orElseGet(() -> Settings.create(this, env));
|
||||
return settings;
|
||||
}
|
||||
|
||||
@@ -71,7 +72,7 @@ public class SettingsProvider implements Supplier<Settings> {
|
||||
try (InputStream in = Files.newInputStream(path, StandardOpenOption.READ)) {
|
||||
var json = JSON.reader().readValue(in, SettingsJson.class);
|
||||
LOG.info("Settings loaded from {}", path);
|
||||
var settings = new Settings(json);
|
||||
var settings = new Settings(this, json);
|
||||
return Stream.of(settings);
|
||||
} catch (JacksonException e) {
|
||||
LOG.warn("Failed to parse json file {}", path, e);
|
||||
@@ -84,19 +85,33 @@ public class SettingsProvider implements Supplier<Settings> {
|
||||
}
|
||||
}
|
||||
|
||||
private void scheduleSave(Settings settings) {
|
||||
if (settings == null) {
|
||||
return;
|
||||
void saveNow(Settings settings) {
|
||||
try {
|
||||
scheduleSave(settings, 0L).get();
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
LOG.error("Saving settings was interrupted.", e);
|
||||
} catch (ExecutionException e) {
|
||||
LOG.error("Unexpected exception while saving.", e);
|
||||
}
|
||||
final Optional<Path> settingsPath = env.getSettingsPath().findFirst(); // always save to preferred (first) path
|
||||
settingsPath.ifPresent(path -> {
|
||||
Runnable saveCommand = () -> this.save(settings, path);
|
||||
ScheduledFuture<?> scheduledTask = scheduler.schedule(saveCommand, SAVE_DELAY_MS, TimeUnit.MILLISECONDS);
|
||||
ScheduledFuture<?> previouslyScheduledTask = scheduledSaveCmd.getAndSet(scheduledTask);
|
||||
if (previouslyScheduledTask != null) {
|
||||
previouslyScheduledTask.cancel(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void scheduleSave(Settings settings) {
|
||||
scheduleSave(settings, SAVE_DELAY_MS);
|
||||
}
|
||||
|
||||
private Future<?> scheduleSave(Settings settings, long delayMillis) {
|
||||
if (settings == null) {
|
||||
return CompletableFuture.completedFuture(null);
|
||||
}
|
||||
final Path settingsPath = env.getSettingsPath().findFirst().orElseThrow(); // always save to preferred (first) path
|
||||
Runnable saveCommand = () -> this.save(settings, settingsPath);
|
||||
ScheduledFuture<?> scheduledTask = scheduler.schedule(saveCommand, delayMillis, TimeUnit.MILLISECONDS);
|
||||
ScheduledFuture<?> previouslyScheduledTask = scheduledSaveCmd.getAndSet(scheduledTask);
|
||||
if (previouslyScheduledTask != null) {
|
||||
previouslyScheduledTask.cancel(false);
|
||||
}
|
||||
return scheduledTask;
|
||||
}
|
||||
|
||||
private void save(Settings settings, Path settingsPath) {
|
||||
@@ -107,7 +122,7 @@ public class SettingsProvider implements Supplier<Settings> {
|
||||
Path tmpPath = settingsPath.resolveSibling(settingsPath.getFileName().toString() + ".tmp");
|
||||
try (OutputStream out = Files.newOutputStream(tmpPath, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.WRITE)) {
|
||||
var jsonObj = settings.serialized();
|
||||
jsonObj.writtenByVersion = env.getAppVersion() + env.getBuildNumber().map("-"::concat).orElse("");
|
||||
jsonObj.writtenByVersion = env.getAppVersionWithBuildNumber();
|
||||
JSON.writerWithDefaultPrettyPrinter().writeValue(out, jsonObj);
|
||||
}
|
||||
Files.move(tmpPath, settingsPath, StandardCopyOption.REPLACE_EXISTING);
|
||||
|
||||
@@ -20,7 +20,6 @@ import java.util.ResourceBundle;
|
||||
public class PasswordStrengthUtil {
|
||||
|
||||
private static final int PW_TRUNC_LEN = 100; // truncate very long passwords, since zxcvbn memory and runtime depends vastly on the length
|
||||
private static final String RESSOURCE_PREFIX = "passwordStrength.messageLabel.";
|
||||
private static final List<String> SANITIZED_INPUTS = List.of("cryptomator");
|
||||
|
||||
private final ResourceBundle resourceBundle;
|
||||
@@ -48,13 +47,15 @@ public class PasswordStrengthUtil {
|
||||
}
|
||||
|
||||
public String getStrengthDescription(Number score) {
|
||||
if (score.intValue() == -1) {
|
||||
return String.format(resourceBundle.getString(RESSOURCE_PREFIX + "tooShort"), minPwLength);
|
||||
} else if (resourceBundle.containsKey(RESSOURCE_PREFIX + score.intValue())) {
|
||||
return resourceBundle.getString(RESSOURCE_PREFIX + score.intValue());
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
return switch (score.intValue()) {
|
||||
case -1 -> String.format(resourceBundle.getString("passwordStrength.messageLabel.tooShort"), minPwLength);
|
||||
case 0 -> resourceBundle.getString("passwordStrength.messageLabel.0");
|
||||
case 1 -> resourceBundle.getString("passwordStrength.messageLabel.1");
|
||||
case 2 -> resourceBundle.getString("passwordStrength.messageLabel.2");
|
||||
case 3 -> resourceBundle.getString("passwordStrength.messageLabel.3");
|
||||
case 4 -> resourceBundle.getString("passwordStrength.messageLabel.4");
|
||||
default -> "";
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -194,7 +194,7 @@ public class DecryptFileNamesViewController implements FxController {
|
||||
}
|
||||
}
|
||||
|
||||
//obvservable getter
|
||||
//observable getter
|
||||
|
||||
public ObservableValue<String> dropZoneTextProperty() {
|
||||
return dropZoneText;
|
||||
|
||||
@@ -2,6 +2,7 @@ package org.cryptomator.ui.dialogs;
|
||||
|
||||
import org.cryptomator.common.settings.Settings;
|
||||
import org.cryptomator.common.vaults.Vault;
|
||||
import org.cryptomator.ui.common.DefaultSceneFactory;
|
||||
import org.cryptomator.ui.common.StageFactory;
|
||||
import org.cryptomator.ui.controls.FontAwesome5Icon;
|
||||
import org.cryptomator.ui.fxapp.FxApplicationScoped;
|
||||
@@ -19,19 +20,21 @@ public class Dialogs {
|
||||
|
||||
private final ResourceBundle resourceBundle;
|
||||
private final StageFactory stageFactory;
|
||||
private final DefaultSceneFactory sceneFactory;
|
||||
|
||||
private static final String BUTTON_KEY_CLOSE = "generic.button.close";
|
||||
|
||||
@Inject
|
||||
public Dialogs(ResourceBundle resourceBundle, StageFactory stageFactory) {
|
||||
public Dialogs(ResourceBundle resourceBundle, StageFactory stageFactory, DefaultSceneFactory sceneFactory) {
|
||||
this.resourceBundle = resourceBundle;
|
||||
this.stageFactory = stageFactory;
|
||||
this.sceneFactory = sceneFactory;
|
||||
}
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(Dialogs.class);
|
||||
|
||||
private SimpleDialog.Builder createDialogBuilder() {
|
||||
return new SimpleDialog.Builder(resourceBundle, stageFactory);
|
||||
return new SimpleDialog.Builder(resourceBundle, stageFactory, sceneFactory);
|
||||
}
|
||||
|
||||
public SimpleDialog.Builder prepareRemoveVaultDialog(Stage window, Vault vault, ObservableList<Vault> vaults) {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.cryptomator.ui.dialogs;
|
||||
|
||||
import org.cryptomator.ui.common.DefaultSceneFactory;
|
||||
import org.cryptomator.ui.common.FxmlFile;
|
||||
import org.cryptomator.ui.common.FxmlLoaderFactory;
|
||||
import org.cryptomator.ui.common.StageFactory;
|
||||
@@ -36,9 +37,9 @@ public class SimpleDialog {
|
||||
builder.cancelButtonKey != null ? resolveText(builder.cancelButtonKey, null) : null, //
|
||||
() -> builder.okAction.accept(dialogStage), //
|
||||
() -> builder.cancelAction.accept(dialogStage)), //
|
||||
Scene::new, builder.resourceBundle);
|
||||
builder.sceneFactory, builder.resourceBundle);
|
||||
|
||||
dialogStage.setScene(new Scene(loaderFactory.load(FxmlFile.SIMPLE_DIALOG.getRessourcePathString()).getRoot()));
|
||||
dialogStage.setScene(loaderFactory.createScene(FxmlFile.SIMPLE_DIALOG));
|
||||
}
|
||||
|
||||
public void showAndWait() {
|
||||
@@ -62,6 +63,7 @@ public class SimpleDialog {
|
||||
private Stage owner;
|
||||
private final ResourceBundle resourceBundle;
|
||||
private final StageFactory stageFactory;
|
||||
private final DefaultSceneFactory sceneFactory;
|
||||
private String titleKey;
|
||||
private String[] titleArgs;
|
||||
private String messageKey;
|
||||
@@ -73,9 +75,10 @@ public class SimpleDialog {
|
||||
private Consumer<Stage> okAction = Stage::close;
|
||||
private Consumer<Stage> cancelAction = Stage::close;
|
||||
|
||||
public Builder(ResourceBundle resourceBundle, StageFactory stageFactory) {
|
||||
public Builder(ResourceBundle resourceBundle, StageFactory stageFactory, DefaultSceneFactory sceneFactory) {
|
||||
this.resourceBundle = resourceBundle;
|
||||
this.stageFactory = stageFactory;
|
||||
this.sceneFactory = sceneFactory;
|
||||
}
|
||||
|
||||
public Builder setOwner(Stage owner) {
|
||||
|
||||
@@ -26,7 +26,7 @@ import javafx.scene.image.Image;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
@Module(includes = {UpdateCheckerModule.class}, subcomponents = {TrayMenuComponent.class, //
|
||||
@Module(subcomponents = {TrayMenuComponent.class, //
|
||||
DecryptNameComponent.class, //
|
||||
MainWindowComponent.class, //
|
||||
PreferencesComponent.class, //
|
||||
|
||||
@@ -1,135 +0,0 @@
|
||||
package org.cryptomator.ui.fxapp;
|
||||
|
||||
import org.cryptomator.common.Environment;
|
||||
import org.cryptomator.common.SemVerComparator;
|
||||
import org.cryptomator.common.settings.Settings;
|
||||
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.ObjectProperty;
|
||||
import javafx.beans.property.ReadOnlyStringProperty;
|
||||
import javafx.beans.property.SimpleObjectProperty;
|
||||
import javafx.beans.property.SimpleStringProperty;
|
||||
import javafx.beans.property.StringProperty;
|
||||
import javafx.concurrent.ScheduledService;
|
||||
import javafx.concurrent.Worker;
|
||||
import javafx.concurrent.WorkerStateEvent;
|
||||
import javafx.util.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.Comparator;
|
||||
|
||||
@FxApplicationScoped
|
||||
public class UpdateChecker {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(UpdateChecker.class);
|
||||
private static final Duration AUTO_CHECK_DELAY = Duration.seconds(5);
|
||||
|
||||
private final Environment env;
|
||||
private final Settings settings;
|
||||
private final StringProperty latestVersion = new SimpleStringProperty();
|
||||
private final ScheduledService<String> updateCheckerService;
|
||||
private final ObjectProperty<UpdateCheckState> state = new SimpleObjectProperty<>(UpdateCheckState.NOT_CHECKED);
|
||||
private final ObjectProperty<Instant> lastSuccessfulUpdateCheck;
|
||||
private final Comparator<String> versionComparator = new SemVerComparator();
|
||||
private final BooleanBinding updateAvailable;
|
||||
private final BooleanBinding checkFailed;
|
||||
|
||||
@Inject
|
||||
UpdateChecker(Settings settings, //
|
||||
Environment env, //
|
||||
ScheduledService<String> updateCheckerService) {
|
||||
this.env = env;
|
||||
this.settings = settings;
|
||||
this.updateCheckerService = updateCheckerService;
|
||||
this.lastSuccessfulUpdateCheck = settings.lastSuccessfulUpdateCheck;
|
||||
this.updateAvailable = Bindings.createBooleanBinding(this::isUpdateAvailable, latestVersion);
|
||||
this.checkFailed = Bindings.equal(UpdateCheckState.CHECK_FAILED, state);
|
||||
}
|
||||
|
||||
public void automaticallyCheckForUpdatesIfEnabled() {
|
||||
if (!env.disableUpdateCheck() && settings.checkForUpdates.get()) {
|
||||
startCheckingForUpdates(AUTO_CHECK_DELAY);
|
||||
}
|
||||
}
|
||||
|
||||
public void checkForUpdatesNow() {
|
||||
startCheckingForUpdates(Duration.ZERO);
|
||||
}
|
||||
|
||||
private void startCheckingForUpdates(Duration initialDelay) {
|
||||
updateCheckerService.cancel();
|
||||
updateCheckerService.reset();
|
||||
updateCheckerService.setDelay(initialDelay);
|
||||
updateCheckerService.setOnRunning(this::checkStarted);
|
||||
updateCheckerService.setOnSucceeded(this::checkSucceeded);
|
||||
updateCheckerService.setOnFailed(this::checkFailed);
|
||||
updateCheckerService.start();
|
||||
}
|
||||
|
||||
private void checkStarted(WorkerStateEvent event) {
|
||||
LOG.debug("Checking for updates...");
|
||||
state.set(UpdateCheckState.IS_CHECKING);
|
||||
}
|
||||
|
||||
private void checkSucceeded(WorkerStateEvent event) {
|
||||
var latestVersionString = updateCheckerService.getValue();
|
||||
LOG.info("Current version: {}, latest version: {}", getCurrentVersion(), latestVersionString);
|
||||
lastSuccessfulUpdateCheck.set(Instant.now());
|
||||
latestVersion.set(latestVersionString);
|
||||
state.set(UpdateCheckState.CHECK_SUCCESSFUL);
|
||||
}
|
||||
|
||||
private void checkFailed(WorkerStateEvent event) {
|
||||
state.set(UpdateCheckState.CHECK_FAILED);
|
||||
}
|
||||
|
||||
public enum UpdateCheckState {
|
||||
NOT_CHECKED,
|
||||
IS_CHECKING,
|
||||
CHECK_SUCCESSFUL,
|
||||
CHECK_FAILED;
|
||||
}
|
||||
|
||||
/* Observable Properties */
|
||||
public BooleanBinding checkingForUpdatesProperty() {
|
||||
return updateCheckerService.stateProperty().isEqualTo(Worker.State.RUNNING);
|
||||
}
|
||||
|
||||
public ReadOnlyStringProperty latestVersionProperty() {
|
||||
return latestVersion;
|
||||
}
|
||||
|
||||
public BooleanBinding updateAvailableProperty() {
|
||||
return updateAvailable;
|
||||
}
|
||||
|
||||
public BooleanBinding checkFailedProperty() {
|
||||
return checkFailed;
|
||||
}
|
||||
|
||||
public boolean isUpdateAvailable() {
|
||||
String currentVersion = getCurrentVersion();
|
||||
String latestVersionString = latestVersion.get();
|
||||
|
||||
if (currentVersion == null || latestVersionString == null) {
|
||||
return false;
|
||||
} else {
|
||||
return versionComparator.compare(currentVersion, latestVersionString) < 0;
|
||||
}
|
||||
}
|
||||
|
||||
public ObjectProperty<Instant> lastSuccessfulUpdateCheckProperty() {
|
||||
return lastSuccessfulUpdateCheck;
|
||||
}
|
||||
|
||||
public ObjectProperty<UpdateCheckState> updateCheckStateProperty() {
|
||||
return state;
|
||||
}
|
||||
|
||||
public String getCurrentVersion() {
|
||||
return env.getAppVersion();
|
||||
}
|
||||
}
|
||||
@@ -1,93 +0,0 @@
|
||||
package org.cryptomator.ui.fxapp;
|
||||
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
import org.apache.commons.lang3.SystemUtils;
|
||||
import org.cryptomator.common.Environment;
|
||||
import org.cryptomator.common.settings.Settings;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.inject.Named;
|
||||
import javafx.beans.binding.Bindings;
|
||||
import javafx.beans.binding.ObjectBinding;
|
||||
import javafx.concurrent.ScheduledService;
|
||||
import javafx.concurrent.Task;
|
||||
import javafx.util.Duration;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.net.URI;
|
||||
import java.net.http.HttpClient;
|
||||
import java.net.http.HttpRequest;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
|
||||
@Module
|
||||
public abstract class UpdateCheckerModule {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(UpdateCheckerModule.class);
|
||||
|
||||
private static final URI LATEST_VERSION_URI = URI.create("https://api.cryptomator.org/desktop/latest-version.json");
|
||||
private static final Duration UPDATE_CHECK_INTERVAL = Duration.hours(3);
|
||||
private static final Duration DISABLED_UPDATE_CHECK_INTERVAL = Duration.hours(100000); // Duration.INDEFINITE leads to overflows...
|
||||
|
||||
@Provides
|
||||
@FxApplicationScoped
|
||||
static Optional<HttpClient> provideHttpClient() {
|
||||
try {
|
||||
return Optional.of(HttpClient.newBuilder() //
|
||||
.followRedirects(HttpClient.Redirect.NORMAL) // from version 1.6.11 onwards, Cryptomator can follow redirects, in case this URL ever changes
|
||||
.build());
|
||||
} catch (UncheckedIOException e) {
|
||||
LOG.error("HttpClient for update check cannot be created.", e);
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
|
||||
@Provides
|
||||
@FxApplicationScoped
|
||||
static HttpRequest provideCheckForUpdatesRequest(Environment env) {
|
||||
String userAgent = String.format("Cryptomator VersionChecker/%s %s %s (%s)", //
|
||||
env.getAppVersion(), //
|
||||
SystemUtils.OS_NAME, //
|
||||
SystemUtils.OS_VERSION, //
|
||||
SystemUtils.OS_ARCH); //
|
||||
return HttpRequest.newBuilder() //
|
||||
.uri(LATEST_VERSION_URI) //
|
||||
.header("User-Agent", userAgent) //
|
||||
.timeout(java.time.Duration.ofSeconds(10))
|
||||
.build();
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Named("checkForUpdatesInterval")
|
||||
@FxApplicationScoped
|
||||
static ObjectBinding<Duration> provideCheckForUpdateInterval(Settings settings) {
|
||||
return Bindings.when(settings.checkForUpdates).then(UPDATE_CHECK_INTERVAL).otherwise(DISABLED_UPDATE_CHECK_INTERVAL);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@FxApplicationScoped
|
||||
static ScheduledService<String> provideCheckForUpdatesService(ExecutorService executor, Optional<HttpClient> httpClient, HttpRequest checkForUpdatesRequest, @Named("checkForUpdatesInterval") ObjectBinding<Duration> period) {
|
||||
ScheduledService<String> service = new ScheduledService<>() {
|
||||
@Override
|
||||
protected Task<String> createTask() {
|
||||
if (httpClient.isPresent()) {
|
||||
return new UpdateCheckerTask(httpClient.get(), checkForUpdatesRequest);
|
||||
} else {
|
||||
return new Task<>() {
|
||||
@Override
|
||||
protected String call() {
|
||||
throw new NullPointerException("No HttpClient present.");
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
service.setOnFailed(event -> LOG.error("Failed to execute update service", service.getException()));
|
||||
service.setExecutor(executor);
|
||||
service.periodProperty().bind(period);
|
||||
return service;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
package org.cryptomator.ui.fxapp;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.google.common.io.ByteStreams;
|
||||
import org.apache.commons.lang3.SystemUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javafx.concurrent.Task;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.http.HttpClient;
|
||||
import java.net.http.HttpRequest;
|
||||
import java.net.http.HttpResponse;
|
||||
|
||||
public class UpdateCheckerTask extends Task<String> {
|
||||
|
||||
private static final ObjectMapper JSON = new ObjectMapper();
|
||||
private static final Logger LOG = LoggerFactory.getLogger(UpdateCheckerTask.class);
|
||||
|
||||
private static final long MAX_RESPONSE_SIZE = 10L * 1024; // 10kb should be sufficient. protect against flooding
|
||||
|
||||
private final HttpClient httpClient;
|
||||
private final HttpRequest checkForUpdatesRequest;
|
||||
|
||||
UpdateCheckerTask(HttpClient httpClient, HttpRequest checkForUpdatesRequest) {
|
||||
this.httpClient = httpClient;
|
||||
this.checkForUpdatesRequest = checkForUpdatesRequest;
|
||||
|
||||
setOnFailed(event -> LOG.error("Failed to check for updates", getException()));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String call() throws IOException, InterruptedException {
|
||||
HttpResponse<InputStream> response = httpClient.send(checkForUpdatesRequest, HttpResponse.BodyHandlers.ofInputStream());
|
||||
if (response.statusCode() == 200) {
|
||||
return processBody(response);
|
||||
} else {
|
||||
throw new IOException("Unexpected HTTP response code " + response.statusCode());
|
||||
}
|
||||
}
|
||||
|
||||
private String processBody(HttpResponse<InputStream> response) throws IOException {
|
||||
try (InputStream in = response.body(); //
|
||||
InputStream limitedIn = ByteStreams.limit(in, MAX_RESPONSE_SIZE)) {
|
||||
var json = JSON.reader().readTree(limitedIn);
|
||||
if (SystemUtils.IS_OS_MAC_OSX) {
|
||||
return json.get("mac").asText();
|
||||
} else if (SystemUtils.IS_OS_WINDOWS) {
|
||||
return json.get("win").asText();
|
||||
} else if (SystemUtils.IS_OS_LINUX) {
|
||||
return json.get("linux").asText();
|
||||
} else {
|
||||
throw new IllegalStateException("Unsupported operating system");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,7 @@ import org.cryptomator.common.vaults.Vault;
|
||||
import org.cryptomator.common.vaults.VaultListManager;
|
||||
import org.cryptomator.ui.common.FxController;
|
||||
import org.cryptomator.ui.fxapp.FxApplicationWindows;
|
||||
import org.cryptomator.ui.fxapp.UpdateChecker;
|
||||
import org.cryptomator.updater.UpdateChecker;
|
||||
import org.cryptomator.ui.preferences.SelectedPreferencesTab;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -3,7 +3,7 @@ package org.cryptomator.ui.preferences;
|
||||
import com.google.common.io.CharStreams;
|
||||
import org.cryptomator.common.Environment;
|
||||
import org.cryptomator.ui.common.FxController;
|
||||
import org.cryptomator.ui.fxapp.UpdateChecker;
|
||||
import org.cryptomator.updater.UpdateChecker;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ package org.cryptomator.ui.preferences;
|
||||
|
||||
import org.cryptomator.common.Environment;
|
||||
import org.cryptomator.ui.common.FxController;
|
||||
import org.cryptomator.ui.fxapp.UpdateChecker;
|
||||
import org.cryptomator.updater.UpdateChecker;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
||||
@@ -2,25 +2,37 @@ package org.cryptomator.ui.preferences;
|
||||
|
||||
import org.cryptomator.common.Environment;
|
||||
import org.cryptomator.common.settings.Settings;
|
||||
import org.cryptomator.common.vaults.Vault;
|
||||
import org.cryptomator.integrations.update.UpdateStep;
|
||||
import org.cryptomator.ui.common.FxController;
|
||||
import org.cryptomator.ui.fxapp.UpdateChecker;
|
||||
import org.cryptomator.ui.common.VaultService;
|
||||
import org.cryptomator.updater.UpdateChecker;
|
||||
import org.cryptomator.updater.FallbackUpdateInfo;
|
||||
import org.cryptomator.updater.UpdateService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javafx.animation.PauseTransition;
|
||||
import javafx.application.Application;
|
||||
import javafx.application.Platform;
|
||||
import javafx.beans.binding.Bindings;
|
||||
import javafx.beans.binding.BooleanBinding;
|
||||
import javafx.beans.binding.BooleanExpression;
|
||||
import javafx.beans.binding.ObjectBinding;
|
||||
import javafx.beans.binding.StringBinding;
|
||||
import javafx.beans.property.BooleanProperty;
|
||||
import javafx.beans.property.ReadOnlyStringProperty;
|
||||
import javafx.beans.property.SimpleBooleanProperty;
|
||||
import javafx.beans.property.SimpleStringProperty;
|
||||
import javafx.beans.property.StringProperty;
|
||||
import javafx.beans.value.ObservableValue;
|
||||
import javafx.collections.ObservableList;
|
||||
import javafx.concurrent.Worker;
|
||||
import javafx.concurrent.WorkerStateEvent;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.scene.control.CheckBox;
|
||||
import javafx.scene.control.ContentDisplay;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDateTime;
|
||||
@@ -34,73 +46,64 @@ import java.util.ResourceBundle;
|
||||
@PreferencesScoped
|
||||
public class UpdatesPreferencesController implements FxController {
|
||||
|
||||
private static final String DOWNLOADS_URI_TEMPLATE = "https://cryptomator.org/downloads/" //
|
||||
+ "?utm_source=cryptomator-desktop" //
|
||||
+ "&utm_medium=update-notification&" //
|
||||
+ "utm_campaign=app-update-%s";
|
||||
private static final Logger LOG = LoggerFactory.getLogger(UpdatesPreferencesController.class);
|
||||
private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM).withLocale(Locale.getDefault());
|
||||
|
||||
private final Application application;
|
||||
private final Environment environment;
|
||||
private final ResourceBundle resourceBundle;
|
||||
private final Settings settings;
|
||||
private final UpdateChecker updateChecker;
|
||||
private final ObjectBinding<ContentDisplay> checkForUpdatesButtonState;
|
||||
private final ReadOnlyStringProperty latestVersion;
|
||||
private final ObservableValue<Instant> lastSuccessfulUpdateCheck;
|
||||
private final StringBinding lastUpdateCheckMessage;
|
||||
private final UpdateService updateService;
|
||||
private final ObservableList<Vault> unlockedVaults;
|
||||
private final VaultService vaultService;
|
||||
private final ObjectBinding<Worker<?>> worker;
|
||||
private final BooleanExpression running;
|
||||
private final StringBinding updateButtonTitle;
|
||||
private final ObjectBinding<ContentDisplay> updateButtonState;
|
||||
private final ObservableValue<String> timeDifferenceMessage;
|
||||
private final String currentVersion;
|
||||
private final BooleanBinding updateAvailable;
|
||||
private final BooleanBinding checkFailed;
|
||||
private final StringBinding lastUpdateCheckMessage;
|
||||
private final BooleanBinding prohibitUpdateWhileUnlocked;
|
||||
private final BooleanBinding updateButtonDisabled;
|
||||
private final StringProperty errorMessage = new SimpleStringProperty("");
|
||||
private final BooleanProperty upToDateLabelVisible = new SimpleBooleanProperty(false);
|
||||
private final DateTimeFormatter formatter;
|
||||
private final BooleanBinding upToDate;
|
||||
private final String downloadsUri;
|
||||
|
||||
/* FXML */
|
||||
public CheckBox checkForUpdatesCheckbox;
|
||||
|
||||
@Inject
|
||||
UpdatesPreferencesController(Application application, Environment environment, ResourceBundle resourceBundle, Settings settings, UpdateChecker updateChecker) {
|
||||
UpdatesPreferencesController(Application application, Environment environment, ResourceBundle resourceBundle, Settings settings, UpdateChecker updateChecker, ObservableList<Vault> vaults, VaultService vaultService) {
|
||||
this.application = application;
|
||||
this.environment = environment;
|
||||
this.resourceBundle = resourceBundle;
|
||||
this.settings = settings;
|
||||
this.updateChecker = updateChecker;
|
||||
this.checkForUpdatesButtonState = Bindings.when(updateChecker.checkingForUpdatesProperty()).then(ContentDisplay.LEFT).otherwise(ContentDisplay.TEXT_ONLY);
|
||||
this.latestVersion = updateChecker.latestVersionProperty();
|
||||
this.lastSuccessfulUpdateCheck = updateChecker.lastSuccessfulUpdateCheckProperty();
|
||||
this.timeDifferenceMessage = Bindings.createStringBinding(this::getTimeDifferenceMessage, lastSuccessfulUpdateCheck);
|
||||
this.currentVersion = environment.getAppVersion();
|
||||
this.updateAvailable = updateChecker.updateAvailableProperty();
|
||||
this.formatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM).withLocale(Locale.getDefault());
|
||||
this.upToDate = updateChecker.updateCheckStateProperty().isEqualTo(UpdateChecker.UpdateCheckState.CHECK_SUCCESSFUL).and(latestVersion.isEqualTo(currentVersion));
|
||||
this.checkFailed = updateChecker.checkFailedProperty();
|
||||
this.lastUpdateCheckMessage = Bindings.createStringBinding(this::getLastUpdateCheckMessage, lastSuccessfulUpdateCheck);
|
||||
this.downloadsUri = DOWNLOADS_URI_TEMPLATE.formatted(URLEncoder.encode(currentVersion, StandardCharsets.US_ASCII));
|
||||
this.updateService = new UpdateService(updateChecker.updateProperty());
|
||||
this.unlockedVaults = vaults.filtered(Vault::isUnlocked);
|
||||
this.vaultService = vaultService;
|
||||
this.worker = Bindings.when(updateChecker.updateAvailableProperty()).<Worker<?>>then(this.updateService).otherwise(this.updateChecker);
|
||||
this.running = Bindings.createBooleanBinding(this::isRunning, updateService.stateProperty(), updateChecker.stateProperty());
|
||||
this.updateButtonTitle = Bindings.createStringBinding(this::getUpdateButtonTitle, worker, updateService.stateProperty(), updateService.messageProperty());
|
||||
this.updateButtonState = Bindings.createObjectBinding(this::getUpdateButtonState, updateChecker.stateProperty(), updateService.stateProperty());
|
||||
this.timeDifferenceMessage = Bindings.createStringBinding(this::getTimeDifferenceMessage, updateChecker.lastSuccessfulUpdateCheckProperty());
|
||||
this.lastUpdateCheckMessage = Bindings.createStringBinding(this::getLastUpdateCheckMessage, updateChecker.lastSuccessfulUpdateCheckProperty());
|
||||
this.prohibitUpdateWhileUnlocked = Bindings.createBooleanBinding(this::isProhibitUpdateWhileUnlocked, unlockedVaults, updateChecker.updateProperty());
|
||||
this.updateButtonDisabled = Bindings.when(worker.isEqualTo(updateChecker)).then(running).otherwise(prohibitUpdateWhileUnlocked.or(running));
|
||||
}
|
||||
|
||||
public void initialize() {
|
||||
checkForUpdatesCheckbox.selectedProperty().bindBidirectional(settings.checkForUpdates);
|
||||
|
||||
upToDate.addListener((_, _, newVal) -> {
|
||||
if (newVal) {
|
||||
updateChecker.updateAvailableProperty().addListener((_, _, hasUpdate) -> {
|
||||
if (!hasUpdate) {
|
||||
upToDateLabelVisible.set(true);
|
||||
PauseTransition delay = new PauseTransition(javafx.util.Duration.seconds(5));
|
||||
delay.setOnFinished(_ -> upToDateLabelVisible.set(false));
|
||||
delay.play();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@FXML
|
||||
public void checkNow() {
|
||||
updateChecker.checkForUpdatesNow();
|
||||
}
|
||||
|
||||
@FXML
|
||||
public void visitDownloadsPage() {
|
||||
application.getHostServices().showDocument(downloadsUri);
|
||||
updateChecker.setOnFailed(this::checkFailed);
|
||||
updateService.setOnSucceeded(this::updateSucceeded);
|
||||
updateService.setOnFailed(this::updateFailed);
|
||||
}
|
||||
|
||||
@FXML
|
||||
@@ -108,38 +111,104 @@ public class UpdatesPreferencesController implements FxController {
|
||||
environment.getLogDir().ifPresent(logDirPath -> application.getHostServices().showDocument(logDirPath.toUri().toString()));
|
||||
}
|
||||
|
||||
@FXML
|
||||
public void startWork() {
|
||||
if (worker.get().equals(updateChecker)) {
|
||||
updateChecker.checkForUpdatesNow();
|
||||
} else if (!unlockedVaults.isEmpty()) {
|
||||
LOG.warn("Cannot start update due to unlocked vaults.");
|
||||
} else if (worker.get().equals(updateService)) {
|
||||
LOG.info("User started update to version {}", updateChecker.getUpdate().version());
|
||||
updateService.start();
|
||||
}
|
||||
}
|
||||
|
||||
private void checkFailed(WorkerStateEvent workerStateEvent) {
|
||||
assert workerStateEvent.getSource() == updateChecker;
|
||||
LOG.error("Update check failed.", updateChecker.getException());
|
||||
errorMessage.set(resourceBundle.getString("preferences.updates.checkFailed"));
|
||||
}
|
||||
|
||||
private void updateSucceeded(WorkerStateEvent workerStateEvent) {
|
||||
assert workerStateEvent.getSource() == updateService;
|
||||
var lastStep = updateService.getValue();
|
||||
if (lastStep == UpdateStep.EXIT) {
|
||||
// Record that this version attempted an update, so next launch can choose fallback if needed
|
||||
settings.lastUpdateAttemptedByVersion.set(environment.getAppVersionWithBuildNumber());
|
||||
settings.saveNow();
|
||||
LOG.info("Exiting app to update...");
|
||||
Platform.exit();
|
||||
} else if (lastStep == UpdateStep.RETRY) {
|
||||
updateService.reset();
|
||||
} else {
|
||||
LOG.info("Update succeeded.");
|
||||
}
|
||||
}
|
||||
|
||||
private void updateFailed(WorkerStateEvent workerStateEvent) {
|
||||
assert workerStateEvent.getSource() == updateService;
|
||||
LOG.error("Update failed.", updateService.getException());
|
||||
updateService.reset();
|
||||
errorMessage.set(resourceBundle.getString("preferences.updates.updateFailed"));
|
||||
// try fallback mechanism:
|
||||
updateChecker.recheckWithFallbackMechanism();
|
||||
}
|
||||
|
||||
@FXML
|
||||
public void lockAllGracefully() {
|
||||
vaultService.lockAll(unlockedVaults, false);
|
||||
}
|
||||
|
||||
/* Observable Properties */
|
||||
|
||||
public ObjectBinding<ContentDisplay> checkForUpdatesButtonStateProperty() {
|
||||
return checkForUpdatesButtonState;
|
||||
public UpdateChecker getUpdateChecker() {
|
||||
return updateChecker;
|
||||
}
|
||||
|
||||
public ContentDisplay getCheckForUpdatesButtonState() {
|
||||
return checkForUpdatesButtonState.get();
|
||||
public ObjectBinding<Worker<?>> workerProperty() {
|
||||
return worker;
|
||||
}
|
||||
|
||||
public ReadOnlyStringProperty latestVersionProperty() {
|
||||
return latestVersion;
|
||||
public Worker<?> getWorker() {
|
||||
return worker.get();
|
||||
}
|
||||
|
||||
public String getLatestVersion() {
|
||||
return latestVersion.get();
|
||||
public BooleanExpression runningProperty() {
|
||||
return running;
|
||||
}
|
||||
|
||||
public String getCurrentVersion() {
|
||||
return currentVersion;
|
||||
public boolean isRunning() {
|
||||
return updateChecker.getState() == Worker.State.RUNNING || updateService.getState() == Worker.State.RUNNING;
|
||||
}
|
||||
|
||||
public StringBinding lastUpdateCheckMessageProperty() {
|
||||
return lastUpdateCheckMessage;
|
||||
public StringBinding updateButtonTitleProperty() {
|
||||
return updateButtonTitle;
|
||||
}
|
||||
|
||||
public String getLastUpdateCheckMessage() {
|
||||
Instant lastCheck = lastSuccessfulUpdateCheck.getValue();
|
||||
if (lastCheck != null && !lastCheck.equals(Settings.DEFAULT_TIMESTAMP)) {
|
||||
return formatter.format(LocalDateTime.ofInstant(lastCheck, ZoneId.systemDefault()));
|
||||
public String getUpdateButtonTitle() {
|
||||
if (worker.get() == updateChecker) {
|
||||
return resourceBundle.getString("preferences.updates.checkNowBtn");
|
||||
} else {
|
||||
return "-";
|
||||
return switch (updateService.getState()) {
|
||||
case READY -> updateChecker.getUpdate().updateMechanism().getName();
|
||||
case SCHEDULED, RUNNING -> updateService.getMessage();
|
||||
case SUCCEEDED -> resourceBundle.getString("generic.button.done");
|
||||
case FAILED, CANCELLED -> "failed"; // should never be visible
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public ObjectBinding<ContentDisplay> updateButtonStateProperty() {
|
||||
return updateButtonState;
|
||||
}
|
||||
|
||||
public ContentDisplay getUpdateButtonState() {
|
||||
if (updateService.isRunning()) { // isRunning() covers RUNNING and SCHEDULED states
|
||||
return ContentDisplay.BOTTOM;
|
||||
} else if (updateChecker.getState() == Worker.State.RUNNING) {
|
||||
return ContentDisplay.LEFT;
|
||||
} else {
|
||||
return ContentDisplay.TEXT_ONLY;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -148,7 +217,7 @@ public class UpdatesPreferencesController implements FxController {
|
||||
}
|
||||
|
||||
public String getTimeDifferenceMessage() {
|
||||
var lastSuccessCheck = lastSuccessfulUpdateCheck.getValue();
|
||||
var lastSuccessCheck = updateChecker.getLastSuccessfulUpdateCheck();
|
||||
var duration = Duration.between(lastSuccessCheck, Instant.now());
|
||||
var hours = duration.toHours();
|
||||
if (lastSuccessCheck.equals(Settings.DEFAULT_TIMESTAMP)) {
|
||||
@@ -162,6 +231,44 @@ public class UpdatesPreferencesController implements FxController {
|
||||
}
|
||||
}
|
||||
|
||||
public StringBinding lastUpdateCheckMessageProperty() {
|
||||
return lastUpdateCheckMessage;
|
||||
}
|
||||
|
||||
public String getLastUpdateCheckMessage() {
|
||||
Instant lastCheck = updateChecker.getLastSuccessfulUpdateCheck();
|
||||
if (lastCheck != null && !lastCheck.equals(Settings.DEFAULT_TIMESTAMP)) {
|
||||
return FORMATTER.format(LocalDateTime.ofInstant(lastCheck, ZoneId.systemDefault()));
|
||||
} else {
|
||||
return "-";
|
||||
}
|
||||
}
|
||||
|
||||
public String getErrorMessage() {
|
||||
return errorMessage.get();
|
||||
}
|
||||
|
||||
public ReadOnlyStringProperty errorMessageProperty() {
|
||||
return errorMessage;
|
||||
}
|
||||
|
||||
public boolean isProhibitUpdateWhileUnlocked() {
|
||||
// If the result of the last update check was from the fallback mechanism, we don't need to show the warning
|
||||
return !unlockedVaults.isEmpty() && !FallbackUpdateInfo.class.isInstance(updateChecker.getUpdate());
|
||||
}
|
||||
|
||||
public BooleanBinding prohibitUpdateWhileUnlockedProperty() {
|
||||
return prohibitUpdateWhileUnlocked;
|
||||
}
|
||||
|
||||
public boolean isUpdateButtonDisabled() {
|
||||
return updateButtonDisabled.get();
|
||||
}
|
||||
|
||||
public BooleanBinding updateButtonDisabledProperty() {
|
||||
return updateButtonDisabled;
|
||||
}
|
||||
|
||||
public BooleanProperty upToDateLabelVisibleProperty() {
|
||||
return upToDateLabelVisible;
|
||||
}
|
||||
@@ -170,20 +277,4 @@ public class UpdatesPreferencesController implements FxController {
|
||||
return upToDateLabelVisible.get();
|
||||
}
|
||||
|
||||
public BooleanBinding updateAvailableProperty() {
|
||||
return updateAvailable;
|
||||
}
|
||||
|
||||
public boolean isUpdateAvailable() {
|
||||
return updateAvailable.get();
|
||||
}
|
||||
|
||||
public BooleanBinding checkFailedProperty() {
|
||||
return checkFailed;
|
||||
}
|
||||
|
||||
public boolean isCheckFailed() {
|
||||
return checkFailed.getValue();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -58,9 +58,15 @@ public class ShareVaultController implements FxController {
|
||||
|
||||
private static URI getHubUri(Vault vault) {
|
||||
try {
|
||||
var keyID = new URI(vault.getVaultConfigCache().get().getKeyId().toString());
|
||||
assert keyID.getScheme().startsWith(SCHEME_PREFIX);
|
||||
return new URI(keyID.getScheme().substring(SCHEME_PREFIX.length()) + "://" + keyID.getHost() + "/app/vaults");
|
||||
var keyId = new URI(vault.getVaultConfigCache().get().getKeyId().toString());
|
||||
assert keyId.getScheme().startsWith(SCHEME_PREFIX);
|
||||
var path = keyId.getPath();
|
||||
var apiIdx = path.indexOf("/api/");
|
||||
if (apiIdx < 0) {
|
||||
throw new IllegalArgumentException("Path does not contain /api/: " + path);
|
||||
}
|
||||
var appPath = path.substring(0, apiIdx) + "/app/vaults";
|
||||
return new URI(keyId.getScheme().substring(SCHEME_PREFIX.length()), keyId.getAuthority(), appPath, null, null);
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException(e);
|
||||
} catch (URISyntaxException e) {
|
||||
|
||||
@@ -2,7 +2,7 @@ package org.cryptomator.ui.updatereminder;
|
||||
|
||||
import org.cryptomator.common.settings.Settings;
|
||||
import org.cryptomator.ui.common.FxController;
|
||||
import org.cryptomator.ui.fxapp.UpdateChecker;
|
||||
import org.cryptomator.updater.UpdateChecker;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javafx.fxml.FXML;
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
package org.cryptomator.updater;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.SSLParameters;
|
||||
import java.io.IOException;
|
||||
import java.net.Authenticator;
|
||||
import java.net.CookieHandler;
|
||||
import java.net.ProxySelector;
|
||||
import java.net.http.HttpClient;
|
||||
import java.net.http.HttpRequest;
|
||||
import java.net.http.HttpResponse;
|
||||
import java.time.Duration;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
abstract class DelegatingHttpClient extends HttpClient {
|
||||
|
||||
private final HttpClient delegate;
|
||||
|
||||
public DelegatingHttpClient(HttpClient delegate) {
|
||||
this.delegate = Objects.requireNonNull(delegate, "delegate must not be null");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<CookieHandler> cookieHandler() {
|
||||
return delegate.cookieHandler();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Duration> connectTimeout() {
|
||||
return delegate.connectTimeout();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Redirect followRedirects() {
|
||||
return delegate.followRedirects();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<ProxySelector> proxy() {
|
||||
return delegate.proxy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SSLContext sslContext() {
|
||||
return delegate.sslContext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SSLParameters sslParameters() {
|
||||
return delegate.sslParameters();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Authenticator> authenticator() {
|
||||
return delegate.authenticator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Version version() {
|
||||
return delegate.version();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Executor> executor() {
|
||||
return delegate.executor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> HttpResponse<T> send(HttpRequest request, HttpResponse.BodyHandler<T> responseBodyHandler) throws IOException, InterruptedException {
|
||||
return delegate.send(request, responseBodyHandler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> CompletableFuture<HttpResponse<T>> sendAsync(HttpRequest request, HttpResponse.BodyHandler<T> responseBodyHandler) {
|
||||
return delegate.sendAsync(request, responseBodyHandler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> CompletableFuture<HttpResponse<T>> sendAsync(HttpRequest request, HttpResponse.BodyHandler<T> responseBodyHandler, HttpResponse.PushPromiseHandler<T> pushPromiseHandler) {
|
||||
return delegate.sendAsync(request, responseBodyHandler, pushPromiseHandler);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package org.cryptomator.updater;
|
||||
|
||||
import org.cryptomator.integrations.update.UpdateInfo;
|
||||
import org.cryptomator.integrations.update.UpdateMechanism;
|
||||
|
||||
public record FallbackUpdateInfo(String version, UpdateMechanism<FallbackUpdateInfo> updateMechanism) implements UpdateInfo<FallbackUpdateInfo> {}
|
||||
@@ -0,0 +1,105 @@
|
||||
package org.cryptomator.updater;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.apache.commons.lang3.SystemUtils;
|
||||
import org.cryptomator.common.Environment;
|
||||
import org.cryptomator.integrations.common.LocalizedDisplayName;
|
||||
import org.cryptomator.integrations.update.UpdateMechanism;
|
||||
import org.cryptomator.integrations.update.UpdateStep;
|
||||
import org.cryptomator.ui.fxapp.FxApplicationScoped;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javafx.application.Application;
|
||||
import javafx.application.Platform;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URI;
|
||||
import java.net.URLEncoder;
|
||||
import java.net.http.HttpClient;
|
||||
import java.net.http.HttpRequest;
|
||||
import java.net.http.HttpResponse;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
@FxApplicationScoped
|
||||
@LocalizedDisplayName(bundle = "i18n.strings", key = "preferences.updates.visitDownloadPage")
|
||||
public class FallbackUpdateMechanism implements UpdateMechanism<FallbackUpdateInfo> {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(FallbackUpdateMechanism.class);
|
||||
private static final String LATEST_VERSION_API_URL = "https://api.cryptomator.org/connect/apps/desktop/latest-version";
|
||||
private static final ObjectMapper MAPPER = new ObjectMapper();
|
||||
private static final String DOWNLOADS_URI_TEMPLATE = "https://cryptomator.org/downloads/" //
|
||||
+ "?utm_source=cryptomator-desktop" //
|
||||
+ "&utm_medium=update-notification&" //
|
||||
+ "utm_campaign=app-update-%s";
|
||||
|
||||
private final Application app;
|
||||
private final Environment env;
|
||||
|
||||
@Inject
|
||||
public FallbackUpdateMechanism(Application app, Environment env) {
|
||||
this.app = app;
|
||||
this.env = env;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FallbackUpdateInfo checkForUpdate(String currentVersion, HttpClient httpClient) {
|
||||
try {
|
||||
HttpRequest request = HttpRequest.newBuilder().uri(URI.create(LATEST_VERSION_API_URL)).build();
|
||||
HttpResponse<InputStream> response = httpClient.send(request, HttpResponse.BodyHandlers.ofInputStream());
|
||||
if (response.statusCode() != 200) {
|
||||
throw new RuntimeException("Failed to fetch release: " + response.statusCode());
|
||||
}
|
||||
var release = MAPPER.readValue(response.body(), LatestVersion.class);
|
||||
var updateVersion = release.versionForCurrentOS();
|
||||
if (UpdateMechanism.isUpdateAvailable(updateVersion, currentVersion)) {
|
||||
return new FallbackUpdateInfo(updateVersion, this);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
LOG.warn("Update check interrupted", e);
|
||||
return null;
|
||||
} catch (IOException e) {
|
||||
LOG.warn("Update check failed", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public UpdateStep firstStep(FallbackUpdateInfo updateInfo) {
|
||||
return UpdateStep.of("Go to download page", this::openDownloadPage); // TODO localize
|
||||
}
|
||||
|
||||
private UpdateStep openDownloadPage() {
|
||||
var downloadUrl = DOWNLOADS_URI_TEMPLATE.formatted(URLEncoder.encode(env.getAppVersion(), StandardCharsets.US_ASCII));
|
||||
Platform.runLater(() -> {
|
||||
app.getHostServices().showDocument(downloadUrl);
|
||||
});
|
||||
return UpdateStep.RETRY; // allow running this "update mechanism" as many times as the user wants
|
||||
}
|
||||
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public record LatestVersion(
|
||||
@JsonProperty("mac") String macVersion,
|
||||
@JsonProperty("win") String winVersion,
|
||||
@JsonProperty("linux") String linuxVersion
|
||||
) {
|
||||
public String versionForCurrentOS() {
|
||||
if (SystemUtils.IS_OS_MAC_OSX) {
|
||||
return macVersion;
|
||||
} else if (SystemUtils.IS_OS_WINDOWS) {
|
||||
return winVersion;
|
||||
} else if (SystemUtils.IS_OS_LINUX) {
|
||||
return linuxVersion;
|
||||
} else {
|
||||
throw new IllegalStateException("Unsupported operating system");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,198 @@
|
||||
package org.cryptomator.updater;
|
||||
|
||||
import org.cryptomator.common.Environment;
|
||||
import org.cryptomator.common.settings.Settings;
|
||||
import org.cryptomator.integrations.update.UpdateFailedException;
|
||||
import org.cryptomator.integrations.update.UpdateInfo;
|
||||
import org.cryptomator.integrations.update.UpdateMechanism;
|
||||
import org.cryptomator.ui.fxapp.FxApplicationScoped;
|
||||
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.ObjectBinding;
|
||||
import javafx.beans.binding.StringExpression;
|
||||
import javafx.beans.property.ObjectProperty;
|
||||
import javafx.beans.property.SimpleObjectProperty;
|
||||
import javafx.concurrent.ScheduledService;
|
||||
import javafx.concurrent.Task;
|
||||
import javafx.util.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
@FxApplicationScoped
|
||||
public class UpdateChecker extends ScheduledService<UpdateInfo<?>> {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(UpdateChecker.class);
|
||||
private static final Duration AUTO_CHECK_DELAY = Duration.seconds(5);
|
||||
private static final Duration UPDATE_CHECK_INTERVAL = Duration.hours(3);
|
||||
private static final Duration DISABLED_UPDATE_CHECK_INTERVAL = Duration.hours(100000); // Duration.INDEFINITE leads to overflows...
|
||||
|
||||
public enum UpdateCheckState {
|
||||
NOT_CHECKED,
|
||||
IS_CHECKING,
|
||||
CHECK_SUCCESSFUL,
|
||||
CHECK_FAILED
|
||||
}
|
||||
|
||||
private final Environment env;
|
||||
private final Settings settings;
|
||||
private final ObjectProperty<Instant> lastSuccessfulUpdateCheck;
|
||||
private final ObjectProperty<UpdateInfo<?>> update = new SimpleObjectProperty<>();
|
||||
private final StringExpression latestVersion = StringExpression.stringExpression(update.map(UpdateInfo::version));
|
||||
private final BooleanBinding updateAvailable = update.isNotNull();
|
||||
private final ObjectBinding<UpdateCheckState> updateState = Bindings.createObjectBinding(this::getUpdateCheckState, stateProperty());
|
||||
private final BooleanBinding checkFailed = Bindings.equal(UpdateCheckState.CHECK_FAILED, updateState);
|
||||
private final UpdateMechanism<?> fallbackUpdateMechanism;
|
||||
private UpdateMechanism<?> updateMechanism;
|
||||
|
||||
@Inject
|
||||
UpdateChecker(Settings settings, //
|
||||
Environment env,
|
||||
FallbackUpdateMechanism fallbackUpdateMechanism) {
|
||||
this.env = env;
|
||||
this.settings = settings;
|
||||
this.lastSuccessfulUpdateCheck = settings.lastSuccessfulUpdateCheck;
|
||||
this.fallbackUpdateMechanism = fallbackUpdateMechanism;
|
||||
|
||||
// Prefer the safer fallback mechanism if the last update attempt was already made by this app version
|
||||
var currentVersion = env.getAppVersionWithBuildNumber();
|
||||
var lastAttemptedBy = settings.lastUpdateAttemptedByVersion.get();
|
||||
if (currentVersion != null && currentVersion.equals(lastAttemptedBy)) {
|
||||
this.updateMechanism = fallbackUpdateMechanism; // immediately use fallback mechanism
|
||||
} else {
|
||||
this.updateMechanism = UpdateMechanism.get().orElse(fallbackUpdateMechanism);
|
||||
}
|
||||
|
||||
setExecutor(Executors.newVirtualThreadPerTaskExecutor());
|
||||
periodProperty().bind(Bindings.when(settings.checkForUpdates).then(UPDATE_CHECK_INTERVAL).otherwise(DISABLED_UPDATE_CHECK_INTERVAL));
|
||||
}
|
||||
|
||||
public void automaticallyCheckForUpdatesIfEnabled() {
|
||||
if (!env.disableUpdateCheck() && settings.checkForUpdates.get()) {
|
||||
startCheckingForUpdates(AUTO_CHECK_DELAY);
|
||||
}
|
||||
}
|
||||
|
||||
public void recheckWithFallbackMechanism() {
|
||||
if (updateMechanism == fallbackUpdateMechanism) {
|
||||
return; // already using fallback mechanism
|
||||
}
|
||||
updateMechanism = fallbackUpdateMechanism;
|
||||
checkForUpdatesNow();
|
||||
}
|
||||
|
||||
public void checkForUpdatesNow() {
|
||||
startCheckingForUpdates(Duration.ZERO);
|
||||
}
|
||||
|
||||
private void startCheckingForUpdates(Duration initialDelay) {
|
||||
cancel();
|
||||
reset();
|
||||
setDelay(initialDelay);
|
||||
start();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void succeeded() {
|
||||
var updateInfo = getValue();
|
||||
super.succeeded(); // this will nil the value property!
|
||||
lastSuccessfulUpdateCheck.set(Instant.now());
|
||||
if (updateInfo != null) {
|
||||
LOG.info("Current version: {}, latest version: {}", getCurrentVersion(), updateInfo.version());
|
||||
update.set(updateInfo);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Task<UpdateInfo<?>> createTask() {
|
||||
return new UpdateCheckTask();
|
||||
}
|
||||
|
||||
/* Observable Properties */
|
||||
|
||||
public UpdateInfo<?> getUpdate() {
|
||||
return update.get();
|
||||
}
|
||||
|
||||
public ObjectProperty<UpdateInfo<?>> updateProperty() {
|
||||
return update;
|
||||
}
|
||||
|
||||
public String getLatestVersion() {
|
||||
return latestVersion.get();
|
||||
}
|
||||
|
||||
public StringExpression latestVersionProperty() {
|
||||
return latestVersion;
|
||||
}
|
||||
|
||||
public boolean isUpdateAvailable() {
|
||||
return updateAvailable.get();
|
||||
}
|
||||
|
||||
public BooleanBinding updateAvailableProperty() {
|
||||
return updateAvailable;
|
||||
}
|
||||
|
||||
public boolean isCheckFailed() {
|
||||
return checkFailed.get();
|
||||
}
|
||||
|
||||
public BooleanBinding checkFailedProperty() {
|
||||
return checkFailed;
|
||||
}
|
||||
|
||||
public Instant getLastSuccessfulUpdateCheck() {
|
||||
return lastSuccessfulUpdateCheck.get();
|
||||
}
|
||||
|
||||
public ObjectProperty<Instant> lastSuccessfulUpdateCheckProperty() {
|
||||
return lastSuccessfulUpdateCheck;
|
||||
}
|
||||
|
||||
public ObjectBinding<UpdateCheckState> updateCheckStateProperty() {
|
||||
return updateState;
|
||||
}
|
||||
|
||||
private UpdateCheckState getUpdateCheckState() {
|
||||
return switch (getState()) {
|
||||
case READY -> UpdateCheckState.NOT_CHECKED;
|
||||
case SCHEDULED, RUNNING -> UpdateCheckState.IS_CHECKING;
|
||||
case SUCCEEDED -> UpdateCheckState.CHECK_SUCCESSFUL;
|
||||
case FAILED, CANCELLED -> UpdateCheckState.CHECK_FAILED;
|
||||
};
|
||||
}
|
||||
|
||||
public String getCurrentVersion() {
|
||||
return env.getAppVersion();
|
||||
}
|
||||
|
||||
private class UpdateCheckTask extends Task<UpdateInfo<?>> {
|
||||
|
||||
@Override
|
||||
protected UpdateInfo<?> call() {
|
||||
try (var httpClient = new UpdateCheckerHttpClient(env)) {
|
||||
var result = updateMechanism.checkForUpdate(env.getAppVersion(), httpClient);
|
||||
if (result != null) {
|
||||
return result;
|
||||
}
|
||||
} catch (UpdateFailedException e) {
|
||||
LOG.error("Update check using {} failed.", updateMechanism.getClass(), e);
|
||||
}
|
||||
if (updateMechanism == fallbackUpdateMechanism) {
|
||||
return null;
|
||||
}
|
||||
LOG.debug("Trying fallback update check...");
|
||||
try (var httpClient = new UpdateCheckerHttpClient(env)) {
|
||||
return fallbackUpdateMechanism.checkForUpdate(env.getAppVersion(), httpClient);
|
||||
} catch (UpdateFailedException e) {
|
||||
LOG.error("Fallback update check failed.", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package org.cryptomator.updater;
|
||||
|
||||
import org.apache.commons.lang3.SystemUtils;
|
||||
import org.cryptomator.common.Environment;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.ProxySelector;
|
||||
import java.net.http.HttpClient;
|
||||
import java.net.http.HttpRequest;
|
||||
import java.net.http.HttpResponse;
|
||||
import java.time.Duration;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public class UpdateCheckerHttpClient extends DelegatingHttpClient {
|
||||
|
||||
private final String userAgent;
|
||||
|
||||
public UpdateCheckerHttpClient(Environment env) {
|
||||
var delegate = HttpClient.newBuilder() //
|
||||
.followRedirects(HttpClient.Redirect.NORMAL) // from version 1.6.11 onwards, Cryptomator can follow redirects, in case this URL ever changes
|
||||
.proxy(ProxySelector.getDefault()).build();
|
||||
super(delegate);
|
||||
this.userAgent = String.format("Cryptomator VersionChecker/%s %s %s (%s)", env.getAppVersion(), SystemUtils.OS_NAME, SystemUtils.OS_VERSION, SystemUtils.OS_ARCH);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> HttpResponse<T> send(HttpRequest request, HttpResponse.BodyHandler<T> responseBodyHandler) throws IOException, InterruptedException {
|
||||
return super.send(decorateRequest(request), responseBodyHandler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> CompletableFuture<HttpResponse<T>> sendAsync(HttpRequest request, HttpResponse.BodyHandler<T> responseBodyHandler) {
|
||||
return super.sendAsync(decorateRequest(request), responseBodyHandler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> CompletableFuture<HttpResponse<T>> sendAsync(HttpRequest request, HttpResponse.BodyHandler<T> responseBodyHandler, HttpResponse.PushPromiseHandler<T> pushPromiseHandler) {
|
||||
return super.sendAsync(decorateRequest(request), responseBodyHandler, pushPromiseHandler);
|
||||
}
|
||||
|
||||
private HttpRequest decorateRequest(HttpRequest request) {
|
||||
return HttpRequest.newBuilder(request, (_, _) -> true) //
|
||||
.header("User-Agent", this.userAgent) //
|
||||
.timeout(Duration.ofSeconds(10)) //
|
||||
.build();
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
package org.cryptomator.updater;
|
||||
|
||||
import org.cryptomator.integrations.update.UpdateInfo;
|
||||
import org.cryptomator.integrations.update.UpdateMechanism;
|
||||
import org.cryptomator.integrations.update.UpdateStep;
|
||||
|
||||
import javafx.beans.binding.Bindings;
|
||||
import javafx.beans.binding.BooleanBinding;
|
||||
import javafx.beans.value.ObservableValue;
|
||||
import javafx.concurrent.Service;
|
||||
import javafx.concurrent.Task;
|
||||
import java.io.IOException;
|
||||
import java.io.InterruptedIOException;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* A service that performs all update steps provided by the given {@link UpdateMechanism} in sequence.
|
||||
*/
|
||||
public class UpdateService extends Service<UpdateStep> {
|
||||
|
||||
private final BooleanBinding updateFailed = Bindings.equal(State.FAILED, stateProperty());
|
||||
|
||||
private ObservableValue<UpdateInfo<?>> updateInfo;
|
||||
|
||||
public UpdateService(ObservableValue<UpdateInfo<?>> updateInfo) {
|
||||
setExecutor(Executors.newVirtualThreadPerTaskExecutor());
|
||||
this.updateInfo = updateInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Task<UpdateStep> createTask() {
|
||||
return new RunAllStepsTask(updateInfo.getValue());
|
||||
}
|
||||
|
||||
private static class RunAllStepsTask extends Task<UpdateStep> {
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
private final UpdateInfo updateInfo;
|
||||
|
||||
public RunAllStepsTask(UpdateInfo<?> updateInfo) {
|
||||
this.updateInfo = Objects.requireNonNull(updateInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected UpdateStep call() throws IOException {
|
||||
try {
|
||||
UpdateStep step = updateInfo.useToPrepareFirstStep();
|
||||
UpdateStep lastStep;
|
||||
do {
|
||||
step.start();
|
||||
observeAndWaitFor(step);
|
||||
lastStep = step;
|
||||
step = step.nextStep();
|
||||
} while (step != null);
|
||||
return lastStep;
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
throw new InterruptedIOException("Update interrupted");
|
||||
}
|
||||
}
|
||||
|
||||
private void observeAndWaitFor(UpdateStep step) throws InterruptedException {
|
||||
do {
|
||||
updateProgress(step.preparationProgress(), 1.0);
|
||||
updateMessage(step.description());
|
||||
} while (!step.await(100, TimeUnit.MILLISECONDS));
|
||||
}
|
||||
}
|
||||
|
||||
/* Observable Properties */
|
||||
|
||||
public boolean isUpdateFailed() {
|
||||
return updateFailed.get();
|
||||
}
|
||||
|
||||
public BooleanBinding updateFailedProperty() {
|
||||
return updateFailed;
|
||||
}
|
||||
}
|
||||
@@ -3,55 +3,73 @@
|
||||
<?import org.cryptomator.ui.controls.FontAwesome5IconView?>
|
||||
<?import org.cryptomator.ui.controls.FontAwesome5Spinner?>
|
||||
<?import org.cryptomator.ui.controls.FormattedLabel?>
|
||||
<?import org.cryptomator.ui.controls.FormattedString?>
|
||||
<?import javafx.geometry.Insets?>
|
||||
<?import javafx.scene.control.Button?>
|
||||
<?import javafx.scene.control.CheckBox?>
|
||||
<?import javafx.scene.control.Hyperlink?>
|
||||
<?import javafx.scene.control.Label?>
|
||||
<?import javafx.scene.layout.HBox?>
|
||||
<?import javafx.scene.layout.VBox?>
|
||||
<?import javafx.scene.control.ProgressBar?>
|
||||
<?import javafx.scene.control.Tooltip?>
|
||||
<?import javafx.scene.text.TextFlow?>
|
||||
<?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.preferences.UpdatesPreferencesController"
|
||||
spacing="12">
|
||||
<fx:define>
|
||||
<FormattedString fx:id="linkLabel" format="%preferences.updates.updateAvailable" arg1="${controller.latestVersion}"/>
|
||||
</fx:define>
|
||||
<padding>
|
||||
<Insets topRightBottomLeft="24"/>
|
||||
</padding>
|
||||
<FormattedLabel format="%preferences.updates.currentVersion" arg1="${controller.currentVersion}" textAlignment="CENTER" wrapText="true"/>
|
||||
<FormattedLabel format="%preferences.updates.currentVersion" arg1="${controller.updateChecker.currentVersion}" textAlignment="CENTER" wrapText="true"/>
|
||||
|
||||
<CheckBox fx:id="checkForUpdatesCheckbox" text="%preferences.updates.autoUpdateCheck"/>
|
||||
|
||||
<VBox alignment="CENTER" spacing="12">
|
||||
<Button text="%preferences.updates.checkNowBtn" defaultButton="true" onAction="#checkNow" contentDisplay="${controller.checkForUpdatesButtonState}">
|
||||
<FormattedLabel format="%preferences.updates.updateAvailable" arg1="${controller.updateChecker.latestVersion}" textAlignment="CENTER" wrapText="true" visible="${controller.updateChecker.updateAvailable}"/>
|
||||
|
||||
<Button text="${controller.updateButtonTitle}" defaultButton="true" onAction="#startWork" disable="${controller.updateButtonDisabled}" contentDisplay="${controller.updateButtonState}">
|
||||
<graphic>
|
||||
<FontAwesome5Spinner glyphSize="12"/>
|
||||
<VBox spacing="5" alignment="CENTER">
|
||||
<ProgressBar maxWidth="200"
|
||||
maxHeight="12"
|
||||
visible="${controller.running && controller.worker.progress != -1.0}"
|
||||
managed="${controller.running && controller.worker.progress != -1.0}"
|
||||
progress="${controller.worker.progress}"/>
|
||||
<FontAwesome5Spinner glyphSize="12"
|
||||
visible="${controller.running && controller.worker.progress == -1.0}"
|
||||
managed="${controller.running && controller.worker.progress == -1.0}"/>
|
||||
</VBox>
|
||||
</graphic>
|
||||
</Button>
|
||||
|
||||
<TextFlow styleClass="text-flow" textAlignment="CENTER" visible="${controller.checkFailed}" managed="${controller.checkFailed}">
|
||||
<TextFlow styleClass="text-flow" textAlignment="CENTER" visible="${controller.prohibitUpdateWhileUnlocked}" managed="${controller.prohibitUpdateWhileUnlocked}">
|
||||
<FontAwesome5IconView glyphSize="12" styleClass="glyph-icon-primary" glyph="LOCK_OPEN"/>
|
||||
<Text text=" "/>
|
||||
<Text text="%preferences.updates.prohibitedDueToUnlockedVaults.1"/>
|
||||
<Text text=" "/>
|
||||
<Hyperlink styleClass="hyperlink-underline" text="%preferences.updates.prohibitedDueToUnlockedVaults.2" onAction="#lockAllGracefully"/>
|
||||
<Text text=" "/>
|
||||
<Text text="%preferences.updates.prohibitedDueToUnlockedVaults.3"/>
|
||||
</TextFlow>
|
||||
|
||||
<TextFlow styleClass="text-flow" textAlignment="CENTER" visible="${!controller.errorMessage.empty}" managed="${!controller.errorMessage.empty}">
|
||||
<FontAwesome5IconView glyphSize="12" styleClass="glyph-icon-orange" glyph="EXCLAMATION_TRIANGLE"/>
|
||||
<Text text=" "/>
|
||||
<Text text="%preferences.updates.checkFailed"/>
|
||||
<Text text="${controller.errorMessage}"/>
|
||||
<Text text=" "/>
|
||||
<Hyperlink styleClass="hyperlink-underline" text="%preferences.general.debugDirectory" onAction="#showLogfileDirectory"/>
|
||||
</TextFlow>
|
||||
<FormattedLabel format="%preferences.updates.lastUpdateCheck" arg1="${controller.timeDifferenceMessage}" textAlignment="CENTER" wrapText="true">
|
||||
|
||||
<FormattedLabel format="%preferences.updates.lastUpdateCheck" arg1="${controller.timeDifferenceMessage}" textAlignment="CENTER" wrapText="true" visible="${!controller.updateChecker.updateAvailable}" managed="${!controller.updateChecker.updateAvailable}">
|
||||
<tooltip>
|
||||
<Tooltip text="${controller.lastUpdateCheckMessage}" showDelay="10ms"/>
|
||||
</tooltip>
|
||||
</FormattedLabel>
|
||||
|
||||
<Label text="%preferences.updates.upToDate" visible="${controller.upToDateLabelVisible}" managed="${controller.upToDateLabelVisible}">
|
||||
<graphic>
|
||||
<FontAwesome5IconView glyphSize="12" styleClass="glyph-icon-primary" glyph="CHECK"/>
|
||||
</graphic>
|
||||
</Label>
|
||||
<Hyperlink text="${linkLabel.value}" onAction="#visitDownloadsPage" textAlignment="CENTER" wrapText="true" styleClass="hyperlink-underline" visible="${controller.updateAvailable}" managed="${controller.updateAvailable}"/>
|
||||
</VBox>
|
||||
</VBox>
|
||||
|
||||
@@ -330,8 +330,13 @@ preferences.updates.lastUpdateCheck.never=never
|
||||
preferences.updates.lastUpdateCheck.recently=recently
|
||||
preferences.updates.lastUpdateCheck.daysAgo=%s days ago
|
||||
preferences.updates.lastUpdateCheck.hoursAgo=%s hours ago
|
||||
preferences.updates.prohibitedDueToUnlockedVaults.1=Please
|
||||
preferences.updates.prohibitedDueToUnlockedVaults.2=lock your vaults
|
||||
preferences.updates.prohibitedDueToUnlockedVaults.3=to install the update.
|
||||
preferences.updates.checkFailed=Looking for updates failed. Please check your internet connection or try again later.
|
||||
preferences.updates.updateFailed=Update failed. Please install the update manually.
|
||||
preferences.updates.upToDate=Cryptomator is up-to-date.
|
||||
preferences.updates.visitDownloadPage=Visit Download Page
|
||||
|
||||
## Contribution
|
||||
preferences.contribute=Support Us
|
||||
@@ -522,8 +527,8 @@ recoveryKey.recover.recoverBtn=Recover
|
||||
recoveryKey.recover.resetSuccess.message=Password reset successful
|
||||
recoveryKey.recover.resetSuccess.description=You can unlock your vault with the new password.
|
||||
### Recovery Key Vault Config Reset Success
|
||||
recoveryKey.recover.resetVaultConfigSuccess.message=Vault config reset successful
|
||||
recoveryKey.recover.resetMasterkeyFileSuccess.message=Masterkey file reset successful
|
||||
recoveryKey.recover.resetVaultConfigSuccess.message=Vault configuration recovered
|
||||
recoveryKey.recover.resetMasterkeyFileSuccess.message=Masterkey file recovered
|
||||
recoveryKey.recover.resetMasterkeyFileSuccess.description=You can unlock your vault with your password now.
|
||||
|
||||
# Recover Vault Config File and/or Masterkey
|
||||
|
||||
@@ -87,6 +87,7 @@
|
||||
### Locked
|
||||
### Unlocked
|
||||
### Missing
|
||||
### Missing Vault Config
|
||||
### Needs Migration
|
||||
### Error
|
||||
|
||||
@@ -105,6 +106,25 @@
|
||||
### Enter Recovery Key
|
||||
### Reset Password
|
||||
### Recovery Key Password Reset Success
|
||||
### Recovery Key Vault Config Reset Success
|
||||
|
||||
# Recover Vault Config File and/or Masterkey
|
||||
##Add Existing Vault without recovery - Dialog
|
||||
|
||||
##Vault Already Exists - Dialog
|
||||
|
||||
##Invalid Selection - Dialog
|
||||
|
||||
## Contact Hub Vault Owner - Dialog
|
||||
|
||||
##Dialog Title
|
||||
|
||||
## OnBoarding
|
||||
|
||||
###Vault Config Missing
|
||||
###Masterkey Missing
|
||||
|
||||
## Expert Settings
|
||||
|
||||
# Convert Vault
|
||||
|
||||
|
||||
@@ -394,8 +394,6 @@ main.vaultlist.contextMenu.unlockNow=افتح الان
|
||||
main.vaultlist.contextMenu.vaultoptions=إظهار خيارات المخزن
|
||||
main.vaultlist.contextMenu.reveal=اظهار القرص
|
||||
main.vaultlist.contextMenu.share=مشاركة…
|
||||
main.vaultlist.addVaultBtn.menuItemNew=إنشاء مخزن جديد...
|
||||
main.vaultlist.addVaultBtn.menuItemExisting=افتح مخزن موجود...
|
||||
main.vaultlist.showEventsButton.tooltip=عرض الإشعارات
|
||||
##Notificaition
|
||||
main.notification.updateAvailable=هناك تحديث متاح.
|
||||
@@ -433,6 +431,7 @@ main.vaultDetail.missing.info=لم يتمكن Cryptomator من العثور عل
|
||||
main.vaultDetail.missing.recheck=إعادة الفحص
|
||||
main.vaultDetail.missing.remove=حذف من قائمة الخزنات…
|
||||
main.vaultDetail.missing.changeLocation=تغيير موقع الخزنة…
|
||||
### Missing Vault Config
|
||||
### Needs Migration
|
||||
main.vaultDetail.migrateButton=ترقية الحافظة
|
||||
main.vaultDetail.migratePrompt=يجب ترقية المخزن الخاص بك إلى تنسيق جديد، قبل أن تتمكن من الوصول إليه
|
||||
@@ -512,6 +511,26 @@ recoveryKey.recover.resetBtn=إعادة الضبط
|
||||
### Recovery Key Password Reset Success
|
||||
recoveryKey.recover.resetSuccess.message=تم إعادة تعيين كلمة المرور بنجاح
|
||||
recoveryKey.recover.resetSuccess.description=يمكنك فتح الخزانة الخاصة بك بكلمة المرور الجديدة.
|
||||
### Recovery Key Vault Config Reset Success
|
||||
|
||||
# Recover Vault Config File and/or Masterkey
|
||||
##Add Existing Vault without recovery - Dialog
|
||||
|
||||
##Vault Already Exists - Dialog
|
||||
|
||||
##Invalid Selection - Dialog
|
||||
|
||||
## Contact Hub Vault Owner - Dialog
|
||||
contactHubVaultOwner.title=خزانة Hub
|
||||
|
||||
##Dialog Title
|
||||
|
||||
## OnBoarding
|
||||
|
||||
###Vault Config Missing
|
||||
###Masterkey Missing
|
||||
|
||||
## Expert Settings
|
||||
|
||||
# Convert Vault
|
||||
convertVault.title=تحويل الخزانة
|
||||
|
||||
@@ -394,6 +394,7 @@ main.vaultDetail.missing.info=Cryptomator был юлдан һаҡлағыс т
|
||||
main.vaultDetail.missing.recheck=Яңынан тикшер
|
||||
main.vaultDetail.missing.remove=Һаҡлағыс исемлегенән алып ташла…
|
||||
main.vaultDetail.missing.changeLocation=Һаҡлағыс урынын үҙгәрт…
|
||||
### Missing Vault Config
|
||||
### Needs Migration
|
||||
main.vaultDetail.migrateButton=Һаҡлағысты яңыртыу
|
||||
main.vaultDetail.migratePrompt=Һаҡлағысҡа инер алдынан уны яңы форматҡа тиклем яңыртыу кәрәк
|
||||
@@ -472,6 +473,26 @@ recoveryKey.recover.resetBtn=Яңынан башла
|
||||
### Recovery Key Password Reset Success
|
||||
recoveryKey.recover.resetSuccess.message=Серһүҙ яңыртыу уңышлы тамамланды
|
||||
recoveryKey.recover.resetSuccess.description=Яңы серһүҙ менән һаҡлағысты аса алаһығыҙ.
|
||||
### Recovery Key Vault Config Reset Success
|
||||
|
||||
# Recover Vault Config File and/or Masterkey
|
||||
##Add Existing Vault without recovery - Dialog
|
||||
|
||||
##Vault Already Exists - Dialog
|
||||
|
||||
##Invalid Selection - Dialog
|
||||
|
||||
## Contact Hub Vault Owner - Dialog
|
||||
contactHubVaultOwner.title=Һаҡлағыс хабы
|
||||
|
||||
##Dialog Title
|
||||
|
||||
## OnBoarding
|
||||
|
||||
###Vault Config Missing
|
||||
###Masterkey Missing
|
||||
|
||||
## Expert Settings
|
||||
|
||||
# Convert Vault
|
||||
convertVault.title=Һаҡлағысты үҙгәртеү
|
||||
|
||||
@@ -381,6 +381,7 @@ main.vaultDetail.missing.info=Cryptomator ня змог знайсці скар
|
||||
main.vaultDetail.missing.recheck=Пераправерыць
|
||||
main.vaultDetail.missing.remove=Выдаліць са спісу скарбніц…
|
||||
main.vaultDetail.missing.changeLocation=Змяніць месцазнаходжанне скарбніцы…
|
||||
### Missing Vault Config
|
||||
### Needs Migration
|
||||
main.vaultDetail.migrateButton=Абнавіць скарбніцу
|
||||
main.vaultDetail.migratePrompt=Тваю скарбніцу трэба сканвертаваць у новы фармат, перад тым як ты зможаш атрымаць доступ да яе
|
||||
@@ -454,6 +455,25 @@ recoveryKey.recover.resetBtn=Скінуць
|
||||
### Recovery Key Password Reset Success
|
||||
recoveryKey.recover.resetSuccess.message=Пароль паспяхова скінуты
|
||||
recoveryKey.recover.resetSuccess.description=Ты можаш разамкнуць сваю скарбніцу з дапамогаю новага паролю.
|
||||
### Recovery Key Vault Config Reset Success
|
||||
|
||||
# Recover Vault Config File and/or Masterkey
|
||||
##Add Existing Vault without recovery - Dialog
|
||||
|
||||
##Vault Already Exists - Dialog
|
||||
|
||||
##Invalid Selection - Dialog
|
||||
|
||||
## Contact Hub Vault Owner - Dialog
|
||||
|
||||
##Dialog Title
|
||||
|
||||
## OnBoarding
|
||||
|
||||
###Vault Config Missing
|
||||
###Masterkey Missing
|
||||
|
||||
## Expert Settings
|
||||
|
||||
# Convert Vault
|
||||
convertVault.title=Перабудаваць скарбніцу
|
||||
|
||||
@@ -395,6 +395,7 @@ main.vaultDetail.missing.info=Криптоматор не намира хран
|
||||
main.vaultDetail.missing.recheck=Повторен опит
|
||||
main.vaultDetail.missing.remove=Премахване от списъка с хранилищата…
|
||||
main.vaultDetail.missing.changeLocation=Смяна на мястото на хранилището…
|
||||
### Missing Vault Config
|
||||
### Needs Migration
|
||||
main.vaultDetail.migrateButton=Надграждане на хранилище
|
||||
main.vaultDetail.migratePrompt=Преди да можете да го достъпвате, хранилището трябва да бъде надградено до новия формат
|
||||
@@ -473,6 +474,26 @@ recoveryKey.recover.resetBtn=Нулиране
|
||||
### Recovery Key Password Reset Success
|
||||
recoveryKey.recover.resetSuccess.message=Паролата е променена
|
||||
recoveryKey.recover.resetSuccess.description=Можете да отключите хранилището с новата парола.
|
||||
### Recovery Key Vault Config Reset Success
|
||||
|
||||
# Recover Vault Config File and/or Masterkey
|
||||
##Add Existing Vault without recovery - Dialog
|
||||
|
||||
##Vault Already Exists - Dialog
|
||||
|
||||
##Invalid Selection - Dialog
|
||||
|
||||
## Contact Hub Vault Owner - Dialog
|
||||
contactHubVaultOwner.title=Хранилище на Hub
|
||||
|
||||
##Dialog Title
|
||||
|
||||
## OnBoarding
|
||||
|
||||
###Vault Config Missing
|
||||
###Masterkey Missing
|
||||
|
||||
## Expert Settings
|
||||
|
||||
# Convert Vault
|
||||
convertVault.title=Преобразуване на хранилище
|
||||
|
||||
@@ -149,6 +149,7 @@ main.vaultlist.contextMenu.lock=লক করুন
|
||||
### Unlocked
|
||||
main.vaultDetail.lockBtn=লক করুন
|
||||
### Missing
|
||||
### Missing Vault Config
|
||||
### Needs Migration
|
||||
### Error
|
||||
|
||||
@@ -169,6 +170,25 @@ vaultOptions.mount.mountPoint.directoryPickerButton=নির্বাচন ক
|
||||
### Enter Recovery Key
|
||||
### Reset Password
|
||||
### Recovery Key Password Reset Success
|
||||
### Recovery Key Vault Config Reset Success
|
||||
|
||||
# Recover Vault Config File and/or Masterkey
|
||||
##Add Existing Vault without recovery - Dialog
|
||||
|
||||
##Vault Already Exists - Dialog
|
||||
|
||||
##Invalid Selection - Dialog
|
||||
|
||||
## Contact Hub Vault Owner - Dialog
|
||||
|
||||
##Dialog Title
|
||||
|
||||
## OnBoarding
|
||||
|
||||
###Vault Config Missing
|
||||
###Masterkey Missing
|
||||
|
||||
## Expert Settings
|
||||
|
||||
# Convert Vault
|
||||
|
||||
|
||||
@@ -241,6 +241,7 @@ main.vaultDetail.missing.info=Cryptomator nije mogao pronaći disk na ovoj lokac
|
||||
main.vaultDetail.missing.recheck=Provjeri ponovo
|
||||
main.vaultDetail.missing.remove=Ukloni sa liste sefova…
|
||||
main.vaultDetail.missing.changeLocation=Promijeni lokaciju sefa…
|
||||
### Missing Vault Config
|
||||
### Needs Migration
|
||||
main.vaultDetail.migrateButton=Nadogradi sef
|
||||
main.vaultDetail.migratePrompt=Da biste mogli pristupiti svom sefu, morate ga nadograditi na novi format
|
||||
@@ -294,6 +295,25 @@ recoveryKey.recover.correctKey=Ključ za oporavak je ispravan
|
||||
recoveryKey.printout.heading=Cryptomator Ključ za oporavak za \n"%s"\n
|
||||
### Reset Password
|
||||
### Recovery Key Password Reset Success
|
||||
### Recovery Key Vault Config Reset Success
|
||||
|
||||
# Recover Vault Config File and/or Masterkey
|
||||
##Add Existing Vault without recovery - Dialog
|
||||
|
||||
##Vault Already Exists - Dialog
|
||||
|
||||
##Invalid Selection - Dialog
|
||||
|
||||
## Contact Hub Vault Owner - Dialog
|
||||
|
||||
##Dialog Title
|
||||
|
||||
## OnBoarding
|
||||
|
||||
###Vault Config Missing
|
||||
###Masterkey Missing
|
||||
|
||||
## Expert Settings
|
||||
|
||||
# Convert Vault
|
||||
|
||||
|
||||
@@ -394,8 +394,6 @@ main.vaultlist.contextMenu.unlockNow=Desbloqueja ara
|
||||
main.vaultlist.contextMenu.vaultoptions=Opcions de la caixa forta
|
||||
main.vaultlist.contextMenu.reveal=Mostra la unitat
|
||||
main.vaultlist.contextMenu.share=Compateix…
|
||||
main.vaultlist.addVaultBtn.menuItemNew=Crea una nova caixa forta…
|
||||
main.vaultlist.addVaultBtn.menuItemExisting=Obri una caixa forta existent...
|
||||
##Notificaition
|
||||
main.notification.updateAvailable=Hi ha una actualització disponible.
|
||||
main.notification.support=Doneu suport a Cryptomator.
|
||||
@@ -429,6 +427,7 @@ main.vaultDetail.missing.info=Cryptomator no ha trobat una caixa forta en aquest
|
||||
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…
|
||||
### Missing Vault Config
|
||||
### Needs Migration
|
||||
main.vaultDetail.migrateButton=Actualitza la caixa forta
|
||||
main.vaultDetail.migratePrompt=Per accedir a la vostra caixa forta abans cal actualitzar-la al nou format
|
||||
@@ -508,6 +507,26 @@ recoveryKey.recover.resetBtn=Reinicia
|
||||
### Recovery Key Password Reset Success
|
||||
recoveryKey.recover.resetSuccess.message=S'ha modificat la contrasenya correctament
|
||||
recoveryKey.recover.resetSuccess.description=Pots desbloquejar la caixa forta amb la nova contrasenya.
|
||||
### Recovery Key Vault Config Reset Success
|
||||
|
||||
# Recover Vault Config File and/or Masterkey
|
||||
##Add Existing Vault without recovery - Dialog
|
||||
|
||||
##Vault Already Exists - Dialog
|
||||
|
||||
##Invalid Selection - Dialog
|
||||
|
||||
## Contact Hub Vault Owner - Dialog
|
||||
contactHubVaultOwner.title=Caixa forta de Hub
|
||||
|
||||
##Dialog Title
|
||||
|
||||
## OnBoarding
|
||||
|
||||
###Vault Config Missing
|
||||
###Masterkey Missing
|
||||
|
||||
## Expert Settings
|
||||
|
||||
# Convert Vault
|
||||
convertVault.title=Convertir la caixa forta
|
||||
|
||||
@@ -396,6 +396,7 @@ main.vaultDetail.missing.info=Cryptomator nemohl najít trezor na této cestě.
|
||||
main.vaultDetail.missing.recheck=Znovu zkontrolovat
|
||||
main.vaultDetail.missing.remove=Odebrat ze seznamu trezorů…
|
||||
main.vaultDetail.missing.changeLocation=Změnit umístění trezoru…
|
||||
### Missing Vault Config
|
||||
### Needs Migration
|
||||
main.vaultDetail.migrateButton=Upgrade trezoru
|
||||
main.vaultDetail.migratePrompt=Váš trezor musí být aktualizován na nový formát, než k němu budete mít přístup
|
||||
@@ -473,6 +474,26 @@ recoveryKey.recover.resetBtn=Resetovat
|
||||
### Recovery Key Password Reset Success
|
||||
recoveryKey.recover.resetSuccess.message=Resetování hesla bylo úspěšné
|
||||
recoveryKey.recover.resetSuccess.description=Můžete odemknout váš trezor pomocí nového hesla.
|
||||
### Recovery Key Vault Config Reset Success
|
||||
|
||||
# Recover Vault Config File and/or Masterkey
|
||||
##Add Existing Vault without recovery - Dialog
|
||||
|
||||
##Vault Already Exists - Dialog
|
||||
|
||||
##Invalid Selection - Dialog
|
||||
|
||||
## Contact Hub Vault Owner - Dialog
|
||||
contactHubVaultOwner.title=Hub trezor
|
||||
|
||||
##Dialog Title
|
||||
|
||||
## OnBoarding
|
||||
|
||||
###Vault Config Missing
|
||||
###Masterkey Missing
|
||||
|
||||
## Expert Settings
|
||||
|
||||
# Convert Vault
|
||||
convertVault.title=Převést trezor
|
||||
|
||||
@@ -96,6 +96,7 @@ addvault.new.readme.accessLocation.4=Fjern denne fil hvis du har lyst.
|
||||
## Existing
|
||||
addvaultwizard.existing.title=Tilføj Eksisterende Boks
|
||||
addvaultwizard.existing.instruction=Vælgt filen "vault.cryptomator" i mappen med dine boks-filer. Hvis der kun findes en fil med navnet "masterkey.cryptomator", skal du vælge den i stedet.
|
||||
addvaultwizard.existing.restore=Gendan…
|
||||
addvaultwizard.existing.chooseBtn=Vælg…
|
||||
addvaultwizard.existing.filePickerTitle=Vælg boks-fil
|
||||
addvaultwizard.existing.filePickerMimeDesc=Cryptomator boks
|
||||
@@ -127,6 +128,7 @@ unlock.unlockBtn=Lås op
|
||||
## Select
|
||||
unlock.chooseMasterkey.message=Hovednøgle-fil ikke fundet
|
||||
unlock.chooseMasterkey.description=Cryptomator kunne ikke finde hovednøgle-filen for boksen "%s". Vælg venligst filen manuelt.
|
||||
unlock.chooseMasterkey.restoreInstead=Gendan i stedet masterkey-filen
|
||||
unlock.chooseMasterkey.filePickerTitle=Vælg hovednøgle-fil
|
||||
unlock.chooseMasterkey.filePickerMimeDesc=Cryptomator hovednøgle
|
||||
## Success
|
||||
@@ -394,8 +396,9 @@ main.vaultlist.contextMenu.unlockNow=Lås op nu
|
||||
main.vaultlist.contextMenu.vaultoptions=Vis boksindstillinger
|
||||
main.vaultlist.contextMenu.reveal=Vis drev
|
||||
main.vaultlist.contextMenu.share=Del…
|
||||
main.vaultlist.addVaultBtn.menuItemNew=Opret ny boks...
|
||||
main.vaultlist.addVaultBtn.menuItemExisting=Åbn eksisterende boks...
|
||||
main.vaultlist.addVaultBtn.menuItemNew=Opret ny boks…
|
||||
main.vaultlist.addVaultBtn.menuItemExisting=Åbn eksisterende boks…
|
||||
main.vaultlist.addVaultBtn.menuItemRecover=Genopret eksisterende boks…
|
||||
main.vaultlist.showEventsButton.tooltip=Åbn begivenhedsvisning
|
||||
##Notificaition
|
||||
main.notification.updateAvailable=Opdatering er tilgængelig.
|
||||
@@ -433,6 +436,9 @@ main.vaultDetail.missing.info=Cryptomator kunne ikke finde en boks på denne sti
|
||||
main.vaultDetail.missing.recheck=Kontrollér igen
|
||||
main.vaultDetail.missing.remove=Fjern fra listen over bokse…
|
||||
main.vaultDetail.missing.changeLocation=Skift placering for boks…
|
||||
### Missing Vault Config
|
||||
main.vaultDetail.missingVaultConfig.info=Bokskonfiguration mangler.
|
||||
main.vaultDetail.missingVaultConfig.restore=Gendan bokskonfiguration
|
||||
### Needs Migration
|
||||
main.vaultDetail.migrateButton=Opgradér boks
|
||||
main.vaultDetail.migratePrompt=Din boks skal opgraderes til et nyt format, før du kan tilgå den
|
||||
@@ -497,6 +503,7 @@ vaultOptions.hub.convertBtn=Konvertér til adgangskodebaseret boks
|
||||
recoveryKey.display.title=Vis gendannelsesnøgle
|
||||
recoveryKey.create.message=Adgangskode krævet
|
||||
recoveryKey.create.description=Indtast adgangskoden for "%s", for at vise gendannelsesnøglen.
|
||||
recoveryKey.recover.description=Indtast adgangskoden for "%s" for at gendanne bokskonfiguration.
|
||||
recoveryKey.display.description=Den følgende gendannelsesnøgle kan bruges til at genskabe adgang til "%s":
|
||||
recoveryKey.display.StorageHints=Opbevar den et meget sikkert sted, som fx:\n • Gem den i din adgangskode-manager\n • Gem den på et USB-drev\n • Print den ud på papir
|
||||
## Reset Password
|
||||
@@ -509,9 +516,57 @@ recoveryKey.recover.invalidKey=Denne gendannelsesnøgle er ikke gyldig
|
||||
recoveryKey.printout.heading=Cryptomator gendannelsesnøgle\n"%s"\n
|
||||
### Reset Password
|
||||
recoveryKey.recover.resetBtn=Nulstil
|
||||
recoveryKey.recover.recoverBtn=Gendan
|
||||
### Recovery Key Password Reset Success
|
||||
recoveryKey.recover.resetSuccess.message=Adgangskod nulstillet
|
||||
recoveryKey.recover.resetSuccess.description=Du kan nu låse din boks op med den nye adgangskode.
|
||||
### Recovery Key Vault Config Reset Success
|
||||
recoveryKey.recover.resetMasterkeyFileSuccess.description=Du kan låse din boks op med din adgangskode nu.
|
||||
|
||||
# Recover Vault Config File and/or Masterkey
|
||||
##Add Existing Vault without recovery - Dialog
|
||||
recover.existing.title=Boks tilføjet
|
||||
recover.existing.message=Boksen blev tilføjet med succes
|
||||
recover.existing.description=Din boks "%s" er blevet tilføjet til bokslisten. Ingen genoprettelsesproces var nødvendig.
|
||||
|
||||
##Vault Already Exists - Dialog
|
||||
recover.alreadyExists.title=Boksen findes allerede
|
||||
recover.alreadyExists.message=Denne boks er allerede tilføjet
|
||||
recover.alreadyExists.description=Din boks "%s" er allerede til stede i din boksliste og blev derfor ikke tilføjet igen.
|
||||
|
||||
##Invalid Selection - Dialog
|
||||
recover.invalidSelection.title=Ugyldigt valg
|
||||
recover.invalidSelection.message=Dit valg er ikke en boks
|
||||
recover.invalidSelection.description=Den valgte mappe skal være en gyldig Cryptomator boks.
|
||||
|
||||
## Contact Hub Vault Owner - Dialog
|
||||
contactHubVaultOwner.title=Hub Boks
|
||||
contactHubVaultOwner.message=Denne boks blev oprettet med Cryptomator Hub
|
||||
contactHubVaultOwner.description=Tag venligst kontakt til boksenejer for at gendanne den manglende fil. De kan downloade boksskabelon fra Cryptomator Hub.
|
||||
|
||||
##Dialog Title
|
||||
recover.recoverVaultConfig.title=Gendan bokskonfiguration
|
||||
recover.recoverMasterkey.title=Gendan Masterkey
|
||||
|
||||
## OnBoarding
|
||||
recover.onBoarding.chooseMethod=Vælg genoprettelsesmetode:
|
||||
recover.onBoarding.useRecoveryKey=Brug gendannelsesnøgle
|
||||
recover.onBoarding.usePassword=Brug adgangskode
|
||||
recover.onBoarding.intro=Sørg for at tjekke følgende:
|
||||
recover.onBoarding.pleaseConfirm=Før der fortsættes, bekræftes at:
|
||||
recover.onBoarding.otherwisePleaseConfirm=I modsat fald bekræftes følgende:
|
||||
recover.onBoarding.allMissing.intro=Hvis denne boks administreres af Cryptomator Hub, skal boksejer gendanne den for dig.
|
||||
recover.onBoarding.intro.ensure=Alle filer er fuldt synkroniserede.
|
||||
recover.onBoarding.affirmation=Jeg har læst og forstået disse krav
|
||||
|
||||
###Vault Config Missing
|
||||
recover.onBoarding.intro.recoveryKey=Du har gendannelsesnøglen og ved, om ekspertindstillinger blev brugt.
|
||||
recover.onBoarding.intro.password=Du har boksens adgangskode og ved, om ekspertindstillinger blev brugt.
|
||||
###Masterkey Missing
|
||||
recover.onBoarding.intro.masterkey.recoveryKey=Du har boksens gendannelsesnøgle.
|
||||
|
||||
## Expert Settings
|
||||
recover.expertSettings.shorteningThreshold.title=Denne værdi skal matche den, der blev brugt før gendannelse for at sikre kompatibilitet med tidligere krypterede data.
|
||||
|
||||
# Convert Vault
|
||||
convertVault.title=Konvertér boks
|
||||
@@ -561,6 +616,7 @@ dokanySupportEnd.preferencesBtn=Åbn Indstillinger
|
||||
retryIfReadonly.title=Begrænset boksadgang
|
||||
retryIfReadonly.message=Ingen skriveadgang til boksens mappe
|
||||
retryIfReadonly.description=Cryptomator kan ikke skrive til boksens mappe. Du kan ændre boksen til at være skrivebeskyttet og prøve igen. Denne indstilling kan være deaktiveret i boksens indstillinger.
|
||||
retryIfReadonly.retry=Skift og prøv igen
|
||||
|
||||
# Share Vault
|
||||
shareVault.title=Del Boks
|
||||
@@ -584,10 +640,39 @@ shareVault.hub.openHub=Åben Cryptomator Hub
|
||||
|
||||
# Decrypt File Names
|
||||
decryptNames.title=Dekryptér Filnavne
|
||||
decryptNames.filePicker.title=Vælg krypteret fil
|
||||
decryptNames.filePicker.extensionDescription=Cryptomator krypteret fil
|
||||
decryptNames.copyTable.tooltip=Kopiér tabel
|
||||
decryptNames.clearTable.tooltip=Ryd tabel
|
||||
decryptNames.copyHint=Kopiér celleindhold med %s
|
||||
decryptNames.dropZone.message=Slip filer eller klik for at vælge
|
||||
decryptNames.dropZone.error.vaultInternalFiles=Boks interne filer med intet dekrypterbart navn valgt
|
||||
decryptNames.dropZone.error.foreignFiles=Filer hører ikke til boksen "%s"
|
||||
decryptNames.dropZone.error.noDirIdBackup=Mappe af valgte filer indeholder ikke dirId.c9r fil
|
||||
decryptNames.dropZone.error.generic=Kunne ikke dekryptere filnavne
|
||||
|
||||
|
||||
# Event View
|
||||
eventView.title=Begivenheder
|
||||
eventView.filter.allVaults=Alle
|
||||
eventView.clearListButton.tooltip=Ryd liste
|
||||
## event list entries
|
||||
eventView.entry.vaultLocked.description=Lås "%s" op for detaljer
|
||||
eventView.entry.conflictResolved.message=Løst konflikt
|
||||
eventView.entry.conflictResolved.showDecrypted=Vis dekrypteret fil
|
||||
eventView.entry.conflictResolved.copyDecrypted=Kopiér dekrypteret sti
|
||||
eventView.entry.conflict.message=Konfliktløsning mislykkedes
|
||||
eventView.entry.conflict.showDecrypted=Vis dekrypteret, original fil
|
||||
eventView.entry.conflict.copyDecrypted=Kopier dekrypteret, original sti
|
||||
eventView.entry.conflict.showEncrypted=Vis modstridende, krypteret fil
|
||||
eventView.entry.conflict.copyEncrypted=Kopier modstridende, krypteret sti
|
||||
eventView.entry.decryptionFailed.message=Dekryptering mislykkedes
|
||||
eventView.entry.decryptionFailed.showEncrypted=Vis krypteret fil
|
||||
eventView.entry.decryptionFailed.copyEncrypted=Kopiér krypteret sti
|
||||
eventView.entry.brokenDirFile.message=Brudt mappelink
|
||||
eventView.entry.brokenDirFile.showEncrypted=Vis brudt, krypteret link
|
||||
eventView.entry.brokenDirFile.copyEncrypted=Kopiér sti til brudt link
|
||||
eventView.entry.brokenFileNode.message=Brudt filsystem-node
|
||||
eventView.entry.brokenFileNode.showEncrypted=Vis brudt, krypteret node
|
||||
eventView.entry.brokenFileNode.copyEncrypted=Kopiér sti af brudt, krypteret node
|
||||
eventView.entry.brokenFileNode.copyDecrypted=Kopiér dekrypteret sti
|
||||
|
||||
@@ -96,6 +96,7 @@ addvault.new.readme.accessLocation.4=Du kannst diese Datei löschen.
|
||||
## Existing
|
||||
addvaultwizard.existing.title=Bestehenden Tresor hinzufügen
|
||||
addvaultwizard.existing.instruction=Wähle die Datei „vault.cryptomator“ deines bestehenden Tresors aus. Falls nur eine Datei mit der Bezeichnung „masterkey.cryptomator“ vorhanden ist, nutze stattdessen diese.
|
||||
addvaultwizard.existing.restore=Wiederherstellen…
|
||||
addvaultwizard.existing.chooseBtn=Durchsuchen …
|
||||
addvaultwizard.existing.filePickerTitle=Tresordatei auswählen
|
||||
addvaultwizard.existing.filePickerMimeDesc=Cryptomator-Tresor
|
||||
@@ -127,6 +128,7 @@ unlock.unlockBtn=Entsperren
|
||||
## Select
|
||||
unlock.chooseMasterkey.message=Masterkey-Datei nicht gefunden
|
||||
unlock.chooseMasterkey.description=Cryptomator konnte die Masterkey-Datei des Tresors „%s“ nicht finden. Bitte wähle die Datei manuell aus.
|
||||
unlock.chooseMasterkey.restoreInstead=Masterkey Datei wiederherstellen
|
||||
unlock.chooseMasterkey.filePickerTitle=Masterkey-Datei auswählen
|
||||
unlock.chooseMasterkey.filePickerMimeDesc=Cryptomator-Masterkey
|
||||
## Success
|
||||
@@ -394,8 +396,9 @@ main.vaultlist.contextMenu.unlockNow=Jetzt entsperren
|
||||
main.vaultlist.contextMenu.vaultoptions=Tresoroptionen anzeigen
|
||||
main.vaultlist.contextMenu.reveal=Laufwerk anzeigen
|
||||
main.vaultlist.contextMenu.share=Teilen …
|
||||
main.vaultlist.addVaultBtn.menuItemNew=Neuen Tresor erstellen...
|
||||
main.vaultlist.addVaultBtn.menuItemExisting=Bestehenden Tresor öffnen...
|
||||
main.vaultlist.addVaultBtn.menuItemNew=Neuen Tresor erstellen…
|
||||
main.vaultlist.addVaultBtn.menuItemExisting=Bestehenden Tresor öffnen…
|
||||
main.vaultlist.addVaultBtn.menuItemRecover=Bestehenden Tresor wiederherstellen…
|
||||
main.vaultlist.showEventsButton.tooltip=Ereignis-Ansicht öffnen
|
||||
##Notificaition
|
||||
main.notification.updateAvailable=Eine neue Version ist verfügbar.
|
||||
@@ -433,6 +436,9 @@ main.vaultDetail.missing.info=Cryptomator konnte keinen Tresor mit diesem Pfad f
|
||||
main.vaultDetail.missing.recheck=Erneut prüfen
|
||||
main.vaultDetail.missing.remove=Aus Tresorliste entfernen …
|
||||
main.vaultDetail.missing.changeLocation=Speicherort des Tresors ändern …
|
||||
### Missing Vault Config
|
||||
main.vaultDetail.missingVaultConfig.info=Tresorkonfiguration fehlt.
|
||||
main.vaultDetail.missingVaultConfig.restore=Tresorkonfiguration wiederherstellen
|
||||
### Needs Migration
|
||||
main.vaultDetail.migrateButton=Tresor upgraden
|
||||
main.vaultDetail.migratePrompt=Dein Tresor muss in ein neues Format konvertiert werden, bevor du auf ihn zugreifen kannst
|
||||
@@ -497,6 +503,7 @@ vaultOptions.hub.convertBtn=In passwortgeschützten Tresor umwandeln
|
||||
recoveryKey.display.title=Wiederherstellungsschlüssel anzeigen
|
||||
recoveryKey.create.message=Passwort erforderlich
|
||||
recoveryKey.create.description=Gib das Passwort für „%s“ ein, um dessen Wiederherstellungsschlüssel anzuzeigen.
|
||||
recoveryKey.recover.description=Gib das Passwort für "%s" ein, um die Tresorkonfiguration wiederherzustellen.
|
||||
recoveryKey.display.description=Mit folgendem Wiederherstellungsschlüssel kannst du den Zugriff auf „%s“ wiederherstellen:
|
||||
recoveryKey.display.StorageHints=Bewahre ihn möglichst sicher auf, z. B.\n • in einem Passwortmanager\n • auf einem USB-Speicherstick\n • auf Papier ausgedruckt
|
||||
## Reset Password
|
||||
@@ -509,9 +516,59 @@ recoveryKey.recover.invalidKey=Dieser Wiederherstellungsschlüssel ist ungültig
|
||||
recoveryKey.printout.heading=Cryptomator-Wiederherstellungsschlüssel\n„%s“\n
|
||||
### Reset Password
|
||||
recoveryKey.recover.resetBtn=Zurücksetzen
|
||||
recoveryKey.recover.recoverBtn=Wiederherstellen
|
||||
### Recovery Key Password Reset Success
|
||||
recoveryKey.recover.resetSuccess.message=Passwort erfolgreich zurückgesetzt
|
||||
recoveryKey.recover.resetSuccess.description=Du kannst deinen Tresor mit dem neuen Passwort entsperren.
|
||||
### Recovery Key Vault Config Reset Success
|
||||
recoveryKey.recover.resetVaultConfigSuccess.message=Tresorkonfiguration wiederhergestellt
|
||||
recoveryKey.recover.resetMasterkeyFileSuccess.message=Masterkey-Datei wiederhergestellt
|
||||
recoveryKey.recover.resetMasterkeyFileSuccess.description=Du kannst deinen Tresor mit dem neuen Passwort jetzt entsperren.
|
||||
|
||||
# Recover Vault Config File and/or Masterkey
|
||||
##Add Existing Vault without recovery - Dialog
|
||||
recover.existing.title=Tresor hinzugefügt
|
||||
recover.existing.message=Der Tresor wurde erfolgreich hinzugefügt
|
||||
recover.existing.description=Dein Tresor "%s" wurde zur Tresorliste hinzugefügt. Es war kein Wiederherstellungsprozess nötig.
|
||||
|
||||
##Vault Already Exists - Dialog
|
||||
recover.alreadyExists.title=Tresor existiert bereits
|
||||
recover.alreadyExists.message=Dieser Tresor wurde bereits hinzugefügt
|
||||
recover.alreadyExists.description=Dein Tresor "%s" ist bereits in der Tresorliste vorhanden und wurde daher nicht erneut hinzugefügt.
|
||||
|
||||
##Invalid Selection - Dialog
|
||||
recover.invalidSelection.title=Ungültige Auswahl
|
||||
recover.invalidSelection.message=Der ausgewählte Ordner ist kein Tresor
|
||||
recover.invalidSelection.description=Der ausgewählte Ordner muss ein gültiger Cryptomator-Tresor sein.
|
||||
|
||||
## Contact Hub Vault Owner - Dialog
|
||||
contactHubVaultOwner.title=Hubtresor
|
||||
contactHubVaultOwner.message=Dieser Tresor wurde mit Cryptomator Hub erstellt
|
||||
contactHubVaultOwner.description=Bitte wenden dich an den Tresorbesitzer, um die fehlende Datei wiederherzustellen. Dieser kann die Tresorvorlage von Cryptomator Hub herunterladen.
|
||||
|
||||
##Dialog Title
|
||||
recover.recoverVaultConfig.title=Tresorkonfiguration wiederherstellen
|
||||
recover.recoverMasterkey.title=Masterkey wiederherstellen
|
||||
|
||||
## OnBoarding
|
||||
recover.onBoarding.chooseMethod=Wähle die Wiederherstellungsmethode:
|
||||
recover.onBoarding.useRecoveryKey=Wiederherstellungsschlüssel verwenden
|
||||
recover.onBoarding.usePassword=Passwort verwenden
|
||||
recover.onBoarding.intro=Stelle sicher, folgendes geprüft zu haben:
|
||||
recover.onBoarding.pleaseConfirm=Bevor es weiter geht, bestätige bitte:
|
||||
recover.onBoarding.otherwisePleaseConfirm=Andernfalls, bestätige bitte:
|
||||
recover.onBoarding.allMissing.intro=Wird der Tresor von Cryptomator Hub verwaltet, muss der Tresorbesitzer ihn für dich wiederherstellen.
|
||||
recover.onBoarding.intro.ensure=Alle Dateien sind vollständig synchronisiert.
|
||||
recover.onBoarding.affirmation=Ich habe die Anforderungen gelesen und verstanden
|
||||
|
||||
###Vault Config Missing
|
||||
recover.onBoarding.intro.recoveryKey=Du besitzt den Wiederherstellungsschlüssel und weißt, ob Experteneinstellungen verwendet wurden.
|
||||
recover.onBoarding.intro.password=Du besitzt das Tresorpasswort und weißt, ob Experteneinstellungen verwendet wurden.
|
||||
###Masterkey Missing
|
||||
recover.onBoarding.intro.masterkey.recoveryKey=Du besitzt den Wiederherstellungsschlüssel.
|
||||
|
||||
## Expert Settings
|
||||
recover.expertSettings.shorteningThreshold.title=Um Kompatibilität mit den verschlüsselten Dateien zu gewährleisten, muss der gleiche Wert wie zur Tresorerstellung verwendet werden.
|
||||
|
||||
# Convert Vault
|
||||
convertVault.title=Tresor umwandeln
|
||||
|
||||
@@ -394,8 +394,6 @@ main.vaultlist.contextMenu.unlockNow=Ξεκλείδωμα τώρα
|
||||
main.vaultlist.contextMenu.vaultoptions=Εμφάνιση επιλογών Vault
|
||||
main.vaultlist.contextMenu.reveal=Αποκάλυψη εικονικού δίσκου
|
||||
main.vaultlist.contextMenu.share=Κοινοποίηση…
|
||||
main.vaultlist.addVaultBtn.menuItemNew=Δημιουργία Νέας Κρύπτης...
|
||||
main.vaultlist.addVaultBtn.menuItemExisting=Άνοιγμα Υπάρχοντος Κρύπτης...
|
||||
main.vaultlist.showEventsButton.tooltip=Άνοιγμα προβολής συμβάντων
|
||||
##Notificaition
|
||||
main.notification.updateAvailable=Η ενημέρωση είναι διαθέσιμη.
|
||||
@@ -433,6 +431,7 @@ main.vaultDetail.missing.info=Cryptomator δεν βρήκε vault σε αυτό
|
||||
main.vaultDetail.missing.recheck=Επανέλεγχος
|
||||
main.vaultDetail.missing.remove=Κατάργηση από την λίστα των Vault…
|
||||
main.vaultDetail.missing.changeLocation=Αλλαγή τοποθεσίας Vault…
|
||||
### Missing Vault Config
|
||||
### Needs Migration
|
||||
main.vaultDetail.migrateButton=Αναβάθμιση Vault
|
||||
main.vaultDetail.migratePrompt=Το vault σας πρέπει να αναβαθμιστεί σε νέα μορφή, προτού να έχετε πρόσβαση σε αυτό
|
||||
@@ -512,6 +511,26 @@ recoveryKey.recover.resetBtn=Επαναφορά
|
||||
### Recovery Key Password Reset Success
|
||||
recoveryKey.recover.resetSuccess.message=Επιτυχής επαναφορά κωδικού πρόσβασης
|
||||
recoveryKey.recover.resetSuccess.description=Μπορείτε να ξεκλειδώσετε την κρύπτη σας με το νέο κωδικό πρόσβασης.
|
||||
### Recovery Key Vault Config Reset Success
|
||||
|
||||
# Recover Vault Config File and/or Masterkey
|
||||
##Add Existing Vault without recovery - Dialog
|
||||
|
||||
##Vault Already Exists - Dialog
|
||||
|
||||
##Invalid Selection - Dialog
|
||||
|
||||
## Contact Hub Vault Owner - Dialog
|
||||
contactHubVaultOwner.title=Κρύπτη Hub
|
||||
|
||||
##Dialog Title
|
||||
|
||||
## OnBoarding
|
||||
|
||||
###Vault Config Missing
|
||||
###Masterkey Missing
|
||||
|
||||
## Expert Settings
|
||||
|
||||
# Convert Vault
|
||||
convertVault.title=Μετατροπή Θησαυ/κιου
|
||||
|
||||
@@ -96,6 +96,7 @@ addvault.new.readme.accessLocation.4=No dude en eliminar este archivo.
|
||||
## Existing
|
||||
addvaultwizard.existing.title=Añadir bóveda existente
|
||||
addvaultwizard.existing.instruction=Elija el archivo "vault.cryptomator" de su bóveda existente. Si solo existe un archivo llamado "masterkey.cryptomator", selecciónelo en su lugar.
|
||||
addvaultwizard.existing.restore=…
|
||||
addvaultwizard.existing.chooseBtn=Elegir…
|
||||
addvaultwizard.existing.filePickerTitle=Seleccionar archivo de bóveda
|
||||
addvaultwizard.existing.filePickerMimeDesc=Bóveda de Cryptomator
|
||||
@@ -127,6 +128,7 @@ unlock.unlockBtn=Desbloquear
|
||||
## Select
|
||||
unlock.chooseMasterkey.message=Archivo de la clave maestra no encontrado
|
||||
unlock.chooseMasterkey.description=No se pudo encontrar el archivo de la clave maestra para la bóveda "%s". Por favor, elija manualmente el archivo de la clave.
|
||||
unlock.chooseMasterkey.restoreInstead=
|
||||
unlock.chooseMasterkey.filePickerTitle=Seleccione el archivo de la clave maestra
|
||||
unlock.chooseMasterkey.filePickerMimeDesc=Clave maestra de Cryptomator
|
||||
## Success
|
||||
@@ -394,8 +396,9 @@ main.vaultlist.contextMenu.unlockNow=Desbloquear ahora
|
||||
main.vaultlist.contextMenu.vaultoptions=Mostrar opciones de la bóveda
|
||||
main.vaultlist.contextMenu.reveal=Revelar unidad
|
||||
main.vaultlist.contextMenu.share=Compartir…
|
||||
main.vaultlist.addVaultBtn.menuItemNew=Crear Bóveda Nueva...
|
||||
main.vaultlist.addVaultBtn.menuItemExisting=Abrir Bóveda Existente...
|
||||
main.vaultlist.addVaultBtn.menuItemNew=
|
||||
main.vaultlist.addVaultBtn.menuItemExisting=
|
||||
main.vaultlist.addVaultBtn.menuItemRecover=
|
||||
main.vaultlist.showEventsButton.tooltip=Abrir vista de evento
|
||||
##Notificaition
|
||||
main.notification.updateAvailable=Existen actualizaciones disponibles.
|
||||
@@ -433,6 +436,9 @@ main.vaultDetail.missing.info=Cryptomator no pudo encontrar una bóveda en esta
|
||||
main.vaultDetail.missing.recheck=Volver a comprobar
|
||||
main.vaultDetail.missing.remove=Eliminar de la lista de bóveda…
|
||||
main.vaultDetail.missing.changeLocation=Cambiar ubicación de la bóveda…
|
||||
### Missing Vault Config
|
||||
main.vaultDetail.missingVaultConfig.info=Falta la configuración de la bóveda.
|
||||
main.vaultDetail.missingVaultConfig.restore=
|
||||
### Needs Migration
|
||||
main.vaultDetail.migrateButton=Actualizar bóveda
|
||||
main.vaultDetail.migratePrompt=Su bóveda necesita ser actualizada a un formato nuevo antes de poder acceder a ella
|
||||
@@ -497,6 +503,7 @@ vaultOptions.hub.convertBtn=Convertir a Bóveda con Contraseña
|
||||
recoveryKey.display.title=Mostrar clave de recuperación
|
||||
recoveryKey.create.message=Contraseña requerida
|
||||
recoveryKey.create.description=Ingresar la contraseña para mostrar la clave de recuperación para "%s":
|
||||
recoveryKey.recover.description=
|
||||
recoveryKey.display.description=La siguiente clave de recuperación puede usarse para restaurar el acceso a "%s":
|
||||
recoveryKey.display.StorageHints=Manténgala en algún lugar seguro, p.ej.:\n • Almacenarla en un administrador de contraseñas\n • Guardarla en una llave USB\n • Imprimirla en un papel
|
||||
## Reset Password
|
||||
@@ -512,6 +519,26 @@ recoveryKey.recover.resetBtn=## Reiniciar contraseña\nrecoveryKey.recover.reset
|
||||
### Recovery Key Password Reset Success
|
||||
recoveryKey.recover.resetSuccess.message=Contraseña restablecida con éxito
|
||||
recoveryKey.recover.resetSuccess.description=Puede desbloquear su bóveda con la contraseña nueva.
|
||||
### Recovery Key Vault Config Reset Success
|
||||
|
||||
# Recover Vault Config File and/or Masterkey
|
||||
##Add Existing Vault without recovery - Dialog
|
||||
|
||||
##Vault Already Exists - Dialog
|
||||
|
||||
##Invalid Selection - Dialog
|
||||
|
||||
## Contact Hub Vault Owner - Dialog
|
||||
contactHubVaultOwner.title=Bóveda de Hub
|
||||
|
||||
##Dialog Title
|
||||
|
||||
## OnBoarding
|
||||
|
||||
###Vault Config Missing
|
||||
###Masterkey Missing
|
||||
|
||||
## Expert Settings
|
||||
|
||||
# Convert Vault
|
||||
convertVault.title=Convertir bóveda
|
||||
|
||||
@@ -183,6 +183,7 @@ main.vaultlist.contextMenu.reveal=نمایش درایو
|
||||
main.vaultDetail.revealBtn=نمایش درایو
|
||||
main.vaultDetail.lockBtn=قفل
|
||||
### Missing
|
||||
### Missing Vault Config
|
||||
### Needs Migration
|
||||
### Error
|
||||
|
||||
@@ -204,6 +205,25 @@ vaultOptions.mount.mountPoint.directoryPickerButton=انتخاب کنید…
|
||||
### Enter Recovery Key
|
||||
### Reset Password
|
||||
### Recovery Key Password Reset Success
|
||||
### Recovery Key Vault Config Reset Success
|
||||
|
||||
# Recover Vault Config File and/or Masterkey
|
||||
##Add Existing Vault without recovery - Dialog
|
||||
|
||||
##Vault Already Exists - Dialog
|
||||
|
||||
##Invalid Selection - Dialog
|
||||
|
||||
## Contact Hub Vault Owner - Dialog
|
||||
|
||||
##Dialog Title
|
||||
|
||||
## OnBoarding
|
||||
|
||||
###Vault Config Missing
|
||||
###Masterkey Missing
|
||||
|
||||
## Expert Settings
|
||||
|
||||
# Convert Vault
|
||||
|
||||
|
||||
@@ -393,8 +393,6 @@ main.vaultlist.contextMenu.unlockNow=Avaa Nyt
|
||||
main.vaultlist.contextMenu.vaultoptions=Näytä holvin asetukset
|
||||
main.vaultlist.contextMenu.reveal=Paljasta Asema
|
||||
main.vaultlist.contextMenu.share=Jaa…
|
||||
main.vaultlist.addVaultBtn.menuItemNew=Luo uusi holvi...
|
||||
main.vaultlist.addVaultBtn.menuItemExisting=Avaa olemassa oleva holvi...
|
||||
main.vaultlist.showEventsButton.tooltip=Avaa tapahtumanäkymä
|
||||
##Notificaition
|
||||
main.notification.updateAvailable=Päivitys on saatavilla.
|
||||
@@ -432,6 +430,7 @@ main.vaultDetail.missing.info=Cryptomator ei löytänyt täältä holvia.
|
||||
main.vaultDetail.missing.recheck=Tarkista uudelleen
|
||||
main.vaultDetail.missing.remove=Poista holvilistalta…
|
||||
main.vaultDetail.missing.changeLocation=Vaihda holvin sijaintia…
|
||||
### Missing Vault Config
|
||||
### Needs Migration
|
||||
main.vaultDetail.migrateButton=Päivitä Holvi
|
||||
main.vaultDetail.migratePrompt=Holvisi täytyy muuntaa uuteen muotoon ennen kuin voit avata sen
|
||||
@@ -511,6 +510,25 @@ recoveryKey.recover.resetBtn=Palauta
|
||||
### Recovery Key Password Reset Success
|
||||
recoveryKey.recover.resetSuccess.message=Salasanan palautus onnistui
|
||||
recoveryKey.recover.resetSuccess.description=Voit avata holvin uudella salasanalla.
|
||||
### Recovery Key Vault Config Reset Success
|
||||
|
||||
# Recover Vault Config File and/or Masterkey
|
||||
##Add Existing Vault without recovery - Dialog
|
||||
|
||||
##Vault Already Exists - Dialog
|
||||
|
||||
##Invalid Selection - Dialog
|
||||
|
||||
## Contact Hub Vault Owner - Dialog
|
||||
|
||||
##Dialog Title
|
||||
|
||||
## OnBoarding
|
||||
|
||||
###Vault Config Missing
|
||||
###Masterkey Missing
|
||||
|
||||
## Expert Settings
|
||||
|
||||
# Convert Vault
|
||||
convertVault.title=Muunna holvi
|
||||
|
||||
@@ -416,6 +416,7 @@ main.vaultDetail.missing.info=Hindi makahanap ng vault ang Cryptomator sa landas
|
||||
main.vaultDetail.missing.recheck=Suriin muli
|
||||
main.vaultDetail.missing.remove=Alisin sa Listahan ng Vault…
|
||||
main.vaultDetail.missing.changeLocation=Baguhin ang Lokasyon ng Vault…
|
||||
### Missing Vault Config
|
||||
### Needs Migration
|
||||
main.vaultDetail.migrateButton=I-upgrade ang Vault
|
||||
main.vaultDetail.migratePrompt=Kailangang i-upgrade ang iyong vault sa bagong format, bago mo ito ma-access
|
||||
@@ -495,6 +496,26 @@ recoveryKey.recover.resetBtn=I-reset
|
||||
### Recovery Key Password Reset Success
|
||||
recoveryKey.recover.resetSuccess.message=Matagumpay ang pag-reset ng password
|
||||
recoveryKey.recover.resetSuccess.description=Maaari mong i-unlock ang iyong vault gamit ang bagong password.
|
||||
### Recovery Key Vault Config Reset Success
|
||||
|
||||
# Recover Vault Config File and/or Masterkey
|
||||
##Add Existing Vault without recovery - Dialog
|
||||
|
||||
##Vault Already Exists - Dialog
|
||||
|
||||
##Invalid Selection - Dialog
|
||||
|
||||
## Contact Hub Vault Owner - Dialog
|
||||
contactHubVaultOwner.title=Hub Vault
|
||||
|
||||
##Dialog Title
|
||||
|
||||
## OnBoarding
|
||||
|
||||
###Vault Config Missing
|
||||
###Masterkey Missing
|
||||
|
||||
## Expert Settings
|
||||
|
||||
# Convert Vault
|
||||
convertVault.title=I-convert ang Vault
|
||||
|
||||
@@ -96,6 +96,7 @@ addvault.new.readme.accessLocation.4=Vous pouvez supprimer ce fichier.
|
||||
## Existing
|
||||
addvaultwizard.existing.title=Ajouter un coffre existant
|
||||
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.restore=Restaurer…
|
||||
addvaultwizard.existing.chooseBtn=Choisir…
|
||||
addvaultwizard.existing.filePickerTitle=Sélectionnez le fichier correspondant au volume chiffré
|
||||
addvaultwizard.existing.filePickerMimeDesc=Coffre-fort Cryptomator
|
||||
@@ -127,6 +128,7 @@ unlock.unlockBtn=Déverrouiller
|
||||
## Select
|
||||
unlock.chooseMasterkey.message=Fichier Masterkey introuvable
|
||||
unlock.chooseMasterkey.description=Impossible de trouver le fichier clef à l'adresse attendue pour l'espace chiffré "%s". Veuillez sélectionner le fichier clef manuellement.
|
||||
unlock.chooseMasterkey.restoreInstead=Restaurez le fichier masterkey à la place
|
||||
unlock.chooseMasterkey.filePickerTitle=Sélectionner le fichier clef
|
||||
unlock.chooseMasterkey.filePickerMimeDesc=Clé principale Cryptomator
|
||||
## Success
|
||||
@@ -394,8 +396,9 @@ main.vaultlist.contextMenu.unlockNow=Déverrouiller maintenant
|
||||
main.vaultlist.contextMenu.vaultoptions=Afficher les options du volume chiffré
|
||||
main.vaultlist.contextMenu.reveal=Afficher le lecteur
|
||||
main.vaultlist.contextMenu.share=Partager…
|
||||
main.vaultlist.addVaultBtn.menuItemNew=Créer un nouveau coffre...
|
||||
main.vaultlist.addVaultBtn.menuItemExisting=Ouvrir un coffre existant...
|
||||
main.vaultlist.addVaultBtn.menuItemNew=Créer un nouveau coffre…
|
||||
main.vaultlist.addVaultBtn.menuItemExisting=Ouvrir le coffre existant…
|
||||
main.vaultlist.addVaultBtn.menuItemRecover=Restaurer le coffre existant…
|
||||
main.vaultlist.showEventsButton.tooltip=Ouvrir la vue Événements
|
||||
##Notificaition
|
||||
main.notification.updateAvailable=Mise à jour disponible.
|
||||
@@ -433,6 +436,9 @@ main.vaultDetail.missing.info=Cryptomator n'a pas pu trouver de volume chiffré
|
||||
main.vaultDetail.missing.recheck=Revérifier
|
||||
main.vaultDetail.missing.remove=Retirer de la liste des volumes…
|
||||
main.vaultDetail.missing.changeLocation=Changer l'emplacement du volume…
|
||||
### Missing Vault Config
|
||||
main.vaultDetail.missingVaultConfig.info=La configuration du coffre est manquante.
|
||||
main.vaultDetail.missingVaultConfig.restore=Restaurer la configuration du coffre
|
||||
### Needs Migration
|
||||
main.vaultDetail.migrateButton=Mettre le volume à jour
|
||||
main.vaultDetail.migratePrompt=Votre coffre doit être converti dans un nouveau format avant d'y accéder
|
||||
@@ -497,6 +503,7 @@ vaultOptions.hub.convertBtn=Convertir en coffre-fort basé sur mot de passe
|
||||
recoveryKey.display.title=Montrer la clé de récupération
|
||||
recoveryKey.create.message=Mot de passe requis
|
||||
recoveryKey.create.description=Entrez le mot de passe de "%s" pour afficher sa clé de récupération.
|
||||
recoveryKey.recover.description=Entrez le mot de passe pour "%s" pour restaurer la configuration du coffre.
|
||||
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 mots de passe\n • Enregistrez-la sur une clé USB\n • Imprimez-la
|
||||
## Reset Password
|
||||
@@ -509,9 +516,57 @@ recoveryKey.recover.invalidKey=Cette clé de récupération n'est pas valide
|
||||
recoveryKey.printout.heading=Clé de récupération Cryptomator "%s"\n
|
||||
### Reset Password
|
||||
recoveryKey.recover.resetBtn=Réinitialiser
|
||||
recoveryKey.recover.recoverBtn=Restaurer
|
||||
### Recovery Key Password Reset Success
|
||||
recoveryKey.recover.resetSuccess.message=Réinitialisation du mot de passe réussie
|
||||
recoveryKey.recover.resetSuccess.description=Vous pouvez déverrouiller votre coffre avec le nouveau mot de passe.
|
||||
### Recovery Key Vault Config Reset Success
|
||||
recoveryKey.recover.resetMasterkeyFileSuccess.description=Vous pouvez maintenant déverrouiller votre coffre avec votre mot de passe.
|
||||
|
||||
# Recover Vault Config File and/or Masterkey
|
||||
##Add Existing Vault without recovery - Dialog
|
||||
recover.existing.title=Coffre ajouté
|
||||
recover.existing.message=Le coffre a été ajouté avec succès
|
||||
recover.existing.description=Votre coffre "%s" a été ajouté à la liste des coffres. Aucun processus de récupération n'a été nécessaire.
|
||||
|
||||
##Vault Already Exists - Dialog
|
||||
recover.alreadyExists.title=Le coffre-fort existe déjà
|
||||
recover.alreadyExists.message=Ce coffre a déjà été ajouté
|
||||
recover.alreadyExists.description=Votre coffre «%s» est déjà présent dans votre liste de coffres et n'a donc pas été ajouté à nouveau.
|
||||
|
||||
##Invalid Selection - Dialog
|
||||
recover.invalidSelection.title=Sélection invalide
|
||||
recover.invalidSelection.message=Votre sélection n'est pas un coffre
|
||||
recover.invalidSelection.description=Le dossier sélectionné doit être un coffre Cryptomator valide.
|
||||
|
||||
## Contact Hub Vault Owner - Dialog
|
||||
contactHubVaultOwner.title=Coffre dans Hub
|
||||
contactHubVaultOwner.message=Ce coffre a été créé avec le Hub Cryptomator
|
||||
contactHubVaultOwner.description=.
|
||||
|
||||
##Dialog Title
|
||||
recover.recoverVaultConfig.title=Récupérer la configuration du coffre
|
||||
recover.recoverMasterkey.title=Récupérer la clé principale
|
||||
|
||||
## OnBoarding
|
||||
recover.onBoarding.chooseMethod=Choisissez la méthode de récupération :
|
||||
recover.onBoarding.useRecoveryKey=Utiliser la clé de récupération
|
||||
recover.onBoarding.usePassword=Utiliser mot de passe
|
||||
recover.onBoarding.intro=Assurez-vous de vérifier ce qui suit :
|
||||
recover.onBoarding.pleaseConfirm=Avant de procéder, veuillez confirmer ceci :
|
||||
recover.onBoarding.otherwisePleaseConfirm=Sinon, veuillez confirmer ceci:
|
||||
recover.onBoarding.allMissing.intro=Si ce coffre est géré par Cryptomator Hub, le propriétaire du coffre doit le restaurer pour vous.
|
||||
recover.onBoarding.intro.ensure=.
|
||||
recover.onBoarding.affirmation=J'ai lu et compris ces prérequis
|
||||
|
||||
###Vault Config Missing
|
||||
recover.onBoarding.intro.recoveryKey=Vous avez la clé de récupération et et savez si les paramètres experts ont été utilisés.
|
||||
recover.onBoarding.intro.password=Vous avez le mot de passe du coffre et savez si les paramètres experts ont été utilisés.
|
||||
###Masterkey Missing
|
||||
recover.onBoarding.intro.masterkey.recoveryKey=Vous avez la clé de récupération du coffre.
|
||||
|
||||
## Expert Settings
|
||||
recover.expertSettings.shorteningThreshold.title=
|
||||
|
||||
# Convert Vault
|
||||
convertVault.title=Convertir le coffre
|
||||
|
||||
@@ -101,6 +101,7 @@ lock.forced.retryBtn=Tentar de novo
|
||||
### Locked
|
||||
### Unlocked
|
||||
### Missing
|
||||
### Missing Vault Config
|
||||
### Needs Migration
|
||||
### Error
|
||||
|
||||
@@ -119,6 +120,25 @@ lock.forced.retryBtn=Tentar de novo
|
||||
### Enter Recovery Key
|
||||
### Reset Password
|
||||
### Recovery Key Password Reset Success
|
||||
### Recovery Key Vault Config Reset Success
|
||||
|
||||
# Recover Vault Config File and/or Masterkey
|
||||
##Add Existing Vault without recovery - Dialog
|
||||
|
||||
##Vault Already Exists - Dialog
|
||||
|
||||
##Invalid Selection - Dialog
|
||||
|
||||
## Contact Hub Vault Owner - Dialog
|
||||
|
||||
##Dialog Title
|
||||
|
||||
## OnBoarding
|
||||
|
||||
###Vault Config Missing
|
||||
###Masterkey Missing
|
||||
|
||||
## Expert Settings
|
||||
|
||||
# Convert Vault
|
||||
|
||||
|
||||
@@ -384,6 +384,7 @@ main.vaultDetail.missing.info=Cryptomator לא הצליח למצוא כספת ב
|
||||
main.vaultDetail.missing.recheck=בדיקה נוספת
|
||||
main.vaultDetail.missing.remove=הסר מרשימה הכספות…
|
||||
main.vaultDetail.missing.changeLocation=שנה את מיקום הכספת…
|
||||
### Missing Vault Config
|
||||
### Needs Migration
|
||||
main.vaultDetail.migrateButton=שדרג הכספת
|
||||
main.vaultDetail.migratePrompt=צריך לשדרג את הכספת שלך לגרסה חדשה לפני שניתן לגשת אליה
|
||||
@@ -455,6 +456,25 @@ recoveryKey.recover.resetBtn=איפוס
|
||||
### Recovery Key Password Reset Success
|
||||
recoveryKey.recover.resetSuccess.message=איפוס סיסמה הצליח
|
||||
recoveryKey.recover.resetSuccess.description=ניתן לפתוח את הכספת עם הסיסמה החדשה.
|
||||
### Recovery Key Vault Config Reset Success
|
||||
|
||||
# Recover Vault Config File and/or Masterkey
|
||||
##Add Existing Vault without recovery - Dialog
|
||||
|
||||
##Vault Already Exists - Dialog
|
||||
|
||||
##Invalid Selection - Dialog
|
||||
|
||||
## Contact Hub Vault Owner - Dialog
|
||||
|
||||
##Dialog Title
|
||||
|
||||
## OnBoarding
|
||||
|
||||
###Vault Config Missing
|
||||
###Masterkey Missing
|
||||
|
||||
## Expert Settings
|
||||
|
||||
# Convert Vault
|
||||
convertVault.convert.convertBtn.before=להמיר
|
||||
|
||||
@@ -256,6 +256,7 @@ main.vaultDetail.lockBtn=लॉक करें
|
||||
main.vaultDetail.stats=वॉल्ट के आंकड़े
|
||||
### Missing
|
||||
main.vaultDetail.missing.remove=वॉल्ट की सूची से हटाए।
|
||||
### Missing Vault Config
|
||||
### Needs Migration
|
||||
main.vaultDetail.migrateButton=वाउल्ट को अपग्रेड करें
|
||||
### Error
|
||||
@@ -291,6 +292,25 @@ recoveryKey.create.description=रिकवरी-की दिखाने क
|
||||
### Enter Recovery Key
|
||||
### Reset Password
|
||||
### Recovery Key Password Reset Success
|
||||
### Recovery Key Vault Config Reset Success
|
||||
|
||||
# Recover Vault Config File and/or Masterkey
|
||||
##Add Existing Vault without recovery - Dialog
|
||||
|
||||
##Vault Already Exists - Dialog
|
||||
|
||||
##Invalid Selection - Dialog
|
||||
|
||||
## Contact Hub Vault Owner - Dialog
|
||||
|
||||
##Dialog Title
|
||||
|
||||
## OnBoarding
|
||||
|
||||
###Vault Config Missing
|
||||
###Masterkey Missing
|
||||
|
||||
## Expert Settings
|
||||
|
||||
# Convert Vault
|
||||
|
||||
|
||||
@@ -298,6 +298,7 @@ main.vaultDetail.missing.info=Cryptomator nije mogao pronaći trezor s ovom puta
|
||||
main.vaultDetail.missing.recheck=Ponovo provjeri
|
||||
main.vaultDetail.missing.remove=Ukloni iz liste trezora…
|
||||
main.vaultDetail.missing.changeLocation=Promijeni lokaciju trezora…
|
||||
### Missing Vault Config
|
||||
### Needs Migration
|
||||
main.vaultDetail.migrateButton=Nadogradi trezor
|
||||
main.vaultDetail.migratePrompt=Vaš trezor treba se nadograditi na novi format, prije nego mu možete pristupiti
|
||||
@@ -357,6 +358,25 @@ recoveryKey.recover.correctKey=Ovo je valjani ključ za oporavak
|
||||
recoveryKey.printout.heading=Cryptomator-ov ključ za oporavak\n"%s"\n
|
||||
### Reset Password
|
||||
### Recovery Key Password Reset Success
|
||||
### Recovery Key Vault Config Reset Success
|
||||
|
||||
# Recover Vault Config File and/or Masterkey
|
||||
##Add Existing Vault without recovery - Dialog
|
||||
|
||||
##Vault Already Exists - Dialog
|
||||
|
||||
##Invalid Selection - Dialog
|
||||
|
||||
## Contact Hub Vault Owner - Dialog
|
||||
|
||||
##Dialog Title
|
||||
|
||||
## OnBoarding
|
||||
|
||||
###Vault Config Missing
|
||||
###Masterkey Missing
|
||||
|
||||
## Expert Settings
|
||||
|
||||
# Convert Vault
|
||||
|
||||
|
||||
@@ -394,8 +394,6 @@ main.vaultlist.contextMenu.unlockNow=Azonnali feloldás
|
||||
main.vaultlist.contextMenu.vaultoptions=Széf beállítások
|
||||
main.vaultlist.contextMenu.reveal=Széf megjelenítése
|
||||
main.vaultlist.contextMenu.share=Megosztás…
|
||||
main.vaultlist.addVaultBtn.menuItemNew=Új széf létrehozása...
|
||||
main.vaultlist.addVaultBtn.menuItemExisting=Meglévő széf megnyitása...
|
||||
##Notificaition
|
||||
main.notification.updateAvailable=Frissítés elérhető.
|
||||
main.notification.support=Cryptomator támogatása.
|
||||
@@ -429,6 +427,7 @@ main.vaultDetail.missing.info=A Cryptomator nem talált széfet ezen az útvonal
|
||||
main.vaultDetail.missing.recheck=Ellenőrizze újra
|
||||
main.vaultDetail.missing.remove=A széf eltávolítása a listából…
|
||||
main.vaultDetail.missing.changeLocation=A széf helyének megváltoztatása…
|
||||
### Missing Vault Config
|
||||
### Needs Migration
|
||||
main.vaultDetail.migrateButton=Széf frissítése
|
||||
main.vaultDetail.migratePrompt=A széfet új formátumra kell frissíteni, mielőtt hozzáférhet
|
||||
@@ -508,6 +507,26 @@ recoveryKey.recover.resetBtn=Visszaállítás
|
||||
### Recovery Key Password Reset Success
|
||||
recoveryKey.recover.resetSuccess.message=A jelszó alaphelyzetbe állítása sikeresen megtörtént
|
||||
recoveryKey.recover.resetSuccess.description=Feloldhatja a széfet az új jelszóval.
|
||||
### Recovery Key Vault Config Reset Success
|
||||
|
||||
# Recover Vault Config File and/or Masterkey
|
||||
##Add Existing Vault without recovery - Dialog
|
||||
|
||||
##Vault Already Exists - Dialog
|
||||
|
||||
##Invalid Selection - Dialog
|
||||
|
||||
## Contact Hub Vault Owner - Dialog
|
||||
contactHubVaultOwner.title=Hub széf
|
||||
|
||||
##Dialog Title
|
||||
|
||||
## OnBoarding
|
||||
|
||||
###Vault Config Missing
|
||||
###Masterkey Missing
|
||||
|
||||
## Expert Settings
|
||||
|
||||
# Convert Vault
|
||||
convertVault.title=Széf átalakítása
|
||||
|
||||
@@ -394,8 +394,6 @@ main.vaultlist.contextMenu.unlockNow=Buka Kunci Sekarang
|
||||
main.vaultlist.contextMenu.vaultoptions=Tampilkan Opsi Vault
|
||||
main.vaultlist.contextMenu.reveal=Buka Drive
|
||||
main.vaultlist.contextMenu.share=Bagikan…
|
||||
main.vaultlist.addVaultBtn.menuItemNew=Buat Vault Baru...
|
||||
main.vaultlist.addVaultBtn.menuItemExisting=Buka Vault yang Tersedia...
|
||||
##Notificaition
|
||||
main.notification.updateAvailable=Pembaruan tersedia.
|
||||
main.notification.support=Dukung Cryptomator.
|
||||
@@ -429,6 +427,7 @@ main.vaultDetail.missing.info=Cryptomator tidak dapat menemukan vault di path in
|
||||
main.vaultDetail.missing.recheck=Periksa kembali
|
||||
main.vaultDetail.missing.remove=Hapus dari Daftar Vault…
|
||||
main.vaultDetail.missing.changeLocation=Ganti Lokasi Vault…
|
||||
### Missing Vault Config
|
||||
### Needs Migration
|
||||
main.vaultDetail.migrateButton=Tingkatkan Vault
|
||||
main.vaultDetail.migratePrompt=Vault Anda perlu ditingkatkan ke format baru, sebelum Anda dapat mengaksesnya
|
||||
@@ -508,6 +507,26 @@ recoveryKey.recover.resetBtn=Atur ulang
|
||||
### Recovery Key Password Reset Success
|
||||
recoveryKey.recover.resetSuccess.message=Atur ulang kata sandi berhasil
|
||||
recoveryKey.recover.resetSuccess.description=Anda dapat membuka kunci vault Anda dengan kata sandi baru.
|
||||
### Recovery Key Vault Config Reset Success
|
||||
|
||||
# Recover Vault Config File and/or Masterkey
|
||||
##Add Existing Vault without recovery - Dialog
|
||||
|
||||
##Vault Already Exists - Dialog
|
||||
|
||||
##Invalid Selection - Dialog
|
||||
|
||||
## Contact Hub Vault Owner - Dialog
|
||||
contactHubVaultOwner.title=Hub Vault
|
||||
|
||||
##Dialog Title
|
||||
|
||||
## OnBoarding
|
||||
|
||||
###Vault Config Missing
|
||||
###Masterkey Missing
|
||||
|
||||
## Expert Settings
|
||||
|
||||
# Convert Vault
|
||||
convertVault.title=Konversi Vault
|
||||
|
||||
@@ -96,6 +96,7 @@ addvault.new.readme.accessLocation.4=Sentiti libero di rimuovere questo file.
|
||||
## Existing
|
||||
addvaultwizard.existing.title=Aggiungi una Cassaforte Esistente
|
||||
addvaultwizard.existing.instruction=Scegliere il file "vault.cryptomator" della tua cassaforte. Se esiste solo un file chiamato "masterkey.cryptomator", allora scegli quello.
|
||||
addvaultwizard.existing.restore=Ripristina…
|
||||
addvaultwizard.existing.chooseBtn=Scegli…
|
||||
addvaultwizard.existing.filePickerTitle=Seleziona file cassaforte
|
||||
addvaultwizard.existing.filePickerMimeDesc=Cassaforte di Cryptomator
|
||||
@@ -127,6 +128,7 @@ unlock.unlockBtn=Sblocca
|
||||
## Select
|
||||
unlock.chooseMasterkey.message=File Masterkey non trovato
|
||||
unlock.chooseMasterkey.description=Impossibile trovare il file Masterkey per questa cassaforte alla sua posizione prevista. Sei pregato di sceglierlo manualmente.
|
||||
unlock.chooseMasterkey.restoreInstead=Ripristina invece il file con la chiave principale
|
||||
unlock.chooseMasterkey.filePickerTitle=Seleziona il File Masterkey
|
||||
unlock.chooseMasterkey.filePickerMimeDesc=Chiave principale di Cryptomator
|
||||
## Success
|
||||
@@ -394,8 +396,9 @@ main.vaultlist.contextMenu.unlockNow=Sblocca Ora
|
||||
main.vaultlist.contextMenu.vaultoptions=Mostra le Opzioni della Cassaforte
|
||||
main.vaultlist.contextMenu.reveal=Rivela Unità
|
||||
main.vaultlist.contextMenu.share=Condividi…
|
||||
main.vaultlist.addVaultBtn.menuItemNew=Crea una nuova cassaforte...
|
||||
main.vaultlist.addVaultBtn.menuItemExisting=Apri una cassaforte esistente...
|
||||
main.vaultlist.addVaultBtn.menuItemNew=Crea una nuova cassaforte…
|
||||
main.vaultlist.addVaultBtn.menuItemExisting=Apri una cassaforte esistente…
|
||||
main.vaultlist.addVaultBtn.menuItemRecover=Recupera una cassaforte esistente…
|
||||
main.vaultlist.showEventsButton.tooltip=Apri vista eventi
|
||||
##Notificaition
|
||||
main.notification.updateAvailable=Aggiornamento disponibile.
|
||||
@@ -433,6 +436,9 @@ main.vaultDetail.missing.info=Cryptomator non è riuscito a trovare una cassafor
|
||||
main.vaultDetail.missing.recheck=Ricontrolla
|
||||
main.vaultDetail.missing.remove=Rimuovi dall'elenco delle casseforti…
|
||||
main.vaultDetail.missing.changeLocation=Cambia la Posizione della Cassaforte…
|
||||
### Missing Vault Config
|
||||
main.vaultDetail.missingVaultConfig.info=Manca la configurazione della cassaforte.
|
||||
main.vaultDetail.missingVaultConfig.restore=Ripristina la configurazione della cassaforte
|
||||
### Needs Migration
|
||||
main.vaultDetail.migrateButton=Aggiorna la Cassaforte
|
||||
main.vaultDetail.migratePrompt=La tua cassaforte dev'esser aggiornata a un nuovo formato, prima di potervi accedere
|
||||
@@ -497,6 +503,7 @@ vaultOptions.hub.convertBtn=Converti in cassaforte basata su password
|
||||
recoveryKey.display.title=Mostra Chiave Di Recupero
|
||||
recoveryKey.create.message=Password richiesta
|
||||
recoveryKey.create.description=Inserisci la password per visualizzare la chiave di recupero per "%s":
|
||||
recoveryKey.recover.description=Inserisci la password di "%s" per recuperare la configurazione della cassaforte.
|
||||
recoveryKey.display.description=La seguente chiave di recupero può essere utilizzata per ripristinare l'accesso a %s":
|
||||
recoveryKey.display.StorageHints=Conservala da qualche parte in modo sicuro, es.\n • Archiviarla usando un gestore di password\n • Salvarla su un'unità flash USB\n • Stamparla su carta
|
||||
## Reset Password
|
||||
@@ -509,9 +516,57 @@ recoveryKey.recover.invalidKey=Questa chiave di recupero non é valida
|
||||
recoveryKey.printout.heading=Chiave di recupero Cryptomator\n"%s"\n
|
||||
### Reset Password
|
||||
recoveryKey.recover.resetBtn=Reimposta
|
||||
recoveryKey.recover.recoverBtn=Recupera
|
||||
### Recovery Key Password Reset Success
|
||||
recoveryKey.recover.resetSuccess.message=Password reimpostata correttamente
|
||||
recoveryKey.recover.resetSuccess.description=Puoi sbloccare la tua cassaforte con la nuova password.
|
||||
### Recovery Key Vault Config Reset Success
|
||||
recoveryKey.recover.resetMasterkeyFileSuccess.description=Ora puoi sbloccare la cassaforte con la tua password.
|
||||
|
||||
# Recover Vault Config File and/or Masterkey
|
||||
##Add Existing Vault without recovery - Dialog
|
||||
recover.existing.title=Cassaforte aggiunta
|
||||
recover.existing.message=La cassaforte è stata aggiunta con successo
|
||||
recover.existing.description=La tua cassaforte "%s" è stata aggiunta alla lista. Non è stata necessaria alcuna azione di recupero.
|
||||
|
||||
##Vault Already Exists - Dialog
|
||||
recover.alreadyExists.title=La cassaforte esiste già
|
||||
recover.alreadyExists.message=Questa cassaforte è già stata aggiunta
|
||||
recover.alreadyExists.description=La tua cassaforte "%s" è già presente nella lista, quindi non è stata aggiunta di nuovo.
|
||||
|
||||
##Invalid Selection - Dialog
|
||||
recover.invalidSelection.title=Selezione non valida
|
||||
recover.invalidSelection.message=Quello che hai selezionato non è una cassaforte
|
||||
recover.invalidSelection.description=La cartella selezionata deve essere una cassaforte Cryptomator.
|
||||
|
||||
## Contact Hub Vault Owner - Dialog
|
||||
contactHubVaultOwner.title=Centrale delle Casseforti
|
||||
contactHubVaultOwner.message=Questa cassaforte è stata creata con Cryptomator Hub
|
||||
contactHubVaultOwner.description=Contatta il proprietario della cassaforte per ripristinare il file mancante. Si può scaricare il modello di cassaforte da Cryptomator Hub.
|
||||
|
||||
##Dialog Title
|
||||
recover.recoverVaultConfig.title=Ripristina la configurazione della cassaforte
|
||||
recover.recoverMasterkey.title=Recupera il file con la chiave principale
|
||||
|
||||
## OnBoarding
|
||||
recover.onBoarding.chooseMethod=Scegli metodo di recupero:
|
||||
recover.onBoarding.useRecoveryKey=Usa la chiave di recupero
|
||||
recover.onBoarding.usePassword=Utilizza la password
|
||||
recover.onBoarding.intro=Assicurati di controllare quanto segue:
|
||||
recover.onBoarding.pleaseConfirm=Prima di procedere, conferma che:
|
||||
recover.onBoarding.otherwisePleaseConfirm=In caso contrario, conferma che:
|
||||
recover.onBoarding.allMissing.intro=Se questa cassaforte è gestita da Cryptomator Hub, è il proprietario della cassaforte che deve ripristinarla.
|
||||
recover.onBoarding.intro.ensure=Tutti i file sono completamente sincronizzati.
|
||||
recover.onBoarding.affirmation=Ho letto e compreso questi requisiti
|
||||
|
||||
###Vault Config Missing
|
||||
recover.onBoarding.intro.recoveryKey=Hai la chiave di recupero e sai se sono state utilizzate configurazioni avanzate.
|
||||
recover.onBoarding.intro.password=Hai la chiave di recupero e sai se sono state utilizzate configurazioni avanzate.
|
||||
###Masterkey Missing
|
||||
recover.onBoarding.intro.masterkey.recoveryKey=Hai la chiave di ripristino della cassaforte.
|
||||
|
||||
## Expert Settings
|
||||
recover.expertSettings.shorteningThreshold.title=Questo valore deve corrispondere a quello usato prima del recupero per garantire la compatibilità con i dati precedentemente crittografati.
|
||||
|
||||
# Convert Vault
|
||||
convertVault.title=Convertire Cassaforte
|
||||
|
||||
@@ -391,8 +391,6 @@ main.vaultlist.contextMenu.unlockNow=今すぐ解錠
|
||||
main.vaultlist.contextMenu.vaultoptions=金庫のオプションを表示
|
||||
main.vaultlist.contextMenu.reveal=ドライブを表示
|
||||
main.vaultlist.contextMenu.share=共有…
|
||||
main.vaultlist.addVaultBtn.menuItemNew=新しい金庫を作成…
|
||||
main.vaultlist.addVaultBtn.menuItemExisting=既存の金庫を開く…
|
||||
##Notificaition
|
||||
main.notification.updateAvailable=アップデートがあります。
|
||||
main.notification.support=Cryptomator を支援する。
|
||||
@@ -429,6 +427,7 @@ main.vaultDetail.missing.info=Cryptomator はこの場所に金庫を見つけ
|
||||
main.vaultDetail.missing.recheck=再確認
|
||||
main.vaultDetail.missing.remove=金庫のリストから削除...
|
||||
main.vaultDetail.missing.changeLocation=金庫の場所を変更...
|
||||
### Missing Vault Config
|
||||
### Needs Migration
|
||||
main.vaultDetail.migrateButton=金庫をアップグレード
|
||||
main.vaultDetail.migratePrompt=金庫にアクセスする前に、 金庫を新しい形式にアップグレードする必要があります
|
||||
@@ -508,6 +507,32 @@ recoveryKey.recover.resetBtn=リセット
|
||||
### Recovery Key Password Reset Success
|
||||
recoveryKey.recover.resetSuccess.message=パスワードをリセットしました
|
||||
recoveryKey.recover.resetSuccess.description=新しいパスワードで金庫の施錠ができます。
|
||||
### Recovery Key Vault Config Reset Success
|
||||
|
||||
# Recover Vault Config File and/or Masterkey
|
||||
##Add Existing Vault without recovery - Dialog
|
||||
|
||||
##Vault Already Exists - Dialog
|
||||
|
||||
##Invalid Selection - Dialog
|
||||
recover.invalidSelection.title=無効な選択
|
||||
|
||||
## Contact Hub Vault Owner - Dialog
|
||||
contactHubVaultOwner.title=
|
||||
|
||||
##Dialog Title
|
||||
|
||||
## OnBoarding
|
||||
recover.onBoarding.useRecoveryKey=回復キーを利用
|
||||
recover.onBoarding.usePassword=パスワードを使用
|
||||
recover.onBoarding.pleaseConfirm=続行する前に、以下を確認してください:
|
||||
recover.onBoarding.intro.ensure=全てのファイルは完全に同期されています。
|
||||
recover.onBoarding.affirmation=私はこれらの要件を読み、理解しました
|
||||
|
||||
###Vault Config Missing
|
||||
###Masterkey Missing
|
||||
|
||||
## Expert Settings
|
||||
|
||||
# Convert Vault
|
||||
convertVault.title=金庫を変換
|
||||
|
||||
@@ -394,8 +394,6 @@ main.vaultlist.contextMenu.unlockNow=지금 잠금 해제
|
||||
main.vaultlist.contextMenu.vaultoptions=Vault 옵션 보기
|
||||
main.vaultlist.contextMenu.reveal=드라이브 표시
|
||||
main.vaultlist.contextMenu.share=공유하기…
|
||||
main.vaultlist.addVaultBtn.menuItemNew=새 Vault 생성...
|
||||
main.vaultlist.addVaultBtn.menuItemExisting=기존 Vault 열기...
|
||||
main.vaultlist.showEventsButton.tooltip=이벤트 뷰어 열기
|
||||
##Notificaition
|
||||
main.notification.updateAvailable=업데이트가 있습니다.
|
||||
@@ -433,6 +431,7 @@ main.vaultDetail.missing.info=Cryptomator가 이 경로에 있는 Vault를 찾
|
||||
main.vaultDetail.missing.recheck=다시 시도
|
||||
main.vaultDetail.missing.remove=Vault 목록에서 제거...
|
||||
main.vaultDetail.missing.changeLocation=Vault 위치 변경
|
||||
### Missing Vault Config
|
||||
### Needs Migration
|
||||
main.vaultDetail.migrateButton=Vault 업그레이드
|
||||
main.vaultDetail.migratePrompt=Vault에 접근하기 전, 새로운 포맷으로 업그레이드가 필요합니다.
|
||||
@@ -512,6 +511,26 @@ recoveryKey.recover.resetBtn=초기화
|
||||
### Recovery Key Password Reset Success
|
||||
recoveryKey.recover.resetSuccess.message=비밀번호 재설정 성공
|
||||
recoveryKey.recover.resetSuccess.description=이제 해당 vault를 새 비밀번호로 잠금 해제할 수 있습니다.
|
||||
### Recovery Key Vault Config Reset Success
|
||||
|
||||
# Recover Vault Config File and/or Masterkey
|
||||
##Add Existing Vault without recovery - Dialog
|
||||
|
||||
##Vault Already Exists - Dialog
|
||||
|
||||
##Invalid Selection - Dialog
|
||||
|
||||
## Contact Hub Vault Owner - Dialog
|
||||
contactHubVaultOwner.title=Hub Vault
|
||||
|
||||
##Dialog Title
|
||||
|
||||
## OnBoarding
|
||||
|
||||
###Vault Config Missing
|
||||
###Masterkey Missing
|
||||
|
||||
## Expert Settings
|
||||
|
||||
# Convert Vault
|
||||
convertVault.title=Vault 변환
|
||||
|
||||
@@ -96,6 +96,7 @@ addvault.new.readme.accessLocation.4=Šo datni var droši noņemt.
|
||||
## Existing
|
||||
addvaultwizard.existing.title=Pievienot esošu glabātavu
|
||||
addvaultwizard.existing.instruction=Jāizvēlas esošas glabātavas datne "vault.cryptomator". Ja pastāv tikai datne ar nosaukumu "masterkey.cryptomator", tad jāatlasā tā.
|
||||
addvaultwizard.existing.restore=Atjaunot…
|
||||
addvaultwizard.existing.chooseBtn=Izvēlēties…
|
||||
addvaultwizard.existing.filePickerTitle=Atlasīt glabātavas datni
|
||||
addvaultwizard.existing.filePickerMimeDesc=Cryptomator glabātava
|
||||
@@ -127,6 +128,7 @@ unlock.unlockBtn=Atslēgt
|
||||
## Select
|
||||
unlock.chooseMasterkey.message=Galvenās atslēgas datne nav atrasta
|
||||
unlock.chooseMasterkey.description=Cryptomator nevarēja atrast galvenās atslēgas datni glabātavai "%s". Lūgums pašrocīgi izvēlēties atslēgas datni.
|
||||
unlock.chooseMasterkey.restoreInstead=Tā vietā atjaunot galvenās atslēgas datni
|
||||
unlock.chooseMasterkey.filePickerTitle=Atlasīt galvenās atslēgas datni
|
||||
unlock.chooseMasterkey.filePickerMimeDesc=Cryptomator galvenā atslēga
|
||||
## Success
|
||||
@@ -394,8 +396,9 @@ main.vaultlist.contextMenu.unlockNow=Atslēgt tagad
|
||||
main.vaultlist.contextMenu.vaultoptions=Rādīt glabātavas iespējas
|
||||
main.vaultlist.contextMenu.reveal=Atklāt disku
|
||||
main.vaultlist.contextMenu.share=Kopīgot…
|
||||
main.vaultlist.addVaultBtn.menuItemNew=Izveidot jaunu glabātavu...
|
||||
main.vaultlist.addVaultBtn.menuItemExisting=Atvērt esošu glabātavu...
|
||||
main.vaultlist.addVaultBtn.menuItemNew=Izveidot jaunu glabātavu…
|
||||
main.vaultlist.addVaultBtn.menuItemExisting=Atvērt esošu glabātavu…
|
||||
main.vaultlist.addVaultBtn.menuItemRecover=Atjaunot esošu glabātavu…
|
||||
main.vaultlist.showEventsButton.tooltip=Atvērt notikumu skatu
|
||||
##Notificaition
|
||||
main.notification.updateAvailable=Ir pieejams atjauninājums.
|
||||
@@ -433,6 +436,9 @@ main.vaultDetail.missing.info=Cryptomator šajā ceļā nevarēja atrast glabāt
|
||||
main.vaultDetail.missing.recheck=Pārbaudīt atkārtoti
|
||||
main.vaultDetail.missing.remove=Noņemt no glabātavu saraksta…
|
||||
main.vaultDetail.missing.changeLocation=Mainīt glabātavas atrašanās vietu…
|
||||
### Missing Vault Config
|
||||
main.vaultDetail.missingVaultConfig.info=Trūkst glabātavas konfigurācijas.
|
||||
main.vaultDetail.missingVaultConfig.restore=Atjaunot glabātavas konfigurāciju
|
||||
### Needs Migration
|
||||
main.vaultDetail.migrateButton=Jaunināt glabātavu
|
||||
main.vaultDetail.migratePrompt=Glabātavu ir nepieciešams jaunināt uz jaunu veidolu, pirms tai varēs piekļūt
|
||||
@@ -497,6 +503,7 @@ vaultOptions.hub.convertBtn=Pārveidot par uz paroli balstītu glabātavu
|
||||
recoveryKey.display.title=Parādīt atkopes atslēgu
|
||||
recoveryKey.create.message=Nepieciešama parole
|
||||
recoveryKey.create.description=Jāievada "%s" parole, lai parādītu tās atkopes atslēgu.
|
||||
recoveryKey.recover.description=Jāievada “%s” parole, lai atkoptu glabātavas konfigurāciju.
|
||||
recoveryKey.display.description=Zemāk esošā atkopes atslēga var tikt izmantota, lai atjaunotu piekļuvi "%s":
|
||||
recoveryKey.display.StorageHints=Tā ir jātur ļoti drošā vietā, piemēram:\n • jāglabā paroļu pārvaldniekā;\n • jāsaglabā USB zibatmiņā;\n • jāizdrukā uz papīra.
|
||||
## Reset Password
|
||||
@@ -509,9 +516,57 @@ recoveryKey.recover.invalidKey=Šī atkopes atslēga nav derīga
|
||||
recoveryKey.printout.heading=Cryptomator atkopes atslēga\n"%s" \n
|
||||
### Reset Password
|
||||
recoveryKey.recover.resetBtn=Atiestatīt
|
||||
recoveryKey.recover.recoverBtn=Atkopt
|
||||
### Recovery Key Password Reset Success
|
||||
recoveryKey.recover.resetSuccess.message=Paroles atiestatīšana sekmīga
|
||||
recoveryKey.recover.resetSuccess.description=Savu glabātavu var atslēgt ar jauno paroli.
|
||||
### Recovery Key Vault Config Reset Success
|
||||
recoveryKey.recover.resetMasterkeyFileSuccess.description=Savu glabātavu tagad var atslēgt ar jauno paroli.
|
||||
|
||||
# Recover Vault Config File and/or Masterkey
|
||||
##Add Existing Vault without recovery - Dialog
|
||||
recover.existing.title=Glabātava pievienota
|
||||
recover.existing.message=Glabātava tika sekmīgi pievienota
|
||||
recover.existing.description=Glabātava “%s” tika pievienota glabātavu sarakstam. Atkope nebija nepieciešama.
|
||||
|
||||
##Vault Already Exists - Dialog
|
||||
recover.alreadyExists.title=Glabātava jau pastāv
|
||||
recover.alreadyExists.message=Šī glabātava jau ir pievienota
|
||||
recover.alreadyExists.description=Glabātava “%s” jau ir glabātavu sarakstā, tādējādi tā netika pievienota vēlreiz.
|
||||
|
||||
##Invalid Selection - Dialog
|
||||
recover.invalidSelection.title=Nederīga atlase
|
||||
recover.invalidSelection.message=Atlasītais nav glabātava
|
||||
recover.invalidSelection.description=Atlasītajai mapei jābūt derīgai Cryptomator glabātavai.
|
||||
|
||||
## Contact Hub Vault Owner - Dialog
|
||||
contactHubVaultOwner.title=Hub glabātava
|
||||
contactHubVaultOwner.message=Šī glabātava tika izveidota ar Cryptomator Hub
|
||||
contactHubVaultOwner.description=Lūgums vērsties pie glabātavas īpašnieka, lai atjaunotu trūkstošo datni. Glabātavas sagatavi var lejupielādēt no Cryptomator Hub.
|
||||
|
||||
##Dialog Title
|
||||
recover.recoverVaultConfig.title=Atkopt glabātavas konfigurāciju
|
||||
recover.recoverMasterkey.title=Atkopt galveno atslēgu
|
||||
|
||||
## OnBoarding
|
||||
recover.onBoarding.chooseMethod=Jāizvēlas atkopes veids:
|
||||
recover.onBoarding.useRecoveryKey=Izmantot atkopes atslēgu
|
||||
recover.onBoarding.usePassword=Izmantot paroli
|
||||
recover.onBoarding.intro=Jāpārliecinās, ka ir pārbaudīts šis:
|
||||
recover.onBoarding.pleaseConfirm=Pirms turpināšanas lūgums apstiprināt, ka:
|
||||
recover.onBoarding.otherwisePleaseConfirm=Pretējā gadījumā lūgums apstiprināt, ka:
|
||||
recover.onBoarding.allMissing.intro=Ja šo glabātavu pārvalda Cryptomator Hub, tā ir jāatjauno glabātavas īpašniekam.
|
||||
recover.onBoarding.intro.ensure=Visas datnes ir pilnībā sinhronizētas.
|
||||
recover.onBoarding.affirmation=Es izlasīju un saprotu šīs prasības
|
||||
|
||||
###Vault Config Missing
|
||||
recover.onBoarding.intro.recoveryKey=Tev ir atkopes atslēga, un Tu zini, vai tika izmantoti lietpratēju iestatījumi.
|
||||
recover.onBoarding.intro.password=Tev ir glabātavas atslēga, un Tu zini, vai tika izmantoti lietpratēju iestatījumi.
|
||||
###Masterkey Missing
|
||||
recover.onBoarding.intro.masterkey.recoveryKey=Tev ir glabātavas atkopes atslēga.
|
||||
|
||||
## Expert Settings
|
||||
recover.expertSettings.shorteningThreshold.title=Šai vērtībai ir jāatbilst tai, kas tika izmantota pirms atkopes, lai nodrošinatu saderību ar iepriekš šifrētajiem datiem.
|
||||
|
||||
# Convert Vault
|
||||
convertVault.title=Pārveidot glabātavu
|
||||
|
||||
@@ -135,6 +135,7 @@ main.vaultlist.contextMenu.lock=Заклучи
|
||||
### Unlocked
|
||||
main.vaultDetail.lockBtn=Заклучи
|
||||
### Missing
|
||||
### Missing Vault Config
|
||||
### Needs Migration
|
||||
### Error
|
||||
|
||||
@@ -155,6 +156,25 @@ vaultOptions.mount.mountPoint.directoryPickerButton=Избор…
|
||||
### Enter Recovery Key
|
||||
### Reset Password
|
||||
### Recovery Key Password Reset Success
|
||||
### Recovery Key Vault Config Reset Success
|
||||
|
||||
# Recover Vault Config File and/or Masterkey
|
||||
##Add Existing Vault without recovery - Dialog
|
||||
|
||||
##Vault Already Exists - Dialog
|
||||
|
||||
##Invalid Selection - Dialog
|
||||
|
||||
## Contact Hub Vault Owner - Dialog
|
||||
|
||||
##Dialog Title
|
||||
|
||||
## OnBoarding
|
||||
|
||||
###Vault Config Missing
|
||||
###Masterkey Missing
|
||||
|
||||
## Expert Settings
|
||||
|
||||
# Convert Vault
|
||||
|
||||
|
||||
@@ -87,6 +87,7 @@
|
||||
### Locked
|
||||
### Unlocked
|
||||
### Missing
|
||||
### Missing Vault Config
|
||||
### Needs Migration
|
||||
### Error
|
||||
|
||||
@@ -105,6 +106,25 @@
|
||||
### Enter Recovery Key
|
||||
### Reset Password
|
||||
### Recovery Key Password Reset Success
|
||||
### Recovery Key Vault Config Reset Success
|
||||
|
||||
# Recover Vault Config File and/or Masterkey
|
||||
##Add Existing Vault without recovery - Dialog
|
||||
|
||||
##Vault Already Exists - Dialog
|
||||
|
||||
##Invalid Selection - Dialog
|
||||
|
||||
## Contact Hub Vault Owner - Dialog
|
||||
|
||||
##Dialog Title
|
||||
|
||||
## OnBoarding
|
||||
|
||||
###Vault Config Missing
|
||||
###Masterkey Missing
|
||||
|
||||
## Expert Settings
|
||||
|
||||
# Convert Vault
|
||||
|
||||
|
||||
@@ -419,6 +419,7 @@ main.vaultDetail.missing.info=Cryptomator kunne ikke finne et hvelv på denne s
|
||||
main.vaultDetail.missing.recheck=Kontroller igjen
|
||||
main.vaultDetail.missing.remove=Fjern fra hvelvlisten…
|
||||
main.vaultDetail.missing.changeLocation=Endre hvelvplassering…
|
||||
### Missing Vault Config
|
||||
### Needs Migration
|
||||
main.vaultDetail.migrateButton=Oppgrader hvelv
|
||||
main.vaultDetail.migratePrompt=Hvelvet ditt må oppgraderes til et nytt format før du kan få tilgang til det
|
||||
@@ -498,6 +499,26 @@ recoveryKey.recover.resetBtn=Nullstill
|
||||
### Recovery Key Password Reset Success
|
||||
recoveryKey.recover.resetSuccess.message=Passordnullstillingen vellykket
|
||||
recoveryKey.recover.resetSuccess.description=Du kan låse opp hvelvet med det nye passordet.
|
||||
### Recovery Key Vault Config Reset Success
|
||||
|
||||
# Recover Vault Config File and/or Masterkey
|
||||
##Add Existing Vault without recovery - Dialog
|
||||
|
||||
##Vault Already Exists - Dialog
|
||||
|
||||
##Invalid Selection - Dialog
|
||||
|
||||
## Contact Hub Vault Owner - Dialog
|
||||
contactHubVaultOwner.title=Hub hvelv
|
||||
|
||||
##Dialog Title
|
||||
|
||||
## OnBoarding
|
||||
|
||||
###Vault Config Missing
|
||||
###Masterkey Missing
|
||||
|
||||
## Expert Settings
|
||||
|
||||
# Convert Vault
|
||||
convertVault.title=Konverter hvelvet
|
||||
|
||||
@@ -96,6 +96,7 @@ addvault.new.readme.accessLocation.4=Voel je vrij om dit bestand te verwijderen.
|
||||
## Existing
|
||||
addvaultwizard.existing.title=Bestaande kluis toevoegen
|
||||
addvaultwizard.existing.instruction=Kies het "vault.cryptomator"-bestand van uw bestaande kluis. Indien er enkel een bestand genaamd "masterkey.cryptomator" anwezig is, kies deze dan in de plaats.
|
||||
addvaultwizard.existing.restore=Herstel…
|
||||
addvaultwizard.existing.chooseBtn=Kies…
|
||||
addvaultwizard.existing.filePickerTitle=Kies kluisbestand
|
||||
addvaultwizard.existing.filePickerMimeDesc=Cryptomator kluis
|
||||
@@ -127,6 +128,7 @@ unlock.unlockBtn=Ontgrendel
|
||||
## Select
|
||||
unlock.chooseMasterkey.message=Masterkey-bestand niet gevonden
|
||||
unlock.chooseMasterkey.description=Kon het sleutelbestand voor deze kluis niet vinden op de gewenste locatie. Kies het sleutelbestand handmatig.
|
||||
unlock.chooseMasterkey.restoreInstead=Herstel inplaats daarvan het hoofdsleutelbestand
|
||||
unlock.chooseMasterkey.filePickerTitle=Selecteer het Masterkey-bestand
|
||||
unlock.chooseMasterkey.filePickerMimeDesc=Cryptomator Masterkey
|
||||
## Success
|
||||
@@ -394,8 +396,9 @@ main.vaultlist.contextMenu.unlockNow=Nu Ontgrendelen
|
||||
main.vaultlist.contextMenu.vaultoptions=Laat kluisinstellingen zien
|
||||
main.vaultlist.contextMenu.reveal=Toon Schijf
|
||||
main.vaultlist.contextMenu.share=Delen…
|
||||
main.vaultlist.addVaultBtn.menuItemNew=Nieuwe Kluis Aanmaken...
|
||||
main.vaultlist.addVaultBtn.menuItemExisting=Open Bestaande Kluis...
|
||||
main.vaultlist.addVaultBtn.menuItemNew=Maak een nieuwe kluis aan…
|
||||
main.vaultlist.addVaultBtn.menuItemExisting=Open bestaande kluis…
|
||||
main.vaultlist.addVaultBtn.menuItemRecover=Herstel bestaande kluis…
|
||||
main.vaultlist.showEventsButton.tooltip=Afspraakweergave openen
|
||||
##Notificaition
|
||||
main.notification.updateAvailable=Update beschikbaar.
|
||||
@@ -433,6 +436,9 @@ main.vaultDetail.missing.info=Cryptomator kon op dit pad geen kluis vinden.
|
||||
main.vaultDetail.missing.recheck=Controleer nog eens
|
||||
main.vaultDetail.missing.remove=Verwijderen van kluislijst…
|
||||
main.vaultDetail.missing.changeLocation=Verander de locatie van de kluis…
|
||||
### Missing Vault Config
|
||||
main.vaultDetail.missingVaultConfig.info=Het configuratiebestand van de kluis ontbreekt.
|
||||
main.vaultDetail.missingVaultConfig.restore=Herstel het configuratiebestand van de kluis
|
||||
### Needs Migration
|
||||
main.vaultDetail.migrateButton=Kluis upgraden
|
||||
main.vaultDetail.migratePrompt=Uw kluis moet worden bijgewerkt naar een nieuw formaat, voordat u deze kunt openen
|
||||
@@ -497,6 +503,7 @@ vaultOptions.hub.convertBtn=Converteren naar Wachtwoord-gebaseerde kluis
|
||||
recoveryKey.display.title=Toon herstelsleutel
|
||||
recoveryKey.create.message=Wachtwoord vereist
|
||||
recoveryKey.create.description=Voer uw wachtwoord in om de herstelsleutel voor "%s" te tonen:
|
||||
recoveryKey.recover.description=Voer het wachtwoord voor "%s" in om de kluis te herstellen.
|
||||
recoveryKey.display.description=De volgende herstelsleutel kan worden gebruikt om "%s" te herstellen:
|
||||
recoveryKey.display.StorageHints=Bewaar het op een veilige plek, bv:\n • Bewaar het in een wachtwoordmanager\n • Sla het op op een USB-stick\n • Print het op papier
|
||||
## Reset Password
|
||||
@@ -509,9 +516,59 @@ recoveryKey.recover.invalidKey=Deze herstelsleutel is niet geldig
|
||||
recoveryKey.printout.heading=Cryptomator herstelsleutel\n"%s"\n
|
||||
### Reset Password
|
||||
recoveryKey.recover.resetBtn=Resetten
|
||||
recoveryKey.recover.recoverBtn=Herstellen
|
||||
### Recovery Key Password Reset Success
|
||||
recoveryKey.recover.resetSuccess.message=Wachtwoord resetten geslaagd
|
||||
recoveryKey.recover.resetSuccess.description=Je kunt je kluis ontgrendelen met het nieuwe wachtwoord.
|
||||
### Recovery Key Vault Config Reset Success
|
||||
recoveryKey.recover.resetVaultConfigSuccess.message=Kluis configuratie hersteld
|
||||
recoveryKey.recover.resetMasterkeyFileSuccess.message=Masterkey-bestand hersteld
|
||||
recoveryKey.recover.resetMasterkeyFileSuccess.description=Je kunt je kluis nu ontgrendelen met je wachtwoord.
|
||||
|
||||
# Recover Vault Config File and/or Masterkey
|
||||
##Add Existing Vault without recovery - Dialog
|
||||
recover.existing.title=Kluis toegevoegd
|
||||
recover.existing.message=De kluis is met succes toegevoegd
|
||||
recover.existing.description=Uw kluis "%s" is toegevoegd aan de lijst van kluizen. Er was geen herstelproces nodig.
|
||||
|
||||
##Vault Already Exists - Dialog
|
||||
recover.alreadyExists.title=Kluis bestaat al
|
||||
recover.alreadyExists.message=Deze kluis is al toegevoegd
|
||||
recover.alreadyExists.description=Je kluis "%s" is al aanwezig in je kluis lijst en is daarom niet meer toegevoegd.
|
||||
|
||||
##Invalid Selection - Dialog
|
||||
recover.invalidSelection.title=Ongeldige selectie
|
||||
recover.invalidSelection.message=Jouw selectie is geen kluis
|
||||
recover.invalidSelection.description=De geselecteerde map moet een geldige Cryptomator kluis zijn.
|
||||
|
||||
## Contact Hub Vault Owner - Dialog
|
||||
contactHubVaultOwner.title=Hub Kluis
|
||||
contactHubVaultOwner.message=Deze kluis is gemaakt met Cryptomator Hub
|
||||
contactHubVaultOwner.description=Neem contact op met de eigenaar van de kluis om het ontbrekende bestand te herstellen. Ze kunnen de kluissjabloon downloaden van Cryptomator Hub.
|
||||
|
||||
##Dialog Title
|
||||
recover.recoverVaultConfig.title=Herstel het configuratiebestand van de kluis
|
||||
recover.recoverMasterkey.title=Masterkey herstellen
|
||||
|
||||
## OnBoarding
|
||||
recover.onBoarding.chooseMethod=Kies een herstelmethode:
|
||||
recover.onBoarding.useRecoveryKey=Herstelsleutel gebruiken
|
||||
recover.onBoarding.usePassword=Wachtwoord gebruiken
|
||||
recover.onBoarding.intro=Zorg ervoor dat je het volgende controleert:
|
||||
recover.onBoarding.pleaseConfirm=Vooraleer verder te gaan, bevestig dat:
|
||||
recover.onBoarding.otherwisePleaseConfirm=Anders bevestig dat:
|
||||
recover.onBoarding.allMissing.intro=Als deze kluis wordt beheerd door Cryptomator Hub, moet de eigenaar van de kluis deze voor je herstellen.
|
||||
recover.onBoarding.intro.ensure=Alle bestanden zijn volledig gesynchroniseerd.
|
||||
recover.onBoarding.affirmation=Ik heb deze vereisten gelezen en begrepen
|
||||
|
||||
###Vault Config Missing
|
||||
recover.onBoarding.intro.recoveryKey=Je beschikt over de herstelsleutel en weet of de geavanceerde instellingen zijn gebruikt.
|
||||
recover.onBoarding.intro.password=Je beschikt over de herstelsleutel en weet of de geavanceerde instellingen zijn gebruikt.
|
||||
###Masterkey Missing
|
||||
recover.onBoarding.intro.masterkey.recoveryKey=Je hebt de kluis herstelsleutel.
|
||||
|
||||
## Expert Settings
|
||||
recover.expertSettings.shorteningThreshold.title=Deze waarde moet overeenkomen met de waarde voor het herstel om de compatibiliteit met eerder versleutelde gegevens te waarborgen.
|
||||
|
||||
# Convert Vault
|
||||
convertVault.title=Kluis converteren
|
||||
|
||||
@@ -202,6 +202,7 @@ main.vaultDetail.throughput.mbps=%.1f MiB/s
|
||||
### Missing
|
||||
main.vaultDetail.missing.info=Cryptomator kunne ikkje finna ein kvelv på denne søkastien.
|
||||
main.vaultDetail.missing.recheck=Kontroller igjen
|
||||
### Missing Vault Config
|
||||
### Needs Migration
|
||||
main.vaultDetail.migrateButton=Oppgrader kvelv
|
||||
main.vaultDetail.migratePrompt=Kvelven din må oppgraderast til eit nytt format før du kan få tilgang til det
|
||||
@@ -254,6 +255,25 @@ recoveryKey.display.StorageHints=Ta vare på han ein veldig sikker stad, t.d. ve
|
||||
recoveryKey.printout.heading=Cryptomator-gjenopprettingsnøkkel\n"%s"\n
|
||||
### Reset Password
|
||||
### Recovery Key Password Reset Success
|
||||
### Recovery Key Vault Config Reset Success
|
||||
|
||||
# Recover Vault Config File and/or Masterkey
|
||||
##Add Existing Vault without recovery - Dialog
|
||||
|
||||
##Vault Already Exists - Dialog
|
||||
|
||||
##Invalid Selection - Dialog
|
||||
|
||||
## Contact Hub Vault Owner - Dialog
|
||||
|
||||
##Dialog Title
|
||||
|
||||
## OnBoarding
|
||||
|
||||
###Vault Config Missing
|
||||
###Masterkey Missing
|
||||
|
||||
## Expert Settings
|
||||
|
||||
# Convert Vault
|
||||
|
||||
|
||||
@@ -87,6 +87,7 @@
|
||||
### Locked
|
||||
### Unlocked
|
||||
### Missing
|
||||
### Missing Vault Config
|
||||
### Needs Migration
|
||||
### Error
|
||||
|
||||
@@ -105,6 +106,25 @@
|
||||
### Enter Recovery Key
|
||||
### Reset Password
|
||||
### Recovery Key Password Reset Success
|
||||
### Recovery Key Vault Config Reset Success
|
||||
|
||||
# Recover Vault Config File and/or Masterkey
|
||||
##Add Existing Vault without recovery - Dialog
|
||||
|
||||
##Vault Already Exists - Dialog
|
||||
|
||||
##Invalid Selection - Dialog
|
||||
|
||||
## Contact Hub Vault Owner - Dialog
|
||||
|
||||
##Dialog Title
|
||||
|
||||
## OnBoarding
|
||||
|
||||
###Vault Config Missing
|
||||
###Masterkey Missing
|
||||
|
||||
## Expert Settings
|
||||
|
||||
# Convert Vault
|
||||
|
||||
|
||||
@@ -329,8 +329,6 @@ main.vaultlist.contextMenu.unlockNow=ਹੁਣੇ ਅਣ-ਲਾਕ ਕਰੋ
|
||||
main.vaultlist.contextMenu.vaultoptions=ਵਾਲਟ ਚੋਣਾਂ ਨੂੰ ਵੇਖਾਓ
|
||||
main.vaultlist.contextMenu.reveal=ਡਰਾਇਵ ਦਿਖਾਓ
|
||||
main.vaultlist.contextMenu.share=…ਸਾਂਝਾ ਕਰੋ
|
||||
main.vaultlist.addVaultBtn.menuItemNew=...ਨਵਾਂ ਵਾਲਟ ਬਣਾਓ
|
||||
main.vaultlist.addVaultBtn.menuItemExisting=...ਮੌਜੂਦਾ ਵਾਲਟ ਨੂੰ ਖੋਲ੍ਹੋ
|
||||
##Notificaition
|
||||
main.notification.updateAvailable=ਅੱਪਡੇਟ ਮੌਜੂਦ ਹੈ।
|
||||
main.notification.support=Cryptomator ਲਈ ਸਹਿਯੋਗ।
|
||||
@@ -362,6 +360,7 @@ main.vaultDetail.missing.info=Cryptomator ਇਸ ਮਾਗਰ ਉੱਤੇ ਵ
|
||||
main.vaultDetail.missing.recheck=ਮੁੜ-ਜਾਂਚੋ
|
||||
main.vaultDetail.missing.remove=ਵਾਲਟ ਸੂਚੀ ਤੋਂ ਹਟਾਓ…
|
||||
main.vaultDetail.missing.changeLocation=ਵਾਲਟ ਟਿਕਾਣੇ ਨੂੰ ਬਦਲੋ…
|
||||
### Missing Vault Config
|
||||
### Needs Migration
|
||||
main.vaultDetail.migrateButton=ਵਾਲਟ ਅੱਪਗਰੇਡ ਕਰੋ
|
||||
main.vaultDetail.migratePrompt=ਤੁਹਾਡੇ ਵਾਲਟ ਨੂੰ ਵਰਤੇ ਜਾਣ ਤੋਂ ਪਹਿਲਾਂ ਨਵੇਂ ਫਾਰਮੈਟ ਲਈ ਅੱਪਗਰੇਡ ਕਰਨ ਦੀ ਲੋੜ ਹੈ
|
||||
@@ -439,6 +438,26 @@ recoveryKey.recover.resetBtn=ਰੀਸੈੱਟ ਕਰੋ
|
||||
### Recovery Key Password Reset Success
|
||||
recoveryKey.recover.resetSuccess.message=ਪਾਸਵਰਡ ਨੂੰ ਕਾਮਯਾਬੀ ਨਾਲ ਮੁੜ-ਸੈੱਟ ਕੀਤਾ ਗਿਆ
|
||||
recoveryKey.recover.resetSuccess.description=ਤੁਸੀਂ ਆਪਣੇ ਵਾਲਟ ਨੂੰ ਨਵੇਂ ਪਾਸਵਰਡ ਨਾਲ ਖੋਲ੍ਹ ਸਕਦੇ ਹੋ
|
||||
### Recovery Key Vault Config Reset Success
|
||||
|
||||
# Recover Vault Config File and/or Masterkey
|
||||
##Add Existing Vault without recovery - Dialog
|
||||
|
||||
##Vault Already Exists - Dialog
|
||||
|
||||
##Invalid Selection - Dialog
|
||||
|
||||
## Contact Hub Vault Owner - Dialog
|
||||
contactHubVaultOwner.title=Hub ਵਾਲਟ
|
||||
|
||||
##Dialog Title
|
||||
|
||||
## OnBoarding
|
||||
|
||||
###Vault Config Missing
|
||||
###Masterkey Missing
|
||||
|
||||
## Expert Settings
|
||||
|
||||
# Convert Vault
|
||||
convertVault.title=ਵਾਲਟ ਨੂੰ ਬਦਲੋ
|
||||
|
||||
@@ -394,8 +394,6 @@ main.vaultlist.contextMenu.unlockNow=Odblokuj teraz
|
||||
main.vaultlist.contextMenu.vaultoptions=Pokaż opcje sejfu
|
||||
main.vaultlist.contextMenu.reveal=Otwórz lokalizację
|
||||
main.vaultlist.contextMenu.share=Udostępnij…
|
||||
main.vaultlist.addVaultBtn.menuItemNew=Utwórz Nowy Sejf...
|
||||
main.vaultlist.addVaultBtn.menuItemExisting=Otwórz Istniejący Sejf...
|
||||
main.vaultlist.showEventsButton.tooltip=Otwórz widok wydarzeń
|
||||
##Notificaition
|
||||
main.notification.updateAvailable=Dostępna aktualizacja.
|
||||
@@ -433,6 +431,7 @@ main.vaultDetail.missing.info=Cryptomator nie mógł znaleźć sejfu w tej lokal
|
||||
main.vaultDetail.missing.recheck=Ponów próbę
|
||||
main.vaultDetail.missing.remove=Usuń z listy sejfów…
|
||||
main.vaultDetail.missing.changeLocation=Zmień lokalizację sejfu…
|
||||
### Missing Vault Config
|
||||
### Needs Migration
|
||||
main.vaultDetail.migrateButton=Aktualizuj sejf
|
||||
main.vaultDetail.migratePrompt=Twój sejf musi zostać zaktualizowany do nowego formatu, zanim będziesz mógł go używać
|
||||
@@ -512,6 +511,26 @@ recoveryKey.recover.resetBtn=Resetuj
|
||||
### Recovery Key Password Reset Success
|
||||
recoveryKey.recover.resetSuccess.message=Hasło zostało zresetowane
|
||||
recoveryKey.recover.resetSuccess.description=Możesz odblokować sejf przy użyciu nowego hasła.
|
||||
### Recovery Key Vault Config Reset Success
|
||||
|
||||
# Recover Vault Config File and/or Masterkey
|
||||
##Add Existing Vault without recovery - Dialog
|
||||
|
||||
##Vault Already Exists - Dialog
|
||||
|
||||
##Invalid Selection - Dialog
|
||||
|
||||
## Contact Hub Vault Owner - Dialog
|
||||
contactHubVaultOwner.title=Hub sejfów
|
||||
|
||||
##Dialog Title
|
||||
|
||||
## OnBoarding
|
||||
|
||||
###Vault Config Missing
|
||||
###Masterkey Missing
|
||||
|
||||
## Expert Settings
|
||||
|
||||
# Convert Vault
|
||||
convertVault.title=Konwertuj sejf
|
||||
|
||||
@@ -96,6 +96,7 @@ addvault.new.readme.accessLocation.4=Sinta-se livre para remover este ficheiro.
|
||||
## Existing
|
||||
addvaultwizard.existing.title=Adicionar cofre existente
|
||||
addvaultwizard.existing.instruction=Escolha o ficheiro "vault.cryptomator" do seu cofre. Se encontrar unicamente o ficheiro "masterkey.cryptomator", selecione-o.
|
||||
addvaultwizard.existing.restore=Restaurar…
|
||||
addvaultwizard.existing.chooseBtn=Escolher…
|
||||
addvaultwizard.existing.filePickerTitle=Selecionar o ficheiro do cofre
|
||||
addvaultwizard.existing.filePickerMimeDesc=Cofre Cryptomator
|
||||
@@ -127,6 +128,7 @@ unlock.unlockBtn=Desbloquear
|
||||
## Select
|
||||
unlock.chooseMasterkey.message=Chave Mestra não encontrada
|
||||
unlock.chooseMasterkey.description=Não foi possível encontrar o ficheiro masterkey no local predefinido para este cofre. Por favor, escolha o ficheiro chave manualmente.
|
||||
unlock.chooseMasterkey.restoreInstead=Restaure o ficheiro da chave mestra
|
||||
unlock.chooseMasterkey.filePickerTitle=Selecionar ficheiro MasterKey
|
||||
unlock.chooseMasterkey.filePickerMimeDesc=Chave Mestra Cryptomator
|
||||
## Success
|
||||
@@ -394,8 +396,9 @@ main.vaultlist.contextMenu.unlockNow=Desbloquear agora
|
||||
main.vaultlist.contextMenu.vaultoptions=Mostrar opções do Cofre
|
||||
main.vaultlist.contextMenu.reveal=Revelar unidade
|
||||
main.vaultlist.contextMenu.share=Partilhar…
|
||||
main.vaultlist.addVaultBtn.menuItemNew=Criar novo cofre...
|
||||
main.vaultlist.addVaultBtn.menuItemExisting=Abrir cofre existente...
|
||||
main.vaultlist.addVaultBtn.menuItemNew=Criar novo cofre…
|
||||
main.vaultlist.addVaultBtn.menuItemExisting=Abrir cofre existente…
|
||||
main.vaultlist.addVaultBtn.menuItemRecover=Recuperar cofre existente…
|
||||
main.vaultlist.showEventsButton.tooltip=Abrir visualização do evento
|
||||
##Notificaition
|
||||
main.notification.updateAvailable=A atualização está disponível.
|
||||
@@ -433,6 +436,9 @@ main.vaultDetail.missing.info=O Cryptomator não conseguiu encontrar um cofre ne
|
||||
main.vaultDetail.missing.recheck=Verificar novamente
|
||||
main.vaultDetail.missing.remove=Remover da Lista de Cofres…
|
||||
main.vaultDetail.missing.changeLocation=Mudar localização do Cofre…
|
||||
### Missing Vault Config
|
||||
main.vaultDetail.missingVaultConfig.info=A configuração do cofre está em falta.
|
||||
main.vaultDetail.missingVaultConfig.restore=Restaurar configuração do cofre
|
||||
### Needs Migration
|
||||
main.vaultDetail.migrateButton=Atualizar Cofre
|
||||
main.vaultDetail.migratePrompt=O cofre precisa de ser atualizado para um novo formato, antes que possa acessá-lo
|
||||
@@ -497,6 +503,7 @@ vaultOptions.hub.convertBtn=Converter para cofre baseado em palavras-passe
|
||||
recoveryKey.display.title=Mostrar chave de recuperação
|
||||
recoveryKey.create.message=Palavra-passe necessária
|
||||
recoveryKey.create.description=Inserir a palavra passe de "%s" para mostrar a chave de recuperação.
|
||||
recoveryKey.recover.description=Introduza a palavra-passe de "%s" para recuperar a configuração do cofre.
|
||||
recoveryKey.display.description=Esta chave de recuperação pode ser usada para restaurar acesso a "%s":
|
||||
recoveryKey.display.StorageHints=Guarde-a num lugar muito seguro, por exemplo:\n • Armazená-la usando um gerenciador de senhas\n • Guarde-a numa ‘pen’ USB\n • Imprima-a em papel
|
||||
## Reset Password
|
||||
@@ -509,9 +516,57 @@ recoveryKey.recover.invalidKey=Esta chave de recupreação não está certa
|
||||
recoveryKey.printout.heading=A chave de recuperação do Cryptomator \n"%s"\n
|
||||
### Reset Password
|
||||
recoveryKey.recover.resetBtn=Repor
|
||||
recoveryKey.recover.recoverBtn=Recuperar
|
||||
### Recovery Key Password Reset Success
|
||||
recoveryKey.recover.resetSuccess.message=Palavra-passe redefinida com sucesso
|
||||
recoveryKey.recover.resetSuccess.description=Você pode desbloquear o seu cofre com a nova senha.
|
||||
### Recovery Key Vault Config Reset Success
|
||||
recoveryKey.recover.resetMasterkeyFileSuccess.description=Agora pode desbloquear o seu cofre com a sua palavra-passe.
|
||||
|
||||
# Recover Vault Config File and/or Masterkey
|
||||
##Add Existing Vault without recovery - Dialog
|
||||
recover.existing.title=Cofre adicionado
|
||||
recover.existing.message=O cofre foi adicionado com sucesso
|
||||
recover.existing.description=O seu cofre "%s" foi adicionado à lista de cofres. Nenhum processo de recuperação foi necessário.
|
||||
|
||||
##Vault Already Exists - Dialog
|
||||
recover.alreadyExists.title=O cofre já existe
|
||||
recover.alreadyExists.message=Este cofre já foi adicionado
|
||||
recover.alreadyExists.description=O seu cofre "%s" já está presente na lista de cofres, por isso, não foi adicionado novamente.
|
||||
|
||||
##Invalid Selection - Dialog
|
||||
recover.invalidSelection.title=Seleção inválida
|
||||
recover.invalidSelection.message=A sua seleção não é um cofre
|
||||
recover.invalidSelection.description=A pasta selecionada precisa ser um cofre válido do Cryptomator.
|
||||
|
||||
## Contact Hub Vault Owner - Dialog
|
||||
contactHubVaultOwner.title=Cofre do Hub
|
||||
contactHubVaultOwner.message=Este cofre foi criado com o Cryptomator Hub
|
||||
contactHubVaultOwner.description=Contacte o proprietário do cofre para restaurar o ficheiro perdido. Pode descarregar o modelo do cofre no Cryptomator Hub.
|
||||
|
||||
##Dialog Title
|
||||
recover.recoverVaultConfig.title=Recuperar configuração do cofre
|
||||
recover.recoverMasterkey.title=Recuperar chave mestra
|
||||
|
||||
## OnBoarding
|
||||
recover.onBoarding.chooseMethod=Escolher método de recuperação:
|
||||
recover.onBoarding.useRecoveryKey=Usar chave de recuperação
|
||||
recover.onBoarding.usePassword=Usar palavra-passe
|
||||
recover.onBoarding.intro=Certifique-se de verificar o seguinte:
|
||||
recover.onBoarding.pleaseConfirm=Antes de prosseguir, por favor confirme que:
|
||||
recover.onBoarding.otherwisePleaseConfirm=Caso contrário, confirme que:
|
||||
recover.onBoarding.allMissing.intro=Se este cofre for gerido pelo Cryptomator Hub, o proprietário do cofre deverá restaurá-lo para si.
|
||||
recover.onBoarding.intro.ensure=Todos os ficheiros estão totalmente sincronizados.
|
||||
recover.onBoarding.affirmation=Li e compreendi estes requisitos
|
||||
|
||||
###Vault Config Missing
|
||||
recover.onBoarding.intro.recoveryKey=Tem a chave de recuperação e sabe se foram utilizadas as definições de especialista.
|
||||
recover.onBoarding.intro.password=Tem a palavra-passe do cofre e sabe se foram usadas configurações de especialista.
|
||||
###Masterkey Missing
|
||||
recover.onBoarding.intro.masterkey.recoveryKey=Você tem a chave de recuperação do cofre.
|
||||
|
||||
## Expert Settings
|
||||
recover.expertSettings.shorteningThreshold.title=Este valor deve corresponder ao utilizado antes da recuperação para garantir a compatibilidade com os dados previamente encriptados.
|
||||
|
||||
# Convert Vault
|
||||
convertVault.title=Converter cofre
|
||||
|
||||
@@ -394,8 +394,6 @@ main.vaultlist.contextMenu.unlockNow=Desbloquear Agora
|
||||
main.vaultlist.contextMenu.vaultoptions=Exibir Opções de Cofre
|
||||
main.vaultlist.contextMenu.reveal=Revelar Volume
|
||||
main.vaultlist.contextMenu.share=Compartilhar…
|
||||
main.vaultlist.addVaultBtn.menuItemNew=Novo Cofre...
|
||||
main.vaultlist.addVaultBtn.menuItemExisting=Abrir Cofre Existente...
|
||||
main.vaultlist.showEventsButton.tooltip=Abrir visualização de evento
|
||||
##Notificaition
|
||||
main.notification.updateAvailable=Atualização disponível.
|
||||
@@ -433,6 +431,7 @@ main.vaultDetail.missing.info=O Cryptomator não encontrou um cofre neste caminh
|
||||
main.vaultDetail.missing.recheck=Verificar novamente
|
||||
main.vaultDetail.missing.remove=Remover da lista de cofres…
|
||||
main.vaultDetail.missing.changeLocation=Alterar Localização do Cofre…
|
||||
### Missing Vault Config
|
||||
### Needs Migration
|
||||
main.vaultDetail.migrateButton=Atualizar Cofre
|
||||
main.vaultDetail.migratePrompt=Seu cofre precisa ser atualizado para um novo formato antes de poder acessá-lo
|
||||
@@ -512,6 +511,26 @@ recoveryKey.recover.resetBtn=Redefinir
|
||||
### Recovery Key Password Reset Success
|
||||
recoveryKey.recover.resetSuccess.message=Senha redefinida com sucesso
|
||||
recoveryKey.recover.resetSuccess.description=Você pode desbloquear o seu cofre com a nova senha.
|
||||
### Recovery Key Vault Config Reset Success
|
||||
|
||||
# Recover Vault Config File and/or Masterkey
|
||||
##Add Existing Vault without recovery - Dialog
|
||||
|
||||
##Vault Already Exists - Dialog
|
||||
|
||||
##Invalid Selection - Dialog
|
||||
|
||||
## Contact Hub Vault Owner - Dialog
|
||||
contactHubVaultOwner.title=Cofre do Hub
|
||||
|
||||
##Dialog Title
|
||||
|
||||
## OnBoarding
|
||||
|
||||
###Vault Config Missing
|
||||
###Masterkey Missing
|
||||
|
||||
## Expert Settings
|
||||
|
||||
# Convert Vault
|
||||
convertVault.title=Converter Cofre
|
||||
|
||||
@@ -390,8 +390,6 @@ main.vaultlist.contextMenu.unlockNow=Deblochează acum
|
||||
main.vaultlist.contextMenu.vaultoptions=Arată opțiunile seifului
|
||||
main.vaultlist.contextMenu.reveal=Dezvăluie unitatea
|
||||
main.vaultlist.contextMenu.share=Distribuie…
|
||||
main.vaultlist.addVaultBtn.menuItemNew=Creare seif nou...
|
||||
main.vaultlist.addVaultBtn.menuItemExisting=Deschide un seif existent...
|
||||
##Notificaition
|
||||
main.notification.updateAvailable=O nouă versiune este valabilă.
|
||||
main.notification.support=Susține Cryptomator.
|
||||
@@ -425,6 +423,7 @@ main.vaultDetail.missing.info=Cryptomator nu a putut găsi un seif pe această c
|
||||
main.vaultDetail.missing.recheck=Verifică din nou
|
||||
main.vaultDetail.missing.remove=Eliminați din lista de seifuri…
|
||||
main.vaultDetail.missing.changeLocation=Schimbați locația seifului…
|
||||
### Missing Vault Config
|
||||
### Needs Migration
|
||||
main.vaultDetail.migrateButton=Îmbunătățește seiful
|
||||
main.vaultDetail.migratePrompt=Înainte de a-l putea accesa, seiful dumneavoastră trebuie actualizat la format nou
|
||||
@@ -504,6 +503,26 @@ recoveryKey.recover.resetBtn=Resetează
|
||||
### Recovery Key Password Reset Success
|
||||
recoveryKey.recover.resetSuccess.message=Parola a fost resetată cu succes
|
||||
recoveryKey.recover.resetSuccess.description=Puteți debloca seiful cu parola noua.
|
||||
### Recovery Key Vault Config Reset Success
|
||||
|
||||
# Recover Vault Config File and/or Masterkey
|
||||
##Add Existing Vault without recovery - Dialog
|
||||
|
||||
##Vault Already Exists - Dialog
|
||||
|
||||
##Invalid Selection - Dialog
|
||||
|
||||
## Contact Hub Vault Owner - Dialog
|
||||
contactHubVaultOwner.title=Seif Hub
|
||||
|
||||
##Dialog Title
|
||||
|
||||
## OnBoarding
|
||||
|
||||
###Vault Config Missing
|
||||
###Masterkey Missing
|
||||
|
||||
## Expert Settings
|
||||
|
||||
# Convert Vault
|
||||
convertVault.title=Transformă seiful
|
||||
|
||||
@@ -96,6 +96,7 @@ addvault.new.readme.accessLocation.4=Этот файл можно удалить
|
||||
## Existing
|
||||
addvaultwizard.existing.title=Добавить имеющееся хранилище
|
||||
addvaultwizard.existing.instruction=Выберите файл "vault.cryptomator" существующего хранилища. Если имеется только файл "masterkey.cryptomator", выберите его.
|
||||
addvaultwizard.existing.restore=Восстановить…
|
||||
addvaultwizard.existing.chooseBtn=Выбрать…
|
||||
addvaultwizard.existing.filePickerTitle=Выберите файл хранилища
|
||||
addvaultwizard.existing.filePickerMimeDesc=Хранилище Cryptomator
|
||||
@@ -127,6 +128,7 @@ unlock.unlockBtn=Разблокировать
|
||||
## Select
|
||||
unlock.chooseMasterkey.message=Файл Masterkey не найден
|
||||
unlock.chooseMasterkey.description=Не удалось найти файл Masterkey для хранилища "%s". Выберите ключевой файл вручную.
|
||||
unlock.chooseMasterkey.restoreInstead=Восстановить файл Masterkey
|
||||
unlock.chooseMasterkey.filePickerTitle=Выберите файл MasterKey
|
||||
unlock.chooseMasterkey.filePickerMimeDesc=Мастер-ключ Cryptomator
|
||||
## Success
|
||||
@@ -394,8 +396,9 @@ main.vaultlist.contextMenu.unlockNow=Разблокировать
|
||||
main.vaultlist.contextMenu.vaultoptions=Параметры хранилища
|
||||
main.vaultlist.contextMenu.reveal=Показать диск
|
||||
main.vaultlist.contextMenu.share=Поделиться…
|
||||
main.vaultlist.addVaultBtn.menuItemNew=Создать хранилище...
|
||||
main.vaultlist.addVaultBtn.menuItemExisting=Открыть имеющееся хранилище...
|
||||
main.vaultlist.addVaultBtn.menuItemNew=Создать хранилище…
|
||||
main.vaultlist.addVaultBtn.menuItemExisting=Открыть имеющееся хранилище…
|
||||
main.vaultlist.addVaultBtn.menuItemRecover=Восстановить имеющееся хранилище…
|
||||
main.vaultlist.showEventsButton.tooltip=Открыть просмотр события
|
||||
##Notificaition
|
||||
main.notification.updateAvailable=Есть обновление.
|
||||
@@ -433,6 +436,9 @@ main.vaultDetail.missing.info=Cryptomator не смог найти хранил
|
||||
main.vaultDetail.missing.recheck=Перепроверить
|
||||
main.vaultDetail.missing.remove=Удалить из списка хранилищ…
|
||||
main.vaultDetail.missing.changeLocation=Изменить расположение хранилища…
|
||||
### Missing Vault Config
|
||||
main.vaultDetail.missingVaultConfig.info=Отсутствует конфигурация хранилища.
|
||||
main.vaultDetail.missingVaultConfig.restore=Восстановить настройки хранилища
|
||||
### Needs Migration
|
||||
main.vaultDetail.migrateButton=Обновить хранилище
|
||||
main.vaultDetail.migratePrompt=Чтобы получить доступ к хранилищу, его нужно преобразовать в новый формат
|
||||
@@ -497,6 +503,7 @@ vaultOptions.hub.convertBtn=Преобразовать в хранилище с
|
||||
recoveryKey.display.title=Показать ключ восстановления
|
||||
recoveryKey.create.message=Требуется пароль
|
||||
recoveryKey.create.description=Введите пароль для "%s", чтобы показать его ключ восстановления.
|
||||
recoveryKey.recover.description=Введите пароль для "%s", чтобы восстановить конфигурацию хранилища.
|
||||
recoveryKey.display.description=Ключ для восстановления доступа к "%s":
|
||||
recoveryKey.display.StorageHints=Храните его в надёжном месте, например:\n • в диспетчере паролей\n • на флеш-накопителе USB\n • распечатанным на бумаге
|
||||
## Reset Password
|
||||
@@ -509,9 +516,57 @@ recoveryKey.recover.invalidKey=Этот ключ восстановления н
|
||||
recoveryKey.printout.heading=Ключ восстановления Cryptomator\n"%s"\n
|
||||
### Reset Password
|
||||
recoveryKey.recover.resetBtn=Сброс
|
||||
recoveryKey.recover.recoverBtn=Восстановить
|
||||
### Recovery Key Password Reset Success
|
||||
recoveryKey.recover.resetSuccess.message=Пароль успешно сброшен
|
||||
recoveryKey.recover.resetSuccess.description=Вы можете разблокировать хранилище новым паролем.
|
||||
### Recovery Key Vault Config Reset Success
|
||||
recoveryKey.recover.resetMasterkeyFileSuccess.description=Теперь вы можете разблокировать хранилище с помощью пароля.
|
||||
|
||||
# Recover Vault Config File and/or Masterkey
|
||||
##Add Existing Vault without recovery - Dialog
|
||||
recover.existing.title=Хранилище добавлено
|
||||
recover.existing.message=Хранилище успешно добавлено
|
||||
recover.existing.description=Хранилище "%s" добавлено в список. Восстановление не потребовалось.
|
||||
|
||||
##Vault Already Exists - Dialog
|
||||
recover.alreadyExists.title=Хранилище уже существует
|
||||
recover.alreadyExists.message=Это хранилище уже добавлено
|
||||
recover.alreadyExists.description=Хранилище "%s" уже есть в списке и поэтому не было добавлено снова.
|
||||
|
||||
##Invalid Selection - Dialog
|
||||
recover.invalidSelection.title=Неверный выбор
|
||||
recover.invalidSelection.message=Выбрано не хранилище
|
||||
recover.invalidSelection.description=Выбранная папка должна быть корректным хранилищем Cryptomator.
|
||||
|
||||
## Contact Hub Vault Owner - Dialog
|
||||
contactHubVaultOwner.title=Хаб-хранилище
|
||||
contactHubVaultOwner.message=Это хранилище было создано с помощью хаба Cryptomator
|
||||
contactHubVaultOwner.description=Свяжитесь с владельцем хранилища для восстановления отсутствующего файла. Шаблон хранилища можно загрузить из хаба Cryptomator.
|
||||
|
||||
##Dialog Title
|
||||
recover.recoverVaultConfig.title=Восстановление конфигурации хранилища
|
||||
recover.recoverMasterkey.title=Восстановить Masterkey
|
||||
|
||||
## OnBoarding
|
||||
recover.onBoarding.chooseMethod=Выберите метод восстановления:
|
||||
recover.onBoarding.useRecoveryKey=Использовать ключ восстановления
|
||||
recover.onBoarding.usePassword=Использовать пароль
|
||||
recover.onBoarding.intro=Проверьте следующее:
|
||||
recover.onBoarding.pleaseConfirm=Прежде чем продолжить, подтвердите, что:
|
||||
recover.onBoarding.otherwisePleaseConfirm=В противном случае подтвердите, что:
|
||||
recover.onBoarding.allMissing.intro=Если это хранилище управляется хабом Cryptomator, владелец хранилища должен восстановить его для вас.
|
||||
recover.onBoarding.intro.ensure=Все файлы полностью синхронизированы.
|
||||
recover.onBoarding.affirmation=Требования прочитаны и понятны
|
||||
|
||||
###Vault Config Missing
|
||||
recover.onBoarding.intro.recoveryKey=У вас есть ключ восстановления и вы знаете, что были использованы экспертные настройки.
|
||||
recover.onBoarding.intro.password=У вас есть пароль хранилища и вы знаете, что были использованы экспертные настройки.
|
||||
###Masterkey Missing
|
||||
recover.onBoarding.intro.masterkey.recoveryKey=У вас есть ключ восстановления хранилища.
|
||||
|
||||
## Expert Settings
|
||||
recover.expertSettings.shorteningThreshold.title=Это значение должно соответствовать значению перед восстановлением, чтобы гарантировать совместимость с ранее зашифрованными данными.
|
||||
|
||||
# Convert Vault
|
||||
convertVault.title=Преобразовать хранилище
|
||||
|
||||
@@ -104,6 +104,7 @@ hub.registerSuccess.unlockBtn=අගුළුහරින්න
|
||||
### Locked
|
||||
### Unlocked
|
||||
### Missing
|
||||
### Missing Vault Config
|
||||
### Needs Migration
|
||||
### Error
|
||||
|
||||
@@ -122,6 +123,25 @@ hub.registerSuccess.unlockBtn=අගුළුහරින්න
|
||||
### Enter Recovery Key
|
||||
### Reset Password
|
||||
### Recovery Key Password Reset Success
|
||||
### Recovery Key Vault Config Reset Success
|
||||
|
||||
# Recover Vault Config File and/or Masterkey
|
||||
##Add Existing Vault without recovery - Dialog
|
||||
|
||||
##Vault Already Exists - Dialog
|
||||
|
||||
##Invalid Selection - Dialog
|
||||
|
||||
## Contact Hub Vault Owner - Dialog
|
||||
|
||||
##Dialog Title
|
||||
|
||||
## OnBoarding
|
||||
|
||||
###Vault Config Missing
|
||||
###Masterkey Missing
|
||||
|
||||
## Expert Settings
|
||||
|
||||
# Convert Vault
|
||||
|
||||
|
||||
@@ -96,6 +96,7 @@ addvault.new.readme.accessLocation.4=Tento súbor môžete kedykoľvek odstráni
|
||||
## Existing
|
||||
addvaultwizard.existing.title=Pridať existujúci trezor
|
||||
addvaultwizard.existing.instruction=Zvoľte "vault.cryptomator" súbor Vášho existujúceho trezora. Ak existuje iba súbor s menom "masterkey.cryptomator", vyberte ho namiesto.
|
||||
addvaultwizard.existing.restore=Obnoviť…
|
||||
addvaultwizard.existing.chooseBtn=Vybrať…
|
||||
addvaultwizard.existing.filePickerTitle=Zvoľte súbor trezora
|
||||
addvaultwizard.existing.filePickerMimeDesc=Trezor Cryptomátora
|
||||
@@ -388,7 +389,6 @@ main.vaultlist.contextMenu.vaultoptions=Ukáž možnosti trezora
|
||||
main.vaultlist.contextMenu.reveal=Odkry disk
|
||||
main.vaultlist.contextMenu.share=Zdieľať…
|
||||
main.vaultlist.addVaultBtn.menuItemNew=Vytvoriť Nový trezor…
|
||||
main.vaultlist.addVaultBtn.menuItemExisting=Otvoriť Existujúci trezor...
|
||||
main.vaultlist.showEventsButton.tooltip=Otvoriť zobrazenie udalosti
|
||||
##Notificaition
|
||||
main.notification.updateAvailable=Aktualizácia je k dispozícii.
|
||||
@@ -426,6 +426,7 @@ main.vaultDetail.missing.info=Cryptomator nevie nájsť trezor na tejto ceste.
|
||||
main.vaultDetail.missing.recheck=Prekontrolovať
|
||||
main.vaultDetail.missing.remove=Odstrániť zo zoznamu trezora…
|
||||
main.vaultDetail.missing.changeLocation=Zmeniť umiestnenie trezora…
|
||||
### Missing Vault Config
|
||||
### Needs Migration
|
||||
main.vaultDetail.migrateButton=Aktualizácia trezora
|
||||
main.vaultDetail.migratePrompt=Váš trezor vyžaduje aktualizáciu na nový formát predtým ako ho použijete
|
||||
@@ -501,9 +502,37 @@ recoveryKey.recover.invalidKey=Toto je neplatný kľúč obnovy
|
||||
recoveryKey.printout.heading=Kľúč obnovy Cryptomator-a\n "%s"\n
|
||||
### Reset Password
|
||||
recoveryKey.recover.resetBtn=Resetovať
|
||||
recoveryKey.recover.recoverBtn=Obnov
|
||||
### Recovery Key Password Reset Success
|
||||
recoveryKey.recover.resetSuccess.message=Heslo úspešne zresetované
|
||||
recoveryKey.recover.resetSuccess.description=Môžte odomknúť trezor s novým heslom.
|
||||
### Recovery Key Vault Config Reset Success
|
||||
recoveryKey.recover.resetVaultConfigSuccess.message=Konfigurácia peňaženky obnovená
|
||||
recoveryKey.recover.resetMasterkeyFileSuccess.message=Hlavný kľuč obnovený
|
||||
recoveryKey.recover.resetMasterkeyFileSuccess.description=Teraz môžte odomknúť Váš trezor s heslom.
|
||||
|
||||
# Recover Vault Config File and/or Masterkey
|
||||
##Add Existing Vault without recovery - Dialog
|
||||
|
||||
##Vault Already Exists - Dialog
|
||||
recover.alreadyExists.title=Trezor už existuje
|
||||
|
||||
##Invalid Selection - Dialog
|
||||
recover.invalidSelection.title=Neplatný výber
|
||||
|
||||
## Contact Hub Vault Owner - Dialog
|
||||
contactHubVaultOwner.title=Hub trezora
|
||||
|
||||
##Dialog Title
|
||||
|
||||
## OnBoarding
|
||||
recover.onBoarding.usePassword=Použite heslo
|
||||
recover.onBoarding.intro.ensure=Všetky súbory sú plne synchronizované.
|
||||
|
||||
###Vault Config Missing
|
||||
###Masterkey Missing
|
||||
|
||||
## Expert Settings
|
||||
|
||||
# Convert Vault
|
||||
convertVault.title=Konvertovať trezor
|
||||
|
||||
@@ -143,6 +143,7 @@ main.vaultDetail.share=Deli…
|
||||
main.vaultDetail.lockBtn=Zakleni
|
||||
main.vaultDetail.locateEncryptedFileBtn=Poišči šifrirano datoteko
|
||||
### Missing
|
||||
### Missing Vault Config
|
||||
### Needs Migration
|
||||
### Error
|
||||
|
||||
@@ -166,6 +167,26 @@ recoveryKey.recover.wrongKey=Ta obnovitveni ključ se ujema z drugim trezorjem
|
||||
recoveryKey.recover.invalidKey=Obnovitveni ključ ni pravilen
|
||||
### Reset Password
|
||||
### Recovery Key Password Reset Success
|
||||
### Recovery Key Vault Config Reset Success
|
||||
|
||||
# Recover Vault Config File and/or Masterkey
|
||||
##Add Existing Vault without recovery - Dialog
|
||||
|
||||
##Vault Already Exists - Dialog
|
||||
|
||||
##Invalid Selection - Dialog
|
||||
|
||||
## Contact Hub Vault Owner - Dialog
|
||||
contactHubVaultOwner.title=Hub trezor
|
||||
|
||||
##Dialog Title
|
||||
|
||||
## OnBoarding
|
||||
|
||||
###Vault Config Missing
|
||||
###Masterkey Missing
|
||||
|
||||
## Expert Settings
|
||||
|
||||
# Convert Vault
|
||||
|
||||
|
||||
@@ -245,6 +245,7 @@ main.vaultDetail.missing.info=Cryptomator није пронашао сеф на
|
||||
main.vaultDetail.missing.recheck=Провери поново
|
||||
main.vaultDetail.missing.remove=Удаљи са листе сефова…
|
||||
main.vaultDetail.missing.changeLocation=Промени локацију сефа…
|
||||
### Missing Vault Config
|
||||
### Needs Migration
|
||||
main.vaultDetail.migrateButton=Nadogradi sef
|
||||
main.vaultDetail.migratePrompt=Да бисте приступили вашем сефу, он мора бити надограђен на нови формат
|
||||
@@ -298,6 +299,25 @@ recoveryKey.recover.correctKey=Ово је исправан резервни к
|
||||
recoveryKey.printout.heading=Cryptomator Резервни Кључ\n"%s"\n
|
||||
### Reset Password
|
||||
### Recovery Key Password Reset Success
|
||||
### Recovery Key Vault Config Reset Success
|
||||
|
||||
# Recover Vault Config File and/or Masterkey
|
||||
##Add Existing Vault without recovery - Dialog
|
||||
|
||||
##Vault Already Exists - Dialog
|
||||
|
||||
##Invalid Selection - Dialog
|
||||
|
||||
## Contact Hub Vault Owner - Dialog
|
||||
|
||||
##Dialog Title
|
||||
|
||||
## OnBoarding
|
||||
|
||||
###Vault Config Missing
|
||||
###Masterkey Missing
|
||||
|
||||
## Expert Settings
|
||||
|
||||
# Convert Vault
|
||||
|
||||
|
||||
@@ -204,6 +204,7 @@ main.vaultDetail.unlockNowBtn=Otključaj sada
|
||||
main.vaultDetail.revealBtn=Otvori disk
|
||||
main.vaultDetail.lockBtn=Zaključaj
|
||||
### Missing
|
||||
### Missing Vault Config
|
||||
### Needs Migration
|
||||
main.vaultDetail.migrateButton=Nadogradi sef
|
||||
### Error
|
||||
@@ -228,6 +229,25 @@ vaultOptions.masterkey.changePasswordBtn=Promena lozinke
|
||||
### Enter Recovery Key
|
||||
### Reset Password
|
||||
### Recovery Key Password Reset Success
|
||||
### Recovery Key Vault Config Reset Success
|
||||
|
||||
# Recover Vault Config File and/or Masterkey
|
||||
##Add Existing Vault without recovery - Dialog
|
||||
|
||||
##Vault Already Exists - Dialog
|
||||
|
||||
##Invalid Selection - Dialog
|
||||
|
||||
## Contact Hub Vault Owner - Dialog
|
||||
|
||||
##Dialog Title
|
||||
|
||||
## OnBoarding
|
||||
|
||||
###Vault Config Missing
|
||||
###Masterkey Missing
|
||||
|
||||
## Expert Settings
|
||||
|
||||
# Convert Vault
|
||||
|
||||
|
||||
@@ -96,6 +96,7 @@ addvault.new.readme.accessLocation.4=Du kan ta bort denna fil.
|
||||
## Existing
|
||||
addvaultwizard.existing.title=Öppna befintligt valv
|
||||
addvaultwizard.existing.instruction=Välj filen "vault.cryptomator" i ditt befintliga valv. Om det endast finns en fil som heter "masterkey.cryptomator", välj den istället.
|
||||
addvaultwizard.existing.restore=Återställ…
|
||||
addvaultwizard.existing.chooseBtn=Välj…
|
||||
addvaultwizard.existing.filePickerTitle=Välj valvfil
|
||||
addvaultwizard.existing.filePickerMimeDesc=Cryptomator valv
|
||||
@@ -127,6 +128,7 @@ unlock.unlockBtn=Lås upp
|
||||
## Select
|
||||
unlock.chooseMasterkey.message=Filen med huvudnyckeln hittades inte
|
||||
unlock.chooseMasterkey.description=Kunde inte hitta Masterkey-filen för detta valv på förväntad plats. Välj filen manuellt.
|
||||
unlock.chooseMasterkey.restoreInstead=Återställ huvudnyckeln istället
|
||||
unlock.chooseMasterkey.filePickerTitle=Välj Masterkey-fil
|
||||
unlock.chooseMasterkey.filePickerMimeDesc=Cryptomator huvudnyckel
|
||||
## Success
|
||||
@@ -394,8 +396,9 @@ main.vaultlist.contextMenu.unlockNow=Lås upp nu
|
||||
main.vaultlist.contextMenu.vaultoptions=Visa inställningar för valv
|
||||
main.vaultlist.contextMenu.reveal=Visa enhet
|
||||
main.vaultlist.contextMenu.share=Dela…
|
||||
main.vaultlist.addVaultBtn.menuItemNew=Skapa nytt valv...
|
||||
main.vaultlist.addVaultBtn.menuItemExisting=Öppna befintligt valv...
|
||||
main.vaultlist.addVaultBtn.menuItemNew=Skapa nytt valv…
|
||||
main.vaultlist.addVaultBtn.menuItemExisting=Öppna befintligt valv…
|
||||
main.vaultlist.addVaultBtn.menuItemRecover=Återställ befintligt valv…
|
||||
main.vaultlist.showEventsButton.tooltip=Öppna händelsevy
|
||||
##Notificaition
|
||||
main.notification.updateAvailable=Uppdatering tillgänglig.
|
||||
@@ -433,6 +436,9 @@ main.vaultDetail.missing.info=Cryptomator kunde inte hitta någt valv i denna s
|
||||
main.vaultDetail.missing.recheck=Kontrollera igen
|
||||
main.vaultDetail.missing.remove=Ta bort från listan…
|
||||
main.vaultDetail.missing.changeLocation=Ändra valvets plats…
|
||||
### Missing Vault Config
|
||||
main.vaultDetail.missingVaultConfig.info=Valvkonfigurationen saknas.
|
||||
main.vaultDetail.missingVaultConfig.restore=Återställ valvkonfiguration
|
||||
### Needs Migration
|
||||
main.vaultDetail.migrateButton=Uppgradera valv
|
||||
main.vaultDetail.migratePrompt=Ditt valv behöver uppgraderas till ett nytt format innan du kan använda det
|
||||
@@ -497,6 +503,7 @@ vaultOptions.hub.convertBtn=Konvertera till Lösenordsbaserat Valv
|
||||
recoveryKey.display.title=Visa återställningsnyckel
|
||||
recoveryKey.create.message=Lösenord krävs
|
||||
recoveryKey.create.description=Ange ditt lösenord för att visa återställningsnyckeln för "%s":
|
||||
recoveryKey.recover.description=Ange lösenordet för "%s" för att återställa valvkonfigurationen.
|
||||
recoveryKey.display.description=Använd denna återställningsnyckel för att återställa åtkomst till "%s":
|
||||
recoveryKey.display.StorageHints=Spara den på en säker plats, t.ex:\n • I en lösenordshanterare\n • På ett USB-minne (förvara säkert) \n • Skriv ut på ett papper (förvara säkert)
|
||||
## Reset Password
|
||||
@@ -509,9 +516,41 @@ recoveryKey.recover.invalidKey=Denna återställningsnyckel är ogiltig
|
||||
recoveryKey.printout.heading=Cryptomator återställningsnyckel\n"%s"\n
|
||||
### Reset Password
|
||||
recoveryKey.recover.resetBtn=Återställ
|
||||
recoveryKey.recover.recoverBtn=Återställ
|
||||
### Recovery Key Password Reset Success
|
||||
recoveryKey.recover.resetSuccess.message=Lösenord återställt
|
||||
recoveryKey.recover.resetSuccess.description=Du kan låsa upp valvet med det nya lösenordet.
|
||||
### Recovery Key Vault Config Reset Success
|
||||
recoveryKey.recover.resetMasterkeyFileSuccess.description=Nu kan du låsa upp valvet med lösenordet.
|
||||
|
||||
# Recover Vault Config File and/or Masterkey
|
||||
##Add Existing Vault without recovery - Dialog
|
||||
recover.existing.title=Valvet tillagt
|
||||
recover.existing.message=Valvet har lagts till
|
||||
recover.existing.description=Ditt valv "%s" har lagts till i valvlistan. Ingen återhämtningsprocess var nödvändig.
|
||||
|
||||
##Vault Already Exists - Dialog
|
||||
recover.alreadyExists.title=Valvet finns redan
|
||||
recover.alreadyExists.message=Detta valv har redan lagts till
|
||||
recover.alreadyExists.description=Ditt valv "%s" finns redan i din valvlista och lades därför inte till igen.
|
||||
|
||||
##Invalid Selection - Dialog
|
||||
recover.invalidSelection.title=Ogiltigt val
|
||||
recover.invalidSelection.message=Ditt val är inte ett valv
|
||||
recover.invalidSelection.description=Den valda mappen måste vara ett giltigt Cryptomatorvalv.
|
||||
|
||||
## Contact Hub Vault Owner - Dialog
|
||||
contactHubVaultOwner.title=Hubb valv
|
||||
contactHubVaultOwner.message=Detta valv skapades med Cryptomator Hub
|
||||
|
||||
##Dialog Title
|
||||
|
||||
## OnBoarding
|
||||
|
||||
###Vault Config Missing
|
||||
###Masterkey Missing
|
||||
|
||||
## Expert Settings
|
||||
|
||||
# Convert Vault
|
||||
convertVault.title=Konvertera valv
|
||||
|
||||
@@ -365,6 +365,7 @@ main.vaultDetail.missing.info=Cryptomator haikuweza kupata kuba katika njia hii.
|
||||
main.vaultDetail.missing.recheck=Kagua upya
|
||||
main.vaultDetail.missing.remove=Ondoa kutoka kwenye Orodha ya Kuba…
|
||||
main.vaultDetail.missing.changeLocation=Badilisha Mahali pa Kuba…
|
||||
### Missing Vault Config
|
||||
### Needs Migration
|
||||
main.vaultDetail.migrateButton=Pandisha daraja Kuba
|
||||
main.vaultDetail.migratePrompt=Kuba yako inahitaji kuboreshwa hadi umbizo jipya, kabla ya kuipata
|
||||
@@ -435,6 +436,25 @@ recoveryKey.recover.resetBtn=Weka upya
|
||||
### Recovery Key Password Reset Success
|
||||
recoveryKey.recover.resetSuccess.message=Kuweka upya nenosiri kumefaulu
|
||||
recoveryKey.recover.resetSuccess.description=Unaweza kufungua chumba chako kwa kutumia neno la siri jipya.
|
||||
### Recovery Key Vault Config Reset Success
|
||||
|
||||
# Recover Vault Config File and/or Masterkey
|
||||
##Add Existing Vault without recovery - Dialog
|
||||
|
||||
##Vault Already Exists - Dialog
|
||||
|
||||
##Invalid Selection - Dialog
|
||||
|
||||
## Contact Hub Vault Owner - Dialog
|
||||
|
||||
##Dialog Title
|
||||
|
||||
## OnBoarding
|
||||
|
||||
###Vault Config Missing
|
||||
###Masterkey Missing
|
||||
|
||||
## Expert Settings
|
||||
|
||||
# Convert Vault
|
||||
|
||||
|
||||
@@ -243,6 +243,7 @@ main.vaultDetail.unlockNowBtn=இப்போது திறக்கவும
|
||||
main.vaultDetail.revealBtn=இயக்ககத்தை வெளிப்படுத்து
|
||||
main.vaultDetail.lockBtn=பூட்டு
|
||||
### Missing
|
||||
### Missing Vault Config
|
||||
### Needs Migration
|
||||
main.vaultDetail.migrateButton=பெட்டகத்தை மேம்படுத்து
|
||||
### Error
|
||||
@@ -280,6 +281,25 @@ vaultOptions.masterkey.changePasswordBtn=கடவுச்சொல்லை
|
||||
### Enter Recovery Key
|
||||
### Reset Password
|
||||
### Recovery Key Password Reset Success
|
||||
### Recovery Key Vault Config Reset Success
|
||||
|
||||
# Recover Vault Config File and/or Masterkey
|
||||
##Add Existing Vault without recovery - Dialog
|
||||
|
||||
##Vault Already Exists - Dialog
|
||||
|
||||
##Invalid Selection - Dialog
|
||||
|
||||
## Contact Hub Vault Owner - Dialog
|
||||
|
||||
##Dialog Title
|
||||
|
||||
## OnBoarding
|
||||
|
||||
###Vault Config Missing
|
||||
###Masterkey Missing
|
||||
|
||||
## Expert Settings
|
||||
|
||||
# Convert Vault
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user