~exprez135/cryptomator-libre

0be97b309b2b73cc0c8ed8aa694978ff67d91491 — Sebastian Stenzel 3 years ago ff373b9 + b8de68b 1.3.2
Merge branch 'release/1.3.2'
58 files changed, 1028 insertions(+), 473 deletions(-)

M .gitignore
M CONTRIBUTING.md
M ISSUE_TEMPLATE.md
M README.md
A SUPPORT.md
M main/ant-kit/pom.xml
M main/commons/pom.xml
M main/jacoco-report/pom.xml
M main/keychain/pom.xml
M main/launcher/pom.xml
M main/launcher/src/main/java/org/cryptomator/launcher/InterProcessCommunicator.java
M main/pom.xml
M main/uber-jar/pom.xml
M main/ui/pom.xml
M main/ui/src/main/java/org/cryptomator/ui/controllers/ChangePasswordController.java
M main/ui/src/main/java/org/cryptomator/ui/controllers/InitializeController.java
M main/ui/src/main/java/org/cryptomator/ui/controllers/MainController.java
M main/ui/src/main/java/org/cryptomator/ui/controllers/UnlockController.java
M main/ui/src/main/java/org/cryptomator/ui/controllers/UpgradeController.java
M main/ui/src/main/java/org/cryptomator/ui/controllers/ViewController.java
M main/ui/src/main/java/org/cryptomator/ui/controls/SecPasswordField.java
M main/ui/src/main/java/org/cryptomator/ui/model/UpgradeStrategy.java
M main/ui/src/main/java/org/cryptomator/ui/model/UpgradeVersion3to4.java
M main/ui/src/main/java/org/cryptomator/ui/model/UpgradeVersion4to5.java
M main/ui/src/main/java/org/cryptomator/ui/model/Vault.java
M main/ui/src/main/java/org/cryptomator/ui/util/PasswordStrengthUtil.java
M main/ui/src/main/resources/css/linux_theme.css
M main/ui/src/main/resources/css/win_theme.css
M main/ui/src/main/resources/fxml/main.fxml
M main/ui/src/main/resources/fxml/unlocked.fxml
M main/ui/src/main/resources/localization/ar.txt
M main/ui/src/main/resources/localization/bg.txt
M main/ui/src/main/resources/localization/da.txt
M main/ui/src/main/resources/localization/de.txt
M main/ui/src/main/resources/localization/en.txt
M main/ui/src/main/resources/localization/es.txt
M main/ui/src/main/resources/localization/fr.txt
M main/ui/src/main/resources/localization/hu.txt
M main/ui/src/main/resources/localization/it.txt
M main/ui/src/main/resources/localization/ja.txt
M main/ui/src/main/resources/localization/ko.txt
M main/ui/src/main/resources/localization/lv.txt
M main/ui/src/main/resources/localization/nl.txt
M main/ui/src/main/resources/localization/pl.txt
M main/ui/src/main/resources/localization/pt.txt
M main/ui/src/main/resources/localization/pt_BR.txt
M main/ui/src/main/resources/localization/ru.txt
M main/ui/src/main/resources/localization/sk.txt
A main/ui/src/main/resources/localization/th.txt
M main/ui/src/main/resources/localization/tr.txt
M main/ui/src/main/resources/localization/uk.txt
M main/ui/src/main/resources/localization/zh.txt
M main/ui/src/main/resources/localization/zh_HK.txt
M main/ui/src/main/resources/localization/zh_TW.txt
A main/ui/src/test/java/org/cryptomator/ui/l10n/LocalizationMock.java
M main/ui/src/test/java/org/cryptomator/ui/l10n/LocalizationTest.java
A main/ui/src/test/java/org/cryptomator/ui/model/UpgradeVersion3to4Test.java
A main/ui/src/test/java/org/cryptomator/ui/util/PasswordStrengthUtilTest.java
M .gitignore => .gitignore +4 -0
@@ 17,3 17,7 @@ test-output/
out/
.idea_modules/
*.iws
*.iml

# Temporary file created by test launcher
main/launcher/.ipcPort.tmp

M CONTRIBUTING.md => CONTRIBUTING.md +2 -13
@@ 4,20 4,9 @@

- Ensure you're running the latest version of Cryptomator.
- Ensure the bug is related to the desktop version of Cryptomator. Bugs concerning the Cryptomator iOS and Android app can be reported on the [Cryptomator for iOS issues list](https://github.com/cryptomator/cryptomator-ios/issues) and [Cryptomator for Android issues list](https://github.com/cryptomator/cryptomator-android/issues) respectively.
- Ensure the bug was not [already reported](https://github.com/cryptomator/cryptomator/issues). You can also check out our [knowledge base](https://cryptomator.freshdesk.com/support/solutions) and our [Wiki](https://github.com/cryptomator/cryptomator/wiki).
- Ensure the bug was not [already reported](https://github.com/cryptomator/cryptomator/issues). You can also check out our [FAQ](https://community.cryptomator.org/c/faq).
- If you're unable to find an open issue addressing the problem, [submit a new one](https://github.com/cryptomator/cryptomator/issues/new).

## Do you have questions?

- Ask questions by [submitting a new issue](https://github.com/cryptomator/cryptomator/issues/new).
- [Contact us](https://cryptomator.org/contact/) directly by writing an email. Wir sprechen auch Deutsch!
- Have a chat with us on [Gitter](https://gitter.im/cryptomator/cryptomator).

## Do you miss a feature?

- Ensure the feature was not [already requested](https://github.com/cryptomator/cryptomator/issues).
- You're welcome to suggest a feature by [submitting a new issue](https://github.com/cryptomator/cryptomator/issues/new).

## Did you write a patch that fixes a bug?

- Open a new pull request with the patch.


@@ 29,7 18,7 @@

## Code of Conduct

Help us keep Cryptomator open and inclusive. Please read and follow our [Code of Conduct](https://github.com/cryptomator/cryptomator/blob/master/CODE_OF_CONDUCT.md).
Help us keep Cryptomator open and inclusive. Please read and follow our [Code of Conduct](https://github.com/cryptomator/cryptomator/blob/develop/CODE_OF_CONDUCT.md).

## Above all, thank you for your contributions


M ISSUE_TEMPLATE.md => ISSUE_TEMPLATE.md +9 -16
@@ 1,24 1,15 @@
To tick a checkbox replace [ ] with [x]. Make sure to replace placeholders (…) accordingly.

## Issue Checklist

Before creating a new issue make sure that you
- [ ] searched [existing (and closed) issues](https://github.com/cryptomator/cryptomator/issues).
- [ ] searched the [knowledge base](https://cryptomator.freshdesk.com/support/solutions).
- [ ] have read the [contribution guide](https://github.com/cryptomator/cryptomator/blob/master/CONTRIBUTING.md).
- [ ] have read the [Code of Conduct](https://github.com/cryptomator/cryptomator/blob/master/CODE_OF_CONDUCT.md).
- searched existing (and closed) issues: https://github.com/cryptomator/cryptomator/issues
- searched the knowledge base: https://community.cryptomator.org/c/kb
- have read the support guide: https://github.com/cryptomator/cryptomator/blob/develop/SUPPORT.md
- have read the contribution guide: https://github.com/cryptomator/cryptomator/blob/develop/CONTRIBUTING.md
- have read the code of conduct: https://github.com/cryptomator/cryptomator/blob/develop/CODE_OF_CONDUCT.md

## Basic Info

This is a
- [ ] bug report.
- [ ] feature request.
- [ ] question or something else.

I'm using
- [ ] Windows in version: …
- [ ] macOS in version: …
- [ ] Linux in version: …
I'm using Windows / macOS / Linux / … in version: …

I'm running Cryptomator in version: …  
(You can check the version in the Cryptomator settings.)


@@ 30,7 21,9 @@ I'm running Cryptomator in version: …

## Attachments (optional)

If you want to add the log file or screenshots, please add them as attachments. If your log file seems empty and doesn't show any errors, you may enable the [debug mode](https://cryptomator.freshdesk.com/support/solutions/articles/16000046480) first and reproduce the problem to ensure all important information is contained in there. You may use test data or redact sensitive information from the log file.
If you want to add the log file or screenshots, please add them as attachments. If your log file seems empty and doesn't show any errors, you may enable the debug mode first. Here is how to do that: https://community.cryptomator.org/t/how-do-i-enable-debug-mode/36

Then reproduce the problem to ensure all important information is contained in there. You may use test data or redact sensitive information from the log file.

You can find the log file
- on Windows: %appdata%/Cryptomator/cryptomator.log

M README.md => README.md +3 -9
@@ 6,6 6,7 @@
[![Twitter](https://img.shields.io/badge/twitter-@Cryptomator-blue.svg?style=flat)](http://twitter.com/Cryptomator)
[![POEditor](https://img.shields.io/badge/POEditor-Help%20Translate-blue.svg?style=flat)](https://poeditor.com/join/project/bHwbvJmx0E)
[![Latest Release](https://img.shields.io/github/release/cryptomator/cryptomator.svg)](https://github.com/cryptomator/cryptomator/releases/latest)
[![Community](https://img.shields.io/badge/help-Community-orange.svg)](https://community.cryptomator.org)

Multi-platform transparent client-side encryption of your files in the cloud.



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

## Features

- Works with Dropbox, Google Drive, OneDrive, Nextcloud and any other cloud storage service which synchronizes with a local directory
- Works with Dropbox, Google Drive, OneDrive, ownCloud, Nextcloud and any other cloud storage service which synchronizes with a local directory
- Open Source means: No backdoors, control is better than trust
- Client-side: No accounts, no data shared with any online service
- Totally transparent: Just work on the virtual drive as if it were a USB flash drive


@@ 21,6 22,7 @@ Download native binaries of Cryptomator on [cryptomator.org](https://cryptomator
- File names get encrypted
- Folder structure gets obfuscated
- Use as many vaults in your Dropbox as you want, each having individual passwords
- One thousand commits for the security of your data!! :tada:

### Privacy



@@ 58,14 60,6 @@ mvn clean install -Prelease

An executable jar file will be created inside `main/uber-jar/target`.

## Contributing to Cryptomator

Please read our [contribution guide](https://github.com/cryptomator/cryptomator/blob/master/CONTRIBUTING.md), if you would like to report a bug, ask a question or help us with coding.

## Code of Conduct

Help us keep Cryptomator open and inclusive. Please read and follow our [Code of Conduct](https://github.com/cryptomator/cryptomator/blob/master/CODE_OF_CONDUCT.md).

## License

This project is dual-licensed under the GPLv3 for FOSS projects as well as a commercial license for independent software vendors and resellers. If you want to modify this application under different conditions, feel free to contact our support team.

A SUPPORT.md => SUPPORT.md +10 -0
@@ 0,0 1,10 @@
# Support for Cryptomator

For development-related topics, GitHub is the right place.

For _everything else_, please visit our official [Cryptomator Community](https://community.cryptomator.org) (we are there, too :wink:). Amongst others, you will find:

- Installation manuals
- Usage guides
- Help with problems
- Tips & tricks

M main/ant-kit/pom.xml => main/ant-kit/pom.xml +1 -1
@@ 4,7 4,7 @@
	<parent>
		<groupId>org.cryptomator</groupId>
		<artifactId>main</artifactId>
		<version>1.3.1</version>
		<version>1.3.2</version>
	</parent>
	<artifactId>ant-kit</artifactId>
	<packaging>pom</packaging>

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


@@ 34,6 34,15 @@
			<groupId>com.google.dagger</groupId>
			<artifactId>dagger</artifactId>
		</dependency>
		<dependency>
			<groupId>com.google.dagger</groupId>
			<artifactId>dagger-compiler</artifactId>
		</dependency>
		
		<dependency>
			<groupId>com.google.dagger</groupId>
			<artifactId>dagger-compiler</artifactId>
		</dependency>

		<!-- Logging -->
		<dependency>

M main/jacoco-report/pom.xml => main/jacoco-report/pom.xml +1 -1
@@ 4,7 4,7 @@
	<parent>
		<groupId>org.cryptomator</groupId>
		<artifactId>main</artifactId>
		<version>1.3.1</version>
		<version>1.3.2</version>
	</parent>
	<artifactId>jacoco-report</artifactId>
	<name>Cryptomator Code Coverage Report</name>

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


@@ 34,6 34,10 @@
			<groupId>com.google.dagger</groupId>
			<artifactId>dagger</artifactId>
		</dependency>
		<dependency>
			<groupId>com.google.dagger</groupId>
			<artifactId>dagger-compiler</artifactId>
		</dependency>
		
		<!-- Logging -->
		<dependency>

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


@@ 34,6 34,10 @@
			<groupId>com.google.dagger</groupId>
			<artifactId>dagger</artifactId>
		</dependency>
		<dependency>
			<groupId>com.google.dagger</groupId>
			<artifactId>dagger-compiler</artifactId>
		</dependency>

		<!-- Logging -->
		<dependency>

M main/launcher/src/main/java/org/cryptomator/launcher/InterProcessCommunicator.java => main/launcher/src/main/java/org/cryptomator/launcher/InterProcessCommunicator.java +70 -36
@@ 9,6 9,9 @@ import java.io.Closeable;
import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritableByteChannel;


@@ 17,6 20,7 @@ import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.rmi.ConnectException;
import java.rmi.ConnectIOException;
import java.rmi.NotBoundException;
import java.rmi.Remote;
import java.rmi.RemoteException;


@@ 55,22 59,19 @@ abstract class InterProcessCommunicator implements InterProcessCommunicationProt
	// visible for testing
	static InterProcessCommunicator start(Path portFilePath, InterProcessCommunicationProtocol endpoint) throws IOException {
		System.setProperty("java.rmi.server.hostname", "localhost");
		// try to connect to existing server:
		int port = readPort(portFilePath);
		LOG.debug("Connecting to running process on TCP port {}...", port);
		try {
			ClientCommunicator client = new ClientCommunicator(port);
			// try to connect to existing server:
			ClientCommunicator client = new ClientCommunicator(portFilePath);
			LOG.trace("Connected to running process.");
			return client;
		} catch (ConnectException | NotBoundException e) {
			LOG.debug("Did not find running process.");
		} catch (ConnectException | ConnectIOException | NotBoundException e) {
			LOG.debug("Could not connect to running process.");
			// continue
		}

		// spawn a new server:
		LOG.trace("Spawning new server...");
		ServerCommunicator server = new ServerCommunicator(endpoint);
		writePort(portFilePath, server.getPort());
		ServerCommunicator server = new ServerCommunicator(endpoint, portFilePath);
		LOG.debug("Server listening on port {}.", server.getPort());
		return server;
	}


@@ 79,7 80,7 @@ abstract class InterProcessCommunicator implements InterProcessCommunicationProt
		final String settingsPathProperty = System.getProperty("cryptomator.ipcPortPath");
		if (settingsPathProperty == null) {
			LOG.warn("System property cryptomator.ipcPortPath not set.");
			return Paths.get("ipcPort.tmp");
			return Paths.get(".ipcPort.tmp");
		} else {
			return Paths.get(replaceHomeDir(settingsPathProperty));
		}


@@ 97,12 98,30 @@ abstract class InterProcessCommunicator implements InterProcessCommunicationProt

		private final IpcProtocolRemote remote;

		private ClientCommunicator(int port) throws ConnectException, NotBoundException, RemoteException {
			if (port == 0) {
				throw new ConnectException("Can not connect to port 0.");
		private ClientCommunicator(Path portFilePath) throws ConnectException, NotBoundException, RemoteException {
			if (Files.notExists(portFilePath)) {
				throw new ConnectException("No IPC port file.");
			}
			try {
				int port = ClientCommunicator.readPort(portFilePath);
				LOG.debug("Connecting to port {}...", port);
				Registry registry = LocateRegistry.getRegistry("localhost", port, new ClientSocketFactory());
				this.remote = (IpcProtocolRemote) registry.lookup(RMI_NAME);
			} catch (IOException e) {
				throw new ConnectException("Error reading IPC port file.");
			}
		}

		private static int readPort(Path portFilePath) throws IOException {
			ByteBuffer buf = ByteBuffer.allocate(Integer.BYTES);
			try (ReadableByteChannel ch = Files.newByteChannel(portFilePath, StandardOpenOption.READ)) {
				if (ch.read(buf) == Integer.BYTES) {
					buf.flip();
					return buf.getInt();
				} else {
					throw new IOException("Invalid IPC port file.");
				}
			}
			Registry registry = LocateRegistry.getRegistry("localhost", port);
			this.remote = (IpcProtocolRemote) registry.lookup(RMI_NAME);
		}

		@Override


@@ 131,8 150,9 @@ abstract class InterProcessCommunicator implements InterProcessCommunicationProt
		private final ServerSocket socket;
		private final Registry registry;
		private final IpcProtocolRemoteImpl remote;
		private final Path portFilePath;

		private ServerCommunicator(InterProcessCommunicationProtocol delegate) throws IOException {
		private ServerCommunicator(InterProcessCommunicationProtocol delegate, Path portFilePath) throws IOException {
			this.socket = new ServerSocket(0, Byte.MAX_VALUE, InetAddress.getByName("localhost"));
			RMIClientSocketFactory csf = RMISocketFactory.getDefaultSocketFactory();
			SingletonServerSocketFactory ssf = new SingletonServerSocketFactory(socket);


@@ 140,6 160,20 @@ abstract class InterProcessCommunicator implements InterProcessCommunicationProt
			this.remote = new IpcProtocolRemoteImpl(delegate);
			UnicastRemoteObject.exportObject(remote, 0);
			registry.rebind(RMI_NAME, remote);
			this.portFilePath = portFilePath;
			ServerCommunicator.writePort(portFilePath, socket.getLocalPort());
		}

		private static void writePort(Path portFilePath, int port) throws IOException {
			ByteBuffer buf = ByteBuffer.allocate(Integer.BYTES);
			buf.putInt(port);
			buf.flip();
			MoreFiles.createParentDirectories(portFilePath);
			try (WritableByteChannel ch = Files.newByteChannel(portFilePath, StandardOpenOption.WRITE, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING)) {
				if (ch.write(buf) != Integer.BYTES) {
					throw new IOException("Did not write expected number of bytes.");
				}
			}
		}

		@Override


@@ 162,6 196,7 @@ abstract class InterProcessCommunicator implements InterProcessCommunicationProt
				registry.unbind(RMI_NAME);
				UnicastRemoteObject.unexportObject(remote, true);
				socket.close();
				Files.deleteIfExists(portFilePath);
				LOG.debug("Server shut down.");
			} catch (NotBoundException | IOException e) {
				LOG.warn("Failed to close IPC Server.", e);


@@ 210,31 245,30 @@ abstract class InterProcessCommunicator implements InterProcessCommunicationProt

	}

	private static int readPort(Path path) throws IOException {
		if (Files.notExists(path)) {
			return 0;
		}
		ByteBuffer buf = ByteBuffer.allocate(Integer.BYTES);
		try (ReadableByteChannel ch = Files.newByteChannel(path, StandardOpenOption.READ)) {
			if (ch.read(buf) == Integer.BYTES) {
				buf.flip();
				return buf.getInt();
			} else {
				return 0;
			}
	/**
	 * Creates client sockets with short timeouts.
	 */
	private static class ClientSocketFactory implements RMIClientSocketFactory {

		@Override
		public Socket createSocket(String host, int port) throws IOException {
			return new SocketWithFixedTimeout(host, port, 1000);
		}

	}

	private static void writePort(Path path, int port) throws IOException {
		ByteBuffer buf = ByteBuffer.allocate(Integer.BYTES);
		buf.putInt(port);
		buf.flip();
		MoreFiles.createParentDirectories(path);
		try (WritableByteChannel ch = Files.newByteChannel(path, StandardOpenOption.WRITE, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING)) {
			if (ch.write(buf) != Integer.BYTES) {
				throw new IOException("Did not write expected number of bytes.");
			}
	private static class SocketWithFixedTimeout extends Socket {

		public SocketWithFixedTimeout(String host, int port, int timeoutInMs) throws UnknownHostException, IOException {
			super(host, port);
			super.setSoTimeout(timeoutInMs);
		}

		@Override
		public synchronized void setSoTimeout(int timeout) throws SocketException {
			// do nothing, timeout is fixed
		}

	}

}

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



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

		<!-- dependency versions -->
		<cryptomator.cryptolib.version>1.1.5</cryptomator.cryptolib.version>
		<cryptomator.cryptofs.version>1.4.1</cryptomator.cryptofs.version>
		<cryptomator.webdav.version>0.6.2</cryptomator.webdav.version>
		<cryptomator.cryptolib.version>1.1.7</cryptomator.cryptolib.version>
		<cryptomator.cryptofs.version>1.4.5</cryptomator.cryptofs.version>
		<cryptomator.webdav.version>1.0.3</cryptomator.webdav.version>
		<cryptomator.jni.version>1.0.2</cryptomator.jni.version>
		
		<commons-io.version>2.5</commons-io.version>


@@ 35,16 35,16 @@
		
		<easybind.version>1.0.3</easybind.version>
		
		<guava.version>22.0</guava.version>
		<guava.version>23.5-jre</guava.version>
		<dagger.version>2.11</dagger.version>
		<gson.version>2.8.1</gson.version>
		<gson.version>2.8.2</gson.version>
		
		<slf4j.version>1.7.25</slf4j.version>
		<logback.version>1.2.2</logback.version>
		<logback.version>1.2.3</logback.version>
		
		<junit.version>4.12</junit.version>
		<junit.hierarchicalrunner.version>4.12.1</junit.hierarchicalrunner.version>
		<mockito.version>2.7.21</mockito.version>
		<mockito.version>2.11.0</mockito.version>
		<hamcrest.version>1.3</hamcrest.version> <!-- keep in sync with version required by JUnit -->
	</properties>



@@ 165,6 165,12 @@
				<version>${dagger.version}</version>
			</dependency>
			<dependency>
				<groupId>com.google.dagger</groupId>
				<artifactId>dagger-compiler</artifactId>
				<version>${dagger.version}</version>
				<optional>true</optional>
			</dependency>
			<dependency>
				<groupId>com.google.code.gson</groupId>
				<artifactId>gson</artifactId>
				<version>${gson.version}</version>


@@ 264,7 270,7 @@
			<plugins>
				<plugin>
					<artifactId>maven-dependency-plugin</artifactId>
					<version>3.0.1</version>
					<version>3.0.2</version>
					<executions>
						<execution>
							<id>copy-libs</id>


@@ 302,17 308,10 @@
		<plugins>
			<plugin>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.6.1</version>
				<version>3.7.0</version>
				<configuration>
					<source>1.8</source>
					<target>1.8</target>
					<annotationProcessorPaths>
						<path>
							<groupId>com.google.dagger</groupId>
							<artifactId>dagger-compiler</artifactId>
							<version>${dagger.version}</version>
						</path>
					</annotationProcessorPaths>
				</configuration>
			</plugin>
		</plugins>

M main/uber-jar/pom.xml => main/uber-jar/pom.xml +1 -1
@@ 4,7 4,7 @@
	<parent>
		<groupId>org.cryptomator</groupId>
		<artifactId>main</artifactId>
		<version>1.3.1</version>
		<version>1.3.2</version>
	</parent>
	<artifactId>uber-jar</artifactId>
	<name>Single über jar with all dependencies</name>

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


@@ 72,6 72,10 @@
			<groupId>com.google.dagger</groupId>
			<artifactId>dagger</artifactId>
		</dependency>
		<dependency>
			<groupId>com.google.dagger</groupId>
			<artifactId>dagger-compiler</artifactId>
		</dependency>

		<!-- Zxcvbn -->
		<dependency>


@@ 86,5 90,13 @@
			<artifactId>slf4j-simple</artifactId>
			<scope>test</scope>
		</dependency>
		
		<!-- Testing -->
		<dependency>
			<groupId>com.google.jimfs</groupId>
			<artifactId>jimfs</artifactId>
			<version>1.1</version>
			<scope>test</scope>
		</dependency>
	</dependencies>
</project>

M main/ui/src/main/java/org/cryptomator/ui/controllers/ChangePasswordController.java => main/ui/src/main/java/org/cryptomator/ui/controllers/ChangePasswordController.java +5 -0
@@ 119,6 119,11 @@ public class ChangePasswordController implements ViewController {
		return root;
	}

	@Override
	public void focus() {
		oldPasswordField.requestFocus();
	}

	void setVault(Vault vault) {
		this.vault = Objects.requireNonNull(vault);
		// trigger "default" change to refresh key bindings:

M main/ui/src/main/java/org/cryptomator/ui/controllers/InitializeController.java => main/ui/src/main/java/org/cryptomator/ui/controllers/InitializeController.java +5 -3
@@ 10,7 10,6 @@
package org.cryptomator.ui.controllers;

import java.io.IOException;
import java.nio.file.DirectoryNotEmptyException;
import java.nio.file.FileAlreadyExistsException;
import java.util.Objects;
import java.util.Optional;


@@ 106,6 105,11 @@ public class InitializeController implements ViewController {
		return root;
	}

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

	void setVault(Vault vault) {
		this.vault = Objects.requireNonNull(vault);
		// trigger "default" change to refresh key bindings:


@@ 125,8 129,6 @@ public class InitializeController implements ViewController {
			listener.ifPresent(this::invokeListenerLater);
		} catch (FileAlreadyExistsException ex) {
			messageLabel.setText(localization.getString("initialize.messageLabel.alreadyInitialized"));
		} catch (DirectoryNotEmptyException ex) {
			messageLabel.setText(localization.getString("initialize.messageLabel.notEmpty"));
		} catch (IOException ex) {
			LOG.error("I/O Exception", ex);
			messageLabel.setText(localization.getString("initialize.messageLabel.initializationFailed"));

M main/ui/src/main/java/org/cryptomator/ui/controllers/MainController.java => main/ui/src/main/java/org/cryptomator/ui/controllers/MainController.java +45 -1
@@ 9,6 9,8 @@
 ******************************************************************************/
package org.cryptomator.ui.controllers;

import static org.cryptomator.ui.util.DialogBuilderUtil.buildErrorDialog;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;


@@ 20,6 22,7 @@ import java.util.Map;
import java.util.Optional;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.stream.Stream;

import javax.inject.Inject;
import javax.inject.Named;


@@ 63,12 66,16 @@ import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.Button;
import javafx.scene.control.ButtonType;
import javafx.scene.control.Cell;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.scene.control.MenuItem;
import javafx.scene.control.ToggleButton;
import javafx.scene.image.Image;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.text.Font;


@@ 162,6 169,7 @@ public class MainController implements ViewController {
	@Override
	public void initialize() {
		vaultList.setItems(vaults);
		vaultList.setOnKeyReleased(this::didPressKeyOnList);
		vaultList.setCellFactory(this::createDirecoryListCell);
		activeController.set(viewControllerLoader.load("/fxml/welcome.fxml"));
		selectedVault.bind(vaultList.getSelectionModel().selectedItemProperty());


@@ 236,6 244,7 @@ public class MainController implements ViewController {
	private ListCell<Vault> createDirecoryListCell(ListView<Vault> param) {
		final DirectoryListCell cell = new DirectoryListCell();
		cell.setVaultContextMenu(vaultListCellContextMenu);
		cell.setOnMouseClicked(this::didClickOnListCell);
		return cell;
	}



@@ 261,7 270,18 @@ public class MainController implements ViewController {
		}
		try {
			final Path vaultDir = file.toPath();
			if (!Files.exists(vaultDir)) {
			if (Files.exists(vaultDir)) {
				try (Stream<Path> stream = Files.list(vaultDir)) {
					if (stream.filter(this::isNotHidden).findAny().isPresent()) {
						buildErrorDialog( //
								localization.getString("main.createVault.nonEmptyDir.title"), //
								localization.getString("main.createVault.nonEmptyDir.header"), //
								localization.getString("main.createVault.nonEmptyDir.content"), //
								ButtonType.OK).show();
						return;
					}
				}
			} else {
				Files.createDirectory(vaultDir);
			}
			addVault(vaultDir, true);


@@ 270,6 290,10 @@ public class MainController implements ViewController {
		}
	}

	private boolean isNotHidden(Path file) {
		return !file.getFileName().toString().startsWith(".");
	}

	@FXML
	private void didClickAddExistingVaults(ActionEvent event) {
		final FileChooser fileChooser = new FileChooser();


@@ 309,6 333,7 @@ public class MainController implements ViewController {
		}
		if (select) {
			vaultList.getSelectionModel().select(vault);
			activeController.get().focus();
		}
	}



@@ 325,6 350,8 @@ public class MainController implements ViewController {
			vaults.remove(selectedVault.get());
			if (vaults.isEmpty()) {
				activeController.set(viewControllerLoader.load("/fxml/welcome.fxml"));
			} else {
				activeController.get().focus();
			}
		}
	}


@@ 375,6 402,18 @@ public class MainController implements ViewController {
		}
	}

	private void didPressKeyOnList(KeyEvent e) {
		if (e.getCode() == KeyCode.ENTER || e.getCode() == KeyCode.SPACE) {
			activeController.get().focus();
		}
	}

	private void didClickOnListCell(MouseEvent e) {
		if (MouseEvent.MOUSE_CLICKED.equals(e.getEventType()) && e.getSource() instanceof Cell && ((Cell<?>) e.getSource()).isSelected()) {
			activeController.get().focus();
		}
	}

	// ****************************************
	// Public Bindings
	// ****************************************


@@ 408,6 447,7 @@ public class MainController implements ViewController {

	public void didInitialize() {
		showUnlockView();
		activeController.get().focus();
	}

	private void showUpgradeView() {


@@ 419,6 459,7 @@ public class MainController implements ViewController {

	public void didUpgrade() {
		showUnlockView();
		activeController.get().focus();
	}

	private void showUnlockView() {


@@ 446,6 487,7 @@ public class MainController implements ViewController {
	public void didLock(UnlockedController ctrl) {
		unlockedVaults.remove(ctrl.getVault());
		showUnlockView();
		activeController.get().focus();
	}

	private void showChangePasswordView() {


@@ 453,10 495,12 @@ public class MainController implements ViewController {
		ctrl.setVault(selectedVault.get());
		ctrl.setListener(this::didChangePassword);
		activeController.set(ctrl);
		Platform.runLater(ctrl::focus);
	}

	public void didChangePassword() {
		showUnlockView();
		activeController.get().focus();
	}

}

M main/ui/src/main/java/org/cryptomator/ui/controllers/UnlockController.java => main/ui/src/main/java/org/cryptomator/ui/controllers/UnlockController.java +5 -0
@@ 155,6 155,11 @@ public class UnlockController implements ViewController {
		return root;
	}

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

	void setVault(Vault vault) {
		vaultSubs.unsubscribe();
		vaultSubs = Subscription.EMPTY;

M main/ui/src/main/java/org/cryptomator/ui/controllers/UpgradeController.java => main/ui/src/main/java/org/cryptomator/ui/controllers/UpgradeController.java +5 -0
@@ 84,6 84,11 @@ public class UpgradeController implements ViewController {
		return root;
	}

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

	void setVault(Vault vault) {
		this.vault = Objects.requireNonNull(vault);
		errorLabel.setText(null);

M main/ui/src/main/java/org/cryptomator/ui/controllers/ViewController.java => main/ui/src/main/java/org/cryptomator/ui/controllers/ViewController.java +4 -0
@@ 24,4 24,8 @@ public interface ViewController extends Initializable {
		// no-op
	}

	default void focus() {
		// no-op
	}

}

M main/ui/src/main/java/org/cryptomator/ui/controls/SecPasswordField.java => main/ui/src/main/java/org/cryptomator/ui/controls/SecPasswordField.java +24 -0
@@ 11,6 11,9 @@ package org.cryptomator.ui.controls;
import java.util.Arrays;

import javafx.scene.control.PasswordField;
import javafx.scene.input.DragEvent;
import javafx.scene.input.Dragboard;
import javafx.scene.input.TransferMode;

/**
 * Compromise in security. While the text can be swiped, any access to the {@link #getText()} method will create a copy of the String in the heap.


@@ 19,6 22,27 @@ public class SecPasswordField extends PasswordField {

	private static final char SWIPE_CHAR = ' ';

	public SecPasswordField() {
		this.onDragOverProperty().set(this::handleDragOver);
		this.onDragDroppedProperty().set(this::handleDragDropped);
	}

	private void handleDragOver(DragEvent event) {
		Dragboard dragboard = event.getDragboard();
		if (dragboard.hasString() && dragboard.getString() != null) {
			event.acceptTransferModes(TransferMode.COPY);
		}
		event.consume();
	}

	private void handleDragDropped(DragEvent event) {
		Dragboard dragboard = event.getDragboard();
		if (dragboard.hasString() && dragboard.getString() != null) {
			insertText(getCaretPosition(), dragboard.getString());
		}
		event.consume();
	}

	/**
	 * {@link #getContent()} uses a StringBuilder, which in turn is backed by a char[].
	 * The delete operation of AbstractStringBuilder closes the gap, that forms by deleting chars, by moving up the following chars.

M main/ui/src/main/java/org/cryptomator/ui/model/UpgradeStrategy.java => main/ui/src/main/java/org/cryptomator/ui/model/UpgradeStrategy.java +2 -7
@@ 112,13 112,8 @@ public abstract class UpgradeStrategy {
	public boolean isApplicable(Vault vault) {
		final Path masterkeyFile = vault.getPath().resolve(MASTERKEY_FILENAME);
		try {
			if (Files.isRegularFile(masterkeyFile)) {
				byte[] masterkeyFileContents = Files.readAllBytes(masterkeyFile);
				return KeyFile.parse(masterkeyFileContents).getVersion() == vaultVersionBeforeUpgrade;
			} else {
				LOG.warn("Not a file: {}", masterkeyFile);
				return false;
			}
			byte[] masterkeyFileContents = Files.readAllBytes(masterkeyFile);
			return KeyFile.parse(masterkeyFileContents).getVersion() == vaultVersionBeforeUpgrade;
		} catch (IOException e) {
			LOG.warn("Could not determine, whether upgrade is applicable.", e);
			return false;

M main/ui/src/main/java/org/cryptomator/ui/model/UpgradeVersion3to4.java => main/ui/src/main/java/org/cryptomator/ui/model/UpgradeVersion3to4.java +35 -20
@@ 42,9 42,10 @@ class UpgradeVersion3to4 extends UpgradeStrategy {
	private static final Logger LOG = LoggerFactory.getLogger(UpgradeVersion3to4.class);
	private static final Pattern LVL1_DIR_PATTERN = Pattern.compile("[A-Z2-7]{2}");
	private static final Pattern LVL2_DIR_PATTERN = Pattern.compile("[A-Z2-7]{30}");
	private static final Pattern BASE32_FOLLOWED_BY_UNDERSCORE_PATTERN = Pattern.compile("^(([A-Z2-7]{8})*[A-Z2-7=]{8})_");
	private static final Pattern BASE32_PATTERN = Pattern.compile("^(([A-Z2-7]{8})*[A-Z2-7=]{8})");
	private static final Pattern BASE32_FOLLOWED_BY_UNDERSCORE_PATTERN = Pattern.compile(BASE32_PATTERN.pattern() + "_");
	private static final int FILE_MIN_SIZE = 88; // vault version 3 files have a header of 88 bytes (assuming no chunks at all)
	private static final String LONG_FILENAME_SUFFIX = ".lng";
	private static final String LONG_FILENAME_EXT = ".lng";
	private static final String OLD_FOLDER_SUFFIX = "_";
	private static final String NEW_FOLDER_PREFIX = "0";



@@ 96,10 97,12 @@ class UpgradeVersion3to4 extends UpgradeStrategy {
				@Override
				public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
					String name = file.getFileName().toString();
					if (name.endsWith(LONG_FILENAME_SUFFIX)) {
					if (attrs.size() > FILE_MIN_SIZE) {
						LOG.trace("Skipping non-directory file {}.", file);
					} else if (name.endsWith(LONG_FILENAME_EXT)) {
						migrateLong(metadataDir, file);
					} else {
						migrate(file, attrs);
						migrate(file);
					}
					return FileVisitResult.CONTINUE;
				}


@@ 112,14 115,13 @@ class UpgradeVersion3to4 extends UpgradeStrategy {
		LOG.info("Migration finished.");
	}

	private void migrate(Path file, BasicFileAttributes attrs) throws IOException {
	private void migrate(Path file) throws IOException {
		String name = file.getFileName().toString();
		long size = attrs.size();
		Matcher m = BASE32_FOLLOWED_BY_UNDERSCORE_PATTERN.matcher(name);
		if (attrs.isRegularFile() && m.find(0) && size < FILE_MIN_SIZE) {
		if (m.find(0)) {
			String base32 = m.group(1);
			String suffix = name.substring(m.end());
			String renamed = NEW_FOLDER_PREFIX + base32 + (suffix.isEmpty() ? "" : " " + suffix);
			String renamed = NEW_FOLDER_PREFIX + base32 + suffix;
			renameWithoutOverwriting(file, renamed);
		}
	}


@@ 135,22 137,35 @@ class UpgradeVersion3to4 extends UpgradeStrategy {

	private void migrateLong(Path metadataDir, Path path) throws IOException {
		String oldName = path.getFileName().toString();
		Path oldMetadataFile = metadataDir.resolve(oldName.substring(0, 2)).resolve(oldName.substring(2, 4)).resolve(oldName);
		if (Files.isRegularFile(oldMetadataFile)) {
			String oldContent = new String(Files.readAllBytes(oldMetadataFile), UTF_8);
			if (oldContent.endsWith(OLD_FOLDER_SUFFIX)) {
				String newContent = NEW_FOLDER_PREFIX + StringUtils.removeEnd(oldContent, OLD_FOLDER_SUFFIX);
				String newName = base32.encodeAsString(sha1.digest(newContent.getBytes(UTF_8))) + LONG_FILENAME_SUFFIX;
		assert oldName.endsWith(LONG_FILENAME_EXT);
		String oldNameBase = StringUtils.removeEnd(oldName, LONG_FILENAME_EXT);

		Matcher m = BASE32_PATTERN.matcher(oldNameBase);
		if (m.find(0)) {
			String oldNameBase32 = m.group(1);
			String oldNameSuffix = oldNameBase.substring(m.end());
			String oldCanonicalName = oldNameBase32 + LONG_FILENAME_EXT;

			Path oldMetadataFile = metadataDir.resolve(oldCanonicalName.substring(0, 2)).resolve(oldCanonicalName.substring(2, 4)).resolve(oldCanonicalName);
			if (!Files.isReadable(oldMetadataFile)) {
				LOG.warn("Found uninflatable long file name. Expected: {}", oldMetadataFile);
				return;
			}

			String oldLongName = new String(Files.readAllBytes(oldMetadataFile), UTF_8);
			if (oldLongName.endsWith(OLD_FOLDER_SUFFIX)) {
				String newLongName = NEW_FOLDER_PREFIX + StringUtils.removeEnd(oldLongName, OLD_FOLDER_SUFFIX);
				String newCanonicalBase32 = base32.encodeAsString(sha1.digest(newLongName.getBytes(UTF_8)));
				String newCanonicalName = newCanonicalBase32 + LONG_FILENAME_EXT;
				Path newMetadataFile = metadataDir.resolve(newCanonicalName.substring(0, 2)).resolve(newCanonicalName.substring(2, 4)).resolve(newCanonicalName);
				String newName = newCanonicalBase32 + oldNameSuffix + LONG_FILENAME_EXT;
				Path newPath = path.resolveSibling(newName);
				Path newMetadataFile = metadataDir.resolve(newName.substring(0, 2)).resolve(newName.substring(2, 4)).resolve(newName);
				Files.move(path, newPath);
				Files.createDirectories(newMetadataFile.getParent());
				Files.write(newMetadataFile, newContent.getBytes(UTF_8));
				Files.delete(oldMetadataFile);
				LOG.info("Renaming {} to {}\nDeleting {}\nCreating {}", path, newName, oldMetadataFile, newMetadataFile);
				Files.write(newMetadataFile, newLongName.getBytes(UTF_8));
				LOG.info("Renaming {} to {}.", path, newName);
				LOG.info("Creating {}.", newMetadataFile);
			}
		} else {
			LOG.warn("Found uninflatable long file name. Expected: {}", oldMetadataFile);
		}
	}


M main/ui/src/main/java/org/cryptomator/ui/model/UpgradeVersion4to5.java => main/ui/src/main/java/org/cryptomator/ui/model/UpgradeVersion4to5.java +1 -1
@@ 83,7 83,7 @@ class UpgradeVersion4to5 extends UpgradeStrategy {

				@Override
				public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
					if (attrs.isRegularFile() && BASE32_PATTERN.matcher(file.getFileName().toString()).find() && attrs.size() > cryptor.fileHeaderCryptor().headerSize()) {
					if (BASE32_PATTERN.matcher(file.getFileName().toString()).find() && attrs.size() > cryptor.fileHeaderCryptor().headerSize()) {
						migrate(file, attrs, cryptor);
					} else {
						LOG.info("Skipping irrelevant file {}.", file);

M main/ui/src/main/java/org/cryptomator/ui/model/Vault.java => main/ui/src/main/java/org/cryptomator/ui/model/Vault.java +17 -9
@@ 9,8 9,8 @@
package org.cryptomator.ui.model;

import java.io.IOException;
import java.nio.file.DirectoryNotEmptyException;
import java.nio.file.DirectoryStream;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.nio.file.FileAlreadyExistsException;
import java.nio.file.FileSystem;
import java.nio.file.Files;


@@ 60,6 60,7 @@ public class Vault {
	public static final Predicate<Vault> NOT_LOCKED = hasState(State.LOCKED).negate();
	private static final Logger LOG = LoggerFactory.getLogger(Vault.class);
	private static final String MASTERKEY_FILENAME = "masterkey.cryptomator";
	private static final String LOCALHOST_ALIAS = "cryptomator-vault";

	private final Settings settings;
	private final VaultSettings vaultSettings;


@@ 99,13 100,6 @@ public class Vault {
	}

	public void create(CharSequence passphrase) throws IOException {
		try (DirectoryStream<Path> stream = Files.newDirectoryStream(getPath())) {
			for (Path file : stream) {
				if (!file.getFileName().toString().startsWith(".")) {
					throw new DirectoryNotEmptyException(getPath().toString());
				}
			}
		}
		if (!isValidVaultDirectory()) {
			CryptoFileSystemProvider.initialize(getPath(), MASTERKEY_FILENAME, passphrase);
		} else {


@@ 137,6 131,7 @@ public class Vault {
		MountParams mountParams = MountParams.create() //
				.withWindowsDriveLetter(vaultSettings.winDriveLetter().get()) //
				.withPreferredGvfsScheme(settings.preferredGvfsScheme().get()) //
				.withWebdavHostname(getLocalhostAliasOrNull()) //
				.build();

		Platform.runLater(() -> {


@@ 148,6 143,19 @@ public class Vault {
		});
	}

	private String getLocalhostAliasOrNull() {
		try {
			InetAddress alias = InetAddress.getByName(LOCALHOST_ALIAS);
			if (alias.getHostAddress().equals("127.0.0.1")) {
				return LOCALHOST_ALIAS;
			} else {
				return null;
			}
		} catch (UnknownHostException e) {
			return null;
		}
	}

	public synchronized void unmount() throws CommandFailedException {
		unmount(Function.identity());
	}

M main/ui/src/main/java/org/cryptomator/ui/util/PasswordStrengthUtil.java => main/ui/src/main/java/org/cryptomator/ui/util/PasswordStrengthUtil.java +4 -2
@@ 14,9 14,9 @@ import java.util.List;
import javax.inject.Inject;
import javax.inject.Singleton;

import org.apache.commons.lang3.StringUtils;
import org.cryptomator.ui.l10n.Localization;

import com.google.common.base.Strings;
import com.nulabinc.zxcvbn.Zxcvbn;

import javafx.geometry.Insets;


@@ 41,8 41,10 @@ public class PasswordStrengthUtil {
	}

	public int computeRate(String password) {
		if (StringUtils.isEmpty(password)) {
		if (Strings.isNullOrEmpty(password)) {
			return -1;
		} else if (password.length() > 100) {
			return 4; // assume this is strong. zxcvbn memory and runtime depends vastly on the password length
		} else {
			return zxcvbn.measure(password, sanitizedInputs).getScore();
		}

M main/ui/src/main/resources/css/linux_theme.css => main/ui/src/main/resources/css/linux_theme.css +25 -0
@@ 108,6 108,13 @@
	-fx-text-fill: COLOR_TEXT_DISABLED;
}

.button:focused,
.toggle-button:focused {
	-fx-border-color: black;
	-fx-border-insets: 2px;
	-fx-border-style: dotted inside;
}

/****************************************************************************
 *																			*
 * Segmented Buttons														*


@@ 157,6 164,10 @@
	-fx-padding: 1;
}

.list-view:focused {
	-fx-border-style: dotted inside;
}

.list-cell {
	-fx-padding: 0.5em;
	-fx-text-fill: COLOR_TEXT;


@@ 243,6 254,12 @@
	-fx-background-color: COLOR_VGRAD_DARK;
}

.tool-bar.list-related-toolbar .toggle-button:focused,
.tool-bar.list-related-toolbar .button:focused {
	-fx-border-style: dotted inside;
	-fx-border-color: black;
}

/*******************************************************************************
 *																			 *
 * PopupMenu																   *


@@ 333,6 350,10 @@
.check-box:selected > .box > .mark {
	-fx-background-color: COLOR_TEXT;
}
/* focused */
.check-box:focused {
	-fx-border-style: dotted inside;
}
/* disabled: */
.check-box:disabled > .box {
	-fx-background-color: COLOR_BORDER, COLOR_BACKGROUND;


@@ 355,6 376,10 @@
	-fx-text-fill: COLOR_TEXT;
}

.choice-box:focused {
	-fx-border-style: dotted inside;
}

.choice-box > .open-button > .arrow {
	-fx-background-color: transparent, COLOR_TEXT;
	-fx-background-insets: 0 0 -1 0, 0;

M main/ui/src/main/resources/css/win_theme.css => main/ui/src/main/resources/css/win_theme.css +22 -0
@@ 157,36 157,48 @@
 
.list-view {
    -fx-background-color: COLOR_BORDER, #FFF;
    -fx-border-style: dotted inside;
    -fx-border-color: transparent;
    -fx-background-insets: 0, 1;
    -fx-padding: 1;
}

.list-view:focused {
	-fx-border-color: black;
}

.list-view > .virtual-flow > .scroll-bar:vertical{
    -fx-background-insets: 0, 0 0 0 1;
    -fx-padding: -1 -1 -1 0;
}

.list-view > .virtual-flow > .scroll-bar:horizontal{
    -fx-background-insets: 0, 1 0 0 0;
    -fx-padding: 0 -1 -1 -1;
}

.list-view > .virtual-flow > .corner {
    -fx-background-color: COLOR_BORDER, COLOR_CONTROL_BASE;
    -fx-background-insets: 0, 1 0 0 1;
}

.list-cell {
    -fx-background-color: #FFF;
    -fx-padding: 0.6em;
    -fx-text-fill: COLOR_TEXT;
    -fx-opacity: 1;
}

.list-view:focused > .virtual-flow > .clipped-container > .sheet > .list-cell:focused {
    -fx-background-color: COLOR_BORDER_FOCUS, #FFF;
    -fx-background-insets: 0, 1;
}

.list-view > .virtual-flow > .clipped-container > .sheet > .list-cell:filled:selected {
    -fx-background-color: #DEDEDE, #F7F7F7;
    -fx-background-insets: 0, 1;
}

.list-cell:filled:hover {
    -fx-background-color: #F7F7F7;
}


@@ 364,6 376,8 @@
.check-box {
    -fx-label-padding: 0 0 0 6px;
    -fx-text-fill: COLOR_TEXT;
    -fx-border-style: dotted inside;
    -fx-border-color: transparent;
}
.check-box > .box {
    -fx-padding: 1px;


@@ 380,6 394,10 @@
.check-box:armed > .box {
	-fx-border-color: COLOR_BORDER_FOCUS;
}
/* focused */
.check-box:focused {
	-fx-border-color: black;
}
/* selected: */
.check-box:selected > .box > .mark {
    -fx-background-color: black;


@@ 406,6 424,10 @@
	-fx-text-fill: COLOR_TEXT;
}

.choice-box:focused {
	-fx-border-style: dotted inside;
}

.choice-box > .open-button > .arrow {
	-fx-background-color: transparent, COLOR_TEXT;
	-fx-background-insets: 0 0 -1 0, 0;

M main/ui/src/main/resources/fxml/main.fxml => main/ui/src/main/resources/fxml/main.fxml +4 -4
@@ 53,7 53,7 @@

	<VBox prefWidth="200.0" cacheShape="true" cache="true">
		<StackPane VBox.vgrow="ALWAYS" cacheShape="true" cache="true">
			<ListView fx:id="vaultList" focusTraversable="false" cacheShape="true" cache="true"/>
			<ListView fx:id="vaultList" focusTraversable="true" cacheShape="true" cache="true"/>
			<AnchorPane fx:id="emptyListInstructions" cacheShape="true" cache="true">
				<HBox AnchorPane.leftAnchor="10.0" AnchorPane.rightAnchor="10.0" AnchorPane.bottomAnchor="100.0" alignment="CENTER" cacheShape="true" cache="true">
					<Label textAlignment="CENTER" text="%main.emptyListInstructions" wrapText="true" cacheShape="true" cache="true"/>


@@ 63,11 63,11 @@
		</StackPane>
		<ToolBar VBox.vgrow="NEVER" styleClass="list-related-toolbar" cacheShape="true" cache="true">
			<items>
				<ToggleButton text="&#xf489;" styleClass="ionicons" fx:id="addVaultButton" onAction="#didClickAddVault" focusTraversable="false" cacheShape="true" cache="true"/>
				<Button text="&#xf462;" styleClass="ionicons" fx:id="removeVaultButton" onAction="#didClickRemoveSelectedEntry" focusTraversable="false" cacheShape="true" cache="true"/>
				<ToggleButton text="&#xf489;" styleClass="ionicons" fx:id="addVaultButton" onAction="#didClickAddVault" focusTraversable="true" cacheShape="true" cache="true"/>
				<Button text="&#xf462;" styleClass="ionicons" fx:id="removeVaultButton" onAction="#didClickRemoveSelectedEntry" focusTraversable="true" cacheShape="true" cache="true"/>
				<Pane HBox.hgrow="ALWAYS" styleClass="spacer" />
				<!-- future use: -->
				<ToggleButton text="&#xf43c;" styleClass="ionicons" fx:id="settingsButton" onAction="#didClickShowSettings" focusTraversable="false" cacheShape="true" cache="true"/>
				<ToggleButton text="&#xf43c;" styleClass="ionicons" fx:id="settingsButton" onAction="#didClickShowSettings" focusTraversable="true" cacheShape="true" cache="true"/>
			</items>
		</ToolBar>
	</VBox>

M main/ui/src/main/resources/fxml/unlocked.fxml => main/ui/src/main/resources/fxml/unlocked.fxml +2 -2
@@ 54,8 54,8 @@
			<Label fx:id="messageLabel" cacheShape="true" cache="true" />
		</Pane>
		<HBox styleClass="segmented-button-bar" HBox.hgrow="NEVER" alignment="CENTER_RIGHT" cacheShape="true" cache="true">
			<Button text="%unlocked.button.lock" styleClass="first" onAction="#didClickLockVault" focusTraversable="false" cacheShape="true" cache="true"/>
			<ToggleButton text="&#xf104;" styleClass="last,ionicons" focusTraversable="false" fx:id="moreOptionsButton" onAction="#didClickMoreOptions" />
			<Button text="%unlocked.button.lock" styleClass="first" onAction="#didClickLockVault" focusTraversable="true" cacheShape="true" cache="true"/>
			<ToggleButton text="&#xf104;" styleClass="last,ionicons" focusTraversable="true" fx:id="moreOptionsButton" onAction="#didClickMoreOptions" />
		</HBox>
	</HBox>


M main/ui/src/main/resources/localization/ar.txt => main/ui/src/main/resources/localization/ar.txt +4 -2
@@ 77,7 77,6 @@ upgrade.version3to4.err.io = Migration failed due to an I/O Exception. See log f
settings.prefGvfsScheme.label = WebDAV Scheme
# upgrade.fxml
upgrade.confirmation.label = Yes, I've made sure that synchronization has finished
initialize.messageLabel.notEmpty = المحفظة غير فارغة
unlock.label.savePassword = حفظ كلمة المرور
unlock.errorMessage.unauthenticVersionMac = Could not authenticate version MAC.
unlocked.label.mountFailed = Connecting drive failed


@@ 101,4 100,7 @@ unlock.errorMessage.unlockFailed = Unlock failed. See log file for details.
unlocked.moreOptions.mount = Mount Drive
unlocked.moreOptions.unmount = Eject Drive
upgrade.version5toX.title = Vault Version Upgrade
upgrade.version5toX.msg = This vault needs to be migrated to a newer format.\nPlease make sure synchronization has finished before proceeding.
\ No newline at end of file
upgrade.version5toX.msg = This vault needs to be migrated to a newer format.\nPlease make sure synchronization has finished before proceeding.
main.createVault.nonEmptyDir.title = Creating vault failed
main.createVault.nonEmptyDir.header = Chosen directory is not empty
main.createVault.nonEmptyDir.content = The selected directory already contains files (possibly hidden). A vault can only be created in an empty directory.
\ No newline at end of file

M main/ui/src/main/resources/localization/bg.txt => main/ui/src/main/resources/localization/bg.txt +75 -73
@@ 1,35 1,35 @@
app.name = Криптоматор
# main.fxml
main.emptyListInstructions = Натиснете тук за да добавите сейф
main.directoryList.contextMenu.remove = Премахнете от листа
main.directoryList.contextMenu.changePassword = Сменете парола
main.addDirectory.contextMenu.new = Създайте нов сейф
main.addDirectory.contextMenu.open = Отворете съществуващ сейф
main.emptyListInstructions = Натиснете тук за добавяне на сейф
main.directoryList.contextMenu.remove = Премахване от листата
main.directoryList.contextMenu.changePassword = Смяна на парола
main.addDirectory.contextMenu.new = Създаване на нов сейф
main.addDirectory.contextMenu.open = Отворяне на съществуващ сейф
# welcome.fxml
welcome.checkForUpdates.label.currentlyChecking = Проверете за нови версии
welcome.newVersionMessage = Version %1$s can be downloaded.\nThis is %2$s.
welcome.checkForUpdates.label.currentlyChecking = Проверка за обновления...
welcome.newVersionMessage = Версия %1$s може да бъде свалена.\nТази е %2$s.
# initialize.fxml
initialize.label.password = Парола
initialize.label.retypePassword = Повторете Паролата
initialize.button.ok = Създайте Сейф
initialize.label.retypePassword = Повторете паролата
initialize.button.ok = Създаване на сейф
initialize.messageLabel.alreadyInitialized = Сейфа е вече активен
initialize.messageLabel.initializationFailed = Неуспешно активиране на сейф. Проверете лог файловете за повече информация.
# notfound.fxml
notfound.label = Сейфа не може да бъде намерен. Може би е бил преместен?
# upgrade.fxml
upgrade.button = Обновете версията на Сейф
upgrade.version3dropBundleExtension.msg = This vault needs to be migrated to a newer format.\n"%1$s" will be renamed to "%2$s".\nPlease make sure synchronization has finished before proceeding.
upgrade.version3dropBundleExtension.err.alreadyExists = Автоматичната миграция е неуспешна. "%s" вече съществува.
upgrade.button = Обновете сейфа
upgrade.version3dropBundleExtension.msg = Този сейф трябва да бъде променен към новия формат.\n"%1$s" ще бъде преименуван в "%2$s".\nМоля, уверете се, че синхронизацията е преключила преди да продължите.
upgrade.version3dropBundleExtension.err.alreadyExists = Автоматичната промяна е неуспешна. "%s" вече съществува.
# unlock.fxml
unlock.label.password = Парола
unlock.label.mountName = Име на диск
unlock.label.winDriveLetter = Инициали на диск
unlock.label.downloadsPageLink = Покажи всички версии на Криптоматор
unlock.label.downloadsPageLink = Всички версии на Криптоматор
unlock.label.advancedHeading = Опции за напреднали
unlock.button.unlock = Отключи Сейф
unlock.button.advancedOptions.show = Покажи повече опции
unlock.button.advancedOptions.hide = Покажи по-малко опции
unlock.choicebox.winDriveLetter.auto = Автоматично наименование на Диска
unlock.button.unlock = Отключване на сейф
unlock.button.advancedOptions.show = Повече опции
unlock.button.advancedOptions.hide = По-малко опции
unlock.choicebox.winDriveLetter.auto = Автоматично наименование на диска
unlock.errorMessage.wrongPassword = Неправилна парола
unlock.errorMessage.unsupportedVersion.vaultOlderThanSoftware = Неподържана версия. Този сейф е бил създаден със стара версия на Криптоматор.
unlock.errorMessage.unsupportedVersion.softwareOlderThanVault = Неподържана версия. Този сейф е бил създаден с по-нова версия на Криптоматор.


@@ 38,67 38,69 @@ unlock.messageLabel.startServerFailed = Неуспешно стартиране 
changePassword.label.oldPassword = Стара парола
changePassword.label.newPassword = Нова парола
changePassword.label.retypePassword = Повторете паролата
changePassword.label.downloadsPageLink = All Cryptomator versions
changePassword.label.downloadsPageLink = Всички версии на Криптоматор
changePassword.button.change = Смени паролата
changePassword.errorMessage.wrongPassword = Неправилна парола
changePassword.errorMessage.decryptionFailed = Неуспешно декриптиране
# unlocked.fxml
unlocked.button.lock = Заключи Сейфа
unlocked.moreOptions.reveal = Покажи 
unlocked.moreOptions.copyUrl = Copy WebDAV URL
unlocked.button.lock = Заключване на Сейфа
unlocked.moreOptions.reveal = Покажи диска
unlocked.moreOptions.copyUrl = Копиране адреса на WebDAV
unlocked.label.revealFailed = Командата е неуспешна
unlocked.label.unmountFailed = Ejecting drive failed
unlocked.label.statsEncrypted = encrypted
unlocked.label.statsDecrypted = decrypted
unlocked.ioGraph.yAxis.label = Throughput (MiB/s)
unlocked.label.unmountFailed = Изваждането на диска е неуспешно
unlocked.label.statsEncrypted = криптирано
unlocked.label.statsDecrypted = декрептирано
unlocked.ioGraph.yAxis.label = Скорост (MB/s)
# settings.fxml
settings.version.label = Version %s
settings.checkForUpdates.label = Check for Updates
settings.port.label = WebDAV Port
settings.port.prompt = 0 \= Choose automatically
settings.requiresRestartLabel = * Cryptomator needs to restart
settings.version.label = Версия %s
settings.checkForUpdates.label = Проверка за обновления
settings.port.label = WebDAV порт
settings.port.prompt = 0 \= Автоматично затваряне
settings.requiresRestartLabel = * Криптоматор трябва да се рестартира
# tray icon
tray.menu.open = Open
tray.menu.quit = Quit
tray.infoMsg.title = Still Running
tray.infoMsg.msg = Cryptomator is still alive. Quit it from the tray icon.
tray.infoMsg.msg.osx = Cryptomator is still alive. Quit it from the menu bar icon.
initialize.messageLabel.passwordStrength.0 = Very weak
initialize.messageLabel.passwordStrength.1 = Weak
initialize.messageLabel.passwordStrength.2 = Fair
initialize.messageLabel.passwordStrength.3 = Strong
initialize.messageLabel.passwordStrength.4 = Very strong
initialize.label.doNotForget = IMPORTANT\: If you forget your password, there is no way to recover your data.
main.directoryList.remove.confirmation.title = Remove Vault
main.directoryList.remove.confirmation.header = Do you really want to remove this vault?
main.directoryList.remove.confirmation.content = The vault will only be removed from the list. To permanently delete it, please delete the vault from your filesystem.
upgrade.version3to4.msg = This vault needs to be migrated to a newer format.\nEncrypted folder names will be updated.\nPlease make sure synchronization has finished before proceeding.
upgrade.version3to4.err.io = Migration failed due to an I/O Exception. See log file for details.
settings.prefGvfsScheme.label = WebDAV Scheme
tray.menu.open = Отворяне
tray.menu.quit = Излизане
tray.infoMsg.title = Все още върви
tray.infoMsg.msg = Криптоматор все още върви. Излезте от иконата в трея.
tray.infoMsg.msg.osx = Криптоматор все още върви. Излезте от иконата в менюто.
initialize.messageLabel.passwordStrength.0 = Прекалено слаба
initialize.messageLabel.passwordStrength.1 = Слаба
initialize.messageLabel.passwordStrength.2 = Добра
initialize.messageLabel.passwordStrength.3 = Силна
initialize.messageLabel.passwordStrength.4 = Много силна
initialize.label.doNotForget = ВАЖНО\: Ако забравите паролата, няма начин да възстановите данните.
main.directoryList.remove.confirmation.title = Премахване на сейф
main.directoryList.remove.confirmation.header = Наистина ли искате да премахнете този сейф?
main.directoryList.remove.confirmation.content = Този сейф ще бъде премахнат само от листа. За да го изтриете напълно, моля, изтрийте сейфа от файл системата.
upgrade.version3to4.msg = Този сейф трябва да бъде преместен към по-нов формат.\nКриптираните имена на папки ще бъдат обновени.\nМоля, проверете дали сихронизацията е приключила преди да продължите.
upgrade.version3to4.err.io = Преместването е отменено поради грешка в диска. Вижте лог файла за детайли.
settings.prefGvfsScheme.label = WebDAV схема
# upgrade.fxml
upgrade.confirmation.label = Yes, I've made sure that synchronization has finished
initialize.messageLabel.notEmpty = Vault not empty
unlock.label.savePassword = Save Password
unlock.errorMessage.unauthenticVersionMac = Could not authenticate version MAC.
unlocked.label.mountFailed = Connecting drive failed
unlock.savePassword.delete.confirmation.title = Delete Saved Password
unlock.savePassword.delete.confirmation.header = Do you really want to delete the saved password of this vault?
unlock.savePassword.delete.confirmation.content = The saved password of this vault will be immediately deleted from your system keychain. If you'd like to save your password again, you'd have to unlock your vault with the "Save Password" option enabled.
settings.debugMode.label = Debug Mode *
upgrade.version3dropBundleExtension.title = Vault Version 3 Upgrade (Drop Bundle Extension)
upgrade.version3to4.title = Vault Version 3 to 4 Upgrade
upgrade.version4to5.title = Vault Version 4 to 5 Upgrade
upgrade.version4to5.msg = This vault needs to be migrated to a newer format.\nEncrypted files will be updated.\nPlease make sure synchronization has finished before proceeding.\n\nNote\: Modification date of all files will be changed to the current date/time in the process.
upgrade.version4to5.err.io = Migration failed due to an I/O Exception. See log file for details.
settings.port.apply = Apply
unlock.label.mountAfterUnlock = Mount Drive
unlock.label.revealAfterMount = Reveal Drive
unlocked.lock.force.confirmation.title = Locking of %1$s failed
unlocked.lock.force.confirmation.header = Do you want to force locking?
unlocked.lock.force.confirmation.content = This may be because other programs are still accessing files in the vault or because some other problem occurred.\n\nPrograms still accessing the files may not work correctly and data not already written by those programs may be lost.
unlock.label.unlockAfterStartup = Auto-Unlock on Start (Experimental)
unlock.errorMessage.unlockFailed = Unlock failed. See log file for details.
unlocked.moreOptions.mount = Mount Drive
unlocked.moreOptions.unmount = Eject Drive
upgrade.version5toX.title = Vault Version Upgrade
upgrade.version5toX.msg = This vault needs to be migrated to a newer format.\nPlease make sure synchronization has finished before proceeding.
\ No newline at end of file
upgrade.confirmation.label = Да, сигурен съм, че сихронизацията е приключила
unlock.label.savePassword = Запазване на парола
unlock.errorMessage.unauthenticVersionMac = Неуспешна оторизация на MAC версията
unlocked.label.mountFailed = Връзката с диска неуспешна
unlock.savePassword.delete.confirmation.title = Изтриване на запазената парола
unlock.savePassword.delete.confirmation.header = Неистина ли искате да изтриете запазената парола за този сейф?
unlock.savePassword.delete.confirmation.content = Запазената парола за този сейф ще бъде незабавно премахната от Вашата система. Ако желаете да запазите паролата отново, трябва да отключите сейса с пусната опция "Запазване на павола".
settings.debugMode.label = Режим за отстраняване на грешки *
upgrade.version3dropBundleExtension.title = Обновяване до сейф версия 3
upgrade.version3to4.title = Обновяване на сейф от 3-та до 4-та версия
upgrade.version4to5.title = Обновяване на сейф от 4-та до 5-та версия
upgrade.version4to5.msg = Този сейф трябва да бъде променен към по-нов формат.\nКриптираните файлове ще бъдат обновени.\nМоля, проверете дали сихронизацията е приключила преди да продължите.\n\nЗабележка\: Датата на промяна на всички файлове ще бъде обновена до момента.
upgrade.version4to5.err.io = Преместването провалено поради грешка в диска. Вижте лог файла за детайли.
settings.port.apply = Прилагане
unlock.label.mountAfterUnlock = Закачане на диска
unlock.label.revealAfterMount = Показване на диска
unlocked.lock.force.confirmation.title = Заключването на %1$s провалено
unlocked.lock.force.confirmation.header = Желаете ли принудително заключване?
unlocked.lock.force.confirmation.content = Това е може би защото други програми все още използват файловете в сейфа или защото има някакъв друг проблем.\n\nПрограмите, имащи достъп до файловете, може да не работят правилно и информацията, незаписана от тези програми, може да бъде изгубена.
unlock.label.unlockAfterStartup = Автоматично отключване при стартиране (Експериментално)
unlock.errorMessage.unlockFailed = Грешка при отключване. Вижте лог файла за детайли.
unlocked.moreOptions.mount = Закачане на диск
unlocked.moreOptions.unmount = Изваждане на диск
upgrade.version5toX.title = Обновяване на версията на сейфа
upgrade.version5toX.msg = Този сейф трябва да бъде обновен до по-нов формат.\nМоля, уверете се, че сихронизацията е приключила, преди да продължите.
main.createVault.nonEmptyDir.title = Creating vault failed
main.createVault.nonEmptyDir.header = Chosen directory is not empty
main.createVault.nonEmptyDir.content = The selected directory already contains files (possibly hidden). A vault can only be created in an empty directory.
\ No newline at end of file

M main/ui/src/main/resources/localization/da.txt => main/ui/src/main/resources/localization/da.txt +4 -2
@@ 77,7 77,6 @@ upgrade.version3to4.err.io = Migrering fejlede pga. en I/O fejl. Se logfilen for
settings.prefGvfsScheme.label = WebDAV Scheme
# upgrade.fxml
upgrade.confirmation.label = Ja, jeg har sikret mig at al synkronisering er gennemført.
initialize.messageLabel.notEmpty = Vault er ikke tom
unlock.label.savePassword = Gem adgangskode
unlock.errorMessage.unauthenticVersionMac = Kunne ikke autentificere versions-MAC
unlocked.label.mountFailed = Montering af drev fejlede


@@ 101,4 100,7 @@ unlock.errorMessage.unlockFailed = Unlock failed. See log file for details.
unlocked.moreOptions.mount = Mount Drive
unlocked.moreOptions.unmount = Eject Drive
upgrade.version5toX.title = Vault Version Upgrade
upgrade.version5toX.msg = This vault needs to be migrated to a newer format.\nPlease make sure synchronization has finished before proceeding.
\ No newline at end of file
upgrade.version5toX.msg = This vault needs to be migrated to a newer format.\nPlease make sure synchronization has finished before proceeding.
main.createVault.nonEmptyDir.title = Creating vault failed
main.createVault.nonEmptyDir.header = Chosen directory is not empty
main.createVault.nonEmptyDir.content = The selected directory already contains files (possibly hidden). A vault can only be created in an empty directory.
\ No newline at end of file

M main/ui/src/main/resources/localization/de.txt => main/ui/src/main/resources/localization/de.txt +4 -2
@@ 77,7 77,6 @@ upgrade.version3to4.err.io = Migration aufgrund eines I/O-Fehlers fehlgeschlagen
settings.prefGvfsScheme.label = WebDAV Schema
# upgrade.fxml
upgrade.confirmation.label = Ja, die Synchronisation ist abgeschlossen
initialize.messageLabel.notEmpty = Tresor ist nicht leer
unlock.label.savePassword = Passwort speichern
unlock.errorMessage.unauthenticVersionMac = Versions-MAC konnte nicht authentifiziert werden.
unlocked.label.mountFailed = Verbinden des Laufwerks fehlgeschlagen


@@ 101,4 100,7 @@ unlock.errorMessage.unlockFailed = Entsperren fehlgeschlagen. Siehe Log-Datei f
unlocked.moreOptions.mount = Laufwerk verbinden
unlocked.moreOptions.unmount = Laufwerk auswerfen
upgrade.version5toX.title = Upgrade Tresor-Version 5 zu X
upgrade.version5toX.msg = Dieser Tresor muss auf ein neueres Format aktualisiert werden.\nStellen Sie sicher, dass keine Synchronisation stattfindet, bevor Sie fortfahren.
\ No newline at end of file
upgrade.version5toX.msg = Dieser Tresor muss auf ein neueres Format aktualisiert werden.\nStellen Sie sicher, dass keine Synchronisation stattfindet, bevor Sie fortfahren.
main.createVault.nonEmptyDir.title = Erstellung des Tresors fehlgeschlagen
main.createVault.nonEmptyDir.header = Ausgewählter Ordner ist nicht leer
main.createVault.nonEmptyDir.content = Der ausgewählte Ordner enthält bereits Dateien (möglicherweise unsichtbar). Ein Tresor kann nur innerhalb eines leeren Ordners erstellt werden.
\ No newline at end of file

M main/ui/src/main/resources/localization/en.txt => main/ui/src/main/resources/localization/en.txt +4 -2
@@ 16,6 16,9 @@ main.addDirectory.contextMenu.open=Open Existing Vault
main.directoryList.remove.confirmation.title=Remove Vault
main.directoryList.remove.confirmation.header=Do you really want to remove this vault?
main.directoryList.remove.confirmation.content=The vault will only be removed from the list. To permanently delete it, please delete the vault from your filesystem.
main.createVault.nonEmptyDir.title=Creating vault failed
main.createVault.nonEmptyDir.header=Chosen directory is not empty
main.createVault.nonEmptyDir.content=The selected directory already contains files (possibly hidden). A vault can only be created in an empty directory.

# welcome.fxml
welcome.checkForUpdates.label.currentlyChecking=Checking for Updates...


@@ 26,7 29,6 @@ initialize.label.password=Password
initialize.label.retypePassword=Retype Password
initialize.button.ok=Create Vault
initialize.messageLabel.alreadyInitialized=Vault already initialized
initialize.messageLabel.notEmpty=Vault not empty
initialize.messageLabel.initializationFailed=Could not initialize vault. See log file for details.
initialize.messageLabel.passwordStrength.0=Very weak
initialize.messageLabel.passwordStrength.1=Weak


@@ 83,7 85,7 @@ unlock.messageLabel.startServerFailed=Starting WebDAV server failed.

# change_password.fxml
changePassword.label.oldPassword=Old Password
changePassword.label.newPassword=New Nassword
changePassword.label.newPassword=New Password
changePassword.label.retypePassword=Retype Password
changePassword.label.downloadsPageLink=All Cryptomator versions
changePassword.button.change=Change Password

M main/ui/src/main/resources/localization/es.txt => main/ui/src/main/resources/localization/es.txt +40 -38
@@ 1,6 1,6 @@
app.name = Cryptomator
# main.fxml
main.emptyListInstructions = Haz clic aquí para añadir una caja fuerte
main.emptyListInstructions = Haga clic aquí para añadir una caja fuerte
# should it be imperative?
main.directoryList.contextMenu.remove = Eliminar de la lista
main.directoryList.contextMenu.changePassword = Cambiar la contraseña


@@ 14,13 14,13 @@ initialize.label.password = Contraseña
initialize.label.retypePassword = Repetir contraseña
initialize.button.ok = Crear caja fuerte
initialize.messageLabel.alreadyInitialized = La caja fuerte ya está inicializada
initialize.messageLabel.initializationFailed = No se pudo inicializar la caja fuerte. Ver archivo de registro para detalles.
initialize.messageLabel.initializationFailed = No se ha podido inicializar la caja fuerte. Consulte el archivo de registro para más información.
# notfound.fxml
notfound.label = No se pudo encontrar la caja fuerte. Se movió a otro lugar?
notfound.label = No se ha encontrado la caja fuerte. ¿Se movió a otro lugar?
# upgrade.fxml
upgrade.button = Actualizar caja fuerte
upgrade.version3dropBundleExtension.msg = Este caja fuerte se debe actualizar a un nuevo formato.\n"%1$s" se renombra a "%2$s".\nPor favor aseguranse que la sincronización ya se terminó antes de continuar.
upgrade.version3dropBundleExtension.err.alreadyExists = Migración automática ha fallado.\n"%s" ya existe.
upgrade.version3dropBundleExtension.msg = Este caja fuerte se debe actualizar a un formato más moderno.\n"%1$s" se renombrará a "%2$s".\nAsegúrese de que la sincronización ha terminado antes de iniciar el proceso.
upgrade.version3dropBundleExtension.err.alreadyExists = Error en la migración automática.\n"%s" ya existe.
# unlock.fxml
unlock.label.password = Contraseña
unlock.label.mountName = Nombre de la unidad


@@ 32,9 32,9 @@ unlock.button.advancedOptions.show = Más opciones
unlock.button.advancedOptions.hide = Menos opciones
unlock.choicebox.winDriveLetter.auto = Asignar automáticamente
unlock.errorMessage.wrongPassword = Contraseña incorrecta
unlock.errorMessage.unsupportedVersion.vaultOlderThanSoftware = Caja fuerte no soportada. Ésta caja se ha creado con una versión anterior de Cryptomator.
unlock.errorMessage.unsupportedVersion.softwareOlderThanVault = Caja fuerte no soportada. Ésta caja se ha creado con una versión nueva de Cryptomator.
unlock.messageLabel.startServerFailed = Iniciación del servidor de WebDAV ha fallado.
unlock.errorMessage.unsupportedVersion.vaultOlderThanSoftware = Caja fuerte no soportada. Esta caja se ha creado con una versión anterior de Cryptomator.
unlock.errorMessage.unsupportedVersion.softwareOlderThanVault = Caja fuerte no soportada. Esta caja se ha creado con una versión más moderna de Cryptomator.
unlock.messageLabel.startServerFailed = Error al iniciar el servidor de WebDAV.
# change_password.fxml
changePassword.label.oldPassword = Contraseña antigua
# Can also use "current password" = "contraseña actual"


@@ 43,65 43,67 @@ changePassword.label.retypePassword = Repetir contraseña
changePassword.label.downloadsPageLink = Todas las versiones de Cryptomator
changePassword.button.change = Cambiar contraseña
changePassword.errorMessage.wrongPassword = Contraseña incorrecta
changePassword.errorMessage.decryptionFailed = Decifración ha fallado
changePassword.errorMessage.decryptionFailed = Error en el descifrado
# unlocked.fxml
unlocked.button.lock = Encerrar caja fuerte
unlocked.button.lock = Bloquear caja fuerte
unlocked.moreOptions.reveal = Revelar unidad
unlocked.moreOptions.copyUrl = Copiar URL de WebDAV
unlocked.label.revealFailed = Comando ha fallado
unlocked.label.unmountFailed = Expulsar el disco ha fallado
unlocked.label.revealFailed = La orden ha fallado
unlocked.label.unmountFailed = Error al expulsar la unidad
unlocked.label.statsEncrypted = cifrado
unlocked.label.statsDecrypted = decifrado
unlocked.ioGraph.yAxis.label = Procesamiento (MiB/s)
unlocked.label.statsDecrypted = descifrado
unlocked.ioGraph.yAxis.label = Rendimiento (MiB/s)
# settings.fxml
settings.version.label = Versión %s
settings.checkForUpdates.label = Comprobar actualizaciones
settings.port.label = Puerto WebDAV
settings.port.prompt = 0 \= Elegir automáticamente
settings.requiresRestartLabel = * Cryptomator se necesita reiniciar
settings.requiresRestartLabel = * Cryptomator necesita reiniciarse
# tray icon
tray.menu.open = Abrir
tray.menu.quit = Salir
tray.infoMsg.title = Todavía en ejecución
tray.infoMsg.msg = Cryptomator todavía esta en ejecución. Para salir usa el icono del tray.
tray.infoMsg.msg.osx = Cryptomator todavía esta en ejecución. Para salir usa el icono de la barra del menú.
tray.infoMsg.msg = Cryptomator todavía está en ejecución. Para salir use el icono de la bandeja.
tray.infoMsg.msg.osx = Cryptomator todavía está en ejecución. Para salir use el icono de la barra del menú.
initialize.messageLabel.passwordStrength.0 = Muy débil
initialize.messageLabel.passwordStrength.1 = Débil
initialize.messageLabel.passwordStrength.2 = Suficiente
initialize.messageLabel.passwordStrength.3 = Fuerte
initialize.messageLabel.passwordStrength.4 = Muy fuerte
initialize.label.doNotForget = IMPORTANTE\: Si olivdas tú contraseña, no hay ninguna manera de recuperar tus datos.
initialize.label.doNotForget = IMPORTANTE\: Si olvida la contraseña, no habrá ninguna manera de recuperar los datos.
main.directoryList.remove.confirmation.title = Borrar caja fuerte
main.directoryList.remove.confirmation.header = ¿Quieres de verdad borrar esta caja fuerte?
main.directoryList.remove.confirmation.content = La caja fuerte solo se borra de la lista. Para eliminarla permanente por favor elimina los datos de tú sistema de archivos.
upgrade.version3to4.msg = Este caja fuerte se debe migrar a un formato más reciente.\nLos nombres de las carpetas cifradas se actualizan.\nPor favor asegurarse de que la sincronización ha terminado antes de seguir.
upgrade.version3to4.err.io = Migración ha fallado por causa de una excepción I/O. Para detalles revisa el archivo de registro.
main.directoryList.remove.confirmation.header = ¿Quiere de realmente eliminar esta caja fuerte?
main.directoryList.remove.confirmation.content = La caja fuerte solo se elimina de la lista. Para borrarla permanente elimine los datos de su sistema de archivos.
upgrade.version3to4.msg = Este caja fuerte se debe migrar a un formato más moderno.\nLos nombres de las carpetas cifradas se actualizarán.\nAsegúrese de que la sincronización ha terminado antes de continuar.
upgrade.version3to4.err.io = Error en la migración debido a una excepción de E/S. Consulte el archivo de registro para más información.
# or esequema WEBDAV but I think sistema sounds better
settings.prefGvfsScheme.label = Esquema WebDAV
settings.prefGvfsScheme.label = Esquema de WebDAV
# upgrade.fxml
upgrade.confirmation.label = Sí, me he asegurado de que la sincronización ha terminado
initialize.messageLabel.notEmpty = Caja fuerte no está vacia
unlock.label.savePassword = Guardar contraseña
unlock.errorMessage.unauthenticVersionMac = No se pudo autentificar la versión de MAC.
unlocked.label.mountFailed = Error al montar la unidad
unlock.savePassword.delete.confirmation.title = Borrar contraseña guardada
unlock.savePassword.delete.confirmation.header = ¿Quieres borrar la contraseña guardada de esta unidad?
unlock.savePassword.delete.confirmation.content = La contraseña guardada de esta caja fuerte, será borrada inmediatamente del sistema de claves. Si quieres guardar tu contraseña de nuevo, tienes que volver a desbloquear la caja fuerte marcando la opción de "Guardar contraseña".
unlock.savePassword.delete.confirmation.header = ¿Quiere realmente borrar la contraseña guardada de esta unidad?
unlock.savePassword.delete.confirmation.content = La contraseña guardada de esta caja fuerte, será borrada inmediatamente del sistema de claves. Si quiere guardar su contraseña de nuevo, tiene que volver a desbloquear la caja fuerte marcando la opción de "Guardar contraseña".
settings.debugMode.label = Modo depuración *
upgrade.version3dropBundleExtension.title = Actualizar caja fuerte a la versión 3 (Drop Bundle Extension)
upgrade.version3to4.title = Actualizar caja fuerte de versión 3 a 4
upgrade.version4to5.title = Actualizar caja fuerte de versión 3 a 4
upgrade.version4to5.msg = Esta caja fuerte tiene que ser migrada a un formato nuevo.\nLos archivos encriptados se actualizarán.\nPor favor, asegúrate de que la sincronización ha terminado antes de empezar con el proceso.\n\nNota\: Las fechas de modificación de todos los archivos, se cambiarán a la fecha actual.
upgrade.version4to5.err.io = La migración ha fallado por una excepción E/S. Consulta el log para ver más detalles.
upgrade.version4to5.title = Actualizar caja fuerte de versión 4 a 5
upgrade.version4to5.msg = Esta caja fuerte tiene que ser migrada a un formato más moderno.\nLos archivos cifrados se actualizarán.\nAsegúrese de que la sincronización ha terminado antes de iniciar el proceso.\n\nNota\: las fechas de modificación de todos los archivos, se cambiarán a la fecha actual.
upgrade.version4to5.err.io = Error en la migración debido a una excepción E/S. Consulte el archivo de registro para más información.
settings.port.apply = Aplicar
unlock.label.mountAfterUnlock = Montar unidad
unlock.label.revealAfterMount = Revelar unidad
unlocked.lock.force.confirmation.title = Locking of %1$s failed
unlocked.lock.force.confirmation.header = Do you want to force locking?
unlocked.lock.force.confirmation.content = This may be because other programs are still accessing files in the vault or because some other problem occurred.\n\nPrograms still accessing the files may not work correctly and data not already written by those programs may be lost.
unlock.label.unlockAfterStartup = Auto-Unlock on Start (Experimental)
unlock.errorMessage.unlockFailed = Unlock failed. See log file for details.
unlocked.moreOptions.mount = Mount Drive
unlocked.moreOptions.unmount = Eject Drive
upgrade.version5toX.title = Vault Version Upgrade
upgrade.version5toX.msg = This vault needs to be migrated to a newer format.\nPlease make sure synchronization has finished before proceeding.
\ No newline at end of file
unlocked.lock.force.confirmation.title = Error al bloquear %1$s
unlocked.lock.force.confirmation.header = ¿Quiere forzar el bloqueo?
unlocked.lock.force.confirmation.content = Esto puede ser debido a que otros programas estén todavía accediendo a la caja fuerte o porque se ha producido algún otro problema.\n\nLos programas que estén todavía accediendo a los archivos pueden no funcionar correctamente y se pueden perder los datos pendientes de escribir por estos programas.
unlock.label.unlockAfterStartup = Autodesbloqueo al arrancar (experimental)
unlock.errorMessage.unlockFailed = Error al desbloquear. Consulte el archivo de registro para más información.
unlocked.moreOptions.mount = Montar unidad
unlocked.moreOptions.unmount = Expulsar unidad
upgrade.version5toX.title = Actualizar la versión de la caja fuerte
upgrade.version5toX.msg = Esta caja fuerte debe ser migrada a un formato más moderno.\nAsegúrese de que la sincronización ha terminado antes de iniciar el proceso.
main.createVault.nonEmptyDir.title = Creating vault failed
main.createVault.nonEmptyDir.header = Chosen directory is not empty
main.createVault.nonEmptyDir.content = The selected directory already contains files (possibly hidden). A vault can only be created in an empty directory.
\ No newline at end of file

M main/ui/src/main/resources/localization/fr.txt => main/ui/src/main/resources/localization/fr.txt +12 -10
@@ 80,7 80,6 @@ upgrade.version3to4.err.io = La migration a échoué à cause d'une erreur d'ent
settings.prefGvfsScheme.label = Schéma d'URI WebDAV
# upgrade.fxml
upgrade.confirmation.label = Oui, je suis certain que la synchronisation est terminée
initialize.messageLabel.notEmpty = Le coffre n'est pas vide
unlock.label.savePassword = Se souvenir du mot de passe
unlock.errorMessage.unauthenticVersionMac = Impossible d'authentifier la version MAC
unlocked.label.mountFailed = Echec de connexion au lecteur


@@ 96,12 95,15 @@ upgrade.version4to5.err.io = Migration échouée due à une erreur de lecture. L
settings.port.apply = Appliquer
unlock.label.mountAfterUnlock = Monter un lecteur
unlock.label.revealAfterMount = Voir le lecteur
unlocked.lock.force.confirmation.title = Locking of %1$s failed
unlocked.lock.force.confirmation.header = Do you want to force locking?
unlocked.lock.force.confirmation.content = This may be because other programs are still accessing files in the vault or because some other problem occurred.\n\nPrograms still accessing the files may not work correctly and data not already written by those programs may be lost.
unlock.label.unlockAfterStartup = Auto-Unlock on Start (Experimental)
unlock.errorMessage.unlockFailed = Unlock failed. See log file for details.
unlocked.moreOptions.mount = Mount Drive
unlocked.moreOptions.unmount = Eject Drive
upgrade.version5toX.title = Vault Version Upgrade
upgrade.version5toX.msg = This vault needs to be migrated to a newer format.\nPlease make sure synchronization has finished before proceeding.
\ No newline at end of file
unlocked.lock.force.confirmation.title = Le vérouillage de %1$s a ćhoué
unlocked.lock.force.confirmation.header = Voulez-vous forcer le vérouillage ?
unlocked.lock.force.confirmation.content = Cela peut être car d'autres programmes sont entrain d'accéder à des fichiers dans le coffre ou car d'autres problème se sont produits.\n\nLes programmes accédant aux fichiers pourraient ne pas fonctionner normalement et les données pas encore sauvegardées par ces programmes pourraient être perdues.
unlock.label.unlockAfterStartup = Déverouiller automatiquement au démarrage (Experimental)
unlock.errorMessage.unlockFailed = Le déverouillage a échoué. Regarder les logs pour plus d'informations.
unlocked.moreOptions.mount = Monter le disque
unlocked.moreOptions.unmount = Ejecter le disque
upgrade.version5toX.title = Mise à niveau de la version du coffre
upgrade.version5toX.msg = Ce coffre doit être converti dans un format plus récent. Veuillez-vous assurez que la synchronisation est finie avant de continuer.
main.createVault.nonEmptyDir.title = Creating vault failed
main.createVault.nonEmptyDir.header = Chosen directory is not empty
main.createVault.nonEmptyDir.content = The selected directory already contains files (possibly hidden). A vault can only be created in an empty directory.
\ No newline at end of file

M main/ui/src/main/resources/localization/hu.txt => main/ui/src/main/resources/localization/hu.txt +4 -2
@@ 77,7 77,6 @@ upgrade.version3to4.err.io = Migráció meghíusúlt egy I/O kivétel miatt. Ké
settings.prefGvfsScheme.label = WebDAV séma
# upgrade.fxml
upgrade.confirmation.label = Igen, meggyőződtem a szinkronizáció befejeztéről
initialize.messageLabel.notEmpty = A széf nem üres
unlock.label.savePassword = Jelszó mentése
unlock.errorMessage.unauthenticVersionMac = Could not authenticate version MAC.
unlocked.label.mountFailed = Meghajtó csatlakoztatása sikertelen


@@ 101,4 100,7 @@ unlock.errorMessage.unlockFailed = Unlock failed. See log file for details.
unlocked.moreOptions.mount = Mount Drive
unlocked.moreOptions.unmount = Eject Drive
upgrade.version5toX.title = Vault Version Upgrade
upgrade.version5toX.msg = This vault needs to be migrated to a newer format.\nPlease make sure synchronization has finished before proceeding.
\ No newline at end of file
upgrade.version5toX.msg = This vault needs to be migrated to a newer format.\nPlease make sure synchronization has finished before proceeding.
main.createVault.nonEmptyDir.title = Creating vault failed
main.createVault.nonEmptyDir.header = Chosen directory is not empty
main.createVault.nonEmptyDir.content = The selected directory already contains files (possibly hidden). A vault can only be created in an empty directory.
\ No newline at end of file

M main/ui/src/main/resources/localization/it.txt => main/ui/src/main/resources/localization/it.txt +4 -2
@@ 77,7 77,6 @@ upgrade.version3to4.err.io = Migrazione fallita a causa di una eccezione I/O. Ve
settings.prefGvfsScheme.label = Schema WebDAV
# upgrade.fxml
upgrade.confirmation.label = Si, sono sicuro che la sincronizzazione e' terminata
initialize.messageLabel.notEmpty = Vault non vuoto
unlock.label.savePassword = Salva Password
unlock.errorMessage.unauthenticVersionMac = Non riesco ad autenticare la versione MAC.
unlocked.label.mountFailed = Tentativo di connessione drive fallito


@@ 101,4 100,7 @@ unlock.errorMessage.unlockFailed = Unlock failed. See log file for details.
unlocked.moreOptions.mount = Mount Drive
unlocked.moreOptions.unmount = Eject Drive
upgrade.version5toX.title = Vault Version Upgrade
upgrade.version5toX.msg = This vault needs to be migrated to a newer format.\nPlease make sure synchronization has finished before proceeding.
\ No newline at end of file
upgrade.version5toX.msg = This vault needs to be migrated to a newer format.\nPlease make sure synchronization has finished before proceeding.
main.createVault.nonEmptyDir.title = Creating vault failed
main.createVault.nonEmptyDir.header = Chosen directory is not empty
main.createVault.nonEmptyDir.content = The selected directory already contains files (possibly hidden). A vault can only be created in an empty directory.
\ No newline at end of file

M main/ui/src/main/resources/localization/ja.txt => main/ui/src/main/resources/localization/ja.txt +70 -68
@@ 1,104 1,106 @@
app.name = Cryptomator
# main.fxml
main.emptyListInstructions = ここをクリックして金庫を追加する
main.directoryList.contextMenu.remove = リストから削除する
main.directoryList.contextMenu.changePassword = パスワード変更
main.addDirectory.contextMenu.new = 新しい金庫を作成する
main.emptyListInstructions = ここをクリックして金庫を追加
main.directoryList.contextMenu.remove = リストから削除
main.directoryList.contextMenu.changePassword = パスワードの変更
main.addDirectory.contextMenu.new = 新しい金庫を作成
main.addDirectory.contextMenu.open = 既存の金庫を開く
# welcome.fxml
welcome.checkForUpdates.label.currentlyChecking = アップデートを確認中...
welcome.newVersionMessage = バージョン%1$sがダウンロードできます。\n現在のバージョンは%2$sです。
welcome.checkForUpdates.label.currentlyChecking = アップデートを確認しています...
welcome.newVersionMessage = バージョン %1$s がダウンロード可能です。\n現在のバージョンは %2$s です。
# initialize.fxml
initialize.label.password = パスワード
initialize.label.retypePassword = パスワード再入力
initialize.label.retypePassword = パスワードの再入力
initialize.button.ok = 金庫を作成
initialize.messageLabel.alreadyInitialized = 金庫がすでに初期化されています。
initialize.messageLabel.alreadyInitialized = 金庫は既に初期化されています。
initialize.messageLabel.initializationFailed = 金庫の初期化ができませんでした。詳細はログファイルをご覧ください。
# notfound.fxml
notfound.label = 金庫が見つかりませんでした。動かされたのですか?
notfound.label = 金庫が見つかりません。移動しましたか?
# upgrade.fxml
upgrade.button = 金庫をアップグレードする
upgrade.version3dropBundleExtension.msg = この金庫を新しい形式に移行する必要があります。\n"%1$s"は"%2$s"に変更されます。\n続行する前に同期が完了していることをご確認ください。
upgrade.version3dropBundleExtension.err.alreadyExists = 自動移行が失敗しました。\n"%s"はすでに存在します。
upgrade.button = 金庫をアップグレード
upgrade.version3dropBundleExtension.msg = この金庫を新しい形式に移行する必要があります。\n"%1$s" は "%2$s" に変更されます。\n続行する前に同期が完了していることをご確認ください。
upgrade.version3dropBundleExtension.err.alreadyExists = 自動移行が失敗しました。\n"%s" はすでに存在します。
# unlock.fxml
unlock.label.password = パスワード
unlock.label.mountName = ドライブ名
unlock.label.winDriveLetter = ドライブ文字
unlock.label.downloadsPageLink = 全てのCryptomatorバージョン
unlock.label.downloadsPageLink = すべての Cryptomator バージョン
unlock.label.advancedHeading = 詳細オプション
unlock.button.unlock = 金庫を解除する
unlock.button.advancedOptions.show = その他のオプション
unlock.button.advancedOptions.hide = 基本オプション
unlock.choicebox.winDriveLetter.auto = 自動に割り当てる
unlock.errorMessage.wrongPassword = 間違ったパスワード
unlock.errorMessage.unsupportedVersion.vaultOlderThanSoftware = サポートされていない金庫です。この金庫は古いバージョンのCryptomatorから作成されました。
unlock.errorMessage.unsupportedVersion.softwareOlderThanVault = サポートされていない金庫です。この金庫は新しいバージョンのCryptomatorから作成されました。
unlock.messageLabel.startServerFailed = WebDAVサーバーの起動失敗
unlock.button.unlock = 金庫を解錠
unlock.button.advancedOptions.show = オプションを表示
unlock.button.advancedOptions.hide = オプションを非表示
unlock.choicebox.winDriveLetter.auto = 自動的に割り当てる
unlock.errorMessage.wrongPassword = パスワードが無効です
unlock.errorMessage.unsupportedVersion.vaultOlderThanSoftware = サポートされない金庫です。この金庫は古いバージョンの Cryptomator から作成されました。
unlock.errorMessage.unsupportedVersion.softwareOlderThanVault = サポートされない金庫です。この金庫は新しいバージョンの Cryptomator から作成されました。
unlock.messageLabel.startServerFailed = WebDAV サーバーの起動に失敗しました。
# change_password.fxml
changePassword.label.oldPassword = 古いパスワード
changePassword.label.newPassword = 新しいパスワード
changePassword.label.retypePassword = 二回目のパスワード(確認用)
changePassword.label.downloadsPageLink = 全てのCryptomatorのバージョン
changePassword.label.retypePassword = パスワードの再入力
changePassword.label.downloadsPageLink = すべての Cryptomator バージョン
changePassword.button.change = パスワードの変更
changePassword.errorMessage.wrongPassword = 違うパスワード
changePassword.errorMessage.decryptionFailed = 解読不可
changePassword.errorMessage.wrongPassword = パスワードが無効です
changePassword.errorMessage.decryptionFailed = 復号に失敗しました。
# unlocked.fxml
unlocked.button.lock = 金庫の施錠
unlocked.moreOptions.reveal = 金庫ドライブの表示
unlocked.moreOptions.copyUrl = WebDAVのURLのコピー
unlocked.moreOptions.reveal = ドライブの表示
unlocked.moreOptions.copyUrl = WebDAV URL のコピー
unlocked.label.revealFailed = 入力エラー
unlocked.label.unmountFailed = 外部出力の排出エラー
unlocked.label.statsEncrypted = 暗号化
unlocked.label.statsDecrypted = 解読
unlocked.ioGraph.yAxis.label = 情報処理量
unlocked.label.unmountFailed = ドライブの取り出しに失敗
unlocked.label.statsEncrypted = 暗号化済み
unlocked.label.statsDecrypted = 復号済み
unlocked.ioGraph.yAxis.label = スループット (MiB/s)
# settings.fxml
settings.version.label = バージョンの%s
settings.version.label = バージョン %s
settings.checkForUpdates.label = 最新版のチェック
settings.port.label = WebDAVの移動
settings.port.prompt = 0=自動的に選択します
settings.requiresRestartLabel = Cryptomatorの再起動が必要です
settings.port.label = WebDAV ポート
settings.port.prompt = 0 \= 自動的に選択
settings.requiresRestartLabel = *Cryptomatorの再起動が必要
# tray icon
tray.menu.open = 開く
tray.menu.quit = 閉じる
tray.infoMsg.title = バックグラウンドで稼働中
tray.infoMsg.msg = Cryptomatorはまだ稼働しています。終了はトレイアイコンからしてください。
tray.infoMsg.msg.osx = Cryptomatorはまだ稼働しています。終了はメヌーバーアイコンからしてください。
tray.infoMsg.title = バックグラウンドで実行中
tray.infoMsg.msg = まだ Cryptomator は実行中です。トレイアイコンのアイコンから閉じてください。
tray.infoMsg.msg.osx = まだ Cryptomator は実行中です。メニューバーのアイコンから閉じてください。
initialize.messageLabel.passwordStrength.0 = 非常に弱い
initialize.messageLabel.passwordStrength.1 = 弱い
initialize.messageLabel.passwordStrength.2 = 普通
initialize.messageLabel.passwordStrength.3 = 強い
initialize.messageLabel.passwordStrength.4 = 非常に強い
initialize.label.doNotForget = 重要:パスワードを忘れましたら、あなたのデータは復旧できません。
main.directoryList.remove.confirmation.title = 金庫の削除
main.directoryList.remove.confirmation.header = 本当にこの金庫を取り除きたいですか?
main.directoryList.remove.confirmation.content = 金庫はリストのみで削除されます。永久に削除するなら、ファイルシステムからファイルを削除してください。
upgrade.version3to4.msg = この金庫は新しいフォーマットに移行する必要があります。暗号化されたフォルダの名前は更新されます。進行する前に同期が完了していることをご確認ください。
upgrade.version3to4.err.io = I/O例外のため移行が失敗しました。詳細はログをご確認ください。
settings.prefGvfsScheme.label = WebDAVスキーム
initialize.label.doNotForget = 重要\: パスワードを忘れると、データの復旧はできません。
main.directoryList.remove.confirmation.title = 金庫を削除
main.directoryList.remove.confirmation.header = この金庫を本当に削除しますか?
main.directoryList.remove.confirmation.content = 金庫はリストのみで削除されます。完全に削除するには、ファイルシステムからファイルを削除してください。
upgrade.version3to4.msg = この金庫は新しいフォーマットに移行する必要があります。\n暗号化されたフォルダの名前は更新されます。\n続行する前に同期が完了していることをご確認ください。
upgrade.version3to4.err.io = I/O の例外で移行に失敗しました。詳細はログをご確認ください。
settings.prefGvfsScheme.label = WebDAV スキーム
# upgrade.fxml
upgrade.confirmation.label = はい、同期が完了していることを確認しました。
initialize.messageLabel.notEmpty = 金庫が空いていません。
unlock.label.savePassword = パスワード保存
unlock.errorMessage.unauthenticVersionMac = バージョンMACを認証できません。
unlocked.label.mountFailed = ドライブの接続に失敗しました。
unlock.savePassword.delete.confirmation.title = 保存されたパスワードを削除
unlock.savePassword.delete.confirmation.header = あなたは本当にこの金庫の保存されたパスワードを削除しますか?
unlock.savePassword.delete.confirmation.content = この金庫の保存されたパスワードはあなたのシステムキーチェーンから直ちに削除されます。もしまたパスワードを保存したい際には、”パスワード保存”オプションを有効にした上に金庫を解除する必要があります。
settings.debugMode.label = デバッグモード
upgrade.version3dropBundleExtension.title = 金庫バージョン3アップグレード(Drop Bundle Extension)
upgrade.version3to4.title = 金庫バージョン3から4にアップグレード
upgrade.version4to5.title = 金庫バージョン4から5にアップグレード
upgrade.version4to5.msg = この金庫は新しいフォーマットに移行する必要があります。暗号化されたファイルは更新されます。進行する前に同期が完了していることをご確認ください。\n\n注意:すべてのファイルの変更日は、現在の日付・時刻に変わります。
upgrade.version4to5.err.io = I/O例外のため移行が失敗しました。詳細はログをご確認ください。
unlock.label.savePassword = パスワードを保存
unlock.errorMessage.unauthenticVersionMac = MAC バージョンを認証できません。
unlocked.label.mountFailed = ドライブの接続に失敗
unlock.savePassword.delete.confirmation.title = 保存済みのパスワードを削除
unlock.savePassword.delete.confirmation.header = 本当にこの金庫の保存済みパスワードを削除しますか?
unlock.savePassword.delete.confirmation.content = この金庫の保存済みパスワードは、直ちにシステムのキーチェーンから削除されます。もう一度パスワードを保存するには、"Save Password" オプションを有効にして金庫を解錠する必要があります。
settings.debugMode.label = デバッグモード *
upgrade.version3dropBundleExtension.title = 金庫をバージョン 3 にアップグレード(Drop Bundle Extension)
upgrade.version3to4.title = 金庫をバージョン 3 から 4 にアップグレード
upgrade.version4to5.title = 金庫をバージョン 4 から 5 にアップグレード
upgrade.version4to5.msg = この金庫は新しいフォーマットに移行する必要があります。\n暗号化されたファイルは更新されます。\n続行する前に同期が完了していることをご確認ください。\n\n注意:すべてのファイルの変更日は、現在の日付・時刻に変わります。
upgrade.version4to5.err.io = I/O の例外で移行に失敗しました。詳細はログをご確認ください。
settings.port.apply = 適用
unlock.label.mountAfterUnlock = ドライブをマウント
unlock.label.revealAfterMount = ドライブを明らかにする
unlocked.lock.force.confirmation.title = Locking of %1$s failed
unlocked.lock.force.confirmation.header = Do you want to force locking?
unlocked.lock.force.confirmation.content = This may be because other programs are still accessing files in the vault or because some other problem occurred.\n\nPrograms still accessing the files may not work correctly and data not already written by those programs may be lost.
unlock.label.unlockAfterStartup = Auto-Unlock on Start (Experimental)
unlock.errorMessage.unlockFailed = Unlock failed. See log file for details.
unlocked.moreOptions.mount = Mount Drive
unlocked.moreOptions.unmount = Eject Drive
upgrade.version5toX.title = Vault Version Upgrade
upgrade.version5toX.msg = This vault needs to be migrated to a newer format.\nPlease make sure synchronization has finished before proceeding.
\ No newline at end of file
unlock.label.revealAfterMount = ドライブの表示
unlocked.lock.force.confirmation.title = %1$s の施錠に失敗しました
unlocked.lock.force.confirmation.header = 強制的にロックしますか?
unlocked.lock.force.confirmation.content = これは恐らく他のプログラムがこの金庫のファイルをまだアクセスしているか、あるいは別の問題が発生したためです。\n\nまだファイルにアクセスしているプログラムが正しく動作しない可能性があり、それらのプログラムによってまだ書き込まれていないデータが失われる可能性があります。
unlock.label.unlockAfterStartup = 起動時に解錠 (実験的)
unlock.errorMessage.unlockFailed = 施錠に失敗しました。詳細をログファイルで確認してください。
unlocked.moreOptions.mount = ドライブのマウント
unlocked.moreOptions.unmount = ドライブの取り出し
upgrade.version5toX.title = 金庫のバージョンをアップグレード
upgrade.version5toX.msg = この金庫を新しいバージョンに移行する必要があります。\n進行する前に同期が完了していることをご確認ください。
main.createVault.nonEmptyDir.title = Creating vault failed
main.createVault.nonEmptyDir.header = Chosen directory is not empty
main.createVault.nonEmptyDir.content = The selected directory already contains files (possibly hidden). A vault can only be created in an empty directory.
\ No newline at end of file

M main/ui/src/main/resources/localization/ko.txt => main/ui/src/main/resources/localization/ko.txt +25 -23
@@ 30,7 30,7 @@ unlock.button.unlock = 보관함 해제
unlock.button.advancedOptions.show = 더 많은 옵션
unlock.button.advancedOptions.hide = 기본 옵션
unlock.choicebox.winDriveLetter.auto = 자동으로 할당
unlock.errorMessage.wrongPassword = 틀린 비밀번호
unlock.errorMessage.wrongPassword = 잘못된 비밀번호
unlock.errorMessage.unsupportedVersion.vaultOlderThanSoftware = 지원되지 않는 보관함. 이 보관함은 이전 버전의 Cryptomator에서 생성되었습니다.
unlock.errorMessage.unsupportedVersion.softwareOlderThanVault = 지원되지 않는 보관함. 이 보관함은 상위 버전의 Cryptomator에서 생성되었습니다.
unlock.messageLabel.startServerFailed = WedDAV 서버 시작 실패


@@ 40,14 40,14 @@ changePassword.label.newPassword = 새로운 비밀번호
changePassword.label.retypePassword = 비밀번호 재입력
changePassword.label.downloadsPageLink = 모든 Cryptomator 버전
changePassword.button.change = 비밀번호 변경
changePassword.errorMessage.wrongPassword = 틀린 비밀번호
changePassword.errorMessage.decryptionFailed = 복호화 실패
changePassword.errorMessage.wrongPassword = 잘못된 비밀번호
changePassword.errorMessage.decryptionFailed = 암호화 해제 실패
# unlocked.fxml
unlocked.button.lock = 보관함 잠그기
unlocked.moreOptions.reveal = 드라이브 표시
unlocked.moreOptions.copyUrl = WebDAV 주소 복사
unlocked.label.revealFailed = 명령 실패
unlocked.label.unmountFailed = 드라이브 추출 실패
unlocked.label.unmountFailed = 드라이브 꺼내기 실패
unlocked.label.statsEncrypted = 암호화
unlocked.label.statsDecrypted = 복호화
unlocked.ioGraph.yAxis.label = 처리량 (MiB/s)


@@ 61,8 61,8 @@ settings.requiresRestartLabel = * Cryptomator 재시작 필요
tray.menu.open = 열기
tray.menu.quit = 종료
tray.infoMsg.title = 계속 실행 중입니다.
tray.infoMsg.msg = Cryptomator가 계속 실행 중입니다. 종료하실려면 트레이 아이콘에서 해주세요.
tray.infoMsg.msg.osx = Cryptomator가 계속 실행중입니다. 종료하실려면 메뉴 바 아이콘에서 해주세요.
tray.infoMsg.msg = Cryptomator가 계속 실행 중입니다. 종료는 트레이 아이콘에서 해주세요.
tray.infoMsg.msg.osx = Cryptomator가 계속 실행중입니다. 종료는 메뉴바 아이콘에서 해주세요.
initialize.messageLabel.passwordStrength.0 = 매우 약함
initialize.messageLabel.passwordStrength.1 = 약함
initialize.messageLabel.passwordStrength.2 = 괜찮음


@@ 71,34 71,36 @@ initialize.messageLabel.passwordStrength.4 = 매우 강력함
initialize.label.doNotForget = 중요\: 만약 비밀번호를 잊으셨다면, 여러분의 데이터를 복구할 수 없습니다.
main.directoryList.remove.confirmation.title = 보관함 삭제
main.directoryList.remove.confirmation.header = 정말 이 보관함을 삭제하시겠습니까?
main.directoryList.remove.confirmation.content = 보관함이 목록에서만 제거되었습니다. 데이터를 완전히 제거하시려면, 여러분의 파일시스템이서 제거해 주시기 바랍니다.
upgrade.version3to4.msg = 이 보관함은 새로운 형식으로 바뀔 필요가 있습니다. 암호화된 폴더 이름이 업데이트 될 것입니다. 진행하기 전에 동기화가 완료되었는지 확인하기 바랍니다.
upgrade.version3to4.err.io = 입출력 예외 문제로 마이그레이션이 실패하였습니다. 자세한 사항은 로그 파일을 확인하세요.
settings.prefGvfsScheme.label = WebDAV sceme
main.directoryList.remove.confirmation.content = 보관함이 목록에서만 제거되었습니다. 데이터를 완전히 제거하시려면, 사용자의 파일시스템이서 제거해 주시기 바랍니다.
upgrade.version3to4.msg = 이 보관함은 새로운 형식으로 이전되어야 합니다. 암호화된 폴더 이름이 업데이트 될 것입니다. 진행하기 전에 동기화가 완료되었는지 확인하기 바랍니다.
upgrade.version3to4.err.io = I/O 예외 문제로 마이그레이션이 실패하였습니다. 자세한 사항은 로그 파일을 확인하세요.
settings.prefGvfsScheme.label = WebDAV 스키마
# upgrade.fxml
upgrade.confirmation.label = 네. 동기화가 완료되었음을 확인하였습니다.
initialize.messageLabel.notEmpty = 보관함이 비어있지 않음
unlock.label.savePassword = 비밀번호 저장
unlock.errorMessage.unauthenticVersionMac = 인증할 수 없는 버전의 맥입니다
unlock.errorMessage.unauthenticVersionMac = 인증할 수 없는 버전의 MAC(Message Authentication Code)입니다
unlocked.label.mountFailed = 드라이브 연결 실패
unlock.savePassword.delete.confirmation.title = 저장된 비밀번호 삭제
unlock.savePassword.delete.confirmation.header = 정말로 이 보관함의 저장된 비밀번호를 지우시겠습니까?
unlock.savePassword.delete.confirmation.content = 이 보관함의 저장된 비밀번호는 당신의 시스템 키체인에서 즉시 삭제될 것입니다. 다시 비밀번호를 저장하고 싶으시다면, 보관함을 열 때 "비밀번호 저장" 옵션을 활성화해야 합니다
settings.debugMode.label = 디버그 모드
settings.debugMode.label = 디버그 모드 *
upgrade.version3dropBundleExtension.title = 버전 3 보관함 업그레이드 (Drop Bundle Extension)
upgrade.version3to4.title = 보관함 버전 3에서 4로 업그레이드
upgrade.version4to5.title = 보관함 버전 4에서 5로 업그레이드
upgrade.version4to5.msg = 이 보관함은 새로운 포맷으로 이전되어야 합니다.\n암호화된 파일들은 업데이트 될 것입니다.\n진행하기 전에 동기화가 완료되었는지 확인해주세요.\n\n참고\: 모든 파일의  수정 날짜는 과정 진행 중에 현재 날짜/시간으로 바뀔 것입니다.
upgrade.version4to5.msg = 이 보관함은 새로운 형식으로 이전되어야 합니다.\n암호화된 파일들은 업데이트 될 것입니다.\n진행하기 전에 동기화가 완료되었는지 확인해주세요.\n\n참고\: 모든 파일의  수정 날짜는 과정 진행 중에 현재 날짜/시간으로 바뀔 것입니다.
upgrade.version4to5.err.io = I/O 예외에 의해 마이그레이션 실패. 자세한 사항은 로그 파일을 참조하세요.
settings.port.apply = 적용
unlock.label.mountAfterUnlock = 드라이브 마운트
unlock.label.revealAfterMount = 드라이브 공개
unlocked.lock.force.confirmation.title = Locking of %1$s failed
unlocked.lock.force.confirmation.header = Do you want to force locking?
unlocked.lock.force.confirmation.content = This may be because other programs are still accessing files in the vault or because some other problem occurred.\n\nPrograms still accessing the files may not work correctly and data not already written by those programs may be lost.
unlock.label.unlockAfterStartup = Auto-Unlock on Start (Experimental)
unlock.errorMessage.unlockFailed = Unlock failed. See log file for details.
unlocked.moreOptions.mount = Mount Drive
unlocked.moreOptions.unmount = Eject Drive
upgrade.version5toX.title = Vault Version Upgrade
upgrade.version5toX.msg = This vault needs to be migrated to a newer format.\nPlease make sure synchronization has finished before proceeding.
\ No newline at end of file
unlocked.lock.force.confirmation.title = %1$s 잠그기 실패
unlocked.lock.force.confirmation.header = 강제로 잠그시겠습니까?
unlocked.lock.force.confirmation.content = 이는 다른 프로그램이 보관함 내의 파일을 접근하고 있거나, 다른 문제가 발생했기 때문일 수 있습니다.\n\n파일을 접근하고 있는 프로그램이 제대로 동작하지 않을 수 있으며, 프로그램이 쓰지 않은 데이터는 손실될 수 있습니다.
unlock.label.unlockAfterStartup = 시작 시 자동 잠금 해제 (실험적)
unlock.errorMessage.unlockFailed = 잠금 해제 실패. 자세한 사항은 로그 파일을 참조하세요.
unlocked.moreOptions.mount = 드라이브 마운트
unlocked.moreOptions.unmount = 드라이브 꺼내기
upgrade.version5toX.title = 보관함 버전 업그레이드
upgrade.version5toX.msg = 이 보관함은 새로운 버전으로 이전되어야 합니다.\n진행하기 전에 동기화가 완료되었는지 확인해주세요.
main.createVault.nonEmptyDir.title = Creating vault failed
main.createVault.nonEmptyDir.header = Chosen directory is not empty
main.createVault.nonEmptyDir.content = The selected directory already contains files (possibly hidden). A vault can only be created in an empty directory.
\ No newline at end of file

M main/ui/src/main/resources/localization/lv.txt => main/ui/src/main/resources/localization/lv.txt +4 -2
@@ 78,7 78,6 @@ upgrade.version3to4.err.io = Migrācija neizdevās dēļ I/O izņēmuma. Sīkāk
settings.prefGvfsScheme.label = WebDAV shēma
# upgrade.fxml
upgrade.confirmation.label = Jā, esmu pārliecinājies, ka sinhronizācija ir pabeigta.
initialize.messageLabel.notEmpty = Glabātuve nav tukša
unlock.label.savePassword = Saglabāt paroli
unlock.errorMessage.unauthenticVersionMac = Nevar autentificēt versijas MAC
unlocked.label.mountFailed = Diska pievienošana neizdevās


@@ 102,4 101,7 @@ unlock.errorMessage.unlockFailed = Unlock failed. See log file for details.
unlocked.moreOptions.mount = Mount Drive
unlocked.moreOptions.unmount = Eject Drive
upgrade.version5toX.title = Vault Version Upgrade
upgrade.version5toX.msg = This vault needs to be migrated to a newer format.\nPlease make sure synchronization has finished before proceeding.
\ No newline at end of file
upgrade.version5toX.msg = This vault needs to be migrated to a newer format.\nPlease make sure synchronization has finished before proceeding.
main.createVault.nonEmptyDir.title = Creating vault failed
main.createVault.nonEmptyDir.header = Chosen directory is not empty
main.createVault.nonEmptyDir.content = The selected directory already contains files (possibly hidden). A vault can only be created in an empty directory.
\ No newline at end of file

M main/ui/src/main/resources/localization/nl.txt => main/ui/src/main/resources/localization/nl.txt +4 -2
@@ 79,7 79,6 @@ upgrade.version3to4.err.io = I/O Exception\: migratie mislukt. Zie logbestand vo
settings.prefGvfsScheme.label = WebDAV schema
# upgrade.fxml
upgrade.confirmation.label = Ja, ik heb geverifieerd dat de synchronisatie voltooid is
initialize.messageLabel.notEmpty = Kluis niet leeg
unlock.label.savePassword = Wachtwoord Opslaan
unlock.errorMessage.unauthenticVersionMac = MAC authenticatie mislukt
unlocked.label.mountFailed = Verbinden van schijf mislukt


@@ 103,4 102,7 @@ unlock.errorMessage.unlockFailed = Unlock failed. See log file for details.
unlocked.moreOptions.mount = Mount Drive
unlocked.moreOptions.unmount = Eject Drive
upgrade.version5toX.title = Vault Version Upgrade
upgrade.version5toX.msg = This vault needs to be migrated to a newer format.\nPlease make sure synchronization has finished before proceeding.
\ No newline at end of file
upgrade.version5toX.msg = This vault needs to be migrated to a newer format.\nPlease make sure synchronization has finished before proceeding.
main.createVault.nonEmptyDir.title = Creating vault failed
main.createVault.nonEmptyDir.header = Chosen directory is not empty
main.createVault.nonEmptyDir.content = The selected directory already contains files (possibly hidden). A vault can only be created in an empty directory.
\ No newline at end of file

M main/ui/src/main/resources/localization/pl.txt => main/ui/src/main/resources/localization/pl.txt +4 -2
@@ 77,7 77,6 @@ upgrade.version3to4.err.io = Błąd aktualizacji z powodu problemów z odczytem/
settings.prefGvfsScheme.label = Schemat WebDAV
# upgrade.fxml
upgrade.confirmation.label = Tak, synchronizacja plików na pewno została ukończona.
initialize.messageLabel.notEmpty = Krypta nie jest pusta
unlock.label.savePassword = Zapisz hasło
unlock.errorMessage.unauthenticVersionMac = Nie udało się uwierzytelnić wersji MAC
unlocked.label.mountFailed = Błąd podłączanie dysku.


@@ 101,4 100,7 @@ unlock.errorMessage.unlockFailed = Błąd odblokowywania. Szczegóły błędu zn
unlocked.moreOptions.mount = Podłącz dysk
unlocked.moreOptions.unmount = Odłącz dysk
upgrade.version5toX.title = Aktualizacja wersji krypty
upgrade.version5toX.msg = Krypta wymaga aktualizacji do nowszej wersji.\nZanim kontynuujesz, upewnij się, że synchronizacja plików została ukończona.
\ No newline at end of file
upgrade.version5toX.msg = Krypta wymaga aktualizacji do nowszej wersji.\nZanim kontynuujesz, upewnij się, że synchronizacja plików została ukończona.
main.createVault.nonEmptyDir.title = Creating vault failed
main.createVault.nonEmptyDir.header = Chosen directory is not empty
main.createVault.nonEmptyDir.content = The selected directory already contains files (possibly hidden). A vault can only be created in an empty directory.
\ No newline at end of file

M main/ui/src/main/resources/localization/pt.txt => main/ui/src/main/resources/localization/pt.txt +4 -2
@@ 77,7 77,6 @@ upgrade.version3to4.err.io = Falha na migração devido a um erro de E/S. Veja o
settings.prefGvfsScheme.label = Esquema WebDAV
# upgrade.fxml
upgrade.confirmation.label = Sim, tenho certeza de que a sincronização foi concluída
initialize.messageLabel.notEmpty = Cofre não vazio
unlock.label.savePassword = Armazenar senha
unlock.errorMessage.unauthenticVersionMac = Não foi possível autenticar a versão do MAC.
unlocked.label.mountFailed = Falha ao conectar o drive


@@ 101,4 100,7 @@ unlock.errorMessage.unlockFailed = Unlock failed. See log file for details.
unlocked.moreOptions.mount = Mount Drive
unlocked.moreOptions.unmount = Eject Drive
upgrade.version5toX.title = Vault Version Upgrade
upgrade.version5toX.msg = This vault needs to be migrated to a newer format.\nPlease make sure synchronization has finished before proceeding.
\ No newline at end of file
upgrade.version5toX.msg = This vault needs to be migrated to a newer format.\nPlease make sure synchronization has finished before proceeding.
main.createVault.nonEmptyDir.title = Creating vault failed
main.createVault.nonEmptyDir.header = Chosen directory is not empty
main.createVault.nonEmptyDir.content = The selected directory already contains files (possibly hidden). A vault can only be created in an empty directory.
\ No newline at end of file

M main/ui/src/main/resources/localization/pt_BR.txt => main/ui/src/main/resources/localization/pt_BR.txt +4 -2
@@ 77,7 77,6 @@ upgrade.version3to4.err.io = A migração falhou devido a uma falha de entrada e
settings.prefGvfsScheme.label = Esquema WebDAV
# upgrade.fxml
upgrade.confirmation.label = Sim, tenho certeza que a sincronização tá terminada.
initialize.messageLabel.notEmpty = Cofre não vazio
unlock.label.savePassword = Salvar senha
unlock.errorMessage.unauthenticVersionMac = Não pude autenticar a versão da MAC
unlocked.label.mountFailed = Conexão do volume falhou


@@ 101,4 100,7 @@ unlock.errorMessage.unlockFailed = Unlock failed. See log file for details.
unlocked.moreOptions.mount = Mount Drive
unlocked.moreOptions.unmount = Eject Drive
upgrade.version5toX.title = Vault Version Upgrade
upgrade.version5toX.msg = This vault needs to be migrated to a newer format.\nPlease make sure synchronization has finished before proceeding.
\ No newline at end of file
upgrade.version5toX.msg = This vault needs to be migrated to a newer format.\nPlease make sure synchronization has finished before proceeding.
main.createVault.nonEmptyDir.title = Creating vault failed
main.createVault.nonEmptyDir.header = Chosen directory is not empty
main.createVault.nonEmptyDir.content = The selected directory already contains files (possibly hidden). A vault can only be created in an empty directory.
\ No newline at end of file

M main/ui/src/main/resources/localization/ru.txt => main/ui/src/main/resources/localization/ru.txt +5 -3
@@ 79,7 79,6 @@ upgrade.version3to4.err.io = Преобразование не выполнен
settings.prefGvfsScheme.label = Схема WebDAV
# upgrade.fxml
upgrade.confirmation.label = Да, синхронизация точно завершена
initialize.messageLabel.notEmpty = Хранилище не пусто
unlock.label.savePassword = Сохранить пароль
unlock.errorMessage.unauthenticVersionMac = Не удалось идентифицировать версию MAC.
unlocked.label.mountFailed = Ошибка подключения к диску


@@ 102,5 101,8 @@ unlock.label.unlockAfterStartup = Автоблокировка при старт
unlock.errorMessage.unlockFailed = Ошибка разблокировки. См. подробности в отчёте.
unlocked.moreOptions.mount = Смонтировать диск
unlocked.moreOptions.unmount = Извлечь диск
upgrade.version5toX.title = Vault Version Upgrade
upgrade.version5toX.msg = This vault needs to be migrated to a newer format.\nPlease make sure synchronization has finished before proceeding.
\ No newline at end of file
upgrade.version5toX.title = Обновление версии хранилища
upgrade.version5toX.msg = Это хранилище нужно преобразовать в новый формат. Прежде чем продолжить, убедитесь, что завершена синхронизация.
main.createVault.nonEmptyDir.title = Creating vault failed
main.createVault.nonEmptyDir.header = Chosen directory is not empty
main.createVault.nonEmptyDir.content = The selected directory already contains files (possibly hidden). A vault can only be created in an empty directory.
\ No newline at end of file

M main/ui/src/main/resources/localization/sk.txt => main/ui/src/main/resources/localization/sk.txt +4 -2
@@ 80,7 80,6 @@ upgrade.version3to4.err.io = Migrácia zlyhala kvôli I/O Exception. Skontrolujt
settings.prefGvfsScheme.label = WebDAV Schéma
# upgrade.fxml
upgrade.confirmation.label = Áno, som si istý že synchronizácia je hotová
initialize.messageLabel.notEmpty = Trezor nie je prázdny
unlock.label.savePassword = Uložiť heslo
unlock.errorMessage.unauthenticVersionMac = Could not authenticate version MAC.
unlocked.label.mountFailed = Connecting drive failed


@@ 104,4 103,7 @@ unlock.errorMessage.unlockFailed = Unlock failed. See log file for details.
unlocked.moreOptions.mount = Mount Drive
unlocked.moreOptions.unmount = Eject Drive
upgrade.version5toX.title = Vault Version Upgrade
upgrade.version5toX.msg = This vault needs to be migrated to a newer format.\nPlease make sure synchronization has finished before proceeding.
\ No newline at end of file
upgrade.version5toX.msg = This vault needs to be migrated to a newer format.\nPlease make sure synchronization has finished before proceeding.
main.createVault.nonEmptyDir.title = Creating vault failed
main.createVault.nonEmptyDir.header = Chosen directory is not empty
main.createVault.nonEmptyDir.content = The selected directory already contains files (possibly hidden). A vault can only be created in an empty directory.
\ No newline at end of file

A main/ui/src/main/resources/localization/th.txt => main/ui/src/main/resources/localization/th.txt +106 -0
@@ 0,0 1,106 @@
app.name = Cryptomator
# main.fxml
main.emptyListInstructions = คลิกเพื่อเพิ่มกล่องข้อมูล
main.directoryList.contextMenu.remove = ลบออกจากรายการ
main.directoryList.contextMenu.changePassword = เปลี่ยนรหัสผ่าน
main.addDirectory.contextMenu.new = สร้างกล่องข้อมูลใหม่
main.addDirectory.contextMenu.open = เปิดกล่องข้อมูลที่มีอยู่
# welcome.fxml
welcome.checkForUpdates.label.currentlyChecking = ตรวจหาอัพเดท...
welcome.newVersionMessage = เวอร์ชั่น %1$s พร้อมให้ดาวโหลดแล้ว\nเวอร์ชั่นที่ใช้อยู่คือ %2$s
# initialize.fxml
initialize.label.password = รหัสผ่าน
initialize.label.retypePassword = ยืนยันรหัสผ่าน
initialize.button.ok = สร้างกล่องข้อมูล
initialize.messageLabel.alreadyInitialized = กล่องข้อมูลสร้างเสร็จแล้ว
initialize.messageLabel.initializationFailed = ไม่สามารถสร้างกล่องข้อมูลได้ ดูรายละเอียดได้ใน Log ไฟล์
# notfound.fxml
notfound.label = ไม่พบกล่องข้อมูล กล่องอาจถูกย้าย?
# upgrade.fxml
upgrade.button = อัพเกรดกล่องข้อมูล
upgrade.version3dropBundleExtension.msg = กล่องข้อมูลต้องการอัพเกรดเป็นเวอร์ชั่นใหม่\n"%1$s" จะถูกเปลี่ยนชื่อเป็น "%2$s"\nกรุณารอการอัพเกรดให้เสร็จสิ้นก่อนเริ่มใช้งาน
upgrade.version3dropBundleExtension.err.alreadyExists = การอัพเกรดล้มเหลว\nสำเร็จไป "%s"
# unlock.fxml
unlock.label.password = รหัสผ่าน
unlock.label.mountName = ชื่อไดรฟ์
unlock.label.winDriveLetter = เลือกไดรฟ์
unlock.label.downloadsPageLink = เวอร์ชั่น Cryptomator ทั้งหมด
unlock.label.advancedHeading = ตั้งค่าขั้นสูง
unlock.button.unlock = ปลดล็อคกล่องข้อมูล
unlock.button.advancedOptions.show = ตั้งค่าเพิ่มเติม
unlock.button.advancedOptions.hide = ย่อเมนู
unlock.choicebox.winDriveLetter.auto = เลือกไดรฟ์อัตโนมัติ
unlock.errorMessage.wrongPassword = รหัสผ่านไม่ถูกต้อง
unlock.errorMessage.unsupportedVersion.vaultOlderThanSoftware = ไม่รองรับกล่องข้อมูลนี้ อาจเป็นกล่องข้อมูลของเวอชั่นเก่า
unlock.errorMessage.unsupportedVersion.softwareOlderThanVault = ไม่รองรับกล่องข้อมูลนี้ อาจเป็นกล่องข้อมูลของเวอชั่นใหม่กว่า
unlock.messageLabel.startServerFailed = WebDAV เซฟเวอร์เริ่มต้นล้มเหลว
# change_password.fxml
changePassword.label.oldPassword = รหัสผ่านเดิม
changePassword.label.newPassword = รหัสผ่านใหม่
changePassword.label.retypePassword = ยืนยันรหัสผ่านใหม่
changePassword.label.downloadsPageLink = เวอร์ชั่น Cryptomator ทั้งหมด
changePassword.button.change = เปลี่ยนรหัสผ่าน
changePassword.errorMessage.wrongPassword = รหัสผ่านไม่ถูกต้อง
changePassword.errorMessage.decryptionFailed = การถอดรหัสล้มเหลว
# unlocked.fxml
unlocked.button.lock = ล็อคกล่องข้อมูล
unlocked.moreOptions.reveal = โชว์ไดรฟ์
unlocked.moreOptions.copyUrl = คัดลอก WebDEV ลิ้งค์
unlocked.label.revealFailed = คำสั่งล้มเหลว
unlocked.label.unmountFailed = Eject ไดรว์ล้มเหลว
unlocked.label.statsEncrypted = เข้ารหัสแล้ว
unlocked.label.statsDecrypted = ถอดรหัสแล้ว
unlocked.ioGraph.yAxis.label = ความเร็วอ่านเขียน (MiB/s)
# settings.fxml
settings.version.label = เวอร์ชั่น %s
settings.checkForUpdates.label = ค้นหาอัพเดท
settings.port.label = WebDAV Port
settings.port.prompt = 0 \= เลือกอัตโนมัติ
settings.requiresRestartLabel = * ต้องรีสตาร์ท Cryptomator ใหม่
# tray icon
tray.menu.open = เปิด
tray.menu.quit = ออก
tray.infoMsg.title = กำลังทำงาน
tray.infoMsg.msg = Cryptomator กำลังทำงาน คลิ้กออกตรง tray icon
tray.infoMsg.msg.osx = Cryptomator กำลังทำงาน คลิ้กออกตรงแถบเมนู
initialize.messageLabel.passwordStrength.0 = คาดเดาง่ายมาก
initialize.messageLabel.passwordStrength.1 = คาดเดาง่าย
initialize.messageLabel.passwordStrength.2 = ปลอดภัย
initialize.messageLabel.passwordStrength.3 = คาดเดายาก
initialize.messageLabel.passwordStrength.4 = คาดเดายากมาก
initialize.label.doNotForget = คำเตือน\!\!\!\: ถ้าคุณลืมรหัสผ่าน คุณจะไม่สามารถเข้าถึงและกู้ข้อมูลได้
main.directoryList.remove.confirmation.title = ลบกล่องข้อมูล
main.directoryList.remove.confirmation.header = คุณต้องการลบกล่องข้อมูลใช่หรือไม่ ?
main.directoryList.remove.confirmation.content = กล่องข้อมูลแค่ถูกลบออกจากรายการ หากต้องการลบข้อมูล ต้องไปลบในที่อยู่ไฟล์ของคุณ
upgrade.version3to4.msg = กล่องข้อมูลต้องการอัพเกรดเป็นเวอร์ชั่นใหม่\nชื่อโฟลเดอร์จะถูกอัพเดท\nกรุณารอการอัพเกรดให้เสร็จสิ้นก่อนเริ่มใช้งาน
upgrade.version3to4.err.io = อัพเกรดล้มเหลวเนื่องจากข้อยกเว้น I/O ดูรายละเอียดได้ใน Log ไฟล์
settings.prefGvfsScheme.label = WebDAV Scheme
# upgrade.fxml
upgrade.confirmation.label = ใช่ ฉันมั่นใจว่าอัพเกรดเสร็จเรียบร้อยแล้ว
unlock.label.savePassword = เซฟรหัสผ่าน
unlock.errorMessage.unauthenticVersionMac = ไม่ตรวจพบเวอร์ชั่นของ MAC
unlocked.label.mountFailed = เชื่อมต่อไดรฟ์ล้มเหลว
unlock.savePassword.delete.confirmation.title = ลบรหัสผ่านที่เซฟ
unlock.savePassword.delete.confirmation.header = คุณต้องการลบลบรหัสผ่านที่เซฟไว้กับกล่องข้อมูลใช่หรือไม่ ?
unlock.savePassword.delete.confirmation.content = รหัสผ่านที่เซฟถูกลบจาก system keychain แล้ว ถ้าคุณต้องการเซฟรหัสผ่านใหม่อีกครั้ง ให้คุณคลิ้กเลือก "เซฟรหัสผ่าน"
settings.debugMode.label = โหมด Debug *
upgrade.version3dropBundleExtension.title = อัพเกรดกล่องข้อมูลเวอร์ชั่น 3  (Drop Bundle Extension)
upgrade.version3to4.title = อัพเกรดกล่องข้อมูลเวอร์ชั่น 3 ไปยัง 4
upgrade.version4to5.title = อัพเกรดกล่องข้อมูลเวอร์ชั่น 4 ไปยัง 5
upgrade.version4to5.msg = กล่องข้อมูลนี้ต้องการอัพเกรดเป็นเวอร์ชั่นใหม่\nไฟล์เข้ารหัสจะได้รับการอัพเกรด\nกรุณารอการอัพเกรดให้เสร็จสิ้นก่อนเริ่มใช้งาน\n\nเพิ่มเติม\: วันที่ Modification ของไฟล์จะถูกเปลี่ยนเป็นเวลา ณ ปัจจุบัน
upgrade.version4to5.err.io = อัพเกรดล้มเหลวเนื่องจากข้อยกเว้น I/O ดูรายละเอียดได้ใน Log ไฟล์
settings.port.apply = ตกลง
unlock.label.mountAfterUnlock = เมาท์ไดรฟ์
unlock.label.revealAfterMount = ไปยังไดรฟ์
unlocked.lock.force.confirmation.title = ล็อค %1$s ล้มเหลว
unlocked.lock.force.confirmation.header = คุณต้องการล็อคแบบ Force หรือไม่ ?
unlocked.lock.force.confirmation.content = เนื่องจากบางโปรแกรมกำลังเรียกใช้ไฟล์ในกล่องข้อมูลอยู่ในขณะนี้ หรือเนื่องจากปัญหาอื่นๆ\n\nโปรแกรมที่เรียกใช้ไฟล์อาจทำงานได้ไม่สมบูรณ์ ข้อมูลอาจสูญหายได้
unlock.label.unlockAfterStartup = ปลดล็อคอัตโนมัติตอนเปิดคอม (Experimental)
unlock.errorMessage.unlockFailed = ปลดล็อคล้มเหลว ดูรายละเอียดได้ใน Log ไฟล์
unlocked.moreOptions.mount = เมาท์ไดรฟ์
unlocked.moreOptions.unmount = Eject ไดรฟ์
upgrade.version5toX.title = อัพเกรดเวอร์ชั่นกล่องข้อมูล
upgrade.version5toX.msg = กล่องข้อมูลต้องการอัพเกรดเป็นเวอร์ชั่นใหม่\nกรุณารอการอัพเกรดให้เสร็จสิ้นก่อนเริ่มใช้งาน
main.createVault.nonEmptyDir.title = การสร้างกล่องข้อมูลล้มเหลว
main.createVault.nonEmptyDir.header = โฟลเดอร์ที่เลือกมีไฟล์อยู่
main.createVault.nonEmptyDir.content = โฟลเดอที่เลือกมีไฟล์อยู่ (อาจจะซ่อนอยู่)\nกล่องข้อมูลสามารถสร้างได้จากโฟลเดอร์เปล่าเท่านั้น
\ No newline at end of file

M main/ui/src/main/resources/localization/tr.txt => main/ui/src/main/resources/localization/tr.txt +4 -2
@@ 77,7 77,6 @@ upgrade.version3to4.err.io = Format değiştirme işlemi I/O Hatası dolayısı 
settings.prefGvfsScheme.label = WebDAV Scheme
# upgrade.fxml
upgrade.confirmation.label = Yes, I've made sure that synchronization has finished
initialize.messageLabel.notEmpty = Vault not empty
unlock.label.savePassword = Save Password
unlock.errorMessage.unauthenticVersionMac = Could not authenticate version MAC.
unlocked.label.mountFailed = Connecting drive failed


@@ 101,4 100,7 @@ unlock.errorMessage.unlockFailed = Unlock failed. See log file for details.
unlocked.moreOptions.mount = Mount Drive
unlocked.moreOptions.unmount = Eject Drive
upgrade.version5toX.title = Vault Version Upgrade
upgrade.version5toX.msg = This vault needs to be migrated to a newer format.\nPlease make sure synchronization has finished before proceeding.
\ No newline at end of file
upgrade.version5toX.msg = This vault needs to be migrated to a newer format.\nPlease make sure synchronization has finished before proceeding.
main.createVault.nonEmptyDir.title = Creating vault failed
main.createVault.nonEmptyDir.header = Chosen directory is not empty
main.createVault.nonEmptyDir.content = The selected directory already contains files (possibly hidden). A vault can only be created in an empty directory.
\ No newline at end of file

M main/ui/src/main/resources/localization/uk.txt => main/ui/src/main/resources/localization/uk.txt +4 -2
@@ 77,7 77,6 @@ upgrade.version3to4.err.io = Перетворення невдале через 
settings.prefGvfsScheme.label = WebDAV Scheme
# upgrade.fxml
upgrade.confirmation.label = Yes, I've made sure that synchronization has finished
initialize.messageLabel.notEmpty = Vault not empty
unlock.label.savePassword = Save Password
unlock.errorMessage.unauthenticVersionMac = Could not authenticate version MAC.
unlocked.label.mountFailed = Connecting drive failed


@@ 101,4 100,7 @@ unlock.errorMessage.unlockFailed = Unlock failed. See log file for details.
unlocked.moreOptions.mount = Mount Drive
unlocked.moreOptions.unmount = Eject Drive
upgrade.version5toX.title = Vault Version Upgrade
upgrade.version5toX.msg = This vault needs to be migrated to a newer format.\nPlease make sure synchronization has finished before proceeding.
\ No newline at end of file
upgrade.version5toX.msg = This vault needs to be migrated to a newer format.\nPlease make sure synchronization has finished before proceeding.
main.createVault.nonEmptyDir.title = Creating vault failed
main.createVault.nonEmptyDir.header = Chosen directory is not empty
main.createVault.nonEmptyDir.content = The selected directory already contains files (possibly hidden). A vault can only be created in an empty directory.
\ No newline at end of file

M main/ui/src/main/resources/localization/zh.txt => main/ui/src/main/resources/localization/zh.txt +76 -74
@@ 1,106 1,108 @@
app.name = Cryptomator
# main.fxml
main.emptyListInstructions = 单击此处添加保管库
main.directoryList.contextMenu.remove = 从列表中删除
main.directoryList.contextMenu.changePassword = 更改密码
main.addDirectory.contextMenu.new = 创建新保管库
main.addDirectory.contextMenu.open = 打开现有保管库
main.emptyListInstructions = 点按这里添加资料库
main.directoryList.contextMenu.remove = 从列表中移除
main.directoryList.contextMenu.changePassword = 变更密码
main.addDirectory.contextMenu.new = 新建资料库
main.addDirectory.contextMenu.open = 使用现有资料库
# welcome.fxml
welcome.checkForUpdates.label.currentlyChecking = 正在检查更新……
welcome.newVersionMessage = 发现新版本版本%1$s\n当前版本%2$s
welcome.checkForUpdates.label.currentlyChecking = 检查更新中……
welcome.newVersionMessage = 新版本 %1$s 已发布\n当前版本%2$s
# initialize.fxml
initialize.label.password = 密码
initialize.label.retypePassword = 确认密码
initialize.button.ok = 创建保管库
initialize.messageLabel.alreadyInitialized = 保管库已初始化
initialize.messageLabel.initializationFailed = 无法初始化保管库。 有关详情,请参阅日志文件。
initialize.label.retypePassword = 重新输入密码
initialize.button.ok = 新建资料库
initialize.messageLabel.alreadyInitialized = 已新建资料库
initialize.messageLabel.initializationFailed = 无法创建资料库。请查看日志来获得详细信息。
# notfound.fxml
notfound.label = 找不到保险柜。 是否已被移动?
notfound.label = 找不到这个资料库,是否已移动到别的地方?
# upgrade.fxml
upgrade.button = 升级保险柜
upgrade.version3dropBundleExtension.msg = 此保管库需要迁移到较新的格式。\n"%1$s"将重命名为"%2$s"。\n请确保同步已完成,然后再继续。
upgrade.version3dropBundleExtension.err.alreadyExists = 自动迁移失败。\n"%s"已存在
upgrade.button = 升级资料库
upgrade.version3dropBundleExtension.msg = 此资料库需要升级至最新版本,\n"%1$s" 将重命名为 "%2$s"。\n请确保同步完成后再继续操作。
upgrade.version3dropBundleExtension.err.alreadyExists = 自动迁移失败。\n「%s」已存在。
# unlock.fxml
unlock.label.password = 密码
unlock.label.mountName = 驱动器名称
unlock.label.winDriveLetter = 驱动器号
unlock.label.downloadsPageLink = 所有Cryptomator版本
unlock.label.downloadsPageLink = 所有 Cryptomator 版本
unlock.label.advancedHeading = 高级选项
unlock.button.unlock = 保险柜解锁
unlock.button.unlock = 解锁资料库
unlock.button.advancedOptions.show = 更多选项
unlock.button.advancedOptions.hide = 更少选项
unlock.choicebox.winDriveLetter.auto = 自动分配
unlock.errorMessage.wrongPassword = 密码错误
unlock.errorMessage.unsupportedVersion.vaultOlderThanSoftware = 不支持的保管库。 此保管库由旧版本的Cryptomator创建。
unlock.errorMessage.unsupportedVersion.softwareOlderThanVault = 不支持的保管库。 此保管库由较新版本的Cryptomator创建。
unlock.messageLabel.startServerFailed = 启动WebDAV服务器失败。
unlock.errorMessage.unsupportedVersion.vaultOlderThanSoftware = 此资料库属于过时版本的 Cryptomator,无法在此版本中使用。
unlock.errorMessage.unsupportedVersion.softwareOlderThanVault = 此资料库属于较新版本的 Cryptomator,无法在此版本中使用。
unlock.messageLabel.startServerFailed = 无法启动 WebDAV 服务器。
# change_password.fxml
changePassword.label.oldPassword = 旧密码
changePassword.label.oldPassword = 原密码
changePassword.label.newPassword = 新密码
changePassword.label.retypePassword = 确认新密码
changePassword.label.downloadsPageLink = 所有Cryptomator版本
changePassword.button.change = 更改密码
changePassword.label.retypePassword = 再次输入新密码
changePassword.label.downloadsPageLink = 所有 Cryptomator 版本
changePassword.button.change = 更换密码
changePassword.errorMessage.wrongPassword = 密码错误
changePassword.errorMessage.decryptionFailed = 解密失败
# unlocked.fxml
unlocked.button.lock = 保险柜上锁
unlocked.moreOptions.reveal = 显示驱动器
unlocked.moreOptions.copyUrl = 复制WebDAV地址(URL)
unlocked.label.revealFailed = 命令失败
unlocked.label.unmountFailed = 弹出驱动器失败
unlocked.label.statsEncrypted = 加密
unlocked.label.statsDecrypted = 解密
unlocked.ioGraph.yAxis.label = 吞吐量(Mib/s)
unlocked.button.lock = 锁定资料库
unlocked.moreOptions.reveal = 打开驱动器
unlocked.moreOptions.copyUrl = 复制 WebDAV 网址
unlocked.label.revealFailed = 指令无法执行
unlocked.label.unmountFailed = 无法弹出驱动器
unlocked.label.statsEncrypted = 已加密
unlocked.label.statsDecrypted = 已解密
unlocked.ioGraph.yAxis.label = 吞吐量 (Mib/s)
# settings.fxml
settings.version.label = 版本%s
settings.version.label = 版本 %s
settings.checkForUpdates.label = 检查更新
# What's the "*" mean?
settings.port.label = WebDAV 端口 *
settings.port.prompt = 0 \=自动选择
settings.requiresRestartLabel = * Cryptomator需要重新启动
settings.port.label = WebDAV 端口*
settings.port.prompt = 0 \= 自动选择
settings.requiresRestartLabel = * Cryptomator 需要重启
# tray icon
tray.menu.open = 打开
tray.menu.quit = 退出
tray.infoMsg.title = 仍在运行
tray.infoMsg.msg = Cryptomator仍在运行。 从托盘图标中退出。
tray.infoMsg.msg.osx = Cryptomator仍在运行。 从菜单栏图标中退出。
initialize.messageLabel.passwordStrength.0 = 非常简单
initialize.messageLabel.passwordStrength.1 = 简单
initialize.messageLabel.passwordStrength.2 = 平均水平
initialize.messageLabel.passwordStrength.3 = 强壮
initialize.messageLabel.passwordStrength.4 = 非常强壮
initialize.label.doNotForget = 重要信息:如果您忘记了密码,将无法恢复您的数据。
main.directoryList.remove.confirmation.title = 移除保险柜
main.directoryList.remove.confirmation.header = 您确定要删除此保管库吗?
main.directoryList.remove.confirmation.content = 文件库将仅从列表中删除。 要永久删除它,请从文件系统中删除这些文件。
upgrade.version3to4.msg = 此保管库需要迁移到较新的格式。\n加密的文件夹名称将更新。\n请确保同步已完成,然后再继续。
upgrade.version3to4.err.io = 由于I/O异常,迁移失败。有关详情,请参阅日志文件。
settings.prefGvfsScheme.label = WebDAV方案
tray.infoMsg.msg = Cryptomator 仍在运行。 从托盘图标中退出。
tray.infoMsg.msg.osx = Cryptomator 仍在运行。 从菜单栏图标中退出。
initialize.messageLabel.passwordStrength.0 = 非常弱
initialize.messageLabel.passwordStrength.1 = 略弱
initialize.messageLabel.passwordStrength.2 = 可接受
initialize.messageLabel.passwordStrength.3 = 较强
initialize.messageLabel.passwordStrength.4 = 非常强
initialize.label.doNotForget = 重要:若忘记此密码,数据将无法找回。
main.directoryList.remove.confirmation.title = 移除资料库
main.directoryList.remove.confirmation.header = 确定要移除此资料库吗?
main.directoryList.remove.confirmation.content = 资料库将仅从列表中移除,如需永久删除,请从文件系统中删除这些文件。
upgrade.version3to4.msg = 此资料库需要升级至最新版本,\n已加密的文件夹名称将更新。\n请确保同步完成后再继续操作。
upgrade.version3to4.err.io = 由于 I/O 异常,迁移失败。请查看日志来获得详细信息。
settings.prefGvfsScheme.label = WebDAV 格式
# upgrade.fxml
upgrade.confirmation.label = 是的,我确保同步已完成
initialize.messageLabel.notEmpty = 保险柜非空
upgrade.confirmation.label = 没错,同步已完成。
unlock.label.savePassword = 保存密码
# This Mac means Mac(Apple) or Mac address?
unlock.errorMessage.unauthenticVersionMac = 无法验证消息验证代码的版本。
unlocked.label.mountFailed = 连接设备失败
unlock.savePassword.delete.confirmation.title = 删除已保存的密码
unlock.savePassword.delete.confirmation.header = 您真的要删除此密码库已保存的密码吗?
unlock.savePassword.delete.confirmation.content = 此密码库保存的密码将立即从系统钥匙串中删除。如果您想再次保存密码,则必须通过启用“保存密码”选项启用您的密码库。
unlock.errorMessage.unauthenticVersionMac = 无法确认消息认证码版本。
unlocked.label.mountFailed = 无法连接到驱动器
unlock.savePassword.delete.confirmation.title = 删除已储存的密码
unlock.savePassword.delete.confirmation.header = 真的要删除为此资料库储存的密码吗?
unlock.savePassword.delete.confirmation.content = 此资料库储存的密码将立即从系统钥匙串中删除。如果您想再次保存密码,则必须通过启用“保存密码”选项启用您的密码库。
settings.debugMode.label = 调试模式 *
upgrade.version3dropBundleExtension.title = 升级Vault版本3(Drop Bundle Extension)
upgrade.version3to4.title = Vault Version 3 to 4 Upgrade
upgrade.version4to5.title = Vault Version 4 to 5 Upgrade
upgrade.version4to5.msg = This vault needs to be migrated to a newer format.\nEncrypted files will be updated.\nPlease make sure synchronization has finished before proceeding.\n\nNote\: Modification date of all files will be changed to the current date/time in the process.
upgrade.version4to5.err.io = Migration failed due to an I/O Exception. See log file for details.
settings.port.apply = Apply
unlock.label.mountAfterUnlock = Mount Drive
unlock.label.revealAfterMount = Reveal Drive
unlocked.lock.force.confirmation.title = Locking of %1$s failed
unlocked.lock.force.confirmation.header = Do you want to force locking?
unlocked.lock.force.confirmation.content = This may be because other programs are still accessing files in the vault or because some other problem occurred.\n\nPrograms still accessing the files may not work correctly and data not already written by those programs may be lost.
unlock.label.unlockAfterStartup = Auto-Unlock on Start (Experimental)
unlock.errorMessage.unlockFailed = Unlock failed. See log file for details.
unlocked.moreOptions.mount = Mount Drive
unlocked.moreOptions.unmount = Eject Drive
upgrade.version5toX.title = Vault Version Upgrade
upgrade.version5toX.msg = This vault needs to be migrated to a newer format.\nPlease make sure synchronization has finished before proceeding.
\ No newline at end of file
upgrade.version3dropBundleExtension.title = 升级资料库到第三版(移除 Bundle Extension)
upgrade.version3to4.title = 升级资料库到第四版
upgrade.version4to5.title = 升级资料库到第五版
upgrade.version4to5.msg = 此资料库需要升级至最新版本,\n已加密的数据将被更新。\n请确保同步完成后再继续操作。
upgrade.version4to5.err.io = 升级因 I/O 错误失败。请查看日志来获得详细信息。
settings.port.apply = 应用
unlock.label.mountAfterUnlock = 装载驱动器
unlock.label.revealAfterMount = 显示驱动器
unlocked.lock.force.confirmation.title = 无法锁定 %1$s
unlocked.lock.force.confirmation.header = 要强制锁定吗?
unlocked.lock.force.confirmation.content = 此错误可能是因为其他应用程序仍在使用此资料库中的文件,或遇到了其他问题。\n\n如强制锁定,正在使用文件的应用程序可能会出错并丢失部分还没有保存的资料。
unlock.label.unlockAfterStartup = 启动时自动解锁(试验功能)
unlock.errorMessage.unlockFailed = 无法解锁。请查看日志来获得详细信息。
unlocked.moreOptions.mount = 装载驱动器
unlocked.moreOptions.unmount = 弹出驱动器
upgrade.version5toX.title = 资料库版本升级
upgrade.version5toX.msg = 此资料库需要升级至最新版本,\n请确保同步完成后再继续操作。
main.createVault.nonEmptyDir.title = Creating vault failed
main.createVault.nonEmptyDir.header = Chosen directory is not empty
main.createVault.nonEmptyDir.content = The selected directory already contains files (possibly hidden). A vault can only be created in an empty directory.
\ No newline at end of file

M main/ui/src/main/resources/localization/zh_HK.txt => main/ui/src/main/resources/localization/zh_HK.txt +4 -2
@@ 77,7 77,6 @@ upgrade.version3to4.err.io = 由於I/O的例外,轉移失敗。取得詳細資
settings.prefGvfsScheme.label = WebDAV的格式
# upgrade.fxml
upgrade.confirmation.label = 是的,請確認同步已完成。
initialize.messageLabel.notEmpty = 檔案庫不是空的
unlock.label.savePassword = 儲存密碼
unlock.errorMessage.unauthenticVersionMac = 無法認證消息驗證碼版本。
unlocked.label.mountFailed = Connecting drive failed


@@ 101,4 100,7 @@ unlock.errorMessage.unlockFailed = Unlock failed. See log file for details.
unlocked.moreOptions.mount = Mount Drive
unlocked.moreOptions.unmount = Eject Drive
upgrade.version5toX.title = Vault Version Upgrade
upgrade.version5toX.msg = This vault needs to be migrated to a newer format.\nPlease make sure synchronization has finished before proceeding.
\ No newline at end of file
upgrade.version5toX.msg = This vault needs to be migrated to a newer format.\nPlease make sure synchronization has finished before proceeding.
main.createVault.nonEmptyDir.title = Creating vault failed
main.createVault.nonEmptyDir.header = Chosen directory is not empty
main.createVault.nonEmptyDir.content = The selected directory already contains files (possibly hidden). A vault can only be created in an empty directory.
\ No newline at end of file

M main/ui/src/main/resources/localization/zh_TW.txt => main/ui/src/main/resources/localization/zh_TW.txt +8 -6
@@ 77,7 77,6 @@ upgrade.version3to4.err.io = 由於 I/O 的例外,轉移失敗。取得詳細
settings.prefGvfsScheme.label = WebDAV 格式
# upgrade.fxml
upgrade.confirmation.label = 是的,請確認同步已完成。
initialize.messageLabel.notEmpty = 檔案庫不是空的
unlock.label.savePassword = 儲存密碼
unlock.errorMessage.unauthenticVersionMac = 無法認證消息驗證碼版本。
unlocked.label.mountFailed = 連線到磁碟失敗


@@ 97,8 96,11 @@ unlocked.lock.force.confirmation.title = %1$s 鎖定失敗
unlocked.lock.force.confirmation.header = 你想要強制鎖定?
unlocked.lock.force.confirmation.content = 這可能是因為其他軟體仍在存取這個檔案庫,或者發生其他問題。\n\n仍然在存取檔案的軟體可能無法正常運作,而且會造成寫入的資料遺失。
unlock.label.unlockAfterStartup = 啟動時,自動解鎖(實驗中)
unlock.errorMessage.unlockFailed = Unlock failed. See log file for details.
unlocked.moreOptions.mount = Mount Drive
unlocked.moreOptions.unmount = Eject Drive
upgrade.version5toX.title = Vault Version Upgrade
upgrade.version5toX.msg = This vault needs to be migrated to a newer format.\nPlease make sure synchronization has finished before proceeding.
\ No newline at end of file
unlock.errorMessage.unlockFailed = 解鎖失敗。詳請查看日誌檔。
unlocked.moreOptions.mount = 掛載硬碟
unlocked.moreOptions.unmount = 退出硬碟
upgrade.version5toX.title = 檔案庫版本升級
upgrade.version5toX.msg = 這個檔案庫需要轉移到新的格式。\n進行前,請確認已經完成所有同步。
main.createVault.nonEmptyDir.title = Creating vault failed
main.createVault.nonEmptyDir.header = Chosen directory is not empty
main.createVault.nonEmptyDir.content = The selected directory already contains files (possibly hidden). A vault can only be created in an empty directory.
\ No newline at end of file

A main/ui/src/test/java/org/cryptomator/ui/l10n/LocalizationMock.java => main/ui/src/test/java/org/cryptomator/ui/l10n/LocalizationMock.java +10 -0
@@ 0,0 1,10 @@
package org.cryptomator.ui.l10n;

public class LocalizationMock extends Localization {

	@Override
	public String handleGetObject(String key) {
		return key;
	}

}

M main/ui/src/test/java/org/cryptomator/ui/l10n/LocalizationTest.java => main/ui/src/test/java/org/cryptomator/ui/l10n/LocalizationTest.java +1 -1
@@ 32,7 32,7 @@ public class LocalizationTest {
	private static final String RESOURCE_FOLDER_PATH = "/localization/";
	private static final String REF_FILE_NAME = "en.txt";
	private static final String[] LANG_FILE_NAMES = {"ar.txt", "bg.txt", "da.txt", "de.txt", "es.txt", "fr.txt", "hu.txt", "it.txt", "ja.txt", //
			"ko.txt", "lv.txt", "nl.txt", "pl.txt", "pt.txt", "pt_BR.txt", "ru.txt", "sk.txt", "tr.txt", "uk.txt", "zh_HK.txt", "zh_TW.txt", "zh.txt"};
			"ko.txt", "lv.txt", "nl.txt", "pl.txt", "pt.txt", "pt_BR.txt", "ru.txt", "sk.txt", "th.txt", "tr.txt", "uk.txt", "zh_HK.txt", "zh_TW.txt", "zh.txt"};

	/*
	 * @see Formatter

A main/ui/src/test/java/org/cryptomator/ui/model/UpgradeVersion3to4Test.java => main/ui/src/test/java/org/cryptomator/ui/model/UpgradeVersion3to4Test.java +164 -0
@@ 0,0 1,164 @@
package org.cryptomator.ui.model;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.FileSystem;
import java.nio.file.Files;
import java.nio.file.Path;

import org.cryptomator.ui.l10n.Localization;
import org.cryptomator.ui.l10n.LocalizationMock;
import org.cryptomator.ui.model.UpgradeStrategy.UpgradeFailedException;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.mockito.Mockito;

import com.google.common.jimfs.Configuration;
import com.google.common.jimfs.Jimfs;

public class UpgradeVersion3to4Test {

	private static final Localization L10N = new LocalizationMock();
	private static final String NULL_KEY_CONTENTS = "{" //
			+ "  \"version\": 3," //
			+ "  \"scryptSalt\": \"AAAAAAAAAAA=\"," //
			+ "  \"scryptCostParam\": 16384," //
			+ "  \"scryptBlockSize\": 8," //
			+ "  \"primaryMasterKey\": \"BJPIq5pvhN24iDtPJLMFPLaVJWdGog9k4n0P03j4ru+ivbWY9OaRGQ==\"," //
			+ "  \"hmacMasterKey\": \"BJPIq5pvhN24iDtPJLMFPLaVJWdGog9k4n0P03j4ru+ivbWY9OaRGQ==\"," //
			+ "  \"versionMac\": \"iUmRRHITuyJsJbVNqGNw+82YQ4A3Rma7j/y1v0DCVLA=\"" //
			+ "}";

	@Rule
	public final ExpectedException thrown = ExpectedException.none();
	private final UpgradeStrategy upgradeStrategy = new UpgradeVersion3to4(L10N);
	private FileSystem fs;
	private Path fsRoot;
	private Vault vault;
	private Path dataDir;
	private Path metadataDir;

	@Before
	public void setup() throws IOException {
		fs = Jimfs.newFileSystem(Configuration.unix());
		fsRoot = fs.getPath("/");
		dataDir = fsRoot.resolve("d");
		metadataDir = fsRoot.resolve("m");
		vault = Mockito.mock(Vault.class);
		Mockito.when(vault.getPath()).thenReturn(fsRoot);

		Files.write(fsRoot.resolve("masterkey.cryptomator"), NULL_KEY_CONTENTS.getBytes(StandardCharsets.US_ASCII));
	}

	@After
	public void teardown() throws IOException {
		fs.close();
	}

	@Test
	public void upgradeFailsWithWrongPassword() throws UpgradeFailedException {
		thrown.expect(UpgradeFailedException.class);
		thrown.expectMessage("unlock.errorMessage.wrongPassword");
		upgradeStrategy.upgrade(vault, "asdd");
	}

	@Test
	public void upgradeCreatesBackup() throws UpgradeFailedException {
		upgradeStrategy.upgrade(vault, "asd");
		Assert.assertTrue(Files.exists(fsRoot.resolve("masterkey.cryptomator.bkup")));
	}

	@Test
	public void upgradeRenamesSimpleDirFile() throws IOException, UpgradeFailedException {
		Path lvl2Dir = dataDir.resolve("AB/CDEFGHIJKLMNOPQRSTUVWXYZ234567");
		Files.createDirectories(lvl2Dir);
		Path oldFile = lvl2Dir.resolve("ABCDEFGH_");
		Files.createFile(oldFile);

		upgradeStrategy.upgrade(vault, "asd");
		Path newFile = lvl2Dir.resolve("0ABCDEFGH");
		Assert.assertTrue(Files.exists(newFile));
		Assert.assertTrue(Files.notExists(oldFile));
	}

	@Test
	public void upgradeRenamesConflictingDirFile() throws IOException, UpgradeFailedException {
		Path lvl2Dir = dataDir.resolve("AB/CDEFGHIJKLMNOPQRSTUVWXYZ234567");
		Files.createDirectories(lvl2Dir);
		Path oldFile = lvl2Dir.resolve("ABCDEFGH_ (1)");
		Files.createFile(oldFile);

		upgradeStrategy.upgrade(vault, "asd");
		Path newFile = lvl2Dir.resolve("0ABCDEFGH (1)");
		Assert.assertTrue(Files.exists(newFile));
		Assert.assertTrue(Files.notExists(oldFile));
	}

	@Test
	public void upgradeDontRenameNonDirFile() throws IOException, UpgradeFailedException {
		Path lvl2Dir = dataDir.resolve("AB/CDEFGHIJKLMNOPQRSTUVWXYZ234567");
		Files.createDirectories(lvl2Dir);
		Path oldFile = lvl2Dir.resolve("ABCDEFGH");
		Files.createFile(oldFile);

		upgradeStrategy.upgrade(vault, "asd");
		Assert.assertTrue(Files.exists(oldFile));
	}

	@Test
	public void upgradeRenameSimpleLongDirFile() throws IOException, UpgradeFailedException {
		Path lvl2Dir = dataDir.resolve("AB/CDEFGHIJKLMNOPQRSTUVWXYZ234567");
		Files.createDirectories(lvl2Dir);
		Path oldFile = lvl2Dir.resolve("ABCDEFGH.lng");
		Files.createFile(oldFile);
		Path oldMetadataFile = metadataDir.resolve("AB/CD/ABCDEFGH.lng");
		Files.createDirectories(oldMetadataFile.getParent());
		Files.write(oldMetadataFile, "OPQRSTUVWXYZ====_".getBytes(StandardCharsets.UTF_8));

		upgradeStrategy.upgrade(vault, "asd");
		// hex2base32(sha1("0OPQRSTUVWXYZ====")) = DDLCFQ3ODTEAHEZJPHIJQRDHROB3K42G
		Path newMetadataFile = metadataDir.resolve("DD/LC/DDLCFQ3ODTEAHEZJPHIJQRDHROB3K42G.lng");
		Path newFile = lvl2Dir.resolve("DDLCFQ3ODTEAHEZJPHIJQRDHROB3K42G.lng");
		Assert.assertTrue(Files.exists(newFile));
		Assert.assertTrue(Files.exists(newMetadataFile));
		Assert.assertTrue(Files.notExists(oldFile));
	}

	@Test
	public void upgradeRenameConflictingLongDirFile() throws IOException, UpgradeFailedException {
		Path lvl2Dir = dataDir.resolve("AB/CDEFGHIJKLMNOPQRSTUVWXYZ234567");
		Files.createDirectories(lvl2Dir);
		Path oldFile = lvl2Dir.resolve("ABCDEFGH (1).lng");
		Files.createFile(oldFile);
		Path oldMetadataFile = metadataDir.resolve("AB/CD/ABCDEFGH.lng");
		Files.createDirectories(oldMetadataFile.getParent());
		Files.write(oldMetadataFile, "OPQRSTUVWXYZ====_".getBytes(StandardCharsets.UTF_8));

		upgradeStrategy.upgrade(vault, "asd");
		// hex2base32(sha1("0OPQRSTUVWXYZ====")) = DDLCFQ3ODTEAHEZJPHIJQRDHROB3K42G
		Path newMetadataFile = metadataDir.resolve("DD/LC/DDLCFQ3ODTEAHEZJPHIJQRDHROB3K42G.lng");
		Path newFile = lvl2Dir.resolve("DDLCFQ3ODTEAHEZJPHIJQRDHROB3K42G (1).lng");
		Assert.assertTrue(Files.exists(newFile));
		Assert.assertTrue(Files.exists(newMetadataFile));
		Assert.assertTrue(Files.notExists(oldFile));
	}

	@Test
	public void upgradeDontRenameLongNonDirFile() throws IOException, UpgradeFailedException {
		Path lvl2Dir = dataDir.resolve("AB/CDEFGHIJKLMNOPQRSTUVWXYZ234567");
		Files.createDirectories(lvl2Dir);
		Path oldFile = lvl2Dir.resolve("ABCDEFGH.lng");
		Files.createFile(oldFile);
		Path oldMetadataFile = metadataDir.resolve("AB/CD/ABCDEFGH.lng");
		Files.createDirectories(oldMetadataFile.getParent());
		Files.write(oldMetadataFile, "OPQRSTUVWXYZ====".getBytes(StandardCharsets.UTF_8));

		upgradeStrategy.upgrade(vault, "asd");
		Assert.assertTrue(Files.exists(oldFile));
	}

}

A main/ui/src/test/java/org/cryptomator/ui/util/PasswordStrengthUtilTest.java => main/ui/src/test/java/org/cryptomator/ui/util/PasswordStrengthUtilTest.java +21 -0
@@ 0,0 1,21 @@
package org.cryptomator.ui.util;

import org.cryptomator.ui.l10n.Localization;
import org.junit.Assert;
import org.junit.Test;
import org.mockito.Mockito;

public class PasswordStrengthUtilTest {

	@Test
	public void testLongPasswordsWillBeRatedAsStrong() {
		PasswordStrengthUtil util = new PasswordStrengthUtil(Mockito.mock(Localization.class));
		StringBuilder longPwBuilder = new StringBuilder();
		for (int i = 0; i < 101; i++) {
			longPwBuilder.append('x');
		}
		int strength = util.computeRate(longPwBuilder.toString());
		Assert.assertEquals(4, strength);
	}

}