~exprez135/cryptomator-libre

8db889dbf558b8780b87ccfe1fade6bb0e32552e — Sebastian Stenzel 1 year, 7 months ago d107917 + a869fc2 1.5.1
Merge branch 'release/1.5.1'
48 files changed, 739 insertions(+), 199 deletions(-)

A .github/workflows/build.yml
A .idea/jarRepositories.xml
M .idea/misc.xml
D .travis-deploy-release.tmpl.json
D .travis-deploy-snapshot.json
D .travis.yml
M README.md
M main/buildkit/pom.xml
M main/commons/pom.xml
M main/commons/src/main/java/org/cryptomator/common/settings/SettingsProvider.java
M main/commons/src/main/java/org/cryptomator/common/vaults/Vault.java
M main/commons/src/main/java/org/cryptomator/common/vaults/VaultComponent.java
M main/commons/src/main/java/org/cryptomator/common/vaults/VaultListManager.java
M main/commons/src/main/java/org/cryptomator/common/vaults/VaultModule.java
M main/commons/src/test/java/org/cryptomator/common/settings/SettingsJsonAdapterTest.java
M main/keychain/pom.xml
M main/launcher/pom.xml
M main/pom.xml
M main/ui/pom.xml
M main/ui/src/main/java/org/cryptomator/ui/common/ErrorModule.java
M main/ui/src/main/java/org/cryptomator/ui/controls/NiceSecurePasswordField.java
M main/ui/src/main/java/org/cryptomator/ui/mainwindow/MainWindowModule.java
A main/ui/src/main/java/org/cryptomator/ui/mainwindow/VaultDetailUnknownErrorController.java
M main/ui/src/main/java/org/cryptomator/ui/mainwindow/VaultListController.java
M main/ui/src/main/java/org/cryptomator/ui/migration/MigrationRunController.java
M main/ui/src/main/java/org/cryptomator/ui/unlock/UnlockController.java
M main/ui/src/main/resources/fxml/vault_detail.fxml
A main/ui/src/main/resources/fxml/vault_detail_unknownerror.fxml
M main/ui/src/main/resources/fxml/vault_detail_welcome.fxml
M main/ui/src/main/resources/fxml/wrongfilealert.fxml
M main/ui/src/main/resources/i18n/strings.properties
M main/ui/src/main/resources/i18n/strings_ar.properties
A main/ui/src/main/resources/i18n/strings_ca.properties
M main/ui/src/main/resources/i18n/strings_cs.properties
M main/ui/src/main/resources/i18n/strings_de.properties
M main/ui/src/main/resources/i18n/strings_es.properties
M main/ui/src/main/resources/i18n/strings_fr.properties
M main/ui/src/main/resources/i18n/strings_hi.properties
M main/ui/src/main/resources/i18n/strings_ja.properties
M main/ui/src/main/resources/i18n/strings_ko.properties
A main/ui/src/main/resources/i18n/strings_lv.properties
M main/ui/src/main/resources/i18n/strings_nb.properties
M main/ui/src/main/resources/i18n/strings_nn.properties
M main/ui/src/main/resources/i18n/strings_ru.properties
M main/ui/src/main/resources/i18n/strings_sv.properties
M main/ui/src/main/resources/i18n/strings_tr.properties
M main/ui/src/main/resources/i18n/strings_zh.properties
M main/ui/src/main/resources/i18n/strings_zh_TW.properties
A .github/workflows/build.yml => .github/workflows/build.yml +131 -0
@@ 0,0 1,131 @@
name: Build

on:
  [push]

jobs: 
  test:
    name: Run Tests
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - name: Set up JDK 14
        uses: actions/setup-java@v1
        with:
          java-version: 14
      - uses: actions/cache@v1
        with:
          path: ~/.m2/repository
          key: ${{ runner.os }}-maven-${{ github.run_id }}
          restore-keys: |
            ${{ runner.os }}-maven-
      - name: Ensure to use tagged version
        run: mvn versions:set --file main/pom.xml -DnewVersion=${GITHUB_REF##*/} # use shell parameter expansion to strip of 'refs/tags'
        if: startsWith(github.ref, 'refs/tags/')
      - name: Build with Maven
        run: mvn -B install --file main/pom.xml -Pcoverage
      - name: Run Codacy Coverage Reporter
        run: |
          curl -o ~/codacy-coverage-reporter.jar https://repo.maven.apache.org/maven2/com/codacy/codacy-coverage-reporter/7.1.0/codacy-coverage-reporter-7.1.0-assembly.jar
          $JAVA_HOME/bin/java -jar ~/codacy-coverage-reporter.jar report -l Java -r main/commons/target/site/jacoco/jacoco.xml --partial
          $JAVA_HOME/bin/java -jar ~/codacy-coverage-reporter.jar report -l Java -r main/keychain/target/site/jacoco/jacoco.xml --partial
          $JAVA_HOME/bin/java -jar ~/codacy-coverage-reporter.jar report -l Java -r main/ui/target/site/jacoco/jacoco.xml --partial
          $JAVA_HOME/bin/java -jar ~/codacy-coverage-reporter.jar report -l Java -r main/launcher/target/site/jacoco/jacoco.xml --partial
          $JAVA_HOME/bin/java -jar ~/codacy-coverage-reporter.jar final
        env:
          CODACY_PROJECT_TOKEN: ${{ secrets.CODACY_PROJECT_TOKEN }}
          
  assemble-build-kit:
    name: Assemble Build Kit
    runs-on: ubuntu-latest
    needs: test
    steps:
      - uses: actions/checkout@v2
      - name: Set up JDK 14
        uses: actions/setup-java@v1
        with:
          java-version: 14
      - uses: actions/cache@v1
        with:
          path: ~/.m2/repository
          key: ${{ runner.os }}-maven-${{ github.run_id }}
      - name: Ensure to use tagged version
        run: mvn versions:set --file main/pom.xml -DnewVersion=${GITHUB_REF##*/} # use shell parameter expansion to strip of 'refs/tags'
        if: startsWith(github.ref, 'refs/tags/')
      - name: Build with Maven
        run: mvn -B package -DskipTests --file main/pom.xml --resume-from=buildkit -Prelease
      - name: Upload buildkit-linux.zip
        uses: actions/upload-artifact@v1
        with:
          name: buildkit-linux.zip
          path: main/buildkit/target/buildkit-linux.zip
      - name: Upload buildkit-mac.zip
        uses: actions/upload-artifact@v1
        with:
          name: buildkit-mac.zip
          path: main/buildkit/target/buildkit-mac.zip
      - name: Upload buildkit-win.zip
        uses: actions/upload-artifact@v1
        with:
          name: buildkit-win.zip
          path: main/buildkit/target/buildkit-win.zip
          
  github-release:
    name: Draft a Release on GitHub Releases
    runs-on: ubuntu-latest
    needs: assemble-build-kit
    if: startsWith(github.ref, 'refs/tags/')
    steps:
      - name: Download buildkit-linux.zip
        uses: actions/download-artifact@v1
        with:
          name: buildkit-linux.zip
          path: .
      - name: Download buildkit-mac.zip
        uses: actions/download-artifact@v1
        with:
          name: buildkit-mac.zip
          path: .
      - name: Download buildkit-win.zip
        uses: actions/download-artifact@v1
        with:
          name: buildkit-win.zip
          path: .
      - id: create_release
        uses: actions/create-release@v1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          tag_name: ${{ github.ref }}
          release_name: ${{ github.ref }}
          body: |
            TODO
          draft: true
          prerelease: true
      - name: Upload buildkit-linux.zip to GitHub Releases
        uses: actions/upload-release-asset@v1.0.1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          upload_url: ${{ steps.create_release.outputs.upload_url }}
          asset_path: buildkit-linux.zip
          asset_name: buildkit-linux.zip
          asset_content_type: application/zip
      - name: Upload buildkit-mac.zip to GitHub Releases
        uses: actions/upload-release-asset@v1.0.1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          upload_url: ${{ steps.create_release.outputs.upload_url }}
          asset_path: buildkit-mac.zip
          asset_name: buildkit-mac.zip
          asset_content_type: application/zip
      - name: Upload buildkit-win.zip to GitHub Releases
        uses: actions/upload-release-asset@v1.0.1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          upload_url: ${{ steps.create_release.outputs.upload_url }}
          asset_path: buildkit-win.zip
          asset_name: buildkit-win.zip
          asset_content_type: application/zip
\ No newline at end of file

A .idea/jarRepositories.xml => .idea/jarRepositories.xml +30 -0
@@ 0,0 1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
  <component name="RemoteRepositoriesConfiguration">
    <remote-repository>
      <option name="id" value="bintray" />
      <option name="name" value="Bintray JCenter" />
      <option name="url" value="https://jcenter.bintray.com" />
    </remote-repository>
    <remote-repository>
      <option name="id" value="central" />
      <option name="name" value="Maven Central Repository" />
      <option name="url" value="https://repo.maven.apache.org/maven2" />
    </remote-repository>
    <remote-repository>
      <option name="id" value="central" />
      <option name="name" value="Maven Central repository" />
      <option name="url" value="https://repo1.maven.org/maven2" />
    </remote-repository>
    <remote-repository>
      <option name="id" value="jcenter" />
      <option name="name" value="jcenter" />
      <option name="url" value="https://jcenter.bintray.com" />
    </remote-repository>
    <remote-repository>
      <option name="id" value="jboss.community" />
      <option name="name" value="JBoss Community repository" />
      <option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
    </remote-repository>
  </component>
</project>
\ No newline at end of file

M .idea/misc.xml => .idea/misc.xml +1 -1
@@ 8,7 8,7 @@
      </list>
    </option>
  </component>
  <component name="ProjectRootManager" version="2" languageLevel="JDK_11" default="false" project-jdk-name="11" project-jdk-type="JavaSDK">
  <component name="ProjectRootManager" version="2" languageLevel="JDK_14" default="false" project-jdk-name="14" project-jdk-type="JavaSDK">
    <output url="file://$PROJECT_DIR$/out" />
  </component>
</project>
\ No newline at end of file

D .travis-deploy-release.tmpl.json => .travis-deploy-release.tmpl.json +0 -19
@@ 1,19 0,0 @@
{
  "package": {
	"name": "buildkit",
	"repo": "cryptomator",
	"subject": "cryptomator"
  },
  "version": {
	"name": "$TRAVIS_TAG",
	"desc": "Cryptomator version $TRAVIS_TAG",
	"released": "$TODAY",
	"vcs_tag": "$TRAVIS_TAG",
	"gpgSign": true
  },
  "files":
  [
	{"includePattern": "main/buildkit/target/(buildkit-[a-z]+\\.zip)", "uploadPattern": "/$TRAVIS_TAG/$1"}
  ],
  "publish": true
}

D .travis-deploy-snapshot.json => .travis-deploy-snapshot.json +0 -15
@@ 1,15 0,0 @@
{
  "package": {
	"name": "buildkit",
	"repo": "cryptomator",
	"subject": "cryptomator"
  },
  "version": {
	"name": "snapshot"
  },
  "files":
  [
	{"includePattern": "main/buildkit/target/(buildkit-[a-z]+\\.zip)", "uploadPattern": "/snapshot/$1", "matrixParams": {"override": 1}}
  ],
  "publish": true
}

D .travis.yml => .travis.yml +0 -65
@@ 1,65 0,0 @@
dist: bionic
language: java
sudo: false
jdk:
- openjdk11
cache:
  directories:
  - $HOME/.m2
env:
  global:
    - secure: "HftEaabMmWn5GwKFKksUkOcelc3Mn7xazwAEy+4d4gL1+F8VhID/6DCK7nas+afUymWnxTano8Rv4Ci5MWryNkNkTH+FUPWmF3xWezc3hajSyS7RB92IZ8VPetl4Fo8UI1WwM5apDEaugalPxkIf8a7N+lpG5X/Gpumwzo3Be3w=" # BINTRAY_API_KEY
    - secure: "oWFgRTVP6lyTa7qVxlvkpm20MtVc3BtmsNXQJS6bfg2A0o/iCQMNx7OD59BaafCLGRKvCcJVESiC8FlSylVMS7CDSyYu0gg70NUiIuHp4NBM5inFWYCy/PdQsCTzr5uvNG+rMFQpMFRaCV0FrfM3tLondcVkhsHL68l93Xoexx4=" # CODACY_PROJECT_TOKEN
    - secure: "zJxgytA2Ks5Xzv+7kUaUq+EBFNQw9Qec63lcMJVuXVWczjL16nKW1EzzV515ag+OWL46z3lEPForDhufw0VtFnNmaX68jkO0mp01eLrHApc1llN2Y/U8GBXfNNazN4+Kom4H+z/AO+wJr8EsKMMUczCdQ3APgd9uVI0hzXw/Z3M=" # GITHUB_API_KEY
addons:
  apt:
    packages:
    - haveged
install:
# - curl -o $HOME/.m2/settings.xml https://gist.githubusercontent.com/cryptobot/cf5fbd909c4782aaeeeb7c7f4a1a43da/raw/e60ee486e34ee0c79f89f947abe2c83b4290c6bb/settings.xml
- mvn -fmain/pom.xml clean install -DskipTests -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=WARN org.codehaus.mojo:versions-maven-plugin:help dependency:go-offline -Pcoverage,release # "clean install" needed until we can exclude artifacts currently in the reactor, see https://maven.apache.org/plugins/maven-dependency-plugin/go-offline-mojo.html#excludeReactor and https://issues.apache.org/jira/browse/MDEP-568
before_script:
- |
  if [[ -n "$TRAVIS_TAG" ]]; then
    mvn -fmain/pom.xml org.codehaus.mojo:versions-maven-plugin:set -DnewVersion=$TRAVIS_TAG
  else
    mvn -fmain/pom.xml org.codehaus.mojo:versions-maven-plugin:set -DnewVersion=SNAPSHOT-$(echo $TRAVIS_COMMIT | head -c7)
  fi
script:
- mvn --update-snapshots -fmain/pom.xml clean test verify -Pcoverage
after_success:
- curl -o ~/codacy-coverage-reporter.jar https://repo.maven.apache.org/maven2/com/codacy/codacy-coverage-reporter/7.1.0/codacy-coverage-reporter-7.1.0-assembly.jar
- $JAVA_HOME/bin/java -jar ~/codacy-coverage-reporter.jar report -l Java -r main/commons/target/site/jacoco/jacoco.xml --partial
- $JAVA_HOME/bin/java -jar ~/codacy-coverage-reporter.jar report -l Java -r main/keychain/target/site/jacoco/jacoco.xml --partial
- $JAVA_HOME/bin/java -jar ~/codacy-coverage-reporter.jar report -l Java -r main/ui/target/site/jacoco/jacoco.xml --partial
- $JAVA_HOME/bin/java -jar ~/codacy-coverage-reporter.jar report -l Java -r main/launcher/target/site/jacoco/jacoco.xml --partial
- $JAVA_HOME/bin/java -jar ~/codacy-coverage-reporter.jar final
before_deploy:
- mvn -fmain/pom.xml package -Prelease -DskipTests
- export TODAY=`date +'%Y-%m-%d'`; envsubst '$TRAVIS_TAG $TODAY' < .travis-deploy-release.tmpl.json > .travis-deploy-release.json
deploy:
- provider: bintray # SNAPSHOTS
  file: .travis-deploy-snapshot.json
  user: cryptobot
  key: $BINTRAY_API_KEY
  skip_cleanup: true
  on:
    repo: cryptomator/cryptomator
    branch: develop
- provider: bintray # RELEASES
  file: .travis-deploy-release.json
  user: cryptobot
  key: $BINTRAY_API_KEY
  skip_cleanup: true
  on:
    repo: cryptomator/cryptomator
    tags: true
- provider: releases
  api_key: $GITHUB_API_KEY
  file_glob: true
  file:
    - "main/buildkit/target/buildkit-*.zip"
  skip_cleanup: true
  on:
    repo: cryptomator/cryptomator
    tags: true
\ No newline at end of file

M README.md => README.md +5 -1
@@ 15,6 15,10 @@ Cryptomator is provided free of charge as an open-source project despite the hig
- [One-time or recurring donation via Cryptomator's website.](https://cryptomator.org/#donate)
- [Become a sponsor via Cryptomator's sponsors website.](https://cryptomator.org/sponsors/)

### Gold Sponsors

[<img src="https://cryptomator.org/img/sponsors/geewhiz.svg" alt="gee-whiz" height="96">](https://www.gee-whiz.de/)

### Silver Sponsors

[![TheBestVPN](https://cryptomator.org/img/sponsors/thebestvpn.png)](https://thebestvpn.com/)


@@ 55,7 59,7 @@ Download native binaries of Cryptomator on [cryptomator.org](https://cryptomator

### Security Architecture

For more information on the security details visit [cryptomator.org](https://cryptomator.org/architecture/).
For more information on the security details visit [cryptomator.org](https://docs.cryptomator.org/en/latest/security/architecture/).

## Building


M main/buildkit/pom.xml => main/buildkit/pom.xml +1 -1
@@ 4,7 4,7 @@
	<parent>
		<groupId>org.cryptomator</groupId>
		<artifactId>main</artifactId>
		<version>1.5.0</version>
		<version>1.5.1</version>
	</parent>
	<artifactId>buildkit</artifactId>
	<packaging>pom</packaging>

M main/commons/pom.xml => main/commons/pom.xml +1 -1
@@ 4,7 4,7 @@
	<parent>
		<groupId>org.cryptomator</groupId>
		<artifactId>main</artifactId>
		<version>1.5.0</version>
		<version>1.5.1</version>
	</parent>
	<artifactId>commons</artifactId>
	<name>Cryptomator Commons</name>

M main/commons/src/main/java/org/cryptomator/common/settings/SettingsProvider.java => main/commons/src/main/java/org/cryptomator/common/settings/SettingsProvider.java +10 -5
@@ 10,7 10,9 @@ package org.cryptomator.common.settings;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;
import com.google.gson.JsonParser;
import org.cryptomator.common.Environment;
import org.cryptomator.common.LazyInitializer;
import org.slf4j.Logger;


@@ 77,12 79,15 @@ public class SettingsProvider implements Supplier<Settings> {
		LOG.debug("Attempting to load settings from {}", path);
		try (InputStream in = Files.newInputStream(path, StandardOpenOption.READ); //
			 Reader reader = new InputStreamReader(in, StandardCharsets.UTF_8)) {
			Settings settings = gson.fromJson(reader, Settings.class);
			if (settings == null) {
				throw new IOException("Unexpected EOF");
			JsonElement json = JsonParser.parseReader(reader);
			if (json.isJsonObject()) {
				Settings settings = gson.fromJson(json, Settings.class);
				LOG.info("Settings loaded from {}", path);
				return Stream.of(settings);
			} else {
				LOG.warn("Invalid json file {}", path);
				return Stream.empty();
			}
			LOG.info("Settings loaded from {}", path);
			return Stream.of(settings);
		} catch (NoSuchFileException e) {
			return Stream.empty();
		} catch (IOException e) {

M main/commons/src/main/java/org/cryptomator/common/vaults/Vault.java => main/commons/src/main/java/org/cryptomator/common/vaults/Vault.java +26 -1
@@ 27,6 27,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Provider;
import java.io.IOException;
import java.nio.file.NoSuchFileException;


@@ 51,6 52,7 @@ public class Vault {
	private final StringBinding defaultMountFlags;
	private final AtomicReference<CryptoFileSystem> cryptoFileSystem;
	private final ObjectProperty<VaultState> state;
	private final ObjectProperty<Exception> lastKnownException;
	private final VaultStats stats;
	private final StringBinding displayableName;
	private final StringBinding displayablePath;


@@ 59,18 61,20 @@ public class Vault {
	private final BooleanBinding unlocked;
	private final BooleanBinding missing;
	private final BooleanBinding needsMigration;
	private final BooleanBinding unknownError;
	private final StringBinding accessPoint;
	private final BooleanBinding accessPointPresent;

	private volatile Volume volume;

	@Inject
	Vault(VaultSettings vaultSettings, Provider<Volume> volumeProvider, @DefaultMountFlags StringBinding defaultMountFlags, AtomicReference<CryptoFileSystem> cryptoFileSystem, ObjectProperty<VaultState> state, VaultStats stats) {
	Vault(VaultSettings vaultSettings, Provider<Volume> volumeProvider, @DefaultMountFlags StringBinding defaultMountFlags, AtomicReference<CryptoFileSystem> cryptoFileSystem, ObjectProperty<VaultState> state, @Named("lastKnownException") ObjectProperty<Exception> lastKnownException, VaultStats stats) {
		this.vaultSettings = vaultSettings;
		this.volumeProvider = volumeProvider;
		this.defaultMountFlags = defaultMountFlags;
		this.cryptoFileSystem = cryptoFileSystem;
		this.state = state;
		this.lastKnownException = lastKnownException;
		this.stats = stats;
		this.displayableName = Bindings.createStringBinding(this::getDisplayableName, vaultSettings.path());
		this.displayablePath = Bindings.createStringBinding(this::getDisplayablePath, vaultSettings.path());


@@ 79,6 83,7 @@ public class Vault {
		this.unlocked = Bindings.createBooleanBinding(this::isUnlocked, state);
		this.missing = Bindings.createBooleanBinding(this::isMissing, state);
		this.needsMigration = Bindings.createBooleanBinding(this::isNeedsMigration, state);
		this.unknownError = Bindings.createBooleanBinding(this::isUnknownError, state);
		this.accessPoint = Bindings.createStringBinding(this::getAccessPoint, state);
		this.accessPointPresent = this.accessPoint.isNotEmpty();
	}


@@ 149,6 154,18 @@ public class Vault {
		state.setValue(value);
	}

	public ObjectProperty<Exception> lastKnownExceptionProperty() {
		return lastKnownException;
	}

	public Exception getLastKnownException() {
		return lastKnownException.get();
	}

	public void setLastKnownException(Exception e) {
		lastKnownException.setValue(e);
	}

	public BooleanBinding lockedProperty() {
		return locked;
	}


@@ 189,6 206,14 @@ public class Vault {
		return state.get() == VaultState.NEEDS_MIGRATION;
	}

	public BooleanBinding unknownErrorProperty() {
		return unknownError;
	}

	public boolean isUnknownError() {
		return state.get() == VaultState.ERROR;
	}

	public StringBinding displayableNameProperty() {
		return displayableName;
	}

M main/commons/src/main/java/org/cryptomator/common/vaults/VaultComponent.java => main/commons/src/main/java/org/cryptomator/common/vaults/VaultComponent.java +6 -0
@@ 10,6 10,9 @@ import org.cryptomator.common.settings.VaultSettings;

import dagger.Subcomponent;

import javax.annotation.Nullable;
import javax.inject.Named;

@PerVault
@Subcomponent(modules = {VaultModule.class})
public interface VaultComponent {


@@ 25,6 28,9 @@ public interface VaultComponent {
		@BindsInstance
		Builder initialVaultState(VaultState vaultState);

		@BindsInstance
		Builder initialErrorCause(@Nullable @Named("lastKnownException") Exception initialErrorCause);

		VaultComponent build();
	}


M main/commons/src/main/java/org/cryptomator/common/vaults/VaultListManager.java => main/commons/src/main/java/org/cryptomator/common/vaults/VaultListManager.java +25 -18
@@ 14,6 14,8 @@ import org.cryptomator.common.settings.Settings;
import org.cryptomator.common.settings.VaultSettings;
import org.cryptomator.cryptofs.CryptoFileSystemProvider;
import org.cryptomator.cryptofs.migration.Migrators;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.inject.Inject;
import javax.inject.Singleton;


@@ 29,7 31,9 @@ import static org.cryptomator.common.Constants.MASTERKEY_FILENAME;

@Singleton
public class VaultListManager {
	

	private static final Logger LOG = LoggerFactory.getLogger(VaultListManager.class);

	private final VaultComponent.Builder vaultComponentBuilder;
	private final ObservableList<Vault> vaultList;



@@ 37,7 41,7 @@ public class VaultListManager {
	public VaultListManager(VaultComponent.Builder vaultComponentBuilder, Settings settings) {
		this.vaultComponentBuilder = vaultComponentBuilder;
		this.vaultList = FXCollections.observableArrayList(Vault::observables);
		

		addAll(settings.getDirectories());
		vaultList.addListener(new VaultListChangeListener(settings.getDirectories()));
	}


@@ 61,12 65,12 @@ public class VaultListManager {
			return newVault;
		}
	}
	

	private void addAll(Collection<VaultSettings> vaultSettings) {
		Collection<Vault> vaults = vaultSettings.stream().map(this::create).collect(Collectors.toList());
		vaultList.addAll(vaults);
	}
	

	private Optional<Vault> get(Path vaultPath) {
		return vaultList.stream().filter(v -> {
			try {


@@ 78,22 82,25 @@ public class VaultListManager {
	}

	private Vault create(VaultSettings vaultSettings) {
		VaultState vaultState = determineVaultState(vaultSettings.path().get());
		VaultComponent comp = vaultComponentBuilder.vaultSettings(vaultSettings).initialVaultState(vaultState).build();
		return comp.vault();
	}

	public static VaultState determineVaultState(Path pathToVault) {
		VaultComponent.Builder compBuilder = vaultComponentBuilder.vaultSettings(vaultSettings);
		try {
			if (!CryptoFileSystemProvider.containsVault(pathToVault, MASTERKEY_FILENAME)) {
				return VaultState.MISSING;
			} else if (Migrators.get().needsMigration(pathToVault, MASTERKEY_FILENAME)) {
				return VaultState.NEEDS_MIGRATION;
			} else {
				return VaultState.LOCKED;
			}
			VaultState vaultState = determineVaultState(vaultSettings.path().get());
			compBuilder.initialVaultState(vaultState);
		} catch (IOException e) {
			return VaultState.ERROR;
			LOG.warn("Failed to determine vault state for " + vaultSettings.path().get(), e);
			compBuilder.initialVaultState(VaultState.ERROR);
			compBuilder.initialErrorCause(e);
		}
		return compBuilder.build().vault();
	}

	public static VaultState determineVaultState(Path pathToVault) throws IOException {
		if (!CryptoFileSystemProvider.containsVault(pathToVault, MASTERKEY_FILENAME)) {
			return VaultState.MISSING;
		} else if (Migrators.get().needsMigration(pathToVault, MASTERKEY_FILENAME)) {
			return VaultState.NEEDS_MIGRATION;
		} else {
			return VaultState.LOCKED;
		}
	}


M main/commons/src/main/java/org/cryptomator/common/vaults/VaultModule.java => main/commons/src/main/java/org/cryptomator/common/vaults/VaultModule.java +10 -0
@@ 23,6 23,8 @@ import org.cryptomator.cryptofs.CryptoFileSystem;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.Nullable;
import javax.inject.Named;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;


@@ 47,6 49,14 @@ public class VaultModule {
	}

	@Provides
	@Named("lastKnownException")
	@PerVault
	public ObjectProperty<Exception> provideLastKnownException(@Named("lastKnownException") @Nullable Exception initialErrorCause) {
		return new SimpleObjectProperty<>(initialErrorCause);
	}


	@Provides
	public Volume provideVolume(Settings settings, WebDavVolume webDavVolume, FuseVolume fuseVolume, DokanyVolume dokanyVolume) {
		VolumeImpl preferredImpl = settings.preferredVolumeImpl().get();
		if (VolumeImpl.DOKANY == preferredImpl && dokanyVolume.isSupported()) {

M main/commons/src/test/java/org/cryptomator/common/settings/SettingsJsonAdapterTest.java => main/commons/src/test/java/org/cryptomator/common/settings/SettingsJsonAdapterTest.java +14 -0
@@ 7,6 7,8 @@ package org.cryptomator.common.settings;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;

import java.io.IOException;



@@ 34,4 36,16 @@ public class SettingsJsonAdapterTest {
		Assertions.assertEquals(VolumeImpl.FUSE, settings.preferredVolumeImpl().get());
	}

	@ParameterizedTest(name = "fromJson() should throw IOException for input: {0}")
	@ValueSource(strings = {
			"",
			"<html>",
			"{invalidjson}"
	})
	public void testDeserializeMalformed(String input) {
		Assertions.assertThrows(IOException.class, () -> {
			adapter.fromJson(input);
		});
	}

}

M main/keychain/pom.xml => main/keychain/pom.xml +1 -1
@@ 4,7 4,7 @@
	<parent>
		<groupId>org.cryptomator</groupId>
		<artifactId>main</artifactId>
		<version>1.5.0</version>
		<version>1.5.1</version>
	</parent>
	<artifactId>keychain</artifactId>
	<name>System Keychain Access</name>

M main/launcher/pom.xml => main/launcher/pom.xml +1 -1
@@ 4,7 4,7 @@
	<parent>
		<groupId>org.cryptomator</groupId>
		<artifactId>main</artifactId>
		<version>1.5.0</version>
		<version>1.5.1</version>
	</parent>
	<artifactId>launcher</artifactId>
	<name>Cryptomator Launcher</name>

M main/pom.xml => main/pom.xml +3 -3
@@ 3,7 3,7 @@
	<modelVersion>4.0.0</modelVersion>
	<groupId>org.cryptomator</groupId>
	<artifactId>main</artifactId>
	<version>1.5.0</version>
	<version>1.5.1</version>
	<packaging>pom</packaging>
	<name>Cryptomator</name>



@@ 24,7 24,7 @@
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

		<!-- cryptomator dependencies -->
		<cryptomator.cryptofs.version>1.9.5</cryptomator.cryptofs.version>
		<cryptomator.cryptofs.version>1.9.7</cryptomator.cryptofs.version>
		<cryptomator.jni.version>2.2.2</cryptomator.jni.version>
		<cryptomator.fuse.version>1.2.3</cryptomator.fuse.version>
		<cryptomator.dokany.version>1.1.13</cryptomator.dokany.version>


@@ 331,7 331,7 @@
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.8.1</version>
				<configuration>
					<release>11</release>
					<release>14</release>
					<annotationProcessorPaths>
						<path>
							<groupId>com.google.dagger</groupId>

M main/ui/pom.xml => main/ui/pom.xml +1 -1
@@ 4,7 4,7 @@
	<parent>
		<groupId>org.cryptomator</groupId>
		<artifactId>main</artifactId>
		<version>1.5.0</version>
		<version>1.5.1</version>
	</parent>
	<artifactId>ui</artifactId>
	<name>Cryptomator GUI</name>

M main/ui/src/main/java/org/cryptomator/ui/common/ErrorModule.java => main/ui/src/main/java/org/cryptomator/ui/common/ErrorModule.java +2 -1
@@ 21,10 21,11 @@ abstract class ErrorModule {
	static FXMLLoaderFactory provideFxmlLoaderFactory(Map<Class<? extends FxController>, Provider<FxController>> factories, DefaultSceneFactory sceneFactory, ResourceBundle resourceBundle) {
		return new FXMLLoaderFactory(factories, sceneFactory, resourceBundle);
	}
	

	@Provides
	@Named("stackTrace")
	static String provideStackTrace(Throwable cause) {
		// TODO deduplicate VaultDetailUnknownErrorController.java
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		cause.printStackTrace(new PrintStream(baos));
		return baos.toString(StandardCharsets.UTF_8);

M main/ui/src/main/java/org/cryptomator/ui/controls/NiceSecurePasswordField.java => main/ui/src/main/java/org/cryptomator/ui/controls/NiceSecurePasswordField.java +7 -1
@@ 1,5 1,6 @@
package org.cryptomator.ui.controls;

import javafx.beans.Observable;
import javafx.beans.binding.Bindings;
import javafx.beans.property.StringProperty;
import javafx.geometry.Pos;


@@ 55,19 56,24 @@ public class NiceSecurePasswordField extends StackPane {
		passwordField.revealPasswordProperty().bind(revealPasswordButton.selectedProperty());

		getChildren().addAll(passwordField, iconContainer);
		disabledProperty().addListener(this::disabledChanged);
	}

	private FontAwesome5Icon getRevealPasswordGlyph() {
		return revealPasswordButton.isSelected() ? FontAwesome5Icon.EYE_SLASH : FontAwesome5Icon.EYE;
	}

	private void disabledChanged(@SuppressWarnings("unused") Observable observable) {
		revealPasswordButton.setSelected(false);
	}

	/* Passthrough */

	@Override
	public void requestFocus() {
		passwordField.requestFocus();
	}
	

	public String getText() {
		return passwordField.getText();
	}

M main/ui/src/main/java/org/cryptomator/ui/mainwindow/MainWindowModule.java => main/ui/src/main/java/org/cryptomator/ui/mainwindow/MainWindowModule.java +7 -7
@@ 6,13 6,9 @@ import dagger.Provides;
import dagger.multibindings.IntoMap;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyCodeCombination;
import javafx.scene.input.KeyCombination;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import org.cryptomator.ui.addvaultwizard.AddVaultWizardComponent;
import org.cryptomator.ui.common.DefaultSceneFactory;
import org.cryptomator.ui.common.FXMLLoaderFactory;
import org.cryptomator.ui.common.FxController;
import org.cryptomator.ui.common.FxControllerKey;


@@ 87,7 83,7 @@ abstract class MainWindowModule {
	@IntoMap
	@FxControllerKey(VaultDetailController.class)
	abstract FxController bindVaultDetailController(VaultDetailController controller);
	

	@Binds
	@IntoMap
	@FxControllerKey(WelcomeController.class)


@@ 102,7 98,7 @@ abstract class MainWindowModule {
	@IntoMap
	@FxControllerKey(VaultDetailUnlockedController.class)
	abstract FxController bindVaultDetailUnlockedController(VaultDetailUnlockedController controller);
	

	@Binds
	@IntoMap
	@FxControllerKey(VaultDetailMissingVaultController.class)


@@ 115,9 111,13 @@ abstract class MainWindowModule {

	@Binds
	@IntoMap
	@FxControllerKey(VaultDetailUnknownErrorController.class)
	abstract FxController bindVaultDetailUnknownErrorController(VaultDetailUnknownErrorController controller);

	@Binds
	@IntoMap
	@FxControllerKey(VaultListCellController.class)
	abstract FxController bindVaultListCellController(VaultListCellController controller);



}

A main/ui/src/main/java/org/cryptomator/ui/mainwindow/VaultDetailUnknownErrorController.java => main/ui/src/main/java/org/cryptomator/ui/mainwindow/VaultDetailUnknownErrorController.java +40 -0
@@ 0,0 1,40 @@
package org.cryptomator.ui.mainwindow;

import javafx.beans.binding.Binding;
import javafx.beans.property.ObjectProperty;
import org.cryptomator.common.vaults.Vault;
import org.cryptomator.ui.common.FxController;
import org.fxmisc.easybind.EasyBind;

import javax.inject.Inject;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.nio.charset.StandardCharsets;

@MainWindowScoped
public class VaultDetailUnknownErrorController implements FxController {

	private final Binding<String> stackTrace;

	@Inject
	public VaultDetailUnknownErrorController(ObjectProperty<Vault> vault) {
		this.stackTrace = EasyBind.select(vault).selectObject(Vault::lastKnownExceptionProperty).map(this::provideStackTrace).orElse("");
	}

	private String provideStackTrace(Throwable cause) {
		// TODO deduplicate ErrorModule.java
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		cause.printStackTrace(new PrintStream(baos));
		return baos.toString(StandardCharsets.UTF_8);
	}

	/* Getter/Setter */

	public Binding<String> stackTraceProperty() {
		return stackTrace;
	}

	public String getStackTrace() {
		return stackTrace.getValue();
	}
}

M main/ui/src/main/java/org/cryptomator/ui/mainwindow/VaultListController.java => main/ui/src/main/java/org/cryptomator/ui/mainwindow/VaultListController.java +9 -2
@@ 18,6 18,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.inject.Inject;
import java.io.IOException;

@MainWindowScoped
public class VaultListController implements FxController {


@@ 68,8 69,14 @@ public class VaultListController implements FxController {
			case LOCKED:
			case NEEDS_MIGRATION:
			case MISSING:
				VaultState determinedState = VaultListManager.determineVaultState(newValue.getPath());
				newValue.setState(determinedState);
				try {
					VaultState determinedState = VaultListManager.determineVaultState(newValue.getPath());
					newValue.setState(determinedState);
				} catch (IOException e) {
					LOG.warn("Failed to determine vault state for " + newValue.getPath(), e);
					newValue.setState(VaultState.ERROR);
					newValue.setLastKnownException(e);
				}
				break;
			case ERROR:
			case UNLOCKED:

M main/ui/src/main/java/org/cryptomator/ui/migration/MigrationRunController.java => main/ui/src/main/java/org/cryptomator/ui/migration/MigrationRunController.java +3 -0
@@ 99,6 99,7 @@ public class MigrationRunController implements FxController {
		LOG.info("Migrating vault {}", vault.getPath());
		CharSequence password = passwordField.getCharacters();
		vault.setState(VaultState.PROCESSING);
		passwordField.setDisable(true);
		ScheduledFuture<?> progressSyncTask = scheduler.scheduleAtFixedRate(() -> {
			Platform.runLater(() -> {
				migrationProgress.set(volatileMigrationProgress);


@@ 120,6 121,7 @@ public class MigrationRunController implements FxController {
			}
		}).onError(InvalidPassphraseException.class, e -> {
			Animations.createShakeWindowAnimation(window).play();
			passwordField.setDisable(false);
			passwordField.selectAll();
			passwordField.requestFocus();
			vault.setState(VaultState.NEEDS_MIGRATION);


@@ 133,6 135,7 @@ public class MigrationRunController implements FxController {
			vault.setState(VaultState.NEEDS_MIGRATION);
			errorComponent.cause(e).window(window).returnToScene(startScene.get()).build().showErrorScene();
		}).andFinally(() -> {
			passwordField.setDisable(false);
			progressSyncTask.cancel(true);
		}).runOnce(executor);
	}

M main/ui/src/main/java/org/cryptomator/ui/unlock/UnlockController.java => main/ui/src/main/java/org/cryptomator/ui/unlock/UnlockController.java +5 -5
@@ 4,7 4,6 @@ import dagger.Lazy;
import javafx.beans.binding.Bindings;
import javafx.beans.binding.ObjectBinding;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.ReadOnlyBooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.concurrent.Task;


@@ 30,7 29,6 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.inject.Inject;
import javax.inject.Named;
import java.nio.file.DirectoryNotEmptyException;
import java.nio.file.NotDirectoryException;
import java.util.Arrays;


@@ 90,9 88,11 @@ public class UnlockController implements FxController {
	public void unlock() {
		LOG.trace("UnlockController.unlock()");
		CharSequence password = passwordField.getCharacters();
		

		Task<Vault> task = vaultService.createUnlockTask(vault, password);
		passwordField.setDisable(true);
		task.setOnSucceeded(event -> {
			passwordField.setDisable(false);
			if (keychainAccess.isPresent() && savePassword.isSelected()) {
				try {
					keychainAccess.get().storePassphrase(vault.getId(), password);


@@ 105,12 105,12 @@ public class UnlockController implements FxController {
			window.setScene(successScene.get());
		});
		task.setOnFailed(event -> {
			passwordField.setDisable(false);
			if (task.getException() instanceof InvalidPassphraseException) {
				Animations.createShakeWindowAnimation(window).play();
				passwordField.selectAll();
				passwordField.requestFocus();
			} else if (task.getException() instanceof NotDirectoryException
				|| task.getException() instanceof DirectoryNotEmptyException) {
			} else if (task.getException() instanceof NotDirectoryException || task.getException() instanceof DirectoryNotEmptyException) {
				LOG.error("Unlock failed. Mount point not an empty directory: {}", task.getException().getMessage());
				window.setScene(invalidMountPointScene.get());
			} else {

M main/ui/src/main/resources/fxml/vault_detail.fxml => main/ui/src/main/resources/fxml/vault_detail.fxml +1 -0
@@ 52,5 52,6 @@
		<fx:include VBox.vgrow="ALWAYS" source="vault_detail_unlocked.fxml" visible="${controller.vault.unlocked}" managed="${controller.vault.unlocked}"/>
		<fx:include VBox.vgrow="ALWAYS" source="vault_detail_missing.fxml" visible="${controller.vault.missing}" managed="${controller.vault.missing}"/>
		<fx:include VBox.vgrow="ALWAYS" source="vault_detail_needsmigration.fxml" visible="${controller.vault.needsMigration}" managed="${controller.vault.needsMigration}"/>
		<fx:include VBox.vgrow="ALWAYS" source="vault_detail_unknownerror.fxml" visible="${controller.vault.unknownError}" managed="${controller.vault.unknownError}"/>
	</children>
</VBox>

A main/ui/src/main/resources/fxml/vault_detail_unknownerror.fxml => main/ui/src/main/resources/fxml/vault_detail_unknownerror.fxml +15 -0
@@ 0,0 1,15 @@
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TextArea?>
<?import javafx.scene.layout.VBox?>
<VBox xmlns="http://javafx.com/javafx"
	  xmlns:fx="http://javafx.com/fxml"
	  fx:controller="org.cryptomator.ui.mainwindow.VaultDetailUnknownErrorController"
	  alignment="CENTER"
	  spacing="24">
	<children>
		<Label text="%generic.error.title" wrapText="true"/>
		<Label text="%generic.error.instruction" wrapText="true"/>

		<TextArea VBox.vgrow="ALWAYS" text="${controller.stackTrace}" prefRowCount="5" editable="false"/>
	</children>
</VBox>
\ No newline at end of file

M main/ui/src/main/resources/fxml/vault_detail_welcome.fxml => main/ui/src/main/resources/fxml/vault_detail_welcome.fxml +2 -2
@@ 13,8 13,8 @@
		<ImageView VBox.vgrow="ALWAYS" fitHeight="128" preserveRatio="true" smooth="true" cache="true">
			<Image url="/bot.png"/>
		</ImageView>
		
		<TextFlow prefWidth="-Infinity" visible="${controller.noVaultPresent}" managed="${controller.noVaultPresent}">

		<TextFlow styleClass="text-flow" prefWidth="-Infinity" visible="${controller.noVaultPresent}" managed="${controller.noVaultPresent}">
			<Text text="%main.vaultDetail.welcomeOnboarding"/>
			<Text text=" "/>
			<Hyperlink text="docs.cryptomator.org" styleClass="hyperlink-underline" onAction="#visitGettingStartedGuide"/>

M main/ui/src/main/resources/fxml/wrongfilealert.fxml => main/ui/src/main/resources/fxml/wrongfilealert.fxml +1 -1
@@ 49,7 49,7 @@
				<Label text="%wrongFileAlert.instruction.2" wrapText="true"/>
				<Label text="%wrongFileAlert.instruction.3" wrapText="true"/>
			</VBox>
			<TextFlow>
			<TextFlow styleClass="text-flow">
				<Text text="%wrongFileAlert.link"/>
				<Text text=" "/>
				<Hyperlink styleClass="hyperlink-underline" text="docs.cryptomator.org" onAction="#openDocumentation"/>

M main/ui/src/main/resources/i18n/strings.properties => main/ui/src/main/resources/i18n/strings.properties +1 -1
@@ 191,7 191,7 @@ wrongFileAlert.instruction.0=To encrypt files, follow these steps:
wrongFileAlert.instruction.1=1. Unlock your vault.
wrongFileAlert.instruction.2=2. Click on "Reveal" to open the volume in your file manager.
wrongFileAlert.instruction.3=3. Add your files to this volume.
wrongFileAlert.link=For futher assistance, visit
wrongFileAlert.link=For further assistance, visit

# Vault Options
## General

M main/ui/src/main/resources/i18n/strings_ar.properties => main/ui/src/main/resources/i18n/strings_ar.properties +1 -1
@@ 190,7 190,7 @@ wrongFileAlert.instruction.0=لتشفير الملفات، قم باتباع ا
wrongFileAlert.instruction.1=1. فتح المخزن الخاص بك.
wrongFileAlert.instruction.2=2. انقر على "إظهار" لفتح المجلد في مدير الملفات الخاص بك.
wrongFileAlert.instruction.3=3. أضف ملفاتك إلى هذا المجلد.
wrongFileAlert.link=للحصول على مساعدة اضافية، قم بزيارة
wrongFileAlert.link=لمزيد من المساعدة، قم بزيارة

# Vault Options
## General

A main/ui/src/main/resources/i18n/strings_ca.properties => main/ui/src/main/resources/i18n/strings_ca.properties +241 -0
@@ 0,0 1,241 @@
# Locale Specific CSS files such as CJK, RTL,...

# Generics
## Button
generic.button.apply=Aplica
generic.button.back=Enrere
generic.button.cancel=Cancel·la
generic.button.change=Canvia
generic.button.close=Tanca
generic.button.copy=Copia
generic.button.copied=Copiat!
generic.button.done=Fet
generic.button.next=Següent
generic.button.print=Imprimeix
## Error
generic.error.title=S'ha produït un error inesperat
generic.error.instruction=Això no hauria d'haver passat. Si us plau, informeu del text de l'error i inclogueu una descripció de quins passos han dut a aquest error.

# Tray Menu
traymenu.showMainWindow=Mostra
traymenu.showPreferencesWindow=Preferències
traymenu.lockAllVaults=Bloqueja tot
traymenu.quitApplication=Surt
traymenu.vault.unlock=Desbloqueja
traymenu.vault.lock=Bloqueja
traymenu.vault.reveal=Mostra

# Add Vault Wizard
addvaultwizard.title=Afegir una caixa forta
## Welcome
addvaultwizard.welcome.newButton=Crea una caixa forta nova
addvaultwizard.welcome.existingButton=Obri una caixa forta existent
## New
### Name
addvaultwizard.new.nameInstruction=Introduiu el nom de la caixa forta
addvaultwizard.new.namePrompt=Nom de la caixa forta
### Location
addvaultwizard.new.locationInstruction=On deu emmagatzemar Cryptomator els fitxers xifrats de la vostra caixa forta?
addvaultwizard.new.locationLabel=Ubicació de l'emmagatzematge
addvaultwizard.new.locationPrompt=…
addvaultwizard.new.directoryPickerLabel=Ubicació personalitzada
addvaultwizard.new.directoryPickerButton=Trieu…
addvaultwizard.new.directoryPickerTitle=Seleccioneu el directori
addvaultwizard.new.fileAlreadyExists=No es pot crear una caixa forta en aquest camí perquè ja hi ha algun objecte.
addvaultwizard.new.invalidName=El nom de la caixa forta no és vàlid. Si us plau, escribiu un mom de directori amb caràcters estàndard.
### Password
addvaultwizard.new.createVaultBtn=Crea la caixa forta
addvaultwizard.new.generateRecoveryKeyChoice=No podreu accedir a les vostres dades sense la contrasenya. Voleu crear una clau de recuperació en cas perdre la vostra contrasenya?
addvaultwizard.new.generateRecoveryKeyChoice.yes=Sí, si us plau. Val més prevenir que guarir.
addvaultwizard.new.generateRecoveryKeyChoice.no=No, gràcies. No predré la meva contrasenya
### Information
addvault.new.readme.storageLocation.fileName=IMPORTANT.rtf
addvault.new.readme.storageLocation.1=⚠️  FITXERS DE LA CAIXA FORTA  ⚠️
addvault.new.readme.storageLocation.2=Aquesta és la ubicació d'emmagatzematge de la vostra caixa forta.
addvault.new.readme.storageLocation.3=NO
addvault.new.readme.storageLocation.4=•  modifiqueu cap fitxer dins d'aquest directori ni
addvault.new.readme.storageLocation.5=•  enganxeu cap fitxer a xifrar en aquest directori.
addvault.new.readme.storageLocation.6=Si voleu xifrar fitxers i veure el contigut de la caixa forta, feu el següent:
addvault.new.readme.storageLocation.7=1. Afegiu aquesta caixa forta a Cryptomator.
addvault.new.readme.storageLocation.8=2.  Desbloquejeu la caixa forta enCryptomator.
addvault.new.readme.storageLocation.9=3.  Feu click damunt del botó "Mostra" per obrir la ubicació d'accès.
addvault.new.readme.storageLocation.10=Si us cal ajuda, llegiu la documentació: %s
addvault.new.readme.accessLocation.fileName=BENVINGUTS.rtf
addvault.new.readme.accessLocation.1=🔐️  VOLUM XIFRAT  🔐️
addvault.new.readme.accessLocation.2=Aquesta és la ubicació d'accès de la vostra caixa forta.
addvault.new.readme.accessLocation.3=Cryptomator xifra tots els fitxers afegits a aquest volum. Podeu treballar en aquest volum com en qualsevol altra unitat o carpeta. La vista mostra el contingut desxifrat però els fitxers sempre estan xifrats en el vostre disc dur.
addvault.new.readme.accessLocation.4=Pots esborrar aquest fitxer si vols.
## Existing
addvaultwizard.existing.instruction=Seleccioneu el fitxer "masterkey.cryptomator" de la vostra caixa forta.
addvaultwizard.existing.chooseBtn=Trieu…
addvaultwizard.existing.filePickerTitle=Seleccioneu el fitxer Masterkey
## Success
addvaultwizard.success.nextStepsInstructions=S'ha afegit la caixa forta "%s".\nHeu de desbloquejar-la si voleu accedir-hi o afegir nou contingut. També podeu desbloquejar-la en qualsevol altre moment.
addvaultwizard.success.unlockNow=Desbloqueja ara

# Remove Vault
removeVault.title=Elimina la caixa forta
removeVault.information=Cryptomator simplement deixarà de mostrar la caixa forta. Podeu tornar a afegir-la més endavant. Cap fitxer xifrat serà eliminat del disc dur.
removeVault.confirmBtn=Elimina la caixa forta

# Change Password
changepassword.title=Canvia la contrasenya
changepassword.enterOldPassword=Introduïu la contrasenya actual per a "%s"
changepassword.finalConfirmation=Entenc que no podré accedir les meves dades si oblido la meva contrasenya

# Forget Password
forgetPassword.title=He oblidat la contrasenya
forgetPassword.information=Això eliminarà la contrasenya desada d'aquesta caixa forta del vostre clauer.
forgetPassword.confirmBtn=He oblidat la contrasenya

# Unlock
unlock.title=Desbloquejar la caixa forta
unlock.passwordPrompt=Introduïu la contrasenya de "%s":
unlock.savePassword=Recorda la contrasenya
unlock.unlockBtn=Desbloqueja
## Success
unlock.success.message="%s" s'ha desbloquejat correctament! Ja es pot accedir a la caixa forta.
unlock.success.revealBtn=Mostra la caixa forta
## Invalid Mount Point
unlock.error.invalidMountPoint=El punt de muntatge no és un directori buit: %s

# Migration
migration.title=Actualitza la caixa forta
## Start
migration.start.prompt=La vostra caixa forta "%s" ha de ser actualitzada a un format més nou. Abans de continuar, assegureu-vos de que no hi haja cap sincronització pendent que puga afectar a aquesta caixa forta.
migration.start.confirm=Sí, la meua caixa forta està completament sicronitzada
## Run
migration.run.enterPassword=Introduïu la contrasenya per a "%s"
migration.run.startMigrationBtn=Migrar la caixa forta
## Sucess
migration.success.nextStepsInstructions="%s" s'ha migrat correctament.\nJa podeu desbloquejar la vostra caixa forta.
migration.success.unlockNow=Desbloqueja ara
## Missing file system capabilities
migration.error.missingFileSystemCapabilities.title=El sistema de fitxers no és admès
migration.error.missingFileSystemCapabilities.description=La migració no s'ha iniciat perquè la vostra caixa forta es troba en un sistema de fitxers no compatible.
migration.error.missingFileSystemCapabilities.reason.LONG_FILENAMES=El sistema de fitxers no suporta noms de fitxers llargs.
migration.error.missingFileSystemCapabilities.reason.LONG_PATHS=El sistema de fitxers no suporta camins llargs.

# Preferences
preferences.title=Preferències
## General
preferences.general=General
preferences.general.theme=Apariència
preferences.general.unlockThemes=Desbloqueja el tema fosc
preferences.general.startHidden=Amaga la finestra al iniciar Cryptomator
preferences.general.debugLogging=Habilita el registre de depuració
preferences.general.autoStart=Executa Cryptomator en engegar el sistema
preferences.general.interfaceOrientation=Orientació de la interfície
preferences.general.interfaceOrientation.ltr=Esquerra a dreta
preferences.general.interfaceOrientation.rtl=Dreta a esquerra
## Volume
preferences.volume=Unitat virtual
preferences.volume.type=Tipus de volum
preferences.volume.webdav.port=Port WebDAV
preferences.volume.webdav.scheme=Esquema WebDAV
## Updates
preferences.updates=Actualitzacions
preferences.updates.currentVersion=Versió actual: %s
preferences.updates.autoUpdateCheck=Comprova automàticament si hi ha actualitzacions
preferences.updates.checkNowBtn=Comprova-ho ara
preferences.updates.updateAvailable=L'actualització a la versió %s es troba disponible.
## Donation Key
preferences.donationKey=Donacions
preferences.donationKey.registeredFor=Registrat per %s
preferences.donationKey.noDonationKey=No s'ha trobar una clau de donació vàlida. És sembla a una clau de llicència però per gent meravellosa qui utilitza programari lliure. ;-)
preferences.donationKey.getDonationKey=Obtingau una clau de donació
## About
preferences.about=Quant a

# Main Window
main.closeBtn.tooltip=Tanca
main.minimizeBtn.tooltip=Minimitza
main.preferencesBtn.tooltip=Preferències
main.donationKeyMissing.tooltip=Si us plau, considereu fer una donació
## Drag 'n' Drop
main.dropZone.dropVault=Afegeix aquesta caixa forta
main.dropZone.unknownDragboardContent=Si voleu afegir una caixa forta, arrossegueu-la a aquesta finestra
## Vault List
main.vaultlist.emptyList.onboardingInstruction=Feu clic aquí per afegir una caixa forta
main.vaultlist.contextMenu.remove=Elimina la caixa forta
main.vaultlist.addVaultBtn=Afegir una caixa forta
## Vault Detail
### Welcome
main.vaultDetail.welcomeOnboarding=Gràcies per escollir Cryptomator per protegir els vostres fitxers. Si vos cal ajuda, llegiu les nostres guies per donar els Primers passos:
### Locked
main.vaultDetail.lockedStatus=BLOQUEJADA
main.vaultDetail.unlockBtn=Desbloqueja
main.vaultDetail.optionsBtn=Opcions de la caixa forta
### Unlocked
main.vaultDetail.unlockedStatus=DESBLOQUEJADA
main.vaultDetail.accessLocation=Els continguts de la vostra caixa forta són accessibles aquí:
main.vaultDetail.revealBtn=Mostra la unitat
main.vaultDetail.lockBtn=Bloqueja
main.vaultDetail.bytesPerSecondRead=lectura:
main.vaultDetail.bytesPerSecondWritten=escriptura:
main.vaultDetail.throughput.idle=inactiu
main.vaultDetail.throughput.kbps=%.1f kiB/s
main.vaultDetail.throughput.mbps=%.1f MiB/s
### Missing
main.vaultDetail.missing.info=Cryptomator no ha trobat una caixa forta en aquest camí.
### 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

# Wrong File Alert
wrongFileAlert.title=Com xifrar fitxers
wrongFileAlert.header.title=Heu intentat xifrar aquests fitxers?
wrongFileAlert.header.lead=Per aconseguir tal fi, Cryptomator crea un volum en el vostre gestor de fitxers del sistema.
wrongFileAlert.instruction.0=Sigau aquests pasos per xifrar fitxers:
wrongFileAlert.instruction.1=1. Desbloquejeu la caixa forta.
wrongFileAlert.instruction.2=2. Feu clic en "Mostrar" per obrir el volum en el vostre gestor de fitxers.
wrongFileAlert.instruction.3=3. Afegiu fitxers al volum.
wrongFileAlert.link=Per rebre assistència, visiteu

# Vault Options
## General
vaultOptions.general=General
vaultOptions.general.unlockAfterStartup=Desbloqueja la caixa forta al iniciar Cryptomator
## Mount
vaultOptions.mount=Muntatge
vaultOptions.mount.readonly=Només lectura
vaultOptions.mount.driveName=Nom de la unitat
vaultOptions.mount.customMountFlags=Senyaladors de muntatge personalitzats
vaultOptions.mount.winDriveLetterOccupied=ocupat
vaultOptions.mount.mountPoint=Punt de muntatge
vaultOptions.mount.mountPoint.auto=Tria automàticament una ubicació adequada
vaultOptions.mount.mountPoint.driveLetter=Utilitza la lletra de la unitat assignada
vaultOptions.mount.mountPoint.custom=Camí personalitzat
vaultOptions.mount.mountPoint.directoryPickerButton=Trieu…
vaultOptions.mount.mountPoint.directoryPickerTitle=Esculliu un directori buit
## Master Key
vaultOptions.masterkey=Contrasenya
vaultOptions.masterkey.changePasswordBtn=Canvi de contrasenya
vaultOptions.masterkey.recoveryKeyExpanation=La clau de recuperació és l'unic mitjà de restaurar l'accès a la caixa forta en cas de perdre la contrasenya.
vaultOptions.masterkey.showRecoveryKeyBtn=Mostra la clau de recuperació
vaultOptions.masterkey.recoverPasswordBtn=Recupera la contrasenya

# Recovery Key
recoveryKey.title=Clau de recuperació
recoveryKey.enterPassword.prompt=Introduïu la vostra clau per mostrar la clau de recuperació de "%s":
recoveryKey.display.message=Utilitzeu la següent clau de recuperació per restaurar l'accès a "%s":
recoveryKey.display.StorageHints=Conserveu-la en un lloc molt segur. P. ex.:\n • Emmagatzemeu-la utilitzant un gestor de claus\n • Deseu-la en una memòria USB\n • Imprimiu-la en paper
recoveryKey.recover.prompt=Introduïu la vostra clau de recuperació de "%s":
recoveryKey.recover.validKey=La clau de recuperació és vàlida
recoveryKey.printout.heading=Clau de recuperació de Cryptomator\n"%s"\n

# New Password
newPassword.promptText=Introdueix una contrasenya nova
newPassword.reenterPassword=Confirma la nova contrasenya
newPassword.passwordsMatch=Les contrasenyes coincideixen!
newPassword.passwordsDoNotMatch=Les contrasenyes no coincideixen
passwordStrength.messageLabel.tooShort=Cal un mínim de %d caràcters
passwordStrength.messageLabel.0=Molt poc segura
passwordStrength.messageLabel.1=Poc segura
passwordStrength.messageLabel.2=Suficient
passwordStrength.messageLabel.3=Segura
passwordStrength.messageLabel.4=Molt segura

# Quit
quit.prompt=Sortir de l'aplicació? Hi ha voltes debloquejades.
quit.lockAndQuit=Bloqueja i surt

M main/ui/src/main/resources/i18n/strings_cs.properties => main/ui/src/main/resources/i18n/strings_cs.properties +14 -3
@@ 59,6 59,7 @@ addvault.new.readme.storageLocation.6=Pokud chcete zašifrovat soubory a zobrazi
addvault.new.readme.storageLocation.7=1. Přidejte tento trezor do Cryptomator.
addvault.new.readme.storageLocation.8=2. Odemkněte trezor v Cryptomator.
addvault.new.readme.storageLocation.9=3. Otevřete umístění přístupu kliknutím na tlačítko "Reveal".
addvault.new.readme.storageLocation.10=Pokud potřebujete pomoc, navštivte dokumentaci: %s
addvault.new.readme.accessLocation.fileName=VÍTEJ.rtf
addvault.new.readme.accessLocation.1=🔐️  ZAŠIFROVANÁ JEDNOTKA  🔐️
addvault.new.readme.accessLocation.2=Toto je místo přístupu vašeho trezoru.


@@ 80,6 81,7 @@ removeVault.confirmBtn=Odstranit trezor
# Change Password
changepassword.title=Změnit heslo
changepassword.enterOldPassword=Zadejte současné heslo pro "%s"
changepassword.finalConfirmation=Chápu, že pokud zapomenu své heslo, nebudu mít přístup k mým datům

# Forget Password
forgetPassword.title=Zapomenout heslo


@@ 143,6 145,7 @@ preferences.donationKey.registeredFor=Registrováno na: %s
preferences.donationKey.noDonationKey=Nebyl nalezen žádný platný darovací klíč. Je to jako licenční klíč, ale pro úžasné lidi využívající software zadarmo. ;-)
preferences.donationKey.getDonationKey=Získat darovací klíč
## About
preferences.about=O aplikaci

# Main Window
main.closeBtn.tooltip=Zavřít


@@ 153,7 156,7 @@ main.donationKeyMissing.tooltip=Prosím, zvažte darování
main.dropZone.dropVault=Přidat tento trezor
main.dropZone.unknownDragboardContent=Pokud chcete přidat trezor, přetáhněte jej do tohoto okna
## Vault List
main.vaultlist.emptyList.onboardingInstruction=Klikněte sem pro přidání nového trezoru
main.vaultlist.emptyList.onboardingInstruction=Klikněte zde pro přidání nového trezoru
main.vaultlist.contextMenu.remove=Odstranit trezor
main.vaultlist.addVaultBtn=Přidat trezor
## Vault Detail


@@ 180,6 183,14 @@ 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

# Wrong File Alert
wrongFileAlert.title=Jak šifrovat soubory
wrongFileAlert.header.title=Pokusili jste se tyto soubory zašifrovat?
wrongFileAlert.header.lead=Pro tento účel Cryptomator vytvoří jednotku ve vašem systémovém správci souborů.
wrongFileAlert.instruction.0=Pro zašifrování souborů postupujte následovně:
wrongFileAlert.instruction.1=1. Odemkni svůj trezor.
wrongFileAlert.instruction.2=2. Klikněte na "Zobrazit" pro otevření jednotky ve správci souborů.
wrongFileAlert.instruction.3=3. Přidejte své soubory do této jednotky.
wrongFileAlert.link=Pro další informace navštivte

# Vault Options
## General


@@ 190,10 201,10 @@ vaultOptions.mount=Připojení
vaultOptions.mount.readonly=Pouze pro čtení
vaultOptions.mount.driveName=Jméno jednotky
vaultOptions.mount.customMountFlags=Vlastní parametry
vaultOptions.mount.winDriveLetterOccupied=obsazené
vaultOptions.mount.winDriveLetterOccupied=obsazeno
vaultOptions.mount.mountPoint=Přípojný bod
vaultOptions.mount.mountPoint.auto=Automaticky vybrat vhodné místo
vaultOptions.mount.mountPoint.driveLetter=Použít přiřazené písmeno
vaultOptions.mount.mountPoint.driveLetter=Použít zvolenou jednotku
vaultOptions.mount.mountPoint.custom=Vlastní cesta
vaultOptions.mount.mountPoint.directoryPickerButton=Vybrat...
vaultOptions.mount.mountPoint.directoryPickerTitle=Vyberte prázdný adresář

M main/ui/src/main/resources/i18n/strings_de.properties => main/ui/src/main/resources/i18n/strings_de.properties +6 -6
@@ 143,7 143,7 @@ preferences.updates.updateAvailable=Update auf Version %s verfügbar.
preferences.donationKey=Spende
preferences.donationKey.registeredFor=Registriert für %s
preferences.donationKey.noDonationKey=Kein gültiger Spendenschlüssel gefunden. Er ist wie ein Lizenzschlüssel, aber für tolle Leute, die freie Software verwenden. ;-)
preferences.donationKey.getDonationKey=Einen Spendenschlüssel erhalten
preferences.donationKey.getDonationKey=Hol dir einen Spendenschlüssel
## About
preferences.about=Über



@@ 151,7 151,7 @@ preferences.about=Über
main.closeBtn.tooltip=Schließen
main.minimizeBtn.tooltip=Minimieren
main.preferencesBtn.tooltip=Einstellungen
main.donationKeyMissing.tooltip=Bitte denke über eine Spende nach
main.donationKeyMissing.tooltip=Zieh bitte eine Spende in Betracht
## Drag 'n' Drop
main.dropZone.dropVault=Diesen Tresor hinzufügen
main.dropZone.unknownDragboardContent=Wenn Sie einen Tresor hinzufügen möchten, ziehen Sie ihn in dieses Fenster


@@ 161,7 161,7 @@ main.vaultlist.contextMenu.remove=Tresor entfernen
main.vaultlist.addVaultBtn=Tresor hinzufügen
## Vault Detail
### Welcome
main.vaultDetail.welcomeOnboarding=Danke, dass du zum Schützen deiner Dateien Cryptomator gewählt hast. Falls du Hilfe brauchst, schau dir unsere Anleitungen an:
main.vaultDetail.welcomeOnboarding=Danke, dass du zum Schutz deiner Dateien Cryptomator gewählt hast. Falls du Hilfe brauchst, schau dir unsere Anleitungen an:
### Locked
main.vaultDetail.lockedStatus=GESPERRT
main.vaultDetail.unlockBtn=Entsperren


@@ 180,7 180,7 @@ main.vaultDetail.throughput.mbps=%.1f MiB/s
main.vaultDetail.missing.info=Mit diesem Pfad konnte Cryptomator keinen Tresor finden.
### Needs Migration
main.vaultDetail.migrateButton=Tresor aktualisieren
main.vaultDetail.migratePrompt=Dein Tresor muss auf ein neues Format aktualisiert werden, bevor Du auf ihn zugreifen kannst
main.vaultDetail.migratePrompt=Dein Tresor muss auf ein neues Format aktualisiert werden, bevor du auf ihn zugreifen kannst

# Wrong File Alert
wrongFileAlert.title=Verschlüsseln von Dateien


@@ 190,12 190,12 @@ wrongFileAlert.instruction.0=Folge diesen Schritten, um Dateien zu verschlüssel
wrongFileAlert.instruction.1=1. Entsperre deinen Tresor.
wrongFileAlert.instruction.2=2. Klicke auf „Anzeigen“, um das Laufwerk in deinem Dateimanager zu öffnen.
wrongFileAlert.instruction.3=3. Füge deine Dateien diesem Laufwerk hinzu.
wrongFileAlert.link=Für weitere Hilfe besuche
wrongFileAlert.link=Für weitere Unterstützung besuche

# Vault Options
## General
vaultOptions.general=Allgemein
vaultOptions.general.unlockAfterStartup=Tresor beim Starten von Cryptomator entsperren
vaultOptions.general.unlockAfterStartup=Tresor beim Start von Cryptomator entsperren
## Mount
vaultOptions.mount=Laufwerk
vaultOptions.mount.readonly=Schreibgeschützt

M main/ui/src/main/resources/i18n/strings_es.properties => main/ui/src/main/resources/i18n/strings_es.properties +1 -1
@@ 190,7 190,7 @@ wrongFileAlert.instruction.0=Para cifrar archivos, seguir estos pasos:
wrongFileAlert.instruction.1=1. Desbloquear la bóveda.
wrongFileAlert.instruction.2=2. Hacer clic en "Revelar" para abrir el volumen en el administrador de archivos.
wrongFileAlert.instruction.3=3. Añadir los archivos a este volumen.
wrongFileAlert.link=Para más ayuda, visitar
wrongFileAlert.link=Para más ayuda, visite

# Vault Options
## General

M main/ui/src/main/resources/i18n/strings_fr.properties => main/ui/src/main/resources/i18n/strings_fr.properties +1 -1
@@ 190,7 190,7 @@ wrongFileAlert.instruction.0=Pour chiffrer des fichiers, suivez ces étapes :
wrongFileAlert.instruction.1=1. Déverrouillez votre coffre.
wrongFileAlert.instruction.2=2. Cliquez sur "Révéler" pour ouvrir le volume dans votre gestionnaire de fichiers.
wrongFileAlert.instruction.3=3. Ajoutez vos fichiers à ce volume.
wrongFileAlert.link=Pour plus d'assistance, visitez
wrongFileAlert.link=Pour toute aide supplémentaire, visitez

# Vault Options
## General

M main/ui/src/main/resources/i18n/strings_hi.properties => main/ui/src/main/resources/i18n/strings_hi.properties +4 -0
@@ 58,6 58,7 @@ unlock.unlockBtn=अनलॉक करें
## Invalid Mount Point

# Migration
migration.title=वाउल्ट को अपग्रेड करें
## Start
## Run
## Sucess


@@ 65,12 66,14 @@ unlock.unlockBtn=अनलॉक करें

# Preferences
## General
preferences.general=सामान्य
## Volume
## Updates
## Donation Key
## About

# Main Window
main.closeBtn.tooltip=बंद करें
## Drag 'n' Drop
## Vault List
main.vaultlist.addVaultBtn=वाउल्ट डालें


@@ 88,6 91,7 @@ main.vaultDetail.migrateButton=वाउल्ट को अपग्रेड 

# Wrong File Alert
wrongFileAlert.instruction.1=अपना वाउल्ट खोलें।
wrongFileAlert.link=और मदद लिए, यह जाएं

# Vault Options
## General

M main/ui/src/main/resources/i18n/strings_ja.properties => main/ui/src/main/resources/i18n/strings_ja.properties +1 -1
@@ 52,7 52,7 @@ addvaultwizard.new.generateRecoveryKeyChoice.no=いいえ、パスワードを
addvault.new.readme.storageLocation.fileName=IMPORTANT.rtf
addvault.new.readme.storageLocation.1=⚠️ 金庫ファイル ⚠️
addvault.new.readme.storageLocation.2=ここは金庫のストレージ場所です。
addvault.new.readme.storageLocation.3=しないでください:
addvault.new.readme.storageLocation.3=次のことをしないでください:
addvault.new.readme.storageLocation.4=•  このディレクトリ内のファイルを変更
addvault.new.readme.storageLocation.5=•  このディレクトリに暗号化するファイルを張り付け。
addvault.new.readme.storageLocation.6=ファイルを暗号化したり金庫の内容を確認するには、次の方法に従ってください:

M main/ui/src/main/resources/i18n/strings_ko.properties => main/ui/src/main/resources/i18n/strings_ko.properties +3 -0
@@ 81,6 81,7 @@ removeVault.confirmBtn=Vault 제거
# Change Password
changepassword.title=비밀번호 변경
changepassword.enterOldPassword="%s"의 비밀번호를 입력하여 주십시요.
changepassword.finalConfirmation=비밀번호를 잊어버리면, 데이터에 접근할 수 없음을 이해했습니다.

# Forget Password
forgetPassword.title=비밀번호 분실


@@ 183,6 184,8 @@ main.vaultDetail.migratePrompt=Vault에 접근하기 전, 새로운 포멧으로

# Wrong File Alert
wrongFileAlert.title=파일 암호화 방법
wrongFileAlert.header.title=이 파일들을 암호화하려고 하십니까?
wrongFileAlert.header.lead=이 목적을 위해, Cryptomator는 파일 관리자에 볼륨을 제공합니다.
wrongFileAlert.instruction.0=파일을 암호화 하려면, 다음의 3단계를 따르십시요:
wrongFileAlert.instruction.1=1. Vault의 잠금해제
wrongFileAlert.instruction.2=2. 파일 관리자에서 열람된 볼륨의 "표시" 버튼 클릭

A main/ui/src/main/resources/i18n/strings_lv.properties => main/ui/src/main/resources/i18n/strings_lv.properties +63 -0
@@ 0,0 1,63 @@
# Locale Specific CSS files such as CJK, RTL,...

# Generics
## Button
## Error

# Tray Menu

# Add Vault Wizard
## Welcome
## New
### Name
### Location
### Password
### Information
## Existing
## Success

# Remove Vault

# Change Password

# Forget Password

# Unlock
## Success
## Invalid Mount Point

# Migration
## Start
## Run
## Sucess
## Missing file system capabilities

# Preferences
## General
## Volume
## Updates
## Donation Key
## About

# Main Window
## Drag 'n' Drop
## Vault List
## Vault Detail
### Welcome
### Locked
### Unlocked
### Missing
### Needs Migration

# Wrong File Alert

# Vault Options
## General
## Mount
## Master Key

# Recovery Key

# New Password

# Quit

M main/ui/src/main/resources/i18n/strings_nb.properties => main/ui/src/main/resources/i18n/strings_nb.properties +3 -3
@@ 28,11 28,11 @@ traymenu.vault.reveal=Gjør synlig
# Add Vault Wizard
addvaultwizard.title=Legg til hvelv
## Welcome
addvaultwizard.welcome.newButton=Lag nytt hvelv
addvaultwizard.welcome.existingButton=Åpne eksisterende hvelv
addvaultwizard.welcome.newButton=Lag et nytt hvelv
addvaultwizard.welcome.existingButton=Åpne et eksisterende hvelv
## New
### Name
addvaultwizard.new.nameInstruction=Velg et navn for hvelvet
addvaultwizard.new.nameInstruction=Velg et navn på hvelvet
addvaultwizard.new.namePrompt=Navn på hvelvet
### Location
addvaultwizard.new.locationInstruction=Hvor skal Cryptomator lagre de krypterte filene dine?

M main/ui/src/main/resources/i18n/strings_nn.properties => main/ui/src/main/resources/i18n/strings_nn.properties +3 -3
@@ 28,11 28,11 @@ traymenu.vault.reveal=Gjer synleg
# Add Vault Wizard
addvaultwizard.title=Legg til kvelv
## Welcome
addvaultwizard.welcome.newButton=Opprett ny kvelv
addvaultwizard.welcome.existingButton=Opne eksisterande kvelv
addvaultwizard.welcome.newButton=Opprett ein ny kvelv
addvaultwizard.welcome.existingButton=Opn ein eksisterande kvelv
## New
### Name
addvaultwizard.new.nameInstruction=Vel eit namn for kvelven
addvaultwizard.new.nameInstruction=Vel eit namn på kvelven
addvaultwizard.new.namePrompt=Namn på kvelven
### Location
addvaultwizard.new.locationInstruction=Kvar skal Cryptomator lagra dei krypterte filene i kvelven din?

M main/ui/src/main/resources/i18n/strings_ru.properties => main/ui/src/main/resources/i18n/strings_ru.properties +19 -19
@@ 7,14 7,14 @@ generic.button.back=Назад
generic.button.cancel=Отмена
generic.button.change=Изменить
generic.button.close=Закрыть
generic.button.copy=Копировать
generic.button.copy=Скопировать
generic.button.copied=Скопировано!
generic.button.done=Готово
generic.button.next=Далее
generic.button.print=Распечатать
## Error
generic.error.title=Произошла непредвиденная ошибка
generic.error.instruction=Этого не должно было произойти. Пожалуйста, создайте отчет об ошибке ниже и опишите, какие шаги к ней привели.
generic.error.instruction=Этого не должно было произойти. Создайте отчёт об ошибке ниже и опишите, какие шаги к ней привели.

# Tray Menu
traymenu.showMainWindow=Показать


@@ 38,7 38,7 @@ addvaultwizard.new.namePrompt=Имя хранилища
addvaultwizard.new.locationInstruction=Где Cryptomator должен хранить зашифрованные файлы вашего хранилища?
addvaultwizard.new.locationLabel=Место хранения
addvaultwizard.new.locationPrompt=…
addvaultwizard.new.directoryPickerLabel=Пользовательское расположение
addvaultwizard.new.directoryPickerLabel=Своё расположение
addvaultwizard.new.directoryPickerButton=Выбрать…
addvaultwizard.new.directoryPickerTitle=Выберите каталог
addvaultwizard.new.fileAlreadyExists=Хранилище не может быть создано по этому пути, потому что некоторые объекты уже существуют.


@@ 46,7 46,7 @@ addvaultwizard.new.invalidName=Неверное имя хранилища. Ук
### Password
addvaultwizard.new.createVaultBtn=Создать хранилище
addvaultwizard.new.generateRecoveryKeyChoice=Вы не сможете получить доступ к своим данным без пароля. Хотите создать ключ для восстановления на случай потери пароля?
addvaultwizard.new.generateRecoveryKeyChoice.yes=Да, пожалуй, лучше так, чем потом сожалеть
addvaultwizard.new.generateRecoveryKeyChoice.yes=Да, лучше предостеречься, чем потом жалеть
addvaultwizard.new.generateRecoveryKeyChoice.no=Нет, спасибо, я не потеряю свой пароль
### Information
addvault.new.readme.storageLocation.fileName=ВАЖНО.rtf


@@ 55,7 55,7 @@ addvault.new.readme.storageLocation.2=Это место, где находитс
addvault.new.readme.storageLocation.3=НЕТ
addvault.new.readme.storageLocation.4=• изменяйте любые файлы в этой папке или
addvault.new.readme.storageLocation.5=• добавляйте в эту папку любые файлы для шифрования.
addvault.new.readme.storageLocation.6=Если вы хотите зашифровать файлы и просмотреть содержимое хранилища, сделайте следующее:
addvault.new.readme.storageLocation.6=Чтобы зашифровать файлы и просмотреть содержимое хранилища, сделайте следующее:
addvault.new.readme.storageLocation.7=1. Добавьте это хранилище в Cryptomator.
addvault.new.readme.storageLocation.8=2. Разблокируйте хранилище в Cryptomator.
addvault.new.readme.storageLocation.9=3. Откройте место доступа, нажав кнопку "Показать".


@@ 63,7 63,7 @@ addvault.new.readme.storageLocation.10=Если вам нужна помощь, 
addvault.new.readme.accessLocation.fileName=ПРИВЕТСТВИЕ.rtf
addvault.new.readme.accessLocation.1=🔐️  ЗАШИФРОВАННЫЙ ТОМ  🔐️
addvault.new.readme.accessLocation.2=Это место доступа к вашему хранилищу.
addvault.new.readme.accessLocation.3=Любые файлы, добавленные в этот том, будут зашифрованы Cryptomator. Вы можете работать с ним, как с любым другим диском/папкой. Здесь отображается только расшифрованное содержимое тома, ваши файлы остаются зашифрованными на жестком диске постоянно.
addvault.new.readme.accessLocation.3=Любые файлы, добавленные в этот том, будут зашифрованы Cryptomator. Вы можете работать с ним как с любым другим диском/папкой. Здесь отображается только расшифрованное содержимое тома, ваши файлы остаются зашифрованными на жёстком диске постоянно.
addvault.new.readme.accessLocation.4=Этот файл можно удалить.
## Existing
addvaultwizard.existing.instruction=Выберите файл "masterkey.cryptomator" из имеющегося хранилища.


@@ 85,7 85,7 @@ changepassword.finalConfirmation=Я понимаю, что не смогу по

# Forget Password
forgetPassword.title=Не помню пароль
forgetPassword.information=Это удалит сохраненный пароль от этого хранилища из вашего хранилища ключей.
forgetPassword.information=Сохранённый пароль от этого хранилища будет удалён из вашей связки ключей.
forgetPassword.confirmBtn=Не помню пароль

# Unlock


@@ 102,8 102,8 @@ unlock.error.invalidMountPoint=Точка монтирования - не пус
# Migration
migration.title=Обновить хранилище
## Start
migration.start.prompt=Хранилище "%s" нужно обновить до более нового формата. Прежде чем продолжить, убедитесь, что нет отложенной синхронизации, которая может повлиять на хранилище.
migration.start.confirm=Да, мое хранилище полностью синхронизировано
migration.start.prompt=Хранилище "%s" нужно преобразовать в более новый формат. Прежде чем продолжить, убедитесь, что нет отложенной синхронизации, которая может повлиять на хранилище.
migration.start.confirm=Да, моё хранилище полностью синхронизировано
## Run
migration.run.enterPassword=Введите пароль для "%s"
migration.run.startMigrationBtn=Перенести хранилище


@@ 125,7 125,7 @@ preferences.general.unlockThemes=Разблокировать тёмный ре
preferences.general.startHidden=Скрывать окно при запуске Cryptomator
preferences.general.debugLogging=Вести журнал отладки
preferences.general.autoStart=Запускать Cryptomator при старте системы
preferences.general.interfaceOrientation=Ориентация интерфейса
preferences.general.interfaceOrientation=Интерфейс
preferences.general.interfaceOrientation.ltr=Слева направо
preferences.general.interfaceOrientation.rtl=Справа налево
## Volume


@@ 151,7 151,7 @@ preferences.about=О программе
main.closeBtn.tooltip=Закрыть
main.minimizeBtn.tooltip=Свернуть
main.preferencesBtn.tooltip=Настройки
main.donationKeyMissing.tooltip=Пожалуйста, обдумайте возможность поддержать приложение
main.donationKeyMissing.tooltip=Мы будем рады финансовой помощи
## Drag 'n' Drop
main.dropZone.dropVault=Добавить это хранилище
main.dropZone.unknownDragboardContent=Если вы хотите добавить хранилище, перетащите его в это окно


@@ 161,7 161,7 @@ main.vaultlist.contextMenu.remove=Удалить хранилище
main.vaultlist.addVaultBtn=Добавить хранилище
## Vault Detail
### Welcome
main.vaultDetail.welcomeOnboarding=Спасибо, что выбрали Cryptomator для защиты ваших файлов. Если вам нужна помощь, ознакомьтесь с нашими руководствами по началу работы:
main.vaultDetail.welcomeOnboarding=Благодарим за выбор Cryptomator для защиты ваших файлов. Если требуется помощь, ознакомьтесь с документацией по началу работы:
### Locked
main.vaultDetail.lockedStatus=ЗАБЛОКИРОВАНО
main.vaultDetail.unlockBtn=Разблокировать


@@ 180,15 180,15 @@ main.vaultDetail.throughput.mbps=%.1f МиБ/с
main.vaultDetail.missing.info=Cryptomator не смог найти хранилище по этому пути.
### Needs Migration
main.vaultDetail.migrateButton=Обновить хранилище
main.vaultDetail.migratePrompt=Хранилище должно быть обновлено до нового формата, прежде чем вы сможете получить к нему доступ
main.vaultDetail.migratePrompt=Чтобы получить доступ к хранилищу, его нужно преобразовать в новый формат

# Wrong File Alert
wrongFileAlert.title=Как шифровать файлы
wrongFileAlert.header.title=Вы пытались зашифровать эти файлы?
wrongFileAlert.header.lead=Для этого Cryptomator создает том в системном файловом менеджере.
wrongFileAlert.instruction.0=Чтобы зашифровать файлы, выполните следующие действия:
wrongFileAlert.header.lead=Для этого Cryptomator создаёт том в системном диспетчере файлов.
wrongFileAlert.instruction.0=Чтобы зашифровать файлы, выполните следующее:
wrongFileAlert.instruction.1=1. Разблокируйте хранилище.
wrongFileAlert.instruction.2=2. Нажмите кнопку " Показать", чтобы открыть том в файловом менеджере.
wrongFileAlert.instruction.2=2. Нажмите кнопку "Показать", чтобы открыть том в диспетчере файлов.
wrongFileAlert.instruction.3=3. Добавьте файлы в этот том.
wrongFileAlert.link=Если нужна помощь, посетите



@@ 205,13 205,13 @@ vaultOptions.mount.winDriveLetterOccupied=занято
vaultOptions.mount.mountPoint=Точка монтирования
vaultOptions.mount.mountPoint.auto=Автоматически выбирать подходящую
vaultOptions.mount.mountPoint.driveLetter=Использовать назначенную букву диска
vaultOptions.mount.mountPoint.custom=Пользовательский путь
vaultOptions.mount.mountPoint.custom=Свой путь
vaultOptions.mount.mountPoint.directoryPickerButton=Выбрать…
vaultOptions.mount.mountPoint.directoryPickerTitle=Выберите пустую папку
## Master Key
vaultOptions.masterkey=Пароль
vaultOptions.masterkey.changePasswordBtn=Изменить пароль
vaultOptions.masterkey.recoveryKeyExpanation=Ключ восстановления - это единственный способ восстановить доступ к хранилищу в случае утери пароля.
vaultOptions.masterkey.recoveryKeyExpanation=Ключ восстановления - это единственный способ восстановить доступ к хранилищу при утере пароля.
vaultOptions.masterkey.showRecoveryKeyBtn=Показать ключ восстановления
vaultOptions.masterkey.recoverPasswordBtn=Восстановить пароль



@@ 237,5 237,5 @@ passwordStrength.messageLabel.3=Сильный
passwordStrength.messageLabel.4=Очень сильный

# Quit
quit.prompt=Выйти из приложения? Есть разблокированные хранилища.
quit.prompt=Выйти из приложения? Есть незаблокированные хранилища.
quit.lockAndQuit=Заблокировать и выйти

M main/ui/src/main/resources/i18n/strings_sv.properties => main/ui/src/main/resources/i18n/strings_sv.properties +3 -3
@@ 50,7 50,7 @@ addvaultwizard.new.generateRecoveryKeyChoice.yes=Ja tack. För säkerhets skull
addvaultwizard.new.generateRecoveryKeyChoice.no=Nej tack. Här slarvas inga lösenord bort
### Information
addvault.new.readme.storageLocation.fileName=VIKTIGT.rtf
addvault.new.readme.storageLocation.1=⚠️  VALV FILER ⚠️
addvault.new.readme.storageLocation.1=⚠️  VALVFILER ⚠️
addvault.new.readme.storageLocation.2=Detta är ditt valvs lagringsplats.
addvault.new.readme.storageLocation.3=INTE
addvault.new.readme.storageLocation.4=• ändra någon fil i denna katalog eller


@@ 58,7 58,7 @@ addvault.new.readme.storageLocation.5=• klistra in filer för kryptering i den
addvault.new.readme.storageLocation.6=Om du vill kryptera filer och se innehållet i valvet, gör följande:
addvault.new.readme.storageLocation.7=1. Lägg till detta valv till Cryptomator.
addvault.new.readme.storageLocation.8=2. Lås upp valvet i Cryptomator.
addvault.new.readme.storageLocation.9=3. Öppna åtkomstplatsen genom att klicka på "Visa" knappen.
addvault.new.readme.storageLocation.9=3. Öppna åtkomstplatsen genom att klicka på "Visa"-knappen.
addvault.new.readme.storageLocation.10=Om du behöver hjälp, läs dokumentationen: %s
addvault.new.readme.accessLocation.fileName=WELCOME.rtf
addvault.new.readme.accessLocation.1=\\fs\\qc 🔐️  KRYPTERAD VOLYM  🔐️


@@ 190,7 190,7 @@ wrongFileAlert.instruction.0=För att kryptera filer, följ dessa steg:
wrongFileAlert.instruction.1=1. Lås upp ditt valv.
wrongFileAlert.instruction.2=2. Klicka på "Visa" för att öppna volymen i din filhanterare.
wrongFileAlert.instruction.3=3. Lägg till dina filer i denna volym.
wrongFileAlert.link=För mer hjälp, besök
wrongFileAlert.link=För ytterligare hjälp, besök

# Vault Options
## General

M main/ui/src/main/resources/i18n/strings_tr.properties => main/ui/src/main/resources/i18n/strings_tr.properties +12 -0
@@ 59,6 59,7 @@ addvault.new.readme.storageLocation.6=Dosyaları şifrelemek ve kasanın içeri
addvault.new.readme.storageLocation.7=1. Bu kasayı Cryptomator'a ekleyin.
addvault.new.readme.storageLocation.8=2. Cryptomator'da kasanın kilidini açın.
addvault.new.readme.storageLocation.9=3. "Göster" düğmesini tıklayarak erişim konumunu açın.
addvault.new.readme.storageLocation.10=Yardım lazımsa, belgeleri ziyaret edin: %s
addvault.new.readme.accessLocation.fileName=WELCOME.rtf
addvault.new.readme.accessLocation.1=🔐️  ŞİFRELENMİŞ BİRİM  🔐️
addvault.new.readme.accessLocation.2=Burası kasanızın erişim konumudur.


@@ 80,6 81,7 @@ removeVault.confirmBtn=Kasayı Sil
# Change Password
changepassword.title=Şifreyi Değiştir
changepassword.enterOldPassword="%s" için şuanki şifreyi gir
changepassword.finalConfirmation=Şifremi unutursam verilerime ulaşamayacağımın farkındayım

# Forget Password
forgetPassword.title=Şifreyi Unut


@@ 143,6 145,7 @@ preferences.donationKey.registeredFor=%s için kaydedildi
preferences.donationKey.noDonationKey=Geçerli bir bağış anahtarı bulunamadı. Bu anahtar, lisans anahtarı gibidir ama ücretsiz uygulama kullanan muhteşem insanlar içindir ;-)
preferences.donationKey.getDonationKey=Bir bağış anahtarı al
## About
preferences.about=Hakkında

# Main Window
main.closeBtn.tooltip=Kapat


@@ 180,6 183,14 @@ main.vaultDetail.migrateButton=Kasayı Güncelle
main.vaultDetail.migratePrompt=Kasaya erişmeden önce kasanızın yeni bir formata yükseltilmesi gerekiyor

# Wrong File Alert
wrongFileAlert.title=Dosyalar Nasıl Şifrelenir
wrongFileAlert.header.title=Bu dosyaları şifrelemeye çalıştınız mı?
wrongFileAlert.header.lead=Bu amaçla, Cryptomator sistem dosya yöneticinizde bir birim oluşturur.
wrongFileAlert.instruction.0=Dosyaları şifrelemek için, şu adımları izleyin:
wrongFileAlert.instruction.1=1. Kasanızın kilidini açın.
wrongFileAlert.instruction.2=2. "Sürücüyü Göster"e basarak birimi dosya yöneticinizde açın.
wrongFileAlert.instruction.3=3. Dosyalarınızı bu birime ekleyin.
wrongFileAlert.link=Daha fazla yardım için, ziyaret edin: 

# Vault Options
## General


@@ 211,6 222,7 @@ recoveryKey.display.message=Aşağıdaki kurtarma anahtarı "%s" kasasına eriş
recoveryKey.display.StorageHints=Bunu çok güvenli bir yerde saklayın, örneğin:\n • Şifre yöneticisi kullanarak depolayın\n • USB flash belleğe kaydedin\n • Bir sayfaya yazdırın
recoveryKey.recover.prompt="%s" için kurtarma anahtarınızı girin:
recoveryKey.recover.validKey=Bu geçerli bir kurtarma anahtarı
recoveryKey.printout.heading=Cryptomator Kurtarma Anahtarı\n"%s"\n

# New Password
newPassword.promptText=Yeni bir şifre girin

M main/ui/src/main/resources/i18n/strings_zh.properties => main/ui/src/main/resources/i18n/strings_zh.properties +4 -4
@@ 122,9 122,9 @@ preferences.title=首选项
preferences.general=常规​​​​​
preferences.general.theme=界面外观
preferences.general.unlockThemes=解锁暗黑模式
preferences.general.startHidden=启动Cryptomator时隐藏窗口
preferences.general.startHidden=最小化启动 Cryptomator 到系统托盘
preferences.general.debugLogging=启用调试日志
preferences.general.autoStart=开机运行Cryptomator
preferences.general.autoStart=开机运行 Cryptomator
preferences.general.interfaceOrientation=界面方向
preferences.general.interfaceOrientation.ltr=从左到右
preferences.general.interfaceOrientation.rtl=从右到左


@@ 142,7 142,7 @@ preferences.updates.updateAvailable=可更新到版本 %s
## Donation Key
preferences.donationKey=捐赠
preferences.donationKey.registeredFor=已注册给 %s
preferences.donationKey.noDonationKey=找不到有效的捐赠密钥,它相当于一个专门给使用免费软件的帅哥美女的许可证密钥。;-)
preferences.donationKey.noDonationKey=找不到有效的捐赠密钥,它相当于一个专门给使用免费软件的帅哥美女的许可证密钥 ;-)
preferences.donationKey.getDonationKey=获取一个捐赠密钥
## About
preferences.about=关于


@@ 195,7 195,7 @@ wrongFileAlert.link=如需进一步帮助,请访问
# Vault Options
## General
vaultOptions.general=常规​​​​​
vaultOptions.general.unlockAfterStartup=启动Cryptomator时解锁保险库
vaultOptions.general.unlockAfterStartup=启动 Cryptomator 时解锁保险库 (此功能需先勾选保存密码)
## Mount
vaultOptions.mount=挂载
vaultOptions.mount.readonly=只读

M main/ui/src/main/resources/i18n/strings_zh_TW.properties => main/ui/src/main/resources/i18n/strings_zh_TW.properties +1 -1
@@ 190,7 190,7 @@ wrongFileAlert.instruction.0=請依下列步驟加密檔案:
wrongFileAlert.instruction.1=1. 解鎖您的加密檔案庫。
wrongFileAlert.instruction.2=2. 點擊「顯示」可在檔案總管中檢視磁區。
wrongFileAlert.instruction.3=3. 把您的檔案加入磁區。
wrongFileAlert.link=如果需要進一步的協助,請前往
wrongFileAlert.link=如需進一步協助協助,請前往

# Vault Options
## General