mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-11-10 07:42:08 +00:00
Merge pull request #5741 from dotCooCoo/feat/prefs-folders-choose
Preferences: Additional Plug-ins Folder gets Choose…, and OK checks typed folders
This commit is contained in:
@@ -5055,6 +5055,7 @@ digits Malayalam Malaiàlam
|
||||
@msg damaged malmès
|
||||
@msg Data Recovery has nowhere to keep copies: set Preferences → File Handling → Data Recovery → Folder (recoveryFolder) La recuperació de dades no té cap lloc on guardar còpies: configureu Preferències → Gestió de fitxers → Recuperació de dades → Carpeta (recoveryFolder)
|
||||
@msg Data Recovery can't keep copies in {path}: {e} La recuperació de dades no pot guardar còpies a {path}: {e}
|
||||
@msg Plug-ins can't be loaded from {path}: {e} No es poden carregar complements des de {path}: {e}
|
||||
@msg data the program reads is damaged or cut short, or the program asks for a position in a file that has none les dades que llegeix el programa estan malmeses o tallades, o el programa demana una posició en un fitxer que no en té
|
||||
@msg decimals must be {_1}–{_2} (got {_3}) els decimals han de ser {_1}–{_2} (rebut {_3})
|
||||
@msg Dimension point is outside the canvas El punt de dimensió és fora del llenç
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -4292,6 +4292,7 @@ imageTrace Outline Obrys
|
||||
@msg Create from Selection: the selection has no area Vytvořit z výběru: výběr nemá žádnou plochu
|
||||
@msg Data Recovery has nowhere to keep copies: set Preferences → File Handling → Data Recovery → Folder (recoveryFolder) Obnovení dat nemá kam ukládat kopie: nastavte Předvolby → Práce se soubory → Obnovení dat → Složka (recoveryFolder)
|
||||
@msg Data Recovery can't keep copies in {path}: {e} Obnovení dat nemůže ukládat kopie do {path}: {e}
|
||||
@msg Plug-ins can't be loaded from {path}: {e} Zásuvné moduly nelze načíst z {path}: {e}
|
||||
@msg direct-select anchor points to cut at (not the end points of open paths) nástrojem Přímý výběr vyberte kotevní body, kde se má cesta rozdělit (ne koncové body otevřených cest)
|
||||
@msg Divide Objects Below: select a path Rozdělit objekty pod: vyberte cestu
|
||||
@msg Divide Objects Below: select exactly one path Rozdělit objekty pod: vyberte právě jednu cestu
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -3899,6 +3899,7 @@ theme Appearance Erscheinungsbild
|
||||
@msg Create from Selection: the selection has no area Aus Auswahl erstellen: Die Auswahl hat keine Fläche
|
||||
@msg Data Recovery has nowhere to keep copies: set Preferences → File Handling → Data Recovery → Folder (recoveryFolder) Die Datenwiederherstellung hat keinen Ort für ihre Kopien: Legen Sie Voreinstellungen → Dateihandhabung → Datenwiederherstellung → Ordner (recoveryFolder) fest
|
||||
@msg Data Recovery can't keep copies in {path}: {e} Die Datenwiederherstellung kann keine Kopien in {path} ablegen: {e}
|
||||
@msg Plug-ins can't be loaded from {path}: {e} Aus {path} können keine Plug-ins geladen werden: {e}
|
||||
@msg direct-select anchor points to cut at (not the end points of open paths) wählen Sie mit der Direktauswahl die Ankerpunkte aus, an denen geschnitten werden soll (nicht die Endpunkte offener Pfade)
|
||||
@msg Divide Objects Below: select a path Darunterliegende Objekte aufteilen: Wählen Sie einen Pfad aus
|
||||
@msg Divide Objects Below: select exactly one path Darunterliegende Objekte aufteilen: Wählen Sie genau einen Pfad aus
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -2184,6 +2184,7 @@ axis Both Και τα δύο
|
||||
@msg Create from Selection: the selection has no area Δημιουργία από επιλογή: η επιλογή δεν έχει επιφάνεια
|
||||
@msg Data Recovery has nowhere to keep copies: set Preferences → File Handling → Data Recovery → Folder (recoveryFolder) Η ανάκτηση δεδομένων δεν διαθέτει θέση αποθήκευσης αντιγράφων: ορίστε Προτιμήσεις → Χειρισμός αρχείων → Ανάκτηση δεδομένων → Φάκελος (recoveryFolder)
|
||||
@msg Data Recovery can't keep copies in {path}: {e} Η ανάκτηση δεδομένων δεν μπορεί να αποθηκεύσει αντίγραφα στο {path}: {e}
|
||||
@msg Plug-ins can't be loaded from {path}: {e} Δεν είναι δυνατή η φόρτωση πρόσθετων από το {path}: {e}
|
||||
@msg direct-select anchor points to cut at (not the end points of open paths) Επιλέξτε άμεσα τα σημεία αγκύρωσης όπου θα γίνει η αποκοπή (όχι τα τελικά σημεία ανοιχτών διαδρομών)
|
||||
@msg Divide Objects Below: select a path Διαίρεση αντικειμένων από κάτω: επιλέξτε μια διαδρομή
|
||||
@msg Divide Objects Below: select exactly one path Διαίρεση αντικειμένων από κάτω: επιλέξτε ακριβώς μία διαδρομή
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 163 and column 5.
|
@@ -3984,6 +3984,7 @@ axis Both Ambos
|
||||
@msg Create from Selection: the selection has no area Crear a partir de la selección: la selección no tiene área
|
||||
@msg Data Recovery has nowhere to keep copies: set Preferences → File Handling → Data Recovery → Folder (recoveryFolder) Recuperación de datos no tiene dónde guardar copias: configura Preferencias → Manejo de archivos → Recuperación de datos → Carpeta (recoveryFolder)
|
||||
@msg Data Recovery can't keep copies in {path}: {e} Recuperación de datos no puede guardar copias en {path}: {e}
|
||||
@msg Plug-ins can't be loaded from {path}: {e} No se pueden cargar plugins desde {path}: {e}
|
||||
@msg direct-select anchor points to cut at (not the end points of open paths) selecciona con Selección directa los puntos de ancla en los que cortar (no los puntos finales de trazados abiertos)
|
||||
@msg Divide Objects Below: select a path Dividir objetos inferiores: selecciona un trazado
|
||||
@msg Divide Objects Below: select exactly one path Dividir objetos inferiores: selecciona exactamente un trazado
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -4206,6 +4206,7 @@ imageTrace Outline Ääriviiva
|
||||
@msg Create from Selection: the selection has no area Luo valinnasta: valinnalla ei ole pinta-alaa
|
||||
@msg Data Recovery has nowhere to keep copies: set Preferences → File Handling → Data Recovery → Folder (recoveryFolder) Tietojen palautuksella ei ole paikkaa kopioille: määritä Asetukset → Tiedostojen käsittely → Tietojen palautus → Kansio (recoveryFolder)
|
||||
@msg Data Recovery can't keep copies in {path}: {e} Tietojen palautus ei voi tallentaa kopioita kansioon {path}: {e}
|
||||
@msg Plug-ins can't be loaded from {path}: {e} Laajennuksia ei voi ladata kansiosta {path}: {e}
|
||||
@msg direct-select anchor points to cut at (not the end points of open paths) valitse suoravalinnalla ankkuripisteet, joista leikataan (ei avoimien polkujen päätepisteitä)
|
||||
@msg Divide Objects Below: select a path Jaa alla olevat objektit: valitse polku
|
||||
@msg Divide Objects Below: select exactly one path Jaa alla olevat objektit: valitse tasan yksi polku
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -3974,6 +3974,7 @@ axis Both Les deux
|
||||
@msg Create from Selection: the selection has no area Créer d’après la sélection : la sélection n’a pas de surface
|
||||
@msg Data Recovery has nowhere to keep copies: set Preferences → File Handling → Data Recovery → Folder (recoveryFolder) La récupération des données n’a aucun emplacement où conserver les copies : définissez Préférences → Gestion des fichiers → Récupération des données → Dossier (recoveryFolder)
|
||||
@msg Data Recovery can't keep copies in {path}: {e} La récupération des données ne peut pas conserver de copies dans {path} ({e})
|
||||
@msg Plug-ins can't be loaded from {path}: {e} Impossible de charger les plug-ins depuis {path} ({e})
|
||||
@msg direct-select anchor points to cut at (not the end points of open paths) sélectionnez avec l’outil Sélection directe les points d’ancrage où couper (pas les extrémités des tracés ouverts)
|
||||
@msg Divide Objects Below: select a path Diviser les objets inférieurs : sélectionnez un tracé
|
||||
@msg Divide Objects Below: select exactly one path Diviser les objets inférieurs : sélectionnez exactement un tracé
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -4775,6 +4775,7 @@ imageTrace Outline Körvonal
|
||||
@msg damaged sérült
|
||||
@msg Data Recovery has nowhere to keep copies: set Preferences → File Handling → Data Recovery → Folder (recoveryFolder) Az adat-helyreállításnak nincs hova mentenie a másolatokat: állítsd be a Beállítások → Fájlkezelés → Adat-helyreállítás → Mappa értéket (recoveryFolder)
|
||||
@msg Data Recovery can't keep copies in {path}: {e} Az adat-helyreállítás nem tud másolatokat menteni ide: {path}: {e}
|
||||
@msg Plug-ins can't be loaded from {path}: {e} Innen nem tölthetők be bővítmények: {path}: {e}
|
||||
@msg decimals must be {_1}–{_2} (got {_3}) a tizedesjegyek száma {_1}–{_2} lehet (kapott érték: {_3})
|
||||
@msg direct-select anchor points to cut at (not the end points of open paths) jelöld ki közvetlen kijelöléssel a vágási horgonypontokat (nyitott útvonal végpontja nem lehet)
|
||||
@msgplural Discarded {n} recovered document|Discarded {n} recovered documents Elvetett helyreállított dokumentumok: {n}
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -4026,6 +4026,7 @@ axis Both Entrambi
|
||||
@msg Create from Selection: the selection has no area Crea da selezione: la selezione non ha area
|
||||
@msg Data Recovery has nowhere to keep copies: set Preferences → File Handling → Data Recovery → Folder (recoveryFolder) Il recupero dati non ha dove conservare le copie: imposta Preferenze → Gestione file → Recupero dati → Cartella (recoveryFolder)
|
||||
@msg Data Recovery can't keep copies in {path}: {e} Il recupero dati non può conservare copie in {path}: {e}
|
||||
@msg Plug-ins can't be loaded from {path}: {e} Impossibile caricare plug-in da {path}: {e}
|
||||
@msg direct-select anchor points to cut at (not the end points of open paths) seleziona con Selezione diretta i punti di ancoraggio in cui tagliare (non i punti finali dei tracciati aperti)
|
||||
@msg Divide Objects Below: select a path Dividi oggetti sottostanti: seleziona un tracciato
|
||||
@msg Divide Objects Below: select exactly one path Dividi oggetti sottostanti: seleziona esattamente un tracciato
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -4321,6 +4321,7 @@ swatch Bright Violet ビビッドバイオレット
|
||||
@msg unknown preference `{key}` `{key}` は不明な環境設定の項目です
|
||||
@msg Data Recovery has nowhere to keep copies: set Preferences → File Handling → Data Recovery → Folder (recoveryFolder) データ復帰のコピーを保存する場所がありません: 環境設定 → ファイル管理 → データ復帰 → フォルダー (recoveryFolder) を設定してください
|
||||
@msg Data Recovery can't keep copies in {path}: {e} データ復帰は {path} にコピーを保存できません: {e}
|
||||
@msg Plug-ins can't be loaded from {path}: {e} {path} からプラグインを読み込めません: {e}
|
||||
@msg `{area}` is no recovery area name `{area}` は復帰用領域の名前として使えません
|
||||
@msg `{name}` is no recovery entry name `{name}` は復帰用エントリの名前として使えません
|
||||
@msg no clock to keep a heartbeat by ハートビートの記録に必要な時刻を取得できません
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -3771,6 +3771,7 @@ font-technology Variable ცვლადი
|
||||
@msg Create from Selection: the selection has no area მონიშნულიდან შექმნა: მონიშნულს ფართობი არ აქვს
|
||||
@msg Data Recovery has nowhere to keep copies: set Preferences → File Handling → Data Recovery → Folder (recoveryFolder) მონაცემთა აღდგენას ასლების შესანახი ადგილი არ აქვს: მიუთითეთ პარამეტრები → ფაილების დამუშავება → მონაცემთა აღდგენა → საქაღალდე (recoveryFolder)
|
||||
@msg Data Recovery can't keep copies in {path}: {e} მონაცემთა აღდგენა ვერ ინახავს ასლებს აქ: {path}: {e}
|
||||
@msg Plug-ins can't be loaded from {path}: {e} პლაგინების ჩატვირთვა ვერ ხერხდება აქედან: {path}: {e}
|
||||
@msg direct-select anchor points to cut at (not the end points of open paths) პირდაპირი მონიშვნით მონიშნეთ საყრდენი წერტილები, სადაც გაიჭრება (არა ღია ტრაექტორიების ბოლო წერტილები)
|
||||
@msg Divide Objects Below: select a path ქვედა ობიექტების დაყოფა: მონიშნეთ ტრაექტორია
|
||||
@msg Divide Objects Below: select exactly one path ქვედა ობიექტების დაყოფა: მონიშნეთ ზუსტად ერთი ტრაექტორია
|
||||
|
||||
|
Can't render this file because it is too large.
|
@@ -4248,6 +4248,7 @@ theme Appearance 외관
|
||||
@msg unknown preference `{key}` 알 수 없는 환경 설정 `{key}`
|
||||
@msg Data Recovery has nowhere to keep copies: set Preferences → File Handling → Data Recovery → Folder (recoveryFolder) 데이터 복구에 복사본을 보관할 곳이 없습니다. 환경 설정 → 파일 처리 → 데이터 복구 → 폴더(recoveryFolder)를 지정하세요
|
||||
@msg Data Recovery can't keep copies in {path}: {e} 데이터 복구가 {path}에 복사본을 보관할 수 없습니다: {e}
|
||||
@msg Plug-ins can't be loaded from {path}: {e} {path}에서 플러그인을 불러올 수 없습니다: {e}
|
||||
@msg `{area}` is no recovery area name `{area}`은(는) 복구 영역 이름이 아닙니다
|
||||
@msg `{name}` is no recovery entry name `{name}`은(는) 복구 항목 이름이 아닙니다
|
||||
@msg no clock to keep a heartbeat by 하트비트를 유지할 시계가 없습니다
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -4115,6 +4115,7 @@ imageTrace Outline Kontur
|
||||
@msg Create from Selection: the selection has no area Utwórz z zaznaczenia: zaznaczenie nie ma powierzchni
|
||||
@msg Data Recovery has nowhere to keep copies: set Preferences → File Handling → Data Recovery → Folder (recoveryFolder) Odzyskiwanie danych nie ma gdzie przechowywać kopii: ustaw Preferencje → Obsługa plików → Odzyskiwanie danych → Folder (recoveryFolder)
|
||||
@msg Data Recovery can't keep copies in {path}: {e} Odzyskiwanie danych nie może przechowywać kopii w {path}: {e}
|
||||
@msg Plug-ins can't be loaded from {path}: {e} Nie można wczytać wtyczek z {path}: {e}
|
||||
@msg direct-select anchor points to cut at (not the end points of open paths) zaznacz bezpośrednio punkty kontrolne, w których ma nastąpić cięcie (nie punkty końcowe otwartych ścieżek)
|
||||
@msg Divide Objects Below: select a path Podziel obiekty poniżej: zaznacz ścieżkę
|
||||
@msg Divide Objects Below: select exactly one path Podziel obiekty poniżej: zaznacz dokładnie jedną ścieżkę
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -3573,6 +3573,7 @@ axis Both Ambos
|
||||
@msg Create from Selection: the selection has no area Criar a partir da seleção: a seleção não tem área
|
||||
@msg Data Recovery has nowhere to keep copies: set Preferences → File Handling → Data Recovery → Folder (recoveryFolder) A recuperação de dados não tem onde guardar cópias: defina Preferências → Manipulação de arquivos → Recuperação de dados → Pasta (recoveryFolder)
|
||||
@msg Data Recovery can't keep copies in {path}: {e} A recuperação de dados não pode guardar cópias em {path}: {e}
|
||||
@msg Plug-ins can't be loaded from {path}: {e} Não é possível carregar plug-ins de {path}: {e}
|
||||
@msg direct-select anchor points to cut at (not the end points of open paths) selecione diretamente os pontos de ancoragem onde cortar (não as extremidades de traçados abertos)
|
||||
@msg Divide Objects Below: select a path Dividir objetos abaixo: selecione um traçado
|
||||
@msg Divide Objects Below: select exactly one path Dividir objetos abaixo: selecione exatamente um traçado
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 6 and column 47.
|
@@ -4021,6 +4021,7 @@ axis Both Оба
|
||||
@msg Create from Selection: the selection has no area Создание из выделения: у выделения нет области
|
||||
@msg Data Recovery has nowhere to keep copies: set Preferences → File Handling → Data Recovery → Folder (recoveryFolder) Восстановлению данных негде хранить копии: задайте Настройки → Работа с файлами → Восстановление данных → Папка (recoveryFolder)
|
||||
@msg Data Recovery can't keep copies in {path}: {e} Восстановление данных не может хранить копии в {path}: {e}
|
||||
@msg Plug-ins can't be loaded from {path}: {e} Не удается загрузить модули из {path}: {e}
|
||||
@msg direct-select anchor points to cut at (not the end points of open paths) выделите прямым выделением опорные точки для разреза (не конечные точки открытых контуров)
|
||||
@msg Divide Objects Below: select a path Разделение объектов ниже: выделите контур
|
||||
@msg Divide Objects Below: select exactly one path Разделение объектов ниже: выделите ровно один контур
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -3895,6 +3895,7 @@ axis Both Båda
|
||||
@msg Create from Selection: the selection has no area Skapa från markering: markeringen har ingen area
|
||||
@msg Data Recovery has nowhere to keep copies: set Preferences → File Handling → Data Recovery → Folder (recoveryFolder) Dataåterställning har ingenstans att spara kopior: ange Inställningar → Filhantering → Dataåterställning → Mapp (recoveryFolder)
|
||||
@msg Data Recovery can't keep copies in {path}: {e} Dataåterställning kan inte spara kopior i {path}: {e}
|
||||
@msg Plug-ins can't be loaded from {path}: {e} Det går inte att läsa in plugin-program från {path}: {e}
|
||||
@msg direct-select anchor points to cut at (not the end points of open paths) direktmarkera ankarpunkter att klippa vid (inte slutpunkterna på öppna banor)
|
||||
@msg Divide Objects Below: select a path Dela objekt under: markera en bana
|
||||
@msg Divide Objects Below: select exactly one path Dela objekt under: markera exakt en bana
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 5 and column 25.
|
@@ -3779,6 +3779,7 @@ axis Both Her İkisi
|
||||
@msg Create from Selection: the selection has no area Seçimden Oluştur: Seçimin alanı yok
|
||||
@msg Data Recovery has nowhere to keep copies: set Preferences → File Handling → Data Recovery → Folder (recoveryFolder) Veri Kurtarma'nın kopyaları saklayacak yeri yoktur: Tercihleri ayarlayın → Dosya İşleme → Veri Kurtarma → Klasör (recoveryFolder)
|
||||
@msg Data Recovery can't keep copies in {path}: {e} Veri Kurtarma kopyaları {path} konumunda saklayamıyor: {e}
|
||||
@msg Plug-ins can't be loaded from {path}: {e} Eklentiler {path} konumundan yüklenemiyor: {e}
|
||||
@msg direct-select anchor points to cut at (not the end points of open paths) kesilecek bağlantı noktalarını doğrudan seçin (açık yolların bitiş noktalarını değil)
|
||||
@msg Divide Objects Below: select a path Aşağıdaki Nesneleri Böl: bir yol seçin
|
||||
@msg Divide Objects Below: select exactly one path Aşağıdaki Nesneleri Böl: tam olarak bir yol seçin
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 5 and column 25.
|
@@ -4010,6 +4010,7 @@ axis Both Обидві
|
||||
@msg Create from Selection: the selection has no area Створення з виділення: виділення немає області
|
||||
@msg Data Recovery has nowhere to keep copies: set Preferences → File Handling → Data Recovery → Folder (recoveryFolder) Відновлення даних ніде зберігати копії: задайте Установки → Робота з файлами → Відновлення даних → Папка (recoveryFolder)
|
||||
@msg Data Recovery can't keep copies in {path}: {e} Відновлення даних не може зберігати копії в {path}: {e}
|
||||
@msg Plug-ins can't be loaded from {path}: {e} Не вдається завантажити модулі з {path}: {e}
|
||||
@msg direct-select anchor points to cut at (not the end points of open paths) виділіть прямим виділенням опорні точки для розрізу (не кінцеві точки відкритих контурів)
|
||||
@msg Divide Objects Below: select a path Поділ об’єктів нижче: виділіть контур
|
||||
@msg Divide Objects Below: select exactly one path Поділ об’єктів нижче: виділіть рівно один контур
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 177 and column 5.
|
@@ -4427,6 +4427,7 @@ theme Appearance Giao diện
|
||||
@msg damaged bị hỏng
|
||||
@msg Data Recovery has nowhere to keep copies: set Preferences → File Handling → Data Recovery → Folder (recoveryFolder) Phục hồi dữ liệu không có nơi lưu bản sao: đặt Tùy chọn → Xử lý tệp → Phục hồi dữ liệu → Thư mục (recoveryFolder)
|
||||
@msg Data Recovery can't keep copies in {path}: {e} Phục hồi dữ liệu không thể lưu bản sao vào {path}: {e}
|
||||
@msg Plug-ins can't be loaded from {path}: {e} Không thể tải plug-in từ {path}: {e}
|
||||
@msg decimals must be {_1}–{_2} (got {_3}) số thập phân phải từ {_1}–{_2} (nhận được {_3})
|
||||
@msg direct-select anchor points to cut at (not the end points of open paths) chọn trực tiếp các điểm neo để cắt (không phải điểm cuối của đường dẫn mở)
|
||||
@msgplural Discarded {n} recovered document|Discarded {n} recovered documents Đã loại bỏ {n} tài liệu đã phục hồi
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 199 and column 5.
|
@@ -4047,6 +4047,7 @@ imageTrace Outline 轮廓
|
||||
@msg unknown preference `{key}` 未知首选项 `{key}`
|
||||
@msg Data Recovery has nowhere to keep copies: set Preferences → File Handling → Data Recovery → Folder (recoveryFolder) 数据恢复没有可保存副本的位置:请设置“首选项 → 文件处理 → 数据恢复 → 文件夹” (recoveryFolder)
|
||||
@msg Data Recovery can't keep copies in {path}: {e} 数据恢复无法将副本保存到 {path}:{e}
|
||||
@msg Plug-ins can't be loaded from {path}: {e} 无法从 {path} 载入增效工具:{e}
|
||||
@msg `{area}` is no recovery area name `{area}` 不是恢复区域名称
|
||||
@msg `{name}` is no recovery entry name `{name}` 不是恢复条目名称
|
||||
@msg no clock to keep a heartbeat by 没有可用于维持心跳的时钟
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -1933,6 +1933,7 @@ file-filter Templates 範本
|
||||
@msg unknown preference `{key}` 未知的偏好設定 `{key}`
|
||||
@msg Data Recovery has nowhere to keep copies: set Preferences → File Handling → Data Recovery → Folder (recoveryFolder) 「資料復原」沒有可存放拷貝的位置:請設定「偏好設定 → 檔案處理 → 資料復原 → 資料夾」 (recoveryFolder)
|
||||
@msg Data Recovery can't keep copies in {path}: {e} 「資料復原」無法將拷貝存放到 {path}:{e}
|
||||
@msg Plug-ins can't be loaded from {path}: {e} 無法從 {path} 載入增效模組:{e}
|
||||
@msg `{area}` is no recovery area name `{area}` 不是復原區域名稱
|
||||
@msg `{name}` is no recovery entry name `{name}` 不是復原項目名稱
|
||||
@msg no clock to keep a heartbeat by 沒有可用來維持心跳的時鐘
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 6 and column 47.
|
@@ -40,6 +40,7 @@ pub fn confirm(app: &mut VectorcraftApp) -> Result<Value, String> {
|
||||
let Some(d) = app.ui.dialog.clone() else { return Err("no dialog open".into()) };
|
||||
let values: Map<String, Value> = d.fields.iter().filter(|(k, _)| !k.starts_with("__")).map(|(k, v)| (k.clone(), v.clone())).collect();
|
||||
let touch_ws = values.get("touchWorkspace").and_then(Value::as_bool);
|
||||
check_typed_folders(app, &values)?;
|
||||
app.run("prefs.set", json!({ "values": values }))?;
|
||||
if touch_ws.is_some() {
|
||||
crate::workspaces::sync_touch_workspace(app, app.touch_screen);
|
||||
@@ -386,16 +387,17 @@ fn category_fields(ui: &mut egui::Ui, app: &mut VectorcraftApp, d: &mut Dialog,
|
||||
}
|
||||
});
|
||||
}
|
||||
// File Handling › Data Recovery › Folder: typed, or picked with Choose… where the host
|
||||
// has a folder picker (not on the web).
|
||||
PrefKind::Text if sp.key == "recoveryFolder" => {
|
||||
// File Handling › Data Recovery › Folder and Plug-ins & Scratch Disks › Additional
|
||||
// Plug-ins Folder: typed, or picked with Choose… where the host has a folder picker
|
||||
// (not on the web).
|
||||
PrefKind::Text if folder_check(sp.key).is_some() => {
|
||||
labeled(ui, sp.label, |ui| {
|
||||
let mut s = v.as_str().unwrap_or("").to_string();
|
||||
if ui.add(egui::TextEdit::singleline(&mut s).align(egui::Align2::LEFT_CENTER).desired_width(200.0)).changed() {
|
||||
d.fields.insert(sp.key.into(), json!(s));
|
||||
}
|
||||
if app.services.pick_folder.is_some() && ui.button(tl!("Choose…")).clicked() {
|
||||
choose_recovery_folder(app, d);
|
||||
choose_folder(app, d, sp.key);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -411,15 +413,30 @@ fn category_fields(ui: &mut egui::Ui, app: &mut VectorcraftApp, d: &mut Dialog,
|
||||
}
|
||||
}
|
||||
|
||||
/// Data Recovery › Choose…: the folder picked becomes the Folder field's value when a folder can be
|
||||
/// made in it. Otherwise the status bar says why and the field keeps its value, as it does when
|
||||
/// the picker is canceled. The answer fills the field even when the active document closed while
|
||||
/// the picker was open.
|
||||
fn choose_recovery_folder(app: &mut VectorcraftApp, d: &mut Dialog) {
|
||||
let r = crate::picks::in_app_dialog(app, d, |app, d| {
|
||||
/// A check of a folder path: `Err` says why the folder can't be the preference's value.
|
||||
type FolderCheck = fn(&str) -> Result<(), String>;
|
||||
|
||||
/// The check a folder preference with a Choose… button gives a folder before it becomes the
|
||||
/// preference's value: Data Recovery keeps its copies in its folder, and the Additional Plug-ins
|
||||
/// Folder is read for plug-ins. `None` for any other preference.
|
||||
fn folder_check(key: &str) -> Option<FolderCheck> {
|
||||
match key {
|
||||
"recoveryFolder" => Some(writable_folder),
|
||||
"pluginsFolder" => Some(plugins_folder),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Choose… beside the folder preference `key`: the folder picked becomes the field's value when it
|
||||
/// passes the preference's [`folder_check`]. Otherwise the status bar says why and the field keeps
|
||||
/// its value, as it does when the picker is canceled. The answer fills the field even when the
|
||||
/// active document closed while the picker was open.
|
||||
fn choose_folder(app: &mut VectorcraftApp, d: &mut Dialog, key: &'static str) {
|
||||
let Some(check) = folder_check(key) else { return };
|
||||
let r = crate::picks::in_app_dialog(app, d, move |app, d| {
|
||||
let Some(path) = crate::picks::folder(app) else { return Ok(()) };
|
||||
writable_folder(&path)?;
|
||||
d.fields.insert("recoveryFolder".into(), json!(path));
|
||||
check(&path)?;
|
||||
d.fields.insert(key.into(), json!(path));
|
||||
Ok(())
|
||||
});
|
||||
if let Err(e) = r {
|
||||
@@ -427,10 +444,43 @@ fn choose_recovery_folder(app: &mut VectorcraftApp, d: &mut Dialog) {
|
||||
}
|
||||
}
|
||||
|
||||
/// OK's check of the folder preferences with a Choose… button: a folder typed into one of their
|
||||
/// fields gets the same [`folder_check`] as a picked one. An empty field (the default folder) and
|
||||
/// a folder the preference already holds are not checked. The web has no folders to check.
|
||||
fn check_typed_folders(app: &VectorcraftApp, fields: &Map<String, Value>) -> Result<(), String> {
|
||||
if cfg!(target_arch = "wasm32") {
|
||||
return Ok(());
|
||||
}
|
||||
let saved = app.session.prefs.to_json();
|
||||
for (key, v) in fields {
|
||||
let (Some(check), Some(path)) = (folder_check(key), v.as_str()) else { continue };
|
||||
let path = path.trim();
|
||||
if path.is_empty() || saved[key.as_str()].as_str().is_some_and(|s| s.trim() == path) {
|
||||
continue;
|
||||
}
|
||||
check(path)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// `Ok` when `path` is a folder whose contents can be listed, as the plug-ins in it are found by
|
||||
/// listing it. A folder outside the automation roots in force is refused before it is looked at.
|
||||
fn plugins_folder(path: &str) -> Result<(), String> {
|
||||
vectorcraft_engine::file_access::check_read(path)?;
|
||||
let dir = std::path::Path::new(path);
|
||||
if !dir.is_dir() {
|
||||
return Err(format!("{path} is not a folder"));
|
||||
}
|
||||
std::fs::read_dir(dir).map(drop).map_err(|e| format!("Plug-ins can't be loaded from {path}: {e}"))
|
||||
}
|
||||
|
||||
/// `Ok` when `path` is a folder that can be listed and that a folder can be created in, as the
|
||||
/// recovery store lists its folders there and makes its own: the folder is listed, and an empty
|
||||
/// folder is made there and removed. A folder that can't be removed again is an error too.
|
||||
/// folder is made there and removed. A folder that can't be removed again is an error too. A
|
||||
/// folder outside the automation roots in force is refused before it is looked at.
|
||||
fn writable_folder(path: &str) -> Result<(), String> {
|
||||
vectorcraft_engine::file_access::check_write(path)?;
|
||||
vectorcraft_engine::file_access::check_read(path)?;
|
||||
let dir = std::path::Path::new(path);
|
||||
if !dir.is_dir() {
|
||||
return Err(format!("{path} is not a folder"));
|
||||
|
||||
@@ -458,12 +458,12 @@ fn a_chosen_recovery_folder_fills_the_field_and_cancel_keeps_it() {
|
||||
let answer = picked.clone();
|
||||
a.services.pick_folder = Some(Box::new(move || Some(answer.clone())));
|
||||
let mut d = a.ui.dialog.clone().unwrap();
|
||||
choose_recovery_folder(&mut a, &mut d);
|
||||
choose_folder(&mut a, &mut d, "recoveryFolder");
|
||||
assert_eq!(d.str("recoveryFolder"), picked);
|
||||
assert!(a.ui.status.is_empty(), "{}", a.ui.status);
|
||||
assert_eq!(std::fs::read_dir(&dir).unwrap().count(), 0, "the write check leaves nothing behind");
|
||||
a.services.pick_folder = Some(Box::new(|| None));
|
||||
choose_recovery_folder(&mut a, &mut d);
|
||||
choose_folder(&mut a, &mut d, "recoveryFolder");
|
||||
assert_eq!(d.str("recoveryFolder"), picked, "cancel keeps the field");
|
||||
a.ui.dialog = Some(d);
|
||||
confirm(&mut a).unwrap();
|
||||
@@ -486,7 +486,7 @@ fn a_recovery_folder_that_cannot_be_written_is_refused() {
|
||||
let answer = path.to_string_lossy().into_owned();
|
||||
a.services.pick_folder = Some(Box::new(move || Some(answer.clone())));
|
||||
a.ui.status.clear();
|
||||
choose_recovery_folder(&mut a, &mut d);
|
||||
choose_folder(&mut a, &mut d, "recoveryFolder");
|
||||
assert_eq!(d.str("recoveryFolder"), "kept");
|
||||
assert_eq!(a.ui.status, format!("{} is not a folder", path.to_string_lossy()));
|
||||
}
|
||||
@@ -501,7 +501,7 @@ fn a_recovery_folder_that_cannot_be_written_is_refused() {
|
||||
let answer = locked.to_string_lossy().into_owned();
|
||||
a.services.pick_folder = Some(Box::new(move || Some(answer.clone())));
|
||||
a.ui.status.clear();
|
||||
choose_recovery_folder(&mut a, &mut d);
|
||||
choose_folder(&mut a, &mut d, "recoveryFolder");
|
||||
assert_eq!(d.str("recoveryFolder"), "kept");
|
||||
assert!(a.ui.status.starts_with("Data Recovery can't keep copies in "), "{}", a.ui.status);
|
||||
}
|
||||
@@ -515,7 +515,7 @@ fn a_recovery_folder_that_cannot_be_written_is_refused() {
|
||||
let answer = unlisted.to_string_lossy().into_owned();
|
||||
a.services.pick_folder = Some(Box::new(move || Some(answer.clone())));
|
||||
a.ui.status.clear();
|
||||
choose_recovery_folder(&mut a, &mut d);
|
||||
choose_folder(&mut a, &mut d, "recoveryFolder");
|
||||
assert_eq!(d.str("recoveryFolder"), "kept");
|
||||
assert!(a.ui.status.starts_with("Data Recovery can't keep copies in "), "{}", a.ui.status);
|
||||
}
|
||||
@@ -535,7 +535,7 @@ fn a_chosen_recovery_folder_fills_the_field_after_the_active_document_closes() {
|
||||
a.run("file.new", json!({"width": 100, "height": 80})).unwrap();
|
||||
open(&mut a, Some("File Handling"));
|
||||
let mut d = a.ui.dialog.take().unwrap();
|
||||
choose_recovery_folder(&mut a, &mut d);
|
||||
choose_folder(&mut a, &mut d, "recoveryFolder");
|
||||
a.ui.dialog = Some(d);
|
||||
assert!(matches!(shown.requests().as_slice(), [crate::picks::PickRequest::Folder]));
|
||||
a.session.execute("file.close", &json!({})).unwrap();
|
||||
@@ -546,3 +546,112 @@ fn a_chosen_recovery_folder_fills_the_field_after_the_active_document_closes() {
|
||||
assert_eq!(a.ui.dialog.as_ref().unwrap().str("recoveryFolder"), picked, "{}", a.ui.status);
|
||||
let _ = std::fs::remove_dir_all(&dir);
|
||||
}
|
||||
|
||||
/// Plug-ins & Scratch Disks › Additional Plug-ins Folder has a Choose… button where the host has a
|
||||
/// folder picker, and none where it has not (the web).
|
||||
#[test]
|
||||
fn plugins_folder_has_a_choose_button_with_a_folder_picker() {
|
||||
let mut a = VectorcraftApp::new(Session::new(), Default::default());
|
||||
a.services.pick_folder = Some(Box::new(|| None));
|
||||
open(&mut a, Some("Plug-ins & Scratch Disks"));
|
||||
let text = crate::tests_labels::painted_text(&mut a, |a, ui| show(a, ui.ctx()));
|
||||
assert!(text.contains("Additional Plug-ins Folder") && text.contains("Choose…"), "{text}");
|
||||
a.services.pick_folder = None;
|
||||
let text = crate::tests_labels::painted_text(&mut a, |a, ui| show(a, ui.ctx()));
|
||||
assert!(text.contains("Additional Plug-ins Folder") && !text.contains("Choose…"), "{text}");
|
||||
}
|
||||
|
||||
/// Choose… beside Additional Plug-ins Folder puts the folder picked into the field, and OK saves
|
||||
/// it; a canceled picker, a file and a missing folder leave the field as it was.
|
||||
#[test]
|
||||
fn a_chosen_plugins_folder_fills_the_field_and_others_keep_it() {
|
||||
let dir = temp_folder("plugins-chosen");
|
||||
let file = dir.join("not-a-folder.txt");
|
||||
std::fs::write(&file, b"x").unwrap();
|
||||
let mut a = VectorcraftApp::new(Session::new(), Default::default());
|
||||
open(&mut a, Some("Plug-ins & Scratch Disks"));
|
||||
let mut d = a.ui.dialog.clone().unwrap();
|
||||
for path in [file.clone(), dir.join("missing")] {
|
||||
let answer = path.to_string_lossy().into_owned();
|
||||
a.services.pick_folder = Some(Box::new(move || Some(answer.clone())));
|
||||
a.ui.status.clear();
|
||||
choose_folder(&mut a, &mut d, "pluginsFolder");
|
||||
assert_eq!(d.str("pluginsFolder"), "");
|
||||
assert_eq!(a.ui.status, format!("{} is not a folder", path.to_string_lossy()));
|
||||
}
|
||||
let picked = dir.to_string_lossy().into_owned();
|
||||
let answer = picked.clone();
|
||||
a.services.pick_folder = Some(Box::new(move || Some(answer.clone())));
|
||||
a.ui.status.clear();
|
||||
choose_folder(&mut a, &mut d, "pluginsFolder");
|
||||
assert_eq!(d.str("pluginsFolder"), picked);
|
||||
assert!(a.ui.status.is_empty(), "{}", a.ui.status);
|
||||
a.services.pick_folder = Some(Box::new(|| None));
|
||||
choose_folder(&mut a, &mut d, "pluginsFolder");
|
||||
assert_eq!(d.str("pluginsFolder"), picked, "cancel keeps the field");
|
||||
a.ui.dialog = Some(d);
|
||||
confirm(&mut a).unwrap();
|
||||
assert_eq!(a.session.prefs.plugins_folder, picked);
|
||||
let _ = std::fs::remove_dir_all(&dir);
|
||||
}
|
||||
|
||||
/// OK checks a folder typed into Data Recovery › Folder or Additional Plug-ins Folder as Choose…
|
||||
/// checks a picked one: one that fails keeps the dialog open and changes no preference. An empty
|
||||
/// field and a folder the preference already holds are not checked.
|
||||
#[test]
|
||||
fn ok_refuses_a_typed_folder_that_choose_would_refuse() {
|
||||
let dir = temp_folder("typed-folders");
|
||||
let file = dir.join("not-a-folder.txt");
|
||||
std::fs::write(&file, b"x").unwrap();
|
||||
let missing = dir.join("missing").to_string_lossy().into_owned();
|
||||
for key in ["recoveryFolder", "pluginsFolder"] {
|
||||
let mut a = VectorcraftApp::new(Session::new(), Default::default());
|
||||
open(&mut a, Some("File Handling"));
|
||||
let before = a.session.prefs.to_json();
|
||||
for path in [file.to_string_lossy().into_owned(), missing.clone()] {
|
||||
let d = a.ui.dialog.as_mut().unwrap();
|
||||
d.fields.insert(key.into(), json!(path));
|
||||
d.fields.insert("showToolTips".into(), json!(!a.session.prefs.show_tool_tips));
|
||||
assert_eq!(confirm(&mut a), Err(format!("{path} is not a folder")), "{key}");
|
||||
assert!(a.ui.dialog.is_some(), "{key}: the dialog stays open");
|
||||
assert_eq!(a.session.prefs.to_json(), before, "{key}: no preference changes");
|
||||
}
|
||||
// A typed folder that passes is saved, with the spaces around it as typed.
|
||||
let typed = format!(" {} ", dir.to_string_lossy());
|
||||
a.ui.dialog.as_mut().unwrap().fields.insert(key.into(), json!(typed));
|
||||
confirm(&mut a).unwrap();
|
||||
assert_eq!(a.session.prefs.to_json()[key], json!(typed), "{key}");
|
||||
// An empty field keeps the default folder.
|
||||
open(&mut a, Some("File Handling"));
|
||||
a.ui.dialog.as_mut().unwrap().fields.insert(key.into(), json!(""));
|
||||
confirm(&mut a).unwrap();
|
||||
assert_eq!(a.session.prefs.to_json()[key], json!(""), "{key}");
|
||||
// A folder already saved is not checked again, so OK works while it is unavailable.
|
||||
a.run("prefs.set", json!({"key": key, "value": missing})).unwrap();
|
||||
open(&mut a, Some("File Handling"));
|
||||
a.ui.dialog.as_mut().unwrap().fields.insert("showToolTips".into(), json!(!a.session.prefs.show_tool_tips));
|
||||
confirm(&mut a).unwrap();
|
||||
assert_eq!(a.session.prefs.to_json()[key], json!(missing), "{key}");
|
||||
}
|
||||
let _ = std::fs::remove_dir_all(&dir);
|
||||
}
|
||||
|
||||
/// Under automation roots, OK refuses a typed folder outside them before it looks at the folder.
|
||||
#[test]
|
||||
fn ok_refuses_a_typed_folder_outside_the_automation_roots_before_looking_at_it() {
|
||||
use vectorcraft_engine::file_access::{self, Access};
|
||||
let dir = temp_folder("typed-roots");
|
||||
let inside = dir.join("inside");
|
||||
std::fs::create_dir_all(&inside).unwrap();
|
||||
let outside = dir.join("outside-missing").to_string_lossy().into_owned();
|
||||
let roots = file_access::AutomationRoots::new(&[inside.as_path()], &[inside.as_path()]).unwrap().unwrap();
|
||||
for (key, access) in [("recoveryFolder", Access::Write), ("pluginsFolder", Access::Read)] {
|
||||
let mut a = VectorcraftApp::new(Session::new(), Default::default());
|
||||
open(&mut a, Some("File Handling"));
|
||||
a.ui.dialog.as_mut().unwrap().fields.insert(key.into(), json!(outside));
|
||||
let r = file_access::confine(Some(&roots), || confirm(&mut a));
|
||||
assert_eq!(r, Err(roots.check(&outside, access).unwrap_err()), "{key}");
|
||||
assert!(a.ui.dialog.is_some(), "{key}: the dialog stays open");
|
||||
}
|
||||
let _ = std::fs::remove_dir_all(&dir);
|
||||
}
|
||||
|
||||
+2
-1
@@ -51,7 +51,8 @@ background ([below](#heavy-filters)).
|
||||
|
||||
**Preference folder.** Edit › Preferences › Plug-ins & Scratch Disks › *Additional Plug-ins Folder*: when set, every
|
||||
`*.wasm` in that folder (not recursive) is installed at startup and whenever the preference changes (desktop builds;
|
||||
the web build installs from bytes).
|
||||
the web build installs from bytes). On the desktop, Choose… beside the field picks the folder; the dialog refuses a
|
||||
picked or typed folder whose contents can't be listed.
|
||||
|
||||
Plug-ins are installed **per process**, not per document. Documents store a live effect as an ordinary effect record
|
||||
(`{"id": "plugin.<id>", "params": {…}}`): while the plug-in is installed it is drawn, exported and expanded; without it
|
||||
|
||||
@@ -1144,7 +1144,7 @@ Moved from the ROADMAP's "Shipped so far" on 2026-10-10. Update it when a featur
|
||||
PDF export writes a linear or radial gradient that mixes a spot color with process colors, or two spot colors, as a DeviceN shading of the spot inks and the process inks its stops use, so each spot ink prints on its own plate; an off-center midpoint is written as a stop with the inks halfway between its two stops. A gradient that mixes a spot color with RGB or Lab colors is still written without the spot ink, with a warning. A Perceptual gradient of spot inks is written as a Separation or DeviceN shading of the stops on its curve; a dithered gradient fill, and a Perceptual gradient with RGB or Lab stops other than white or more than 4,096 stops on its curve, are written as images in process colors, with a warning. A Lab spot color in such a shading is named by the same Separation space, with the Lab alternate, as its flat fills (`engine/src/tests/linked_stops.rs`, `engine/src/tests/labspots.rs`).
|
||||
PDF export writes a spot color named All or None (in a Separation space, the names of every plate and of no plate: [ISO 32000-1:2008](https://opensource.adobe.com/dc-acrobat-sdk-docs/pdfstandards/PDF32000_2008.pdf), 8.6.6.4) as the ink All Spot or None Spot (All Spot 2 and on when a spot swatch already has that name) in its fills, strokes, gradients, colorized images and Lab alternates; Registration still prints on every plate (`pdf/src/tests/output.rs`).
|
||||
- `.vectorcraft` (lossless JSON, compressed, atomic saves, save down to v1), Save As with a format chooser, Save a Copy, Revert, templates, Data Recovery after a crash (browser tabs hold their copies with Web Locks too, so a background tab's copies are never taken for a crash's, and a tab repairs copies another removed when it resumes: #367), background save and export. The desktop app writes its warnings and errors (graphics adapter, a lost graphics device, panics the guard recovered from) to standard error and to `logs/vectorcraft.log` next to the preferences, the two previous runs kept and each file capped at 16 MiB, so a launch without a terminal still leaves something to attach to a bug report (#465). Native documents with a lot of path data (traced or generated art, in layers, symbols or patterns) are saved as compact JSON, about a fifth of the size; small documents stay pretty-printed (#1492). Saving to a network drive on macOS falls back to a plain fsync when the share refuses a full flush (#1625, part of #1620; not confirmed on a real share), and a save still succeeds when a folder refuses the temporary file, the rename over the document or copying permissions: the content is written elsewhere first and copied in, and a failed copy keeps the temporary file and names it (#1649, part of #1620). A document opened by a relative path finds its relatively linked images, and `vectorcraft-cli convert` lists what reading the input left out as `importWarnings` (#1606, fixes #1604).
|
||||
Preferences › File Handling › Data Recovery › Folder has a Choose… button on the desktop that picks the folder Data Recovery keeps its copies in ([Illustrator reference, Set Data Recovery preferences](https://web.archive.org/web/20210601162814/https://helpx.adobe.com/pdf/illustrator_reference.pdf)); a picked folder that Data Recovery cannot create its folders in or list is refused with a status message, and the field keeps its value.
|
||||
Preferences › File Handling › Data Recovery › Folder has a Choose… button on the desktop that picks the folder Data Recovery keeps its copies in ([Illustrator reference, Set Data Recovery preferences](https://web.archive.org/web/20210601162814/https://helpx.adobe.com/pdf/illustrator_reference.pdf)); a picked folder that Data Recovery cannot create its folders in or list is refused with a status message, and the field keeps its value. OK applies the same check to a folder typed into the field (VectorCraft's own rule): when it fails, the dialog stays open, the status bar says why and no preference changes; an empty field (the default folder) and the folder already saved are not checked. Preferences › Plug-ins & Scratch Disks is where additional plug-ins folders are set ([Illustrator preferences help](https://helpx.adobe.com/illustrator/desktop/get-started/preferences-and-settings/set-app-preferences.html)); its Additional Plug-ins Folder has a Choose… button on the desktop as well, VectorCraft's own, matching Data Recovery's, and VectorCraft's own rule refuses a picked or typed folder whose contents can't be listed. Additional Fonts Folder and Templates Folder stay typed only.
|
||||
A name typed in the desktop save panel without the file type's extension gets it, and when a file of that name exists, which the panel did not ask about, Save, Save As, Save a Copy, Save as Template, the exports and every other write through a save panel ask before replacing it (dialog `replaceFile`; Cancel writes nothing).
|
||||
A name returned by the desktop save panel with the extension of a format the save does not write has it replaced with the saved format's: Save As of a new document saves `card.ait` and `card.png` as `card.vectorcraft`, and Save as Template saves `card.pdf` as `card.vctemplate`. An extension that names no format stays part of the name (`notes.v2` is saved as `notes.v2.vectorcraft`).
|
||||
Export As, Save as PDF, Save for Office Documents, Save for Web, Text Export Options, print to file, the presets' Export… and the library, swatch and Document Info saves replace a typed extension of another format than the one they write in the same way: Export As PNG writes `card.svg` as `card.png`, Save as PDF writes `card.png` as `card.pdf`, and `document.exportSelection` with a `format` suggests and adds that format's extension. An extension of the written format stays as typed in any letter case (`photo.JPEG` for JPEG), Export As SVG writes `art.svgz` compressed, and `document.exportSelection` without a `format` writes the format the typed extension names (`tests/saveext.rs`).
|
||||
|
||||
Reference in New Issue
Block a user