diff --git a/README.md b/README.md index ec5020e95..15960dcda 100644 --- a/README.md +++ b/README.md @@ -197,6 +197,7 @@ The distributed XPipe application consists out of two parts: - The closed-source extensions, mostly for professional edition features, which are not included in this repository Additional features are available in the professional edition. For more details see https://xpipe.io/pricing. +If your enterprise puts great emphasis on having access to the full source code, there are also full source-available enterprise options available. ## More links diff --git a/app/src/main/java/io/xpipe/app/comp/store/StoreEntryComp.java b/app/src/main/java/io/xpipe/app/comp/store/StoreEntryComp.java index 94f33ba3d..2c88d7c9a 100644 --- a/app/src/main/java/io/xpipe/app/comp/store/StoreEntryComp.java +++ b/app/src/main/java/io/xpipe/app/comp/store/StoreEntryComp.java @@ -482,7 +482,7 @@ public abstract class StoreEntryComp extends SimpleComp { sc.textProperty().bind(AppI18n.observable("base.createShortcut")); sc.setOnAction(event -> { ThreadHelper.runFailableAsync(() -> { - DesktopShortcuts.create( + DesktopShortcuts.createCliOpen( url, DataStorage.get() .getStoreEntryDisplayName( diff --git a/app/src/main/java/io/xpipe/app/core/AppGreetings.java b/app/src/main/java/io/xpipe/app/core/AppGreetings.java index 1d94ed99d..b44ac8813 100644 --- a/app/src/main/java/io/xpipe/app/core/AppGreetings.java +++ b/app/src/main/java/io/xpipe/app/core/AppGreetings.java @@ -55,6 +55,12 @@ public class AppGreetings { if (set || AppProperties.get().isDevelopmentEnvironment()) { return; } + + if (AppProperties.get().isAutoAcceptEula()) { + AppCache.update("legalAccepted", true); + return; + } + var read = new SimpleBooleanProperty(); var accepted = new SimpleBooleanProperty(); AppWindowHelper.showBlockingAlert(alert -> { diff --git a/app/src/main/java/io/xpipe/app/core/AppProperties.java b/app/src/main/java/io/xpipe/app/core/AppProperties.java index 8150cc878..f661ea143 100644 --- a/app/src/main/java/io/xpipe/app/core/AppProperties.java +++ b/app/src/main/java/io/xpipe/app/core/AppProperties.java @@ -42,6 +42,7 @@ public class AppProperties { boolean locatePtb; boolean locatorVersionCheck; boolean isTest; + boolean autoAcceptEula; public AppProperties() { var appDir = Path.of(System.getProperty("user.dir")).resolve("app"); @@ -107,6 +108,9 @@ public class AppProperties { .map(s -> !Boolean.parseBoolean(s)) .orElse(true); isTest = isJUnitTest(); + autoAcceptEula = Optional.ofNullable(System.getProperty("io.xpipe.app.acceptEula")) + .map(Boolean::parseBoolean) + .orElse(false); } private static boolean isJUnitTest() { diff --git a/app/src/main/java/io/xpipe/app/prefs/AppPrefs.java b/app/src/main/java/io/xpipe/app/prefs/AppPrefs.java index 788197266..53f3eae78 100644 --- a/app/src/main/java/io/xpipe/app/prefs/AppPrefs.java +++ b/app/src/main/java/io/xpipe/app/prefs/AppPrefs.java @@ -175,6 +175,7 @@ public class AppPrefs { new SecurityCategory(), new HttpApiCategory(), new WorkflowCategory(), + new ProfilesCategory(), new TroubleshootCategory(), new DeveloperCategory()) .filter(appPrefsCategory -> appPrefsCategory.show()) diff --git a/app/src/main/java/io/xpipe/app/prefs/ProfileCreationAlert.java b/app/src/main/java/io/xpipe/app/prefs/ProfileCreationAlert.java new file mode 100644 index 000000000..5b1cb87d0 --- /dev/null +++ b/app/src/main/java/io/xpipe/app/prefs/ProfileCreationAlert.java @@ -0,0 +1,75 @@ +package io.xpipe.app.prefs; + +import io.xpipe.app.core.AppFont; +import io.xpipe.app.core.AppI18n; +import io.xpipe.app.core.AppProperties; +import io.xpipe.app.core.mode.OperationMode; +import io.xpipe.app.core.window.AppWindowHelper; +import io.xpipe.app.issue.ErrorEvent; +import io.xpipe.app.util.DesktopHelper; +import io.xpipe.app.util.DesktopShortcuts; +import io.xpipe.app.util.OptionsBuilder; +import io.xpipe.app.util.ThreadHelper; +import io.xpipe.core.process.OsType; +import io.xpipe.core.util.XPipeInstallation; +import javafx.beans.property.SimpleObjectProperty; +import javafx.geometry.Insets; +import javafx.scene.control.ButtonType; +import org.apache.commons.io.FileUtils; + +import java.nio.file.Files; + +public class ProfileCreationAlert { + + public static void showAsync() { + ThreadHelper.runFailableAsync(() -> { + show(); + }); + } + + private static void show() throws Exception { + var name = new SimpleObjectProperty<>("New profile"); + var path = new SimpleObjectProperty<>(AppProperties.get().getDataDir()); + var show = AppWindowHelper.showBlockingAlert(alert -> { + alert.setTitle(AppI18n.get("profileCreationAlertTitle")); + var content = new OptionsBuilder() + .nameAndDescription("profileName") + .addString(name) + .nameAndDescription("profilePath") + .addPath(path) + .buildComp() + .minWidth(500) + .padding(new Insets(10)) + .apply(struc -> AppFont.small(struc.get())) + .createRegion(); + alert.getButtonTypes().add(ButtonType.CANCEL); + alert.getButtonTypes().add(ButtonType.OK); + alert.getDialogPane().setContent(content); + }) + .map(b -> b.getButtonData().isDefaultButton()) + .orElse(false); + + if (!show || name.get() == null || path.get() == null) { + return; + } + + if (Files.exists(path.get()) && !FileUtils.isEmptyDirectory(path.get().toFile())) { + ErrorEvent.fromMessage("New profile directory is not empty").expected().handle(); + return; + } + + var shortcutName = (AppProperties.get().isStaging() ? "XPipe PTB" : "XPipe") + " (" + name.get() + ")"; + var file = switch (OsType.getLocal()) { + case OsType.Windows w -> { + var exec = XPipeInstallation.getCurrentInstallationBasePath().resolve(XPipeInstallation.getDaemonExecutablePath(w)).toString(); + yield DesktopShortcuts.create(exec, "-Dio.xpipe.app.dataDir=\"" + path.get().toString() + "\" -Dio.xpipe.app.acceptEula=true", shortcutName); + } + default -> { + var exec = XPipeInstallation.getCurrentInstallationBasePath().resolve(XPipeInstallation.getRelativeCliExecutablePath(OsType.getLocal())).toString(); + yield DesktopShortcuts.create(exec, "-d \"" + path.get().toString() + "\" --accept-eula", shortcutName); + } + }; + DesktopHelper.browseFileInDirectory(file); + OperationMode.close(); + } +} diff --git a/app/src/main/java/io/xpipe/app/prefs/ProfilesCategory.java b/app/src/main/java/io/xpipe/app/prefs/ProfilesCategory.java new file mode 100644 index 000000000..ff0a42855 --- /dev/null +++ b/app/src/main/java/io/xpipe/app/prefs/ProfilesCategory.java @@ -0,0 +1,26 @@ +package io.xpipe.app.prefs; + +import io.xpipe.app.comp.base.ButtonComp; +import io.xpipe.app.core.AppI18n; +import io.xpipe.app.fxcomps.Comp; +import io.xpipe.app.util.OptionsBuilder; + +public class ProfilesCategory extends AppPrefsCategory { + + @Override + protected String getId() { + return "profiles"; + } + + @Override + protected Comp create() { + return new OptionsBuilder() + .addTitle("manageProfiles") + .sub(new OptionsBuilder() + .nameAndDescription("profileAdd") + .addComp( + new ButtonComp(AppI18n.observable("addProfile"), + ProfileCreationAlert::showAsync))) + .buildComp(); + } +} diff --git a/app/src/main/java/io/xpipe/app/util/DesktopShortcuts.java b/app/src/main/java/io/xpipe/app/util/DesktopShortcuts.java index e93f1eee1..bde39a45f 100644 --- a/app/src/main/java/io/xpipe/app/util/DesktopShortcuts.java +++ b/app/src/main/java/io/xpipe/app/util/DesktopShortcuts.java @@ -4,27 +4,31 @@ import io.xpipe.core.process.OsType; import io.xpipe.core.util.XPipeInstallation; import java.nio.file.Files; +import java.nio.file.Path; public class DesktopShortcuts { - private static void createWindowsShortcut(String target, String name) throws Exception { + private static Path createWindowsShortcut(String executable, String args, String name) throws Exception { var icon = XPipeInstallation.getLocalDefaultInstallationIcon(); - var shortcutTarget = XPipeInstallation.getLocalDefaultCliExecutable(); var shortcutPath = DesktopHelper.getDesktopDirectory().resolve(name + ".lnk"); var content = String.format( """ - set "TARGET=%s" - set "SHORTCUT=%s" - set PWS=powershell.exe -ExecutionPolicy Restricted -NoLogo -NonInteractive -NoProfile - - %%PWS%% -Command "$ws = New-Object -ComObject WScript.Shell; $s = $ws.CreateShortcut('%%SHORTCUT%%'); $S.IconLocation='%s'; $S.WindowStyle=7; $S.TargetPath = '%%TARGET%%'; $S.Arguments = 'open %s'; $S.Save()" + $TARGET="%s" + $SHORTCUT="%s" + $ws = New-Object -ComObject WScript.Shell + $s = $ws.CreateShortcut("$SHORTCUT") + $S.IconLocation='%s' + $S.WindowStyle=7 + $S.TargetPath = "$TARGET" + $S.Arguments = '%s' + $S.Save() """, - shortcutTarget, shortcutPath, icon, target); - LocalShell.getShell().executeSimpleCommand(content); + executable, shortcutPath, icon, args); + LocalShell.getLocalPowershell().executeSimpleCommand(content); + return shortcutPath; } - private static void createLinuxShortcut(String target, String name) throws Exception { - var exec = XPipeInstallation.getLocalDefaultCliExecutable(); + private static Path createLinuxShortcut(String executable, String args, String name) throws Exception { var icon = XPipeInstallation.getLocalDefaultInstallationIcon(); var content = String.format( """ @@ -32,19 +36,19 @@ public class DesktopShortcuts { Type=Application Name=%s Comment=Open with XPipe - Exec="%s" open %s + Exec="%s" %s Icon=%s Terminal=false Categories=Utility;Development; """, - name, exec, target, icon); + name, executable, args, icon); var file = DesktopHelper.getDesktopDirectory().resolve(name + ".desktop"); Files.writeString(file, content); file.toFile().setExecutable(true); + return file; } - private static void createMacOSShortcut(String target, String name) throws Exception { - var exec = XPipeInstallation.getLocalDefaultCliExecutable(); + private static Path createMacOSShortcut(String executable, String args, String name) throws Exception { var icon = XPipeInstallation.getLocalDefaultInstallationIcon(); var base = DesktopHelper.getDesktopDirectory().resolve(name + ".app"); var content = String.format( @@ -52,18 +56,18 @@ public class DesktopShortcuts { #!/usr/bin/env sh "%s" open %s """, - exec, target); + executable, args); try (var pc = LocalShell.getShell()) { pc.getShellDialect().deleteFileOrDirectory(pc, base.toString()).executeAndCheck(); pc.executeSimpleCommand(pc.getShellDialect().getMkdirsCommand(base + "/Contents/MacOS")); pc.executeSimpleCommand(pc.getShellDialect().getMkdirsCommand(base + "/Contents/Resources")); - var executable = base + "/Contents/MacOS/" + name; + var macExec = base + "/Contents/MacOS/" + name; pc.getShellDialect() - .createScriptTextFileWriteCommand(pc, content, executable) + .createScriptTextFileWriteCommand(pc, content, macExec) .execute(); - pc.executeSimpleCommand("chmod ugo+x \"" + executable + "\""); + pc.executeSimpleCommand("chmod ugo+x \"" + macExec + "\""); pc.getShellDialect() .createTextFileWriteCommand(pc, "APPL????", base + "/Contents/PkgInfo") @@ -85,15 +89,21 @@ public class DesktopShortcuts { .execute(); pc.executeSimpleCommand("cp \"" + icon + "\" \"" + base + "/Contents/Resources/icon.icns\""); } + return base; } - public static void create(String target, String name) throws Exception { + public static Path createCliOpen(String action, String name) throws Exception { + var exec = XPipeInstallation.getLocalDefaultCliExecutable(); + return create(exec, "open " + action, name); + } + + public static Path create(String executable, String args, String name) throws Exception { if (OsType.getLocal().equals(OsType.WINDOWS)) { - createWindowsShortcut(target, name); + return createWindowsShortcut(executable, args, name); } else if (OsType.getLocal().equals(OsType.LINUX)) { - createLinuxShortcut(target, name); + return createLinuxShortcut(executable, args, name); } else { - createMacOSShortcut(target, name); + return createMacOSShortcut(executable, args, name); } } } diff --git a/lang/app/strings/translations_da.properties b/lang/app/strings/translations_da.properties index c7b267b5d..9d58086f7 100644 --- a/lang/app/strings/translations_da.properties +++ b/lang/app/strings/translations_da.properties @@ -490,3 +490,13 @@ closeLeftTabs=Luk faner til venstre closeRightTabs=Luk faner til højre addSerial=Seriel ... connect=Forbind +profiles=Profiler +manageProfiles=Administrer profiler +addProfile=Tilføj profil ... +profileAdd=Tilføj en ny profil +profileAddDescription=Profiler er forskellige konfigurationer til at køre XPipe. Hver profil har et datakatalog, hvor alle data gemmes lokalt. Det omfatter forbindelsesdata, indstillinger og meget mere.\n\nHvis du bruger synkroniseringsfunktionen, kan du også vælge at synkronisere hver profil med et forskelligt git-repository. +profileName=Navn på profil +profileNameDescription=Profilens visningsnavn +profilePath=Profil sti +profilePathDescription=Placeringen af profilens datakatalog +profileCreationAlertTitle=Oprettelse af profil diff --git a/lang/app/strings/translations_de.properties b/lang/app/strings/translations_de.properties index a5eb109f8..401d2d5a7 100644 --- a/lang/app/strings/translations_de.properties +++ b/lang/app/strings/translations_de.properties @@ -484,3 +484,13 @@ closeLeftTabs=Tabs nach links schließen closeRightTabs=Tabs nach rechts schließen addSerial=Serielle ... connect=Verbinden +profiles=Profile +manageProfiles=Profile verwalten +addProfile=Profil hinzufügen ... +profileAdd=Ein neues Profil hinzufügen +profileAddDescription=Profile sind unterschiedliche Konfigurationen für den Betrieb von XPipe. Jedes Profil hat ein Datenverzeichnis, in dem alle Daten lokal gespeichert werden. Dazu gehören Verbindungsdaten, Einstellungen und mehr.\n\nWenn du die Synchronisierungsfunktion nutzt, kannst du jedes Profil auch mit einem anderen Git-Repository synchronisieren. +profileName=Profilname +profileNameDescription=Der Anzeigename des Profils +profilePath=Profilpfad +profilePathDescription=Der Ort des Profildatenverzeichnisses +profileCreationAlertTitle=Profil erstellen diff --git a/lang/app/strings/translations_en.properties b/lang/app/strings/translations_en.properties index 56e19c3e3..21f8061f0 100644 --- a/lang/app/strings/translations_en.properties +++ b/lang/app/strings/translations_en.properties @@ -488,3 +488,13 @@ closeLeftTabs=Close tabs to the left closeRightTabs=Close tabs to the right addSerial=Serial ... connect=Connect +profiles=Profiles +manageProfiles=Manage profiles +addProfile=Add profile ... +profileAdd=Add a new profile +profileAddDescription=Profiles are distinct configurations for running XPipe. Every profile has a data directory where all data is stored locally. This includes connection data, settings, and more.\n\nIf you use the synchronization feature, you can also choose to synchronize each profile with a different git repository. +profileName=Profile name +profileNameDescription=The display name of the profile +profilePath=Profile path +profilePathDescription=The location of the profile data directory +profileCreationAlertTitle=Profile creation diff --git a/lang/app/strings/translations_es.properties b/lang/app/strings/translations_es.properties index 2d11193b9..e89cb446e 100644 --- a/lang/app/strings/translations_es.properties +++ b/lang/app/strings/translations_es.properties @@ -471,3 +471,13 @@ closeLeftTabs=Cerrar pestañas a la izquierda closeRightTabs=Cerrar pestañas a la derecha addSerial=Serie ... connect=Conecta +profiles=Perfiles +manageProfiles=Gestionar perfiles +addProfile=Añadir perfil ... +profileAdd=Añadir un nuevo perfil +profileAddDescription=Los perfiles son configuraciones distintas para ejecutar XPipe. Cada perfil tiene un directorio de datos donde se almacenan localmente todos los datos. Esto incluye datos de conexión, configuraciones y más.\n\nSi utilizas la función de sincronización, también puedes elegir sincronizar cada perfil con un repositorio git diferente. +profileName=Nombre del perfil +profileNameDescription=El nombre para mostrar del perfil +profilePath=Ruta del perfil +profilePathDescription=La ubicación del directorio de datos del perfil +profileCreationAlertTitle=Creación de perfiles diff --git a/lang/app/strings/translations_fr.properties b/lang/app/strings/translations_fr.properties index 85caf5c34..b9afa8f7b 100644 --- a/lang/app/strings/translations_fr.properties +++ b/lang/app/strings/translations_fr.properties @@ -471,3 +471,13 @@ closeLeftTabs=Ferme les onglets à gauche closeRightTabs=Ferme les onglets à droite addSerial=Série ... connect=Connecter +profiles=Profils +manageProfiles=Gérer les profils +addProfile=Ajouter un profil ... +profileAdd=Ajouter un nouveau profil +profileAddDescription=Les profils sont des configurations distinctes pour l'exécution de XPipe. Chaque profil possède un répertoire de données où toutes les données sont stockées localement. Cela comprend les données de connexion, les paramètres, et plus encore.\n\nSi tu utilises la fonction de synchronisation, tu peux aussi choisir de synchroniser chaque profil avec un dépôt git différent. +profileName=Nom du profil +profileNameDescription=Le nom d'affichage du profil +profilePath=Chemin du profil +profilePathDescription=L'emplacement du répertoire des données de profil +profileCreationAlertTitle=Création de profil diff --git a/lang/app/strings/translations_it.properties b/lang/app/strings/translations_it.properties index 2200e9260..349c09fe0 100644 --- a/lang/app/strings/translations_it.properties +++ b/lang/app/strings/translations_it.properties @@ -471,3 +471,13 @@ closeLeftTabs=Chiudere le schede a sinistra closeRightTabs=Chiudere le schede a destra addSerial=Seriale ... connect=Collegare +profiles=Profili +manageProfiles=Gestire i profili +addProfile=Aggiungi profilo ... +profileAdd=Aggiungere un nuovo profilo +profileAddDescription=I profili sono configurazioni distinte per l'esecuzione di XPipe. Ogni profilo ha una directory di dati in cui vengono memorizzati tutti i dati a livello locale. Questi includono i dati di connessione, le impostazioni e altro ancora.\n\nSe utilizzi la funzione di sincronizzazione, puoi anche scegliere di sincronizzare ogni profilo con un repository git diverso. +profileName=Nome del profilo +profileNameDescription=Il nome visualizzato del profilo +profilePath=Percorso del profilo +profilePathDescription=La posizione della directory dei dati del profilo +profileCreationAlertTitle=Creazione di un profilo diff --git a/lang/app/strings/translations_ja.properties b/lang/app/strings/translations_ja.properties index f9f3d236e..702e749a4 100644 --- a/lang/app/strings/translations_ja.properties +++ b/lang/app/strings/translations_ja.properties @@ -471,3 +471,13 @@ closeLeftTabs=タブを左に閉じる closeRightTabs=タブを右に閉じる addSerial=シリアル ... connect=接続する +profiles=プロフィール +manageProfiles=プロファイルを管理する +addProfile=プロフィールを追加する +profileAdd=新しいプロファイルを追加する +profileAddDescription=プロファイルは、XPipeを実行するための個別の設定である。各プロファイルには、すべてのデータがローカルに保存されるデータディレクトリがある。これには、接続データや設定などが含まれる。\n\n同期機能を使えば、各プロファイルを異なるgitリポジトリと同期させることもできる。 +profileName=プロファイル名 +profileNameDescription=プロファイルの表示名 +profilePath=プロファイルパス +profilePathDescription=プロファイルデータのディレクトリの場所 +profileCreationAlertTitle=プロファイルの作成 diff --git a/lang/app/strings/translations_nl.properties b/lang/app/strings/translations_nl.properties index b23b17e70..fd88ea29e 100644 --- a/lang/app/strings/translations_nl.properties +++ b/lang/app/strings/translations_nl.properties @@ -471,3 +471,13 @@ closeLeftTabs=Tabbladen naar links sluiten closeRightTabs=Tabbladen naar rechts sluiten addSerial=Serieel ... connect=Maak verbinding met +profiles=Profielen +manageProfiles=Profielen beheren +addProfile=Profiel toevoegen ... +profileAdd=Een nieuw profiel toevoegen +profileAddDescription=Profielen zijn verschillende configuraties voor het uitvoeren van XPipe. Elk profiel heeft een datamap waar alle gegevens lokaal worden opgeslagen. Dit omvat verbindingsgegevens, instellingen en meer.\n\nAls je de synchronisatiefunctie gebruikt, kun je er ook voor kiezen om elk profiel met een andere git repository te synchroniseren. +profileName=Naam profiel +profileNameDescription=De weergavenaam van het profiel +profilePath=Profiel pad +profilePathDescription=De locatie van de profielgegevensmap +profileCreationAlertTitle=Profiel maken diff --git a/lang/app/strings/translations_pt.properties b/lang/app/strings/translations_pt.properties index 88377220a..e56893ba6 100644 --- a/lang/app/strings/translations_pt.properties +++ b/lang/app/strings/translations_pt.properties @@ -471,3 +471,13 @@ closeLeftTabs=Fecha os separadores à esquerda closeRightTabs=Fecha os separadores à direita addSerial=Série ... connect=Liga-te +profiles=Perfis +manageProfiles=Gerir perfis +addProfile=Adicionar perfil ... +profileAdd=Adiciona um novo perfil +profileAddDescription=Os perfis são configurações distintas para executar o XPipe. Cada perfil tem um diretório de dados onde todos os dados são armazenados localmente. Isto inclui dados de ligação, definições e muito mais.\n\nSe utilizares a funcionalidade de sincronização, também podes optar por sincronizar cada perfil com um repositório git diferente. +profileName=Nome do perfil +profileNameDescription=O nome de apresentação do perfil +profilePath=Caminho do perfil +profilePathDescription=A localização do diretório de dados do perfil +profileCreationAlertTitle=Criação de perfil diff --git a/lang/app/strings/translations_ru.properties b/lang/app/strings/translations_ru.properties index 4da41d4b1..e31ece22d 100644 --- a/lang/app/strings/translations_ru.properties +++ b/lang/app/strings/translations_ru.properties @@ -471,3 +471,13 @@ closeLeftTabs=Закрыть вкладки слева closeRightTabs=Закрывать вкладки справа addSerial=Серийный ... connect=Connect +profiles=Профили +manageProfiles=Управляй профилями +addProfile=Добавь профиль ... +profileAdd=Добавьте новый профиль +profileAddDescription=Профили - это отдельные конфигурации для запуска XPipe. У каждого профиля есть каталог данных, где все данные хранятся локально. Сюда входят данные о подключении, настройки и многое другое.\n\nЕсли ты используешь функцию синхронизации, ты также можешь выбрать синхронизацию каждого профиля с отдельным git-репозиторием. +profileName=Имя профиля +profileNameDescription=Отображаемое имя профиля +profilePath=Путь к профилю +profilePathDescription=Расположение каталога данных профиля +profileCreationAlertTitle=Создание профиля diff --git a/lang/app/strings/translations_tr.properties b/lang/app/strings/translations_tr.properties index 905afd010..c6cda864b 100644 --- a/lang/app/strings/translations_tr.properties +++ b/lang/app/strings/translations_tr.properties @@ -472,3 +472,13 @@ closeLeftTabs=Sekmeleri sola doğru kapatın closeRightTabs=Sekmeleri sağa doğru kapatın addSerial=Seri ... connect=Bağlan +profiles=Profiller +manageProfiles=Profilleri yönetin +addProfile=Profil ekle ... +profileAdd=Yeni bir profil ekleyin +profileAddDescription=Profiller XPipe'ı çalıştırmak için farklı konfigürasyonlardır. Her profil, tüm verilerin yerel olarak depolandığı bir veri dizinine sahiptir. Buna bağlantı verileri, ayarlar ve daha fazlası dahildir.\n\nSenkronizasyon özelliğini kullanırsanız, her profili farklı bir git deposu ile senkronize etmeyi de seçebilirsiniz. +profileName=Profil adı +profileNameDescription=Profilin görünen adı +profilePath=Profil yolu +profilePathDescription=Profil veri dizininin konumu +profileCreationAlertTitle=Profil oluşturma diff --git a/lang/app/strings/translations_zh.properties b/lang/app/strings/translations_zh.properties index e118201a0..7f3da02f0 100644 --- a/lang/app/strings/translations_zh.properties +++ b/lang/app/strings/translations_zh.properties @@ -471,3 +471,13 @@ closeLeftTabs=向左关闭标签 closeRightTabs=向右关闭标签页 addSerial=串行 ... connect=连接 +profiles=简介 +manageProfiles=管理配置文件 +addProfile=添加配置文件... +profileAdd=添加新的简介 +profileAddDescription=配置文件是运行 XPipe 的不同配置。每个配置文件都有一个数据目录,本地存储所有数据。其中包括连接数据、设置等。\n\n如果使用同步功能,您还可以选择将每个配置文件与不同的 git 仓库同步。 +profileName=简介名称 +profileNameDescription=配置文件的显示名称 +profilePath=配置文件路径 +profilePathDescription=配置文件数据目录的位置 +profileCreationAlertTitle=创建简介