Browse Source

Merge branch 'release/1.17.1'

Armin Schrenk 1 month ago
parent
commit
6c5f3cb72c

+ 65 - 1
.github/workflows/appimage.yml

@@ -52,7 +52,6 @@ jobs:
           java-version: ${{ env.JAVA_VERSION }}
           check-latest: true
           cache: 'maven'
-
       - name: Download OpenJFX jmods
         id: download-jmods
         run: |
@@ -194,3 +193,68 @@ jobs:
             cryptomator-*.AppImage
             cryptomator-*.zsync
             cryptomator-*.asc
+
+  create-aur-bin-pr:
+    name: Create PR for aur-bin repo
+    needs: [build, get-version]
+    runs-on: ubuntu-latest
+    if: github.event_name == 'release'
+    steps:
+      - name: Download AppImages
+        uses: actions/download-artifact@v4
+        with:
+          path: downloads/
+          merge-multiple: true
+      - name: Compute sha256 hash of AppImages
+        id: checksums
+        run: |
+          X64_SHA256=$(sha256sum downloads/cryptomator-*-x86_64.AppImage | cut -d ' ' -f1)
+          echo "x64-sha256sum=${X64_SHA256}" >> "$GITHUB_OUTPUT"
+          AARCH64_SHA256=$(sha256sum downloads/cryptomator-*-aarch64.AppImage | cut -d ' ' -f1)
+          echo "aarch64-sha256sum=${AARCH64_SHA256}" >> "$GITHUB_OUTPUT"
+      - uses: actions/checkout@v4
+        with:
+          repository: 'cryptomator/aur-bin'
+          token: ${{ secrets.CRYPTOBOT_PR_TOKEN }}
+      - name: Install dependencies
+        run: |
+          sudo apt-get update
+          sudo apt-get -y install makepkg pacman-package-manager
+      - name: Checkout release branch
+        run: |
+          git checkout -b release/${{ needs.get-version.outputs.semVerStr }}
+      - name: Update build file
+        run: |
+          sed -i -e 's|^pkgver=.*$|pkgver=${{ needs.get-version.outputs.semVerStr }}|' PKGBUILD
+          sed -i -e 's|^pkgrel=.*$|pkgrel=1|' PKGBUILD
+          sed -i -e "s|^sha256sums_x86_64=.*$|sha256sums_x86_64=('${{ steps.checksums.outputs.x64-sha256sum }}'|" PKGBUILD
+          sed -i -e "s|^sha256sums_aarch64=.*$|sha256sums_aarch64=('${{ steps.checksums.outputs.aarch64-sha256sum}}'|" PKGBUILD
+          makepkg --printsrcinfo > .SRCINFO
+      - name: Commit and push
+        run: |
+          git config user.name "${{ github.actor }}"
+          git config user.email "${{ github.actor_id }}+${{ github.actor }}@users.noreply.github.com"
+          git config push.autoSetupRemote true
+          git stage .
+          git commit -m "Prepare release ${{needs.get-version.outputs.semVerStr}}"
+          git push
+      - name: Create pull request
+        id: create-pr
+        run: |
+          printf "> [!IMPORTANT]\n> Todos:\n> - [ ] Update build instructions\n> - [ ] Check for JDK update\n> - [ ] Check for JFX update" > pr_body.md
+          URL=$(gh pr create --title "Release ${{ needs.get-version.outputs.semVerStr }}" --body-file pr_body.md)
+          echo "PR_URL=$URL" >> "$GITHUB_OUTPUT"
+        env:
+          GH_TOKEN: ${{ secrets.CRYPTOBOT_PR_TOKEN }}
+      - name: Slack Notification
+        uses: rtCamp/action-slack-notify@v2
+        env:
+          SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_URL }}
+          SLACK_USERNAME: 'Cryptobot'
+          SLACK_ICON: false
+          SLACK_ICON_EMOJI: ':bot:'
+          SLACK_CHANNEL: 'cryptomator-desktop'
+          SLACK_TITLE: "AUR-bin release PR for ${{ github.event.repository.name }} ${{ github.event.release.tag_name }} created."
+          SLACK_MESSAGE: "See <${{ steps.create-pr.outputs.PR_URL }}|PR> on how to proceed."
+          SLACK_FOOTER: false
+          MSG_MINIMAL: true

+ 93 - 0
.github/workflows/aur.yml

@@ -0,0 +1,93 @@
+name: Create PR for AUR
+
+on:
+  release:
+    types: [published]
+  workflow_dispatch:
+    inputs:
+      tag:
+        description: 'Release tag'
+        required: true
+
+jobs:
+  get-version:
+    uses: ./.github/workflows/get-version.yml
+    with:
+      version: ${{ inputs.tag }}
+  tarball:
+    name: Determines tarball url and compute checksum
+    runs-on: ubuntu-latest
+    needs: [get-version]
+    if:  github.event_name == 'workflow_dispatch' || needs.get-version.outputs.versionType == 'stable'
+    outputs:
+      url: ${{ steps.url.outputs.url}}
+      sha256: ${{ steps.sha256.outputs.sha256}}
+    steps:
+      - name: Determine tarball url
+        id: url
+        run: |
+          URL="";
+          if [[ -n "${{ inputs.tag }}"  ]]; then
+            URL="https://github.com/cryptomator/cryptomator/archive/refs/tags/${{ inputs.tag }}.tar.gz"
+          else
+            URL="https://github.com/cryptomator/cryptomator/archive/refs/tags/${{ github.event.release.tag_name }}.tar.gz"
+          fi
+          echo "url=${URL}" >> "$GITHUB_OUTPUT"
+      - name: Download source tarball and compute checksum
+        id: sha256
+        run: |
+          curl --silent --fail-with-body -L -H "Accept: application/vnd.github+json" ${{ steps.url.outputs.url }} --output cryptomator.tar.gz
+          TARBALL_SHA256=$(sha256sum cryptomator.tar.gz | cut -d ' ' -f1)
+          echo "sha256=${TARBALL_SHA256}" >> "$GITHUB_OUTPUT"
+  aur:
+    name: Create PR for AUR
+    runs-on: ubuntu-latest
+    needs: [tarball, get-version]
+    env:
+      AUR_PR_URL: tbd
+    steps:
+      - uses: actions/checkout@v4
+        with:
+          repository: 'cryptomator/aur'
+          token: ${{ secrets.CRYPTOBOT_PR_TOKEN }}
+      - name: Install dependencies
+        run: |
+          sudo apt-get update
+          sudo apt-get install makepkg pacman-package-manager
+      - name: Checkout release branch
+        run: |
+          git checkout -b release/${{ needs.get-version.outputs.semVerStr }}
+      - name: Update build file
+        run: |
+          sed -i -e 's|^pkgver=.*$|pkgver=${{ needs.get-version.outputs.semVerStr }}|' PKGBUILD
+          sed -i -e 's|^pkgrel=.*$|pkgrel=1|' PKGBUILD
+          sed -i -e "s|^sha256sums=.*$|sha256sums=('${{ needs.tarball.outputs.sha256 }}'|" PKGBUILD
+          makepkg --printsrcinfo > .SRCINFO
+      - name: Commit and push
+        run: |
+          git config user.name "${{ github.actor }}"
+          git config user.email "${{ github.actor_id }}+${{ github.actor }}@users.noreply.github.com"
+          git config push.autoSetupRemote true
+          git stage .
+          git commit -m "Prepare release ${{needs.get-version.outputs.semVerStr}}"
+          git push
+      - name: Create pull request
+        run: |
+          printf "> [!IMPORTANT]\n> Todos:\n> - [ ] Update build instructions\n> - [ ] Check for JDK update\n> - [ ] Check for JFX update" > pr_body.md
+          PR_URL=$(gh pr create --title "Release ${{ needs.get-version.outputs.semVerStr }}" --body-file pr_body.md)
+          echo "AUR_PR_URL=$PR_URL" >> "$GITHUB_ENV"
+        env:
+          GH_TOKEN: ${{ secrets.CRYPTOBOT_PR_TOKEN }}
+      - name: Slack Notification
+        uses: rtCamp/action-slack-notify@v2
+        if: github.event_name == 'release'
+        env:
+          SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_URL }}
+          SLACK_USERNAME: 'Cryptobot'
+          SLACK_ICON: false
+          SLACK_ICON_EMOJI: ':bot:'
+          SLACK_CHANNEL: 'cryptomator-desktop'
+          SLACK_TITLE: "AUR release PR created for ${{ github.event.repository.name }} ${{ github.event.release.tag_name }} created."
+          SLACK_MESSAGE: "See <${{ env.AUR_PR_URL }}|PR> on how to proceed."
+          SLACK_FOOTER: false
+          MSG_MINIMAL: true

+ 2 - 2
.github/workflows/flathub.yml

@@ -49,7 +49,7 @@ jobs:
       - uses: actions/checkout@v4
         with:
           repository: 'flathub/org.cryptomator.Cryptomator'
-          token: ${{ secrets.CRYPTOBOT_WINGET_TOKEN }}
+          token: ${{ secrets.CRYPTOBOT_PR_TOKEN }}
       - name: Checkout release branch
         run: |
           git checkout -b release/${{ needs.get-version.outputs.semVerStr }}
@@ -72,7 +72,7 @@ jobs:
           PR_URL=$(gh pr create --title "Release ${{ needs.get-version.outputs.semVerStr }}" --body-file pr_body.md)
           echo "FLATHUB_PR_URL=$PR_URL" >> "$GITHUB_ENV"
         env:
-          GH_TOKEN: ${{ secrets.CRYPTOBOT_WINGET_TOKEN }}
+          GH_TOKEN: ${{ secrets.CRYPTOBOT_PR_TOKEN }}
       - name: Slack Notification
         uses: rtCamp/action-slack-notify@v2
         if: github.event_name == 'release'

+ 2 - 2
.github/workflows/winget.yml

@@ -16,7 +16,7 @@ jobs:
         run: |
           gh repo sync cryptomator/winget-pkgs -b master --force
         env:
-          GH_TOKEN: ${{ secrets.CRYPTOBOT_WINGET_TOKEN }}
+          GH_TOKEN: ${{ secrets.CRYPTOBOT_PR_TOKEN }}
       - name: Submit package
         uses: vedantmgoyal2009/winget-releaser@main
         with:
@@ -24,4 +24,4 @@ jobs:
           version: ${{ inputs.tag }}
           release-tag: ${{ inputs.tag }}
           installers-regex: '-x64\.msi$'
-          token: ${{ secrets.CRYPTOBOT_WINGET_TOKEN }}
+          token: ${{ secrets.CRYPTOBOT_PR_TOKEN }}

+ 3 - 0
dist/linux/common/org.cryptomator.Cryptomator.metainfo.xml

@@ -83,6 +83,9 @@
 	</content_rating>
 
 	<releases>
+		<release date="2025-07-08" version="1.17.1">
+			<url type="details">https://github.com/cryptomator/cryptomator/releases/1.17.1</url>
+		</release>
 		<release date="2025-06-24" version="1.17.0">
 			<url type="details">https://github.com/cryptomator/cryptomator/releases/1.17.0</url>
 		</release>

+ 1 - 1
pom.xml

@@ -3,7 +3,7 @@
 	<modelVersion>4.0.0</modelVersion>
 	<groupId>org.cryptomator</groupId>
 	<artifactId>cryptomator</artifactId>
-	<version>1.17.0</version>
+	<version>1.17.1</version>
 	<name>Cryptomator Desktop App</name>
 
 	<organization>

+ 6 - 0
src/main/java/org/cryptomator/common/settings/Settings.java

@@ -25,6 +25,8 @@ import javafx.beans.property.StringProperty;
 import javafx.collections.FXCollections;
 import javafx.collections.ObservableList;
 import javafx.geometry.NodeOrientation;
+
+import java.nio.file.Path;
 import java.time.Instant;
 import java.util.function.Consumer;
 
@@ -75,6 +77,7 @@ public class Settings {
 	public final BooleanProperty checkForUpdates;
 	public final ObjectProperty<Instant> lastUpdateCheckReminder;
 	public final ObjectProperty<Instant> lastSuccessfulUpdateCheck;
+	public final ObjectProperty<Path> previouslyUsedVaultDirectory;
 
 	private Consumer<Settings> saveCmd;
 
@@ -114,6 +117,7 @@ public class Settings {
 		this.checkForUpdates = new SimpleBooleanProperty(this, "checkForUpdates", json.checkForUpdatesEnabled);
 		this.lastUpdateCheckReminder = new SimpleObjectProperty<>(this, "lastUpdateCheckReminder", json.lastReminderForUpdateCheck);
 		this.lastSuccessfulUpdateCheck = new SimpleObjectProperty<>(this, "lastSuccessfulUpdateCheck", json.lastSuccessfulUpdateCheck);
+		this.previouslyUsedVaultDirectory = new SimpleObjectProperty<>(this, "previouslyUsedVaultDirectory", json.previouslyUsedVaultDirectory);
 
 		this.directories.addAll(json.directories.stream().map(VaultSettings::new).toList());
 
@@ -143,6 +147,7 @@ public class Settings {
 		checkForUpdates.addListener(this::somethingChanged);
 		lastUpdateCheckReminder.addListener(this::somethingChanged);
 		lastSuccessfulUpdateCheck.addListener(this::somethingChanged);
+		previouslyUsedVaultDirectory.addListener(this::somethingChanged);
 	}
 
 	@SuppressWarnings("deprecation")
@@ -204,6 +209,7 @@ public class Settings {
 		json.checkForUpdatesEnabled = checkForUpdates.get();
 		json.lastReminderForUpdateCheck = lastUpdateCheckReminder.get();
 		json.lastSuccessfulUpdateCheck = lastSuccessfulUpdateCheck.get();
+		json.previouslyUsedVaultDirectory = previouslyUsedVaultDirectory.get();
 		return json;
 	}
 

+ 4 - 0
src/main/java/org/cryptomator/common/settings/SettingsJson.java

@@ -5,6 +5,7 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
 import com.fasterxml.jackson.annotation.JsonInclude;
 import com.fasterxml.jackson.annotation.JsonProperty;
 
+import java.nio.file.Path;
 import java.time.Instant;
 import java.util.List;
 
@@ -92,4 +93,7 @@ class SettingsJson {
 
 	@JsonProperty("quickAccessService")
 	String quickAccessService = Settings.DEFAULT_QUICKACCESS_SERVICE;
+
+	@JsonProperty("previouslyUsedVaultDirectory")
+	Path previouslyUsedVaultDirectory;
 }

+ 2 - 2
src/main/java/org/cryptomator/common/vaults/VaultListManager.java

@@ -9,13 +9,13 @@
 package org.cryptomator.common.vaults;
 
 import org.apache.commons.lang3.SystemUtils;
-import org.cryptomator.common.Constants;
 import org.cryptomator.common.settings.Settings;
 import org.cryptomator.common.settings.VaultSettings;
 import org.cryptomator.cryptofs.CryptoFileSystemProvider;
 import org.cryptomator.cryptofs.DirStructure;
 import org.cryptomator.cryptofs.migration.Migrators;
 import org.cryptomator.integrations.mount.MountService;
+import org.cryptomator.ui.keyloading.masterkeyfile.MasterkeyFileLoadingStrategy;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -125,7 +125,7 @@ public class VaultListManager {
 					vaultSettings.lastKnownKeyLoader.set(keyIdScheme);
 				}
 			} else if (vaultState == NEEDS_MIGRATION) {
-				vaultSettings.lastKnownKeyLoader.set(Constants.DEFAULT_KEY_ID.toString());
+				vaultSettings.lastKnownKeyLoader.set(MasterkeyFileLoadingStrategy.SCHEME);
 			}
 			return vaultComponentFactory.create(vaultSettings, wrapper, vaultState, null).vault();
 		} catch (IOException e) {

+ 1 - 1
src/main/java/org/cryptomator/ui/addvaultwizard/CreateNewVaultExpertSettingsController.java

@@ -26,7 +26,7 @@ public class CreateNewVaultExpertSettingsController implements FxController {
 
 	public static final int MAX_SHORTENING_THRESHOLD = 220;
 	public static final int MIN_SHORTENING_THRESHOLD = 36;
-	private static final String DOCS_NAME_SHORTENING_URL = "https://docs.cryptomator.org/security/architecture/#name-shortening";
+	private static final String DOCS_NAME_SHORTENING_URL = "https://docs.cryptomator.org/security/vault/#name-shortening";
 
 	private final Stage window;
 	private final Lazy<Application> application;

+ 22 - 0
src/main/java/org/cryptomator/ui/addvaultwizard/CreateNewVaultLocationController.java

@@ -4,6 +4,7 @@ import dagger.Lazy;
 import org.cryptomator.common.ObservableUtil;
 import org.cryptomator.common.locationpresets.LocationPreset;
 import org.cryptomator.common.locationpresets.LocationPresetsProvider;
+import org.cryptomator.common.settings.Settings;
 import org.cryptomator.ui.common.FxController;
 import org.cryptomator.ui.common.FxmlFile;
 import org.cryptomator.ui.common.FxmlScene;
@@ -38,6 +39,7 @@ import javafx.stage.WindowEvent;
 import java.io.File;
 import java.io.IOException;
 import java.nio.file.Files;
+import java.nio.file.InvalidPathException;
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.util.Optional;
@@ -64,6 +66,7 @@ public class CreateNewVaultLocationController implements FxController {
 	private final BooleanProperty loadingPresetLocations = new SimpleBooleanProperty(false);
 	private final ObservableList<Node> radioButtons;
 	private final ObservableList<Node> sortedRadioButtons;
+	private final Settings settings;
 
 	private Path customVaultPath = DEFAULT_CUSTOM_VAULT_PATH;
 
@@ -82,6 +85,7 @@ public class CreateNewVaultLocationController implements FxController {
 									 @FxmlScene(FxmlFile.ADDVAULT_NEW_EXPERT_SETTINGS) Lazy<Scene> chooseExpertSettingsScene, //
 									 ObjectProperty<Path> vaultPath, //
 									 @Named("vaultName") StringProperty vaultName, //
+									 Settings settings, //
 									 ExecutorService backgroundExecutor, ResourceBundle resourceBundle) {
 		this.window = window;
 		this.chooseNameScene = chooseNameScene;
@@ -96,6 +100,18 @@ public class CreateNewVaultLocationController implements FxController {
 		this.usePresetPath = new SimpleBooleanProperty();
 		this.radioButtons = FXCollections.observableArrayList();
 		this.sortedRadioButtons = radioButtons.sorted(this::compareLocationPresets);
+		this.settings = settings;
+
+		Path previouslyUsedDirectory = settings.previouslyUsedVaultDirectory.get();
+		if (previouslyUsedDirectory != null) {
+			try {
+				if (Files.exists(previouslyUsedDirectory) && Files.isDirectory(previouslyUsedDirectory) && isActuallyWritable(previouslyUsedDirectory)) {
+					this.customVaultPath = previouslyUsedDirectory;
+				}
+			} catch (InvalidPathException | NullPointerException e) {
+				LOG.warn("Invalid previously used vault directory path: {}", previouslyUsedDirectory, e);
+			}
+		}
 	}
 
 	private VaultPathStatus validatePath(Path p) throws NullPointerException {
@@ -196,6 +212,12 @@ public class CreateNewVaultLocationController implements FxController {
 	@FXML
 	public void next() {
 		if (validVaultPath.getValue()) {
+			if (this.getVaultPath() != null) {
+				Path parentPath = this.getVaultPath().getParent();
+				if (parentPath != null) {
+					this.settings.previouslyUsedVaultDirectory.setValue(parentPath);
+				}
+			}
 			window.setScene(chooseExpertSettingsScene.get());
 		}
 	}

+ 4 - 3
src/main/java/org/cryptomator/ui/keyloading/KeyLoadingStrategy.java

@@ -46,15 +46,16 @@ public interface KeyLoadingStrategy extends MasterkeyLoader {
 	/**
 	 * Determines whether the provided key loader scheme corresponds to a Masterkey File Vault.
 	 * <p>
-	 * This method checks if the {@code keyLoader} parameter matches the known Masterkey File Vault scheme
+	 * This method checks if the {@code keyLoader} parameter starts with the known Masterkey File Vault scheme
 	 * {@link MasterkeyFileLoadingStrategy#SCHEME}.
+	 * This allows identifying not only exact matches but also variants or extended schemes based on the Masterkey scheme.
 	 * </p>
 	 *
 	 * @param keyLoader A string representing the key loader scheme to be checked.
-	 * @return {@code true} if the given key loader scheme represents a Masterkey File Vault; {@code false} otherwise.
+	 * @return {@code true} if the given key loader scheme starts with the Masterkey File Vault scheme; {@code false} otherwise.
 	 */
 	static boolean isMasterkeyFileVault(String keyLoader) {
-		return MasterkeyFileLoadingStrategy.SCHEME.equals(keyLoader);
+		return keyLoader.startsWith(MasterkeyFileLoadingStrategy.SCHEME);
 	}
 
 	/**

+ 1 - 1
src/main/java/org/cryptomator/ui/sharevault/ShareVaultController.java

@@ -19,7 +19,7 @@ public class ShareVaultController implements FxController {
 
 	private static final String SCHEME_PREFIX = "hub+";
 	private static final String VISIT_HUB_URL = "https://cryptomator.org/hub/";
-	private static final String BEST_PRACTICES_URL = "https://docs.cryptomator.org/en/latest/security/best-practices/#sharing-of-vaults";
+	private static final String BEST_PRACTICES_URL = "https://docs.cryptomator.org/security/best-practices/#sharing-of-vaults";
 
 	private final Stage window;
 	private final Lazy<Application> application;

+ 41 - 5
src/main/resources/i18n/strings_ar.properties

@@ -62,9 +62,9 @@ addvaultwizard.new.locationIsOk=الموقع المناسب للمخزن الخ
 addvaultwizard.new.invalidName=اسم المخزن غير صالح
 addvaultwizard.new.validName=اسم المخزن صالح
 addvaultwizard.new.validCharacters.message=قد يحتوي اسم المخزن على الأحرف التالية:
-addvaultwizard.new.validCharacters.chars=أحرف الكلمات (أمثلة: a, ж, 수)
-addvaultwizard.new.validCharacters.numbers=الأعداد
-addvaultwizard.new.validCharacters.dashes=الشرطة (%s) أو الشرطة السفلية (%s)
+addvaultwizard.new.validCharacters.chars=أحرف لكن دون علامات (#, $, !, @...)
+addvaultwizard.new.validCharacters.numbers=الأرقام
+addvaultwizard.new.validCharacters.dashes=ناقص (%s) أو شِرْطَةٌ سفلية (%s)
 ### Expert Settings
 addvaultwizard.new.expertSettings.enableExpertSettingsCheckbox=تمكين إعدادات الخبراء
 addvaultwizard.new.expertSettings.shorteningThreshold.invalid=أدخل قيمة بين 36 و 220 (الافتراضي 220)
@@ -319,7 +319,7 @@ preferences.volume.feature.readOnly=تحميل للقراءة فقط
 ## Updates
 preferences.updates=تحديثات
 preferences.updates.currentVersion=الإصدار الحالي: %s
-preferences.updates.autoUpdateCheck=تحقق من التحديثات اوتوماتيكيا
+preferences.updates.autoUpdateCheck=التحقق من وجود تحديثات تلقائياً
 preferences.updates.checkNowBtn=تحقق الان
 preferences.updates.updateAvailable=التحديث إلى الإصدار %s متاح.
 preferences.updates.lastUpdateCheck=آخر فحص: %s
@@ -395,6 +395,7 @@ main.vaultlist.contextMenu.vaultoptions=إظهار خيارات المخزن
 main.vaultlist.contextMenu.reveal=اظهار القرص
 main.vaultlist.addVaultBtn.menuItemNew=إنشاء مخزن جديد...
 main.vaultlist.addVaultBtn.menuItemExisting=افتح مخزن موجود...
+main.vaultlist.showEventsButton.tooltip=عرض الإشعارات
 ##Notificaition
 main.notification.updateAvailable=هناك تحديث متاح.
 main.notification.support=دعم Cryptomator.
@@ -423,7 +424,9 @@ main.vaultDetail.stats=إحصائيات الخزنة
 main.vaultDetail.locateEncryptedFileBtn=تحديد موقع الملف المشفر
 main.vaultDetail.locateEncryptedFileBtn.tooltip=اختر ملف من خزانتك لتحديد مكان نظيره المشفر
 main.vaultDetail.encryptedPathsCopied=تم نسخ مسارات الملفات إلى الحافظة!
+main.vaultDetail.locateEncrypted.filePickerTitle=اختر الملَف من الخزنة
 main.vaultDetail.decryptName.buttonLabel=فك تشفير اسم الملف
+main.vaultDetail.decryptName.tooltip=اختر ملَف مشفر لفك تشفير اسمه
 ### Missing
 main.vaultDetail.missing.info=لم يتمكن Cryptomator من العثور على خزنة في هذا المسار.
 main.vaultDetail.missing.recheck=إعادة الفحص
@@ -473,7 +476,7 @@ vaultOptions.mount.mountPoint.custom=استخدام المجلد المختار
 vaultOptions.mount.mountPoint.directoryPickerButton=اختر…
 vaultOptions.mount.mountPoint.directoryPickerTitle=إختر مجلد
 vaultOptions.mount.volumeType.default=الافتراضي (%s)
-vaultOptions.mount.volumeType.restartRequired=لاستخدام هذا النوع من وحدة التخزين يحتاج Cryptomator إلى إعادة تشغيله.
+vaultOptions.mount.volumeType.restartRequired=لاستخدام هذا النوع من وحدة التخزين يحتاج Cryptomator إلى إعادة تشغيل.
 vaultOptions.mount.volume.tcp.port=منفذ TCP
 vaultOptions.mount.volume.type=‮نوع وحدة التخزين
 ## Master Key
@@ -580,7 +583,40 @@ shareVault.hub.instruction.2=2. امنح الوصول لعضو الفريق في
 shareVault.hub.openHub=زيارة Cryptomator Hub
 
 # Decrypt File Names
+decryptNames.title=فك تشفير اسم الملَف
+decryptNames.filePicker.title=اختر ملَف مشفر
+decryptNames.filePicker.extensionDescription=ملف مشفر
+decryptNames.copyTable.tooltip=نسخ الجدول
+decryptNames.clearTable.tooltip=مسح الجدول
+decryptNames.copyHint=نسخ محتوى الخلية مع %s
+decryptNames.dropZone.message=إسقاط الملفات أو انقر لتحديد
+decryptNames.dropZone.error.vaultInternalFiles=مخزن الملفات الداخلية مع عدم تحديد اسم قابل للتشفير
+decryptNames.dropZone.error.foreignFiles=الملفات لا تنتمي إلى مخزن "%s"
+decryptNames.dropZone.error.noDirIdBackup=مسار الملفات المحددة لا يحتوي على ملَف dirId.c9r
+decryptNames.dropZone.error.generic=فشل فك تشفير أسماء الملفات
 
 
 # Event View
+eventView.title=أحداث
+eventView.filter.allVaults=الكل
+eventView.clearListButton.tooltip=تفريغ القائمة
 ## event list entries
+eventView.entry.vaultLocked.description=فتح "%s" للحصول على التفاصيل
+eventView.entry.conflictResolved.message=تم حل التضارب
+eventView.entry.conflictResolved.showDecrypted=إظهار الملف غير المشفر
+eventView.entry.conflictResolved.copyDecrypted=نسخ المسار غير المشفر
+eventView.entry.conflict.message=فشل حل التضارب
+eventView.entry.conflict.showDecrypted=إظهار الملَف غير المشفر الأصلي
+eventView.entry.conflict.copyDecrypted=نسخ المسار غير المشفر والأصلي
+eventView.entry.conflict.showEncrypted=إظهار ملف متضارب ومشفر
+eventView.entry.conflict.copyEncrypted=نسخ مسار التشفير المتعارض
+eventView.entry.decryptionFailed.message=فشل فك التشفير
+eventView.entry.decryptionFailed.showEncrypted=عرض ملَف المشفر
+eventView.entry.decryptionFailed.copyEncrypted=نسخ مسار المشفر
+eventView.entry.brokenDirFile.message=رابط الدليل المكسور
+eventView.entry.brokenDirFile.showEncrypted=إظهار الرابط المكسور، المشفر
+eventView.entry.brokenDirFile.copyEncrypted=نسخ مسار الرابط المكسور
+eventView.entry.brokenFileNode.message=عقدة ملفات النظام التافلة
+eventView.entry.brokenFileNode.showEncrypted=عرض العقدة المشفّرة التافلة
+eventView.entry.brokenFileNode.copyEncrypted=نسخ مسار العقدة المشفّرة التافلة
+eventView.entry.brokenFileNode.copyDecrypted=نسخ المسار غير المشفر

+ 24 - 24
src/main/resources/i18n/strings_pt.properties

@@ -424,9 +424,9 @@ main.vaultDetail.stats=Estatísticas do Cofre
 main.vaultDetail.locateEncryptedFileBtn=Localizar Ficheiro Encriptado
 main.vaultDetail.locateEncryptedFileBtn.tooltip=Escolha um ficheiro do seu cofre para localizar a sua contraparte encriptada
 main.vaultDetail.encryptedPathsCopied=Caminhos copiados para a área de transferência!
-main.vaultDetail.locateEncrypted.filePickerTitle=Selecionar ficheiro dentro do cofre
-main.vaultDetail.decryptName.buttonLabel=Desencriptar nome do ficheiro
-main.vaultDetail.decryptName.tooltip=Escolha um ficheiro de cofre encriptado para desencriptar o seu nome
+main.vaultDetail.locateEncrypted.filePickerTitle=Selecione o ficheiro no cofre
+main.vaultDetail.decryptName.buttonLabel=Descriptografar o nome do ficheiro
+main.vaultDetail.decryptName.tooltip=Escolha um ficheiro encriptado do cofre para desencriptar o seu nome
 ### Missing
 main.vaultDetail.missing.info=O Cryptomator não conseguiu encontrar um cofre neste diretório.
 main.vaultDetail.missing.recheck=Verificar novamente
@@ -583,17 +583,17 @@ shareVault.hub.instruction.2=2. Conceder acesso ao membro da equipe no Hub Crypt
 shareVault.hub.openHub=Abrir Hub do Cryptomator
 
 # Decrypt File Names
-decryptNames.title=Desencriptar nomes de ficheiros
+decryptNames.title=Desencriptar os nomes dos ficheiros
 decryptNames.filePicker.title=Selecione o ficheiro encriptado
-decryptNames.filePicker.extensionDescription=Ficheiro encriptado do Cryptomator
-decryptNames.copyTable.tooltip=Copiar tabela
-decryptNames.clearTable.tooltip=Limpar tabela
-decryptNames.copyHint=Copiar conteúdo da célula com %s
-decryptNames.dropZone.message=Solte os ficheiros ou clique para selecionar
-decryptNames.dropZone.error.vaultInternalFiles=Ficheiros internos do cofre sem nome decifrável selecionado
-decryptNames.dropZone.error.foreignFiles=Ficheiros não pertencem ao cofre "%s"
+decryptNames.filePicker.extensionDescription=Ficheiro encriptado pelo Criptomator
+decryptNames.copyTable.tooltip=Copiar a tabela
+decryptNames.clearTable.tooltip=Limpar a tabela
+decryptNames.copyHint=Copiar o conteúdo da célula com %s
+decryptNames.dropZone.message=Largue os ficheiros ou clique para selecionar
+decryptNames.dropZone.error.vaultInternalFiles=Ficheiros internos do coftre sem nome desencriptável selecionado
+decryptNames.dropZone.error.foreignFiles=Os ficheiros não pertencem ao cofre "%s"
 decryptNames.dropZone.error.noDirIdBackup=O diretório dos ficheiros selecionados não contém o ficheiro dirId.c9r
-decryptNames.dropZone.error.generic=Falha ao desencriptar nomes de ficheiros
+decryptNames.dropZone.error.generic=Falha ao desencriptar os nomes dos ficheiros
 
 
 # Event View
@@ -603,20 +603,20 @@ eventView.clearListButton.tooltip=Limpar lista
 ## event list entries
 eventView.entry.vaultLocked.description=Desbloquear "%s" para detalhes
 eventView.entry.conflictResolved.message=Conflito resolvido
-eventView.entry.conflictResolved.showDecrypted=Mostrar ficheiro desencriptado
-eventView.entry.conflictResolved.copyDecrypted=Copiar caminho desencriptado
-eventView.entry.conflict.message=Resolução de conflito falhou
-eventView.entry.conflict.showDecrypted=Mostrar ficheiro original desencriptado
-eventView.entry.conflict.copyDecrypted=Copie caminho original desencriptado
-eventView.entry.conflict.showEncrypted=Mostrar ficheiro encriptado conflitante
-eventView.entry.conflict.copyEncrypted=Copiar caminho encriptado conflituante
-eventView.entry.decryptionFailed.message=Falha na desencriptação
+eventView.entry.conflictResolved.showDecrypted=Mostrar o ficheiro desencriptado
+eventView.entry.conflictResolved.copyDecrypted=Copiar o caminho desencriptado
+eventView.entry.conflict.message=A resolução do conflito falhou
+eventView.entry.conflict.showDecrypted=Mostrar o ficheiro original desencriptado
+eventView.entry.conflict.copyDecrypted=Copie o caminho original desencriptado
+eventView.entry.conflict.showEncrypted=Mostrar o ficheiro encriptado em conflito
+eventView.entry.conflict.copyEncrypted=Copiar o caminho encriptado em conflito
+eventView.entry.decryptionFailed.message=A desencriptação falhou
 eventView.entry.decryptionFailed.showEncrypted=Mostrar ficheiro encriptado
-eventView.entry.decryptionFailed.copyEncrypted=Copiar caminho de encriptação
+eventView.entry.decryptionFailed.copyEncrypted=Copiar o caminho encriptado
 eventView.entry.brokenDirFile.message=Link de diretório quebrado
-eventView.entry.brokenDirFile.showEncrypted=Mostrar link quebrado e encriptado
+eventView.entry.brokenDirFile.showEncrypted=Mostrar o link quebrado e encriptado
 eventView.entry.brokenDirFile.copyEncrypted=Copiar caminho do link quebrado
 eventView.entry.brokenFileNode.message=Nó do sistema de ficheiros avariado
-eventView.entry.brokenFileNode.showEncrypted=Mostrar nó encriptado quebrado
+eventView.entry.brokenFileNode.showEncrypted=Mostrar nó encriptado e danificado
 eventView.entry.brokenFileNode.copyEncrypted=Copiar o caminho do nó encriptado e danificado
-eventView.entry.brokenFileNode.copyDecrypted=Copiar caminho desencriptado
+eventView.entry.brokenFileNode.copyDecrypted=Copiar o caminho desencriptado