mirror of
https://github.com/penpot/penpot.git
synced 2025-12-23 22:48:40 -05:00
Compare commits
92 Commits
superalex-
...
develop
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
69c880d00e | ||
|
|
9eebc467ef | ||
|
|
b77712ce73 | ||
|
|
3d3e81f314 | ||
|
|
fe6441bb24 | ||
|
|
e15f0baf30 | ||
|
|
c040cbb784 | ||
|
|
7f674b78a9 | ||
|
|
099b78affd | ||
|
|
78cc3f0aa4 | ||
|
|
76f5f12808 | ||
|
|
047483a70a | ||
|
|
8cb2f27de8 | ||
|
|
0433336fc9 | ||
|
|
ce234fbeda | ||
|
|
fc4d31eed7 | ||
|
|
c670aac339 | ||
|
|
1d3fb5434f | ||
|
|
f478399ae0 | ||
|
|
6a1854f180 | ||
|
|
0858e297e5 | ||
|
|
5780a43fe0 | ||
|
|
737eceda3a | ||
|
|
923c3c2dbd | ||
|
|
a14b4561e7 | ||
|
|
bb5568e15a | ||
|
|
5cbcec3db6 | ||
|
|
105e1fe86c | ||
|
|
3e0a916883 | ||
|
|
4f80238bc2 | ||
|
|
5156cc5d9a | ||
|
|
42c46b6cfc | ||
|
|
8b3c40b35e | ||
|
|
d3996e5fb1 | ||
|
|
0c42bca866 | ||
|
|
e5685c1f1c | ||
|
|
2784209bde | ||
|
|
024f460e99 | ||
|
|
1d9b76b62a | ||
|
|
7e17a75b7d | ||
|
|
ca093d6fae | ||
|
|
0f0b7562b5 | ||
|
|
9cdc694697 | ||
|
|
b972a4033b | ||
|
|
cbe9f4da51 | ||
|
|
c583bde9e3 | ||
|
|
3911ebdc4e | ||
|
|
3e3b18667b | ||
|
|
ed81c9b8df | ||
|
|
fbdf98d29c | ||
|
|
e603825a55 | ||
|
|
1d724783e6 | ||
|
|
e0abe7dcb5 | ||
|
|
5c1bbf5be8 | ||
|
|
bbb0d58190 | ||
|
|
88dcf9d1fe | ||
|
|
fe44c14bac | ||
|
|
20061067ad | ||
|
|
336173645e | ||
|
|
2acf15958b | ||
|
|
08267de242 | ||
|
|
35fb376a78 | ||
|
|
13fcf3a9bb | ||
|
|
83bb4bf221 | ||
|
|
dba6ae2820 | ||
|
|
ada101c236 | ||
|
|
ea48fb5825 | ||
|
|
15ed25ca79 | ||
|
|
9aa387a473 | ||
|
|
67ba91b4b9 | ||
|
|
f67f1a6a0e | ||
|
|
82d3e2024e | ||
|
|
4bd846c16d | ||
|
|
8fde6b28ed | ||
|
|
63325ec796 | ||
|
|
84415476d0 | ||
|
|
94f95ca6b8 | ||
|
|
507bf7445b | ||
|
|
81b72c5acd | ||
|
|
974495e08f | ||
|
|
2ed39e43c3 | ||
|
|
b45bdd723f | ||
|
|
8696044620 | ||
|
|
4f3ca6422c | ||
|
|
1c03457fda | ||
|
|
74d4b9b045 | ||
|
|
60df56caa3 | ||
|
|
34da754357 | ||
|
|
39eafae251 | ||
|
|
e1e09b7f96 | ||
|
|
3b39980f2f | ||
|
|
223b12d2c7 |
@@ -12,7 +12,9 @@
|
||||
|
||||
### :sparkles: New features & Enhancements
|
||||
|
||||
- Add new Box Shadow Tokens [Taiga #10201](https://tree.taiga.io/project/penpot/us/10201)
|
||||
- Make i18n translation files load on-demand [Taiga #11474](https://tree.taiga.io/project/penpot/us/11474)
|
||||
- Add deleted files to dashboard [Taiga #8149](https://tree.taiga.io/project/penpot/us/8149)
|
||||
|
||||
### :bug: Bugs fixed
|
||||
|
||||
@@ -83,6 +85,7 @@ example. It's still usable as before, we just removed the example.
|
||||
|
||||
- Ensure consistent snap behavior across all zoom levels [Github #7774](https://github.com/penpot/penpot/pull/7774) by [@Tokytome](https://github.com/Tokytome)
|
||||
- Fix crash in token grid view due to tooltip validation (by @dfelinto) [Github #7887](https://github.com/penpot/penpot/pull/7887)
|
||||
- Enable Hindi translations on the application
|
||||
|
||||
### :sparkles: New features & Enhancements
|
||||
|
||||
@@ -116,6 +119,7 @@ example. It's still usable as before, we just removed the example.
|
||||
- Fix switch variants with paths [Taiga #12841](https://tree.taiga.io/project/penpot/issue/12841)
|
||||
- Fix referencing typography tokens on font-family tokens [Taiga #12492](https://tree.taiga.io/project/penpot/issue/12492)
|
||||
- Fix horizontal scroll on layer panel [Taiga #12843](https://tree.taiga.io/project/penpot/issue/12843)
|
||||
- Fix unicode handling on email template abbreviation filter [Github #7966](https://github.com/penpot/penpot/pull/7966)
|
||||
|
||||
## 2.11.1
|
||||
|
||||
|
||||
@@ -240,4 +240,4 @@
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
</html>
|
||||
|
||||
@@ -331,6 +331,81 @@
|
||||
(set/difference cfeat/backend-only-features))
|
||||
#{}))))
|
||||
|
||||
(defn check-file-exists
|
||||
[cfg id & {:keys [include-deleted?]
|
||||
:or {include-deleted? false}
|
||||
:as options}]
|
||||
(db/get-with-sql cfg [sql:get-minimal-file id]
|
||||
{:db/remove-deleted (not include-deleted?)}))
|
||||
|
||||
(def ^:private sql:file-permissions
|
||||
"select fpr.is_owner,
|
||||
fpr.is_admin,
|
||||
fpr.can_edit
|
||||
from file_profile_rel as fpr
|
||||
inner join file as f on (f.id = fpr.file_id)
|
||||
where fpr.file_id = ?
|
||||
and fpr.profile_id = ?
|
||||
union all
|
||||
select tpr.is_owner,
|
||||
tpr.is_admin,
|
||||
tpr.can_edit
|
||||
from team_profile_rel as tpr
|
||||
inner join project as p on (p.team_id = tpr.team_id)
|
||||
inner join file as f on (p.id = f.project_id)
|
||||
where f.id = ?
|
||||
and tpr.profile_id = ?
|
||||
union all
|
||||
select ppr.is_owner,
|
||||
ppr.is_admin,
|
||||
ppr.can_edit
|
||||
from project_profile_rel as ppr
|
||||
inner join file as f on (f.project_id = ppr.project_id)
|
||||
where f.id = ?
|
||||
and ppr.profile_id = ?")
|
||||
|
||||
(defn- get-file-permissions*
|
||||
[conn profile-id file-id]
|
||||
(when (and profile-id file-id)
|
||||
(db/exec! conn [sql:file-permissions
|
||||
file-id profile-id
|
||||
file-id profile-id
|
||||
file-id profile-id])))
|
||||
|
||||
(defn get-file-permissions
|
||||
([conn profile-id file-id]
|
||||
(let [rows (get-file-permissions* conn profile-id file-id)
|
||||
is-owner (boolean (some :is-owner rows))
|
||||
is-admin (boolean (some :is-admin rows))
|
||||
can-edit (boolean (some :can-edit rows))]
|
||||
(when (seq rows)
|
||||
{:type :membership
|
||||
:is-owner is-owner
|
||||
:is-admin (or is-owner is-admin)
|
||||
:can-edit (or is-owner is-admin can-edit)
|
||||
:can-read true
|
||||
:is-logged (some? profile-id)})))
|
||||
|
||||
([conn profile-id file-id share-id]
|
||||
(let [perms (get-file-permissions conn profile-id file-id)
|
||||
ldata (some-> (db/get* conn :share-link {:id share-id :file-id file-id})
|
||||
(dissoc :flags)
|
||||
(update :pages db/decode-pgarray #{}))]
|
||||
|
||||
;; NOTE: in a future when share-link becomes more powerful and
|
||||
;; will allow us specify which parts of the app is available, we
|
||||
;; will probably need to tweak this function in order to expose
|
||||
;; this flags to the frontend.
|
||||
(cond
|
||||
(some? perms) perms
|
||||
(some? ldata) {:type :share-link
|
||||
:can-read true
|
||||
:pages (:pages ldata)
|
||||
:is-logged (some? profile-id)
|
||||
:who-comment (:who-comment ldata)
|
||||
:who-inspect (:who-inspect ldata)}))))
|
||||
|
||||
|
||||
(defn get-project
|
||||
[cfg project-id]
|
||||
(db/get cfg :project {:id project-id}))
|
||||
|
||||
@@ -821,9 +821,10 @@
|
||||
entries (keep (match-storage-entry-fn) entries)]
|
||||
|
||||
(doseq [{:keys [id entry]} entries]
|
||||
(let [object (->> (read-entry input entry)
|
||||
(decode-storage-object)
|
||||
(validate-storage-object))
|
||||
(let [object (-> (read-entry input entry)
|
||||
(decode-storage-object)
|
||||
(update :bucket d/nilv sto/default-bucket)
|
||||
(validate-storage-object))
|
||||
|
||||
ext (cmedia/mtype->extension (:content-type object))
|
||||
path (str "objects/" id ext)
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
|
||||
(defn- get-file-media-object
|
||||
[pool id]
|
||||
(db/get pool :file-media-object {:id id}))
|
||||
(db/get pool :file-media-object {:id id} {::db/remove-deleted false}))
|
||||
|
||||
(defn- serve-object-from-s3
|
||||
[{:keys [::sto/storage] :as cfg} obj]
|
||||
|
||||
@@ -309,7 +309,7 @@
|
||||
(fn [request]
|
||||
(let [key (yreq/get-header request "x-shared-key")]
|
||||
(if (= key shared-key)
|
||||
(handler request)
|
||||
(handler (assoc request ::http/auth-with-shared-key true))
|
||||
{::yres/status 403}))))
|
||||
(fn [_ _]
|
||||
{::yres/status 403})))
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
[app.common.spec :as us]
|
||||
[app.common.time :as ct]
|
||||
[app.common.uri :as u]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.config :as cf]
|
||||
[app.db :as db]
|
||||
[app.http :as-alias http]
|
||||
@@ -92,7 +93,11 @@
|
||||
(let [handler-name (:type path-params)
|
||||
etag (yreq/get-header request "if-none-match")
|
||||
profile-id (or (::session/profile-id request)
|
||||
(::actoken/profile-id request))
|
||||
(::actoken/profile-id request)
|
||||
(if (::http/auth-with-shared-key request)
|
||||
uuid/zero
|
||||
nil))
|
||||
|
||||
ip-addr (inet/parse-request request)
|
||||
|
||||
data (-> params
|
||||
|
||||
@@ -307,7 +307,8 @@
|
||||
:content-type (:mtype input)})]
|
||||
(:id sobject))
|
||||
(catch Throwable cause
|
||||
(l/err :hint "unable to import profile picture"
|
||||
(l/wrn :hint "unable to import profile picture"
|
||||
:uri uri
|
||||
:cause cause)
|
||||
nil)))
|
||||
|
||||
|
||||
@@ -79,85 +79,14 @@
|
||||
|
||||
;; --- FILE PERMISSIONS
|
||||
|
||||
|
||||
(def ^:private sql:file-permissions
|
||||
"select fpr.is_owner,
|
||||
fpr.is_admin,
|
||||
fpr.can_edit
|
||||
from file_profile_rel as fpr
|
||||
inner join file as f on (f.id = fpr.file_id)
|
||||
where fpr.file_id = ?
|
||||
and fpr.profile_id = ?
|
||||
and f.deleted_at is null
|
||||
union all
|
||||
select tpr.is_owner,
|
||||
tpr.is_admin,
|
||||
tpr.can_edit
|
||||
from team_profile_rel as tpr
|
||||
inner join project as p on (p.team_id = tpr.team_id)
|
||||
inner join file as f on (p.id = f.project_id)
|
||||
where f.id = ?
|
||||
and tpr.profile_id = ?
|
||||
and f.deleted_at is null
|
||||
union all
|
||||
select ppr.is_owner,
|
||||
ppr.is_admin,
|
||||
ppr.can_edit
|
||||
from project_profile_rel as ppr
|
||||
inner join file as f on (f.project_id = ppr.project_id)
|
||||
where f.id = ?
|
||||
and ppr.profile_id = ?
|
||||
and f.deleted_at is null")
|
||||
|
||||
(defn get-file-permissions
|
||||
[conn profile-id file-id]
|
||||
(when (and profile-id file-id)
|
||||
(db/exec! conn [sql:file-permissions
|
||||
file-id profile-id
|
||||
file-id profile-id
|
||||
file-id profile-id])))
|
||||
|
||||
(defn get-permissions
|
||||
([conn profile-id file-id]
|
||||
(let [rows (get-file-permissions conn profile-id file-id)
|
||||
is-owner (boolean (some :is-owner rows))
|
||||
is-admin (boolean (some :is-admin rows))
|
||||
can-edit (boolean (some :can-edit rows))]
|
||||
(when (seq rows)
|
||||
{:type :membership
|
||||
:is-owner is-owner
|
||||
:is-admin (or is-owner is-admin)
|
||||
:can-edit (or is-owner is-admin can-edit)
|
||||
:can-read true
|
||||
:is-logged (some? profile-id)})))
|
||||
|
||||
([conn profile-id file-id share-id]
|
||||
(let [perms (get-permissions conn profile-id file-id)
|
||||
ldata (some-> (db/get* conn :share-link {:id share-id :file-id file-id})
|
||||
(dissoc :flags)
|
||||
(update :pages db/decode-pgarray #{}))]
|
||||
|
||||
;; NOTE: in a future when share-link becomes more powerful and
|
||||
;; will allow us specify which parts of the app is available, we
|
||||
;; will probably need to tweak this function in order to expose
|
||||
;; this flags to the frontend.
|
||||
(cond
|
||||
(some? perms) perms
|
||||
(some? ldata) {:type :share-link
|
||||
:can-read true
|
||||
:pages (:pages ldata)
|
||||
:is-logged (some? profile-id)
|
||||
:who-comment (:who-comment ldata)
|
||||
:who-inspect (:who-inspect ldata)}))))
|
||||
|
||||
(def has-edit-permissions?
|
||||
(perms/make-edition-predicate-fn get-permissions))
|
||||
(perms/make-edition-predicate-fn bfc/get-file-permissions))
|
||||
|
||||
(def has-read-permissions?
|
||||
(perms/make-read-predicate-fn get-permissions))
|
||||
(perms/make-read-predicate-fn bfc/get-file-permissions))
|
||||
|
||||
(def has-comment-permissions?
|
||||
(perms/make-comment-predicate-fn get-permissions))
|
||||
(perms/make-comment-predicate-fn bfc/get-file-permissions))
|
||||
|
||||
(def check-edition-permissions!
|
||||
(perms/make-check-fn has-edit-permissions?))
|
||||
@@ -170,7 +99,7 @@
|
||||
|
||||
(defn check-comment-permissions!
|
||||
[conn profile-id file-id share-id]
|
||||
(let [perms (get-permissions conn profile-id file-id share-id)
|
||||
(let [perms (bfc/get-file-permissions conn profile-id file-id share-id)
|
||||
can-read (has-read-permissions? perms)
|
||||
can-comment (has-comment-permissions? perms)]
|
||||
(when-not (or can-read can-comment)
|
||||
@@ -222,7 +151,7 @@
|
||||
(defn- get-minimal-file-with-perms
|
||||
[cfg {:keys [:id ::rpc/profile-id]}]
|
||||
(let [mfile (get-minimal-file cfg id)
|
||||
perms (get-permissions cfg profile-id id)]
|
||||
perms (bfc/get-file-permissions cfg profile-id id)]
|
||||
(assoc mfile :permissions perms)))
|
||||
|
||||
(defn get-file-etag
|
||||
@@ -248,7 +177,7 @@
|
||||
;; will be already prefetched and we just reuse them instead
|
||||
;; of making an additional database queries.
|
||||
(let [perms (or (:permissions (::cond/object params))
|
||||
(get-permissions conn profile-id id))]
|
||||
(bfc/get-file-permissions conn profile-id id))]
|
||||
(check-read-permissions! perms)
|
||||
|
||||
(let [team (teams/get-team conn
|
||||
@@ -311,7 +240,7 @@
|
||||
::sm/result schema:file-fragment}
|
||||
[cfg {:keys [::rpc/profile-id file-id fragment-id share-id]}]
|
||||
(db/run! cfg (fn [cfg]
|
||||
(let [perms (get-permissions cfg profile-id file-id share-id)]
|
||||
(let [perms (bfc/get-file-permissions cfg profile-id file-id share-id)]
|
||||
(check-read-permissions! perms)
|
||||
(-> (get-file-fragment cfg file-id fragment-id)
|
||||
(rph/with-http-cache long-cache-duration))))))
|
||||
@@ -456,8 +385,7 @@
|
||||
:code :params-validation
|
||||
:hint "page-id is required when object-id is provided"))
|
||||
|
||||
(let [perms (get-permissions conn profile-id file-id share-id)
|
||||
|
||||
(let [perms (bfc/get-file-permissions conn profile-id file-id share-id)
|
||||
file (bfc/get-file cfg file-id :read-only? true)
|
||||
|
||||
proj (db/get conn :project {:id (:project-id file)})
|
||||
@@ -688,11 +616,10 @@
|
||||
"Get libraries used by the specified file."
|
||||
{::doc/added "1.17"
|
||||
::sm/params schema:get-file-libraries}
|
||||
[{:keys [::db/pool] :as cfg} {:keys [::rpc/profile-id file-id]}]
|
||||
(dm/with-open [conn (db/open pool)]
|
||||
(check-read-permissions! conn profile-id file-id)
|
||||
(bfc/get-file-libraries conn file-id)))
|
||||
|
||||
[cfg {:keys [::rpc/profile-id file-id]}]
|
||||
(bfc/check-file-exists cfg file-id)
|
||||
(check-read-permissions! cfg profile-id file-id)
|
||||
(bfc/get-file-libraries cfg file-id))
|
||||
|
||||
;; --- COMMAND QUERY: Files that use this File library
|
||||
|
||||
@@ -785,8 +712,7 @@
|
||||
FROM file AS f
|
||||
INNER JOIN project AS p ON (p.id = f.project_id)
|
||||
LEFT JOIN file_thumbnail AS ft on (ft.file_id = f.id
|
||||
AND ft.revn = f.revn
|
||||
AND ft.deleted_at is null)
|
||||
AND ft.revn = f.revn)
|
||||
WHERE p.team_id = ?
|
||||
AND (p.deleted_at > ?::timestamptz OR
|
||||
f.deleted_at > ?::timestamptz)
|
||||
|
||||
@@ -199,15 +199,13 @@
|
||||
[cfg {:keys [::rpc/profile-id file-id strip-frames-with-thumbnails] :as params}]
|
||||
(db/run! cfg (fn [{:keys [::db/conn] :as cfg}]
|
||||
(files/check-read-permissions! conn profile-id file-id)
|
||||
|
||||
(let [team (teams/get-team conn
|
||||
:profile-id profile-id
|
||||
:file-id file-id)
|
||||
|
||||
file (bfc/get-file cfg file-id
|
||||
:include-deleted? true
|
||||
:realize? true
|
||||
:read-only? true)
|
||||
|
||||
strip-frames-with-thumbnails
|
||||
(or (nil? strip-frames-with-thumbnails) ;; if not present, default to true
|
||||
(true? strip-frames-with-thumbnails))]
|
||||
@@ -333,12 +331,16 @@
|
||||
|
||||
;; --- MUTATION COMMAND: create-file-thumbnail
|
||||
|
||||
(defn- create-file-thumbnail!
|
||||
[{:keys [::db/conn ::sto/storage]} {:keys [file-id revn props media] :as params}]
|
||||
(defn- create-file-thumbnail
|
||||
[{:keys [::db/conn ::sto/storage] :as cfg} {:keys [file-id revn props media] :as params}]
|
||||
(media/validate-media-type! media)
|
||||
(media/validate-media-size! media)
|
||||
|
||||
(let [props (db/tjson (or props {}))
|
||||
(let [file (bfc/get-file cfg file-id
|
||||
:include-deleted? true
|
||||
:load-data? false)
|
||||
|
||||
props (db/tjson (or props {}))
|
||||
path (:path media)
|
||||
mtype (:mtype media)
|
||||
hash (sto/calculate-hash path)
|
||||
@@ -367,7 +369,7 @@
|
||||
|
||||
(db/update! conn :file-thumbnail
|
||||
{:media-id (:id media)
|
||||
:deleted-at nil
|
||||
:deleted-at (:deleted-at file)
|
||||
:updated-at tnow
|
||||
:props props}
|
||||
{:file-id file-id
|
||||
@@ -378,6 +380,7 @@
|
||||
:revn revn
|
||||
:created-at tnow
|
||||
:updated-at tnow
|
||||
:deleted-at (:deleted-at file)
|
||||
:props props
|
||||
:media-id (:id media)}))
|
||||
|
||||
@@ -402,6 +405,8 @@
|
||||
::rtry/when rtry/conflict-exception?
|
||||
::sm/params schema:create-file-thumbnail}
|
||||
|
||||
;; FIXME: do not run the thumbnail upload inside a transaction
|
||||
|
||||
[cfg {:keys [::rpc/profile-id file-id] :as params}]
|
||||
(db/tx-run! cfg (fn [{:keys [::db/conn] :as cfg}]
|
||||
;; TODO For now we check read permissions instead of write,
|
||||
@@ -409,6 +414,6 @@
|
||||
;; review this approach on the future.
|
||||
(files/check-read-permissions! conn profile-id file-id)
|
||||
(when-not (db/read-only? conn)
|
||||
(let [media (create-file-thumbnail! cfg params)]
|
||||
(let [media (create-file-thumbnail cfg params)]
|
||||
{:uri (files/resolve-public-uri (:id media))
|
||||
:id (:id media)})))))
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
(ns app.rpc.commands.fonts
|
||||
(:require
|
||||
[app.binfile.common :as bfc]
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.exceptions :as ex]
|
||||
[app.common.schema :as sm]
|
||||
@@ -66,7 +67,7 @@
|
||||
(uuid? file-id)
|
||||
(let [file (db/get-by-id conn :file file-id {:columns [:id :project-id]})
|
||||
project (db/get-by-id conn :project (:project-id file) {:columns [:id :team-id]})
|
||||
perms (files/get-permissions conn profile-id file-id share-id)]
|
||||
perms (bfc/get-file-permissions conn profile-id file-id share-id)]
|
||||
(files/check-read-permissions! perms)
|
||||
(db/query conn :team-font-variant
|
||||
{:team-id (:team-id project)
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
[app.config :as cf]
|
||||
[app.db :as db]
|
||||
[app.rpc :as-alias rpc]
|
||||
[app.rpc.commands.files :as files]
|
||||
[app.rpc.commands.teams :as teams]
|
||||
[app.rpc.cond :as-alias cond]
|
||||
[app.rpc.doc :as-alias doc]
|
||||
@@ -121,7 +120,7 @@
|
||||
[system {:keys [::rpc/profile-id file-id share-id] :as params}]
|
||||
(db/run! system
|
||||
(fn [{:keys [::db/conn] :as system}]
|
||||
(let [perms (files/get-permissions conn profile-id file-id share-id)
|
||||
(let [perms (bfc/get-file-permissions conn profile-id file-id share-id)
|
||||
params (-> params
|
||||
(assoc ::perms perms)
|
||||
(assoc :profile-id profile-id))]
|
||||
|
||||
@@ -104,28 +104,29 @@
|
||||
(def ^:private schema:limit
|
||||
[:and
|
||||
[:map
|
||||
[::name :any]
|
||||
[::name :keyword]
|
||||
[::strategy schema:strategy]
|
||||
[::key :string]
|
||||
[::opts :string]]
|
||||
[:or
|
||||
[:map
|
||||
[::capacity ::sm/int]
|
||||
[::rate ::sm/int]
|
||||
[::internal ::ct/duration]
|
||||
[::params [::sm/vec :any]]]
|
||||
[:map
|
||||
[::nreq ::sm/int]
|
||||
[::unit [:enum :days :hours :minutes :seconds :weeks]]]]])
|
||||
[::opts :string]
|
||||
[::capacity {:optional true} ::sm/int]
|
||||
[::rate {:optional true} ::sm/int]
|
||||
[::interval {:optional true} ::ct/duration]
|
||||
[::params {:optional true} [::sm/vec :any]]
|
||||
[::permits {:optional true} ::sm/int]
|
||||
[::unit {:optional true} [:enum :days :hours :minutes :seconds :weeks]]]
|
||||
[:fn (fn [attrs]
|
||||
(let [contains-fn (partial contains? attrs)]
|
||||
(or (every? contains-fn [::capacity ::rate ::interval])
|
||||
(every? contains-fn [::permits ::unit]))))]])
|
||||
|
||||
(def ^:private schema:limits
|
||||
[:map-of :keyword [::sm/vec schema:limit]])
|
||||
|
||||
(def ^:private valid-limit-tuple?
|
||||
(sm/lazy-validator schema:limit-tuple))
|
||||
(sm/validator schema:limit-tuple))
|
||||
|
||||
(def ^:private valid-rlimit-instance?
|
||||
(sm/lazy-validator ::rpc/rlimit))
|
||||
(sm/validator ::rpc/rlimit))
|
||||
|
||||
(defmethod parse-limit :window
|
||||
[[name strategy opts :as vlimit]]
|
||||
@@ -134,16 +135,16 @@
|
||||
(merge
|
||||
{::name name
|
||||
::strategy strategy}
|
||||
(if-let [[_ nreq unit] (re-find window-opts-re opts)]
|
||||
(let [nreq (parse-long nreq)]
|
||||
{::nreq nreq
|
||||
(if-let [[_ permits unit] (re-find window-opts-re opts)]
|
||||
(let [permits (parse-long permits)]
|
||||
{::permits permits
|
||||
::unit (case unit
|
||||
"d" :days
|
||||
"h" :hours
|
||||
"m" :minutes
|
||||
"s" :seconds
|
||||
"w" :weeks)
|
||||
::key (str "ratelimit.window." (d/name name))
|
||||
::key (str "penpot.rlimit." (cf/get :tenant) ".window." (d/name name))
|
||||
::opts opts})
|
||||
(ex/raise :type :validation
|
||||
:code :invalid-window-limit-opts
|
||||
@@ -164,15 +165,15 @@
|
||||
::interval interval
|
||||
::opts opts
|
||||
::params [(->seconds interval) rate capacity]
|
||||
::key (str "ratelimit.bucket." (d/name name))})
|
||||
::key (str "penpot.rlimit." (cf/get :tenant) ".bucket." (d/name name))})
|
||||
(ex/raise :type :validation
|
||||
:code :invalid-bucket-limit-opts
|
||||
:hint (str/ffmt "looks like '%' does not have a valid format" opts))))
|
||||
|
||||
(defmethod process-limit :bucket
|
||||
[rconn user-id now {:keys [::key ::params ::service ::capacity ::interval ::rate] :as limit}]
|
||||
[rconn profile-id now {:keys [::key ::params ::service ::capacity ::interval ::rate] :as limit}]
|
||||
(let [script (-> bucket-rate-limit-script
|
||||
(assoc ::rscript/keys [(str key "." service "." user-id)])
|
||||
(assoc ::rscript/keys [(str key "." service "." profile-id)])
|
||||
(assoc ::rscript/vals (conj params (->seconds now))))
|
||||
result (rds/eval rconn script)
|
||||
allowed? (boolean (nth result 0))
|
||||
@@ -192,18 +193,18 @@
|
||||
(assoc ::lresult/remaining remaining))))
|
||||
|
||||
(defmethod process-limit :window
|
||||
[rconn user-id now {:keys [::nreq ::unit ::key ::service] :as limit}]
|
||||
[rconn profile-id now {:keys [::permits ::unit ::key ::service] :as limit}]
|
||||
(let [ts (ct/truncate now unit)
|
||||
ttl (ct/diff now (ct/plus ts {unit 1}))
|
||||
script (-> window-rate-limit-script
|
||||
(assoc ::rscript/keys [(str key "." service "." user-id "." (ct/format-inst ts))])
|
||||
(assoc ::rscript/vals [nreq (->seconds ttl)]))
|
||||
(assoc ::rscript/keys [(str key "." service "." profile-id "." (ct/format-inst ts))])
|
||||
(assoc ::rscript/vals [permits (->seconds ttl)]))
|
||||
result (rds/eval rconn script)
|
||||
allowed? (boolean (nth result 0))
|
||||
remaining (nth result 1)]
|
||||
(l/trace :hint "limit processed"
|
||||
:service service
|
||||
:limit (name (::name limit))
|
||||
:name (name (::name limit))
|
||||
:strategy (name (::strategy limit))
|
||||
:opts (::opts limit)
|
||||
:allowed allowed?
|
||||
@@ -214,8 +215,8 @@
|
||||
(assoc ::lresult/reset (ct/plus ts {unit 1})))))
|
||||
|
||||
(defn- process-limits
|
||||
[rconn user-id limits now]
|
||||
(let [results (into [] (map (partial process-limit rconn user-id now)) limits)
|
||||
[rconn profile-id limits now]
|
||||
(let [results (into [] (map (partial process-limit rconn profile-id now)) limits)
|
||||
remaining (->> results
|
||||
(d/index-by ::name ::lresult/remaining)
|
||||
(uri/map->query-string))
|
||||
@@ -227,7 +228,7 @@
|
||||
|
||||
(when rejected
|
||||
(l/warn :hint "rejected rate limit"
|
||||
:user-id (str user-id)
|
||||
:profile-id (str profile-id)
|
||||
:limit-service (-> rejected ::service name)
|
||||
:limit-name (-> rejected ::name name)
|
||||
:limit-strategy (-> rejected ::strategy name)))
|
||||
@@ -371,12 +372,9 @@
|
||||
(defn- on-refresh-error
|
||||
[_ cause]
|
||||
(when-not (instance? java.util.concurrent.RejectedExecutionException cause)
|
||||
(if-let [explain (-> cause ex-data ex/explain)]
|
||||
(l/warn ::l/raw (str "unable to refresh config, invalid format:\n" explain)
|
||||
::l/sync? true)
|
||||
(l/warn :hint "unexpected exception on loading config"
|
||||
:cause cause
|
||||
::l/sync? true))))
|
||||
(l/warn :hint "unexpected exception on loading config"
|
||||
:cause cause
|
||||
::l/sync? true)))
|
||||
|
||||
(defn- get-config-path
|
||||
[]
|
||||
|
||||
@@ -25,9 +25,9 @@ local allowed = filled >= requested
|
||||
local newTokens = filled
|
||||
if allowed then
|
||||
newTokens = filled - requested
|
||||
redis.call("hset", tokensKey, "tokens", newTokens, "timestamp", timestamp)
|
||||
end
|
||||
|
||||
redis.call("hset", tokensKey, "tokens", newTokens, "timestamp", timestamp)
|
||||
redis.call("expire", tokensKey, ttl)
|
||||
|
||||
return { allowed, newTokens }
|
||||
|
||||
@@ -35,6 +35,9 @@
|
||||
:assets-s3 :s3
|
||||
nil)))
|
||||
|
||||
(def default-bucket
|
||||
"file-media-object")
|
||||
|
||||
(def valid-buckets
|
||||
#{"file-media-object"
|
||||
"team-font-variant"
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
[app.common.time :as ct]
|
||||
[app.config :as cf]
|
||||
[app.db :as db]
|
||||
[app.storage :as-alias sto]
|
||||
[app.storage :as sto]
|
||||
[app.storage.impl :as impl]
|
||||
[integrant.core :as ig]))
|
||||
|
||||
@@ -130,7 +130,7 @@
|
||||
[{:keys [metadata]}]
|
||||
(or (some-> metadata :bucket)
|
||||
(some-> metadata :reference d/name)
|
||||
"file-media-object"))
|
||||
sto/default-bucket))
|
||||
|
||||
(defn- process-objects!
|
||||
[conn has-refs? bucket objects]
|
||||
|
||||
@@ -7,10 +7,18 @@
|
||||
(ns app.util.template
|
||||
(:require
|
||||
[app.common.exceptions :as ex]
|
||||
[cuerdas.core :as str]
|
||||
[selmer.filters :as sf]
|
||||
[selmer.parser :as sp]))
|
||||
|
||||
;; (sp/cache-off!)
|
||||
|
||||
(sf/add-filter! :abbreviate
|
||||
(fn [s n]
|
||||
(let [n (parse-long n)]
|
||||
(str/abbreviate s n))))
|
||||
|
||||
|
||||
(defn render
|
||||
[path context]
|
||||
(try
|
||||
|
||||
@@ -137,33 +137,34 @@ RETURNING task.id, task.queue")
|
||||
::wait)))
|
||||
|
||||
(run-batch []
|
||||
(let [rconn (rds/connect cfg)]
|
||||
(try
|
||||
(-> cfg
|
||||
(assoc ::rds/conn rconn)
|
||||
(db/tx-run! run-batch'))
|
||||
(try
|
||||
(let [rconn (rds/connect cfg)]
|
||||
(try
|
||||
(-> cfg
|
||||
(assoc ::rds/conn rconn)
|
||||
(db/tx-run! run-batch'))
|
||||
(finally
|
||||
(.close ^AutoCloseable rconn))))
|
||||
|
||||
(catch InterruptedException cause
|
||||
(throw cause))
|
||||
(catch Exception cause
|
||||
(cond
|
||||
(rds/exception? cause)
|
||||
(do
|
||||
(l/wrn :hint "redis exception (will retry in an instant)" :cause cause)
|
||||
(px/sleep timeout))
|
||||
(catch InterruptedException cause
|
||||
(throw cause))
|
||||
|
||||
(db/sql-exception? cause)
|
||||
(do
|
||||
(l/wrn :hint "database exception (will retry in an instant)" :cause cause)
|
||||
(px/sleep timeout))
|
||||
(catch Exception cause
|
||||
(cond
|
||||
(rds/exception? cause)
|
||||
(do
|
||||
(l/wrn :hint "redis exception (will retry in an instant)" :cause cause)
|
||||
(px/sleep timeout))
|
||||
|
||||
:else
|
||||
(do
|
||||
(l/err :hint "unhandled exception (will retry in an instant)" :cause cause)
|
||||
(px/sleep timeout))))
|
||||
(db/sql-exception? cause)
|
||||
(do
|
||||
(l/wrn :hint "database exception (will retry in an instant)" :cause cause)
|
||||
(px/sleep timeout))
|
||||
|
||||
(finally
|
||||
(.close ^AutoCloseable rconn)))))
|
||||
:else
|
||||
(do
|
||||
(l/err :hint "unhandled exception (will retry in an instant)" :cause cause)
|
||||
(px/sleep timeout))))))
|
||||
|
||||
(dispatcher []
|
||||
(l/inf :hint "started")
|
||||
@@ -176,7 +177,7 @@ RETURNING task.id, task.queue")
|
||||
(catch InterruptedException _
|
||||
(l/trc :hint "interrupted"))
|
||||
(catch Throwable cause
|
||||
(l/err :hint " unexpected exception" :cause cause))
|
||||
(l/err :hint "unexpected exception" :cause cause))
|
||||
(finally
|
||||
(l/inf :hint "terminated"))))]
|
||||
|
||||
|
||||
@@ -29,8 +29,7 @@
|
||||
java-http-clj/java-http-clj {:mvn/version "0.4.3"}
|
||||
integrant/integrant {:mvn/version "1.0.0"}
|
||||
|
||||
funcool/tubax {:mvn/version "2021.05.20-0"}
|
||||
funcool/cuerdas {:mvn/version "2025.06.16-414"}
|
||||
funcool/cuerdas {:mvn/version "2026.415"}
|
||||
funcool/promesa
|
||||
{:git/sha "46048fc0d4bf5466a2a4121f5d52aefa6337f2e8"
|
||||
:git/url "https://github.com/funcool/promesa"}
|
||||
|
||||
@@ -169,6 +169,7 @@
|
||||
:enable-component-thumbnails
|
||||
:enable-render-wasm-dpr
|
||||
:enable-token-color
|
||||
:enable-token-shadow
|
||||
:enable-inspect-styles
|
||||
:enable-feature-fdata-objects-map])
|
||||
|
||||
|
||||
@@ -340,7 +340,7 @@
|
||||
(dfn-diff t2 t1)))
|
||||
|
||||
#?(:cljs
|
||||
(defn set-default-locale!
|
||||
(defn set-default-locale
|
||||
[locale]
|
||||
(when-let [locale (unchecked-get locales locale)]
|
||||
(dfn-set-default-options #js {:locale locale}))))
|
||||
|
||||
@@ -362,24 +362,24 @@
|
||||
component (ctkl/get-component component-file (:component-id top-instance) true)
|
||||
remote-shape (get-ref-shape component-file component shape)
|
||||
component-container (get-component-container component-file component)
|
||||
[remote-shape component-container]
|
||||
[remote-shape component-container component-file]
|
||||
(if (some? remote-shape)
|
||||
[remote-shape component-container]
|
||||
[remote-shape component-container component-file]
|
||||
;; If not found, try the case of this being a fostered or swapped children
|
||||
(let [head-instance (ctn/get-head-shape (:objects container) shape)
|
||||
component-file (get-in libraries [(:component-file head-instance) :data])
|
||||
head-component (ctkl/get-component component-file (:component-id head-instance) true)
|
||||
remote-shape' (get-ref-shape component-file head-component shape)
|
||||
component-container (get-component-container component-file component)]
|
||||
[remote-shape' component-container]))]
|
||||
(let [head-instance (ctn/get-head-shape (:objects container) shape)
|
||||
component-file (get-in libraries [(:component-file head-instance) :data])
|
||||
head-component (ctkl/get-component component-file (:component-id head-instance) true)
|
||||
remote-shape' (get-ref-shape component-file head-component shape)
|
||||
component-container' (get-component-container component-file head-component)]
|
||||
[remote-shape' component-container' component-file]))]
|
||||
|
||||
(if (nil? remote-shape)
|
||||
nil
|
||||
(if (nil? (:shape-ref remote-shape))
|
||||
(cond-> remote-shape
|
||||
(and remote-shape with-context?)
|
||||
(with-meta {:file {:id (:id file-data)
|
||||
:data file-data}
|
||||
(with-meta {:file {:id (:id component-file)
|
||||
:data component-file}
|
||||
:container component-container}))
|
||||
(find-remote-shape component-container libraries remote-shape :with-context? with-context?)))))
|
||||
|
||||
|
||||
@@ -59,6 +59,7 @@
|
||||
:dimensions "dimension"
|
||||
:font-family "fontFamilies"
|
||||
:font-size "fontSizes"
|
||||
:font-weight "fontWeights"
|
||||
:letter-spacing "letterSpacing"
|
||||
:number "number"
|
||||
:opacity "opacity"
|
||||
@@ -70,7 +71,6 @@
|
||||
:stroke-width "borderWidth"
|
||||
:text-case "textCase"
|
||||
:text-decoration "textDecoration"
|
||||
:font-weight "fontWeights"
|
||||
:typography "typography"})
|
||||
|
||||
(def dtcg-token-type->token-type
|
||||
|
||||
@@ -1410,8 +1410,8 @@ Will return a value that matches this schema:
|
||||
;; NOTE: we can't assign statically at eval time the value of a
|
||||
;; function that is declared but not defined; so we need to pass
|
||||
;; an anonymous function and delegate the resolution to runtime
|
||||
{:encode/json #(export-dtcg-json %)
|
||||
:decode/json #(read-multi-set-dtcg %)
|
||||
{:encode/json #(some-> % export-dtcg-json)
|
||||
:decode/json #(some-> % read-multi-set-dtcg)
|
||||
;; FIXME: add better, more reallistic generator
|
||||
:gen/gen (->> (sg/small-int)
|
||||
(sg/fmap (fn [_]
|
||||
@@ -1545,7 +1545,7 @@ Will return a value that matches this schema:
|
||||
(and (not (contains? decoded-json "$metadata"))
|
||||
(not (contains? decoded-json "$themes"))))
|
||||
|
||||
(defn- convert-dtcg-font-family
|
||||
(defn convert-dtcg-font-family
|
||||
"Convert font-family token value from DTCG format to internal format.
|
||||
- If value is a string, split it into a collection of font families
|
||||
- If value is already an array, keep it as is
|
||||
@@ -1556,7 +1556,7 @@ Will return a value that matches this schema:
|
||||
(sequential? value) value
|
||||
:else value))
|
||||
|
||||
(defn- convert-dtcg-typography-composite
|
||||
(defn convert-dtcg-typography-composite
|
||||
"Convert typography token value keys from DTCG format to internal format."
|
||||
[value]
|
||||
(if (map? value)
|
||||
@@ -1568,7 +1568,7 @@ Will return a value that matches this schema:
|
||||
;; Reference value
|
||||
value))
|
||||
|
||||
(defn- convert-dtcg-shadow-composite
|
||||
(defn convert-dtcg-shadow-composite
|
||||
"Convert shadow token value from DTCG format to internal format."
|
||||
[value]
|
||||
(let [process-shadow (fn [shadow]
|
||||
|
||||
@@ -10,3 +10,7 @@ localhost:3449 {
|
||||
http://localhost:3450 {
|
||||
reverse_proxy localhost:4449
|
||||
}
|
||||
|
||||
http://penpot-devenv-main:3450 {
|
||||
reverse_proxy localhost:4449
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"license": "MPL-2.0",
|
||||
"author": "Kaleidos INC",
|
||||
"private": true,
|
||||
"packageManager": "yarn@4.10.3+sha512.c38cafb5c7bb273f3926d04e55e1d8c9dfa7d9c3ea1f36a4868fa028b9e5f72298f0b7f401ad5eb921749eb012eb1c3bb74bf7503df3ee43fd600d14a018266f",
|
||||
"packageManager": "yarn@4.12.0+sha512.f45ab632439a67f8bc759bf32ead036a1f413287b9042726b7cc4818b7b49e14e9423ba49b18f9e06ea4941c1ad062385b1d8760a8d5091a1a31e5f6219afca8",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/penpot/penpot"
|
||||
@@ -16,9 +16,9 @@
|
||||
"date-fns": "^4.1.0",
|
||||
"generic-pool": "^3.9.0",
|
||||
"inflation": "^2.1.0",
|
||||
"ioredis": "^5.8.1",
|
||||
"playwright": "^1.55.1",
|
||||
"raw-body": "^3.0.1",
|
||||
"ioredis": "^5.8.2",
|
||||
"playwright": "^1.57.0",
|
||||
"raw-body": "^3.0.2",
|
||||
"source-map-support": "^0.5.21",
|
||||
"svgo": "penpot/svgo#v3.1",
|
||||
"undici": "^7.16.0",
|
||||
|
||||
@@ -243,7 +243,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"bytes@npm:3.1.2":
|
||||
"bytes@npm:~3.1.2":
|
||||
version: 3.1.2
|
||||
resolution: "bytes@npm:3.1.2"
|
||||
checksum: 10c0/76d1c43cbd602794ad8ad2ae94095cddeb1de78c5dddaa7005c51af10b0176c69971a6d88e805a90c2b6550d76636e43c40d8427a808b8645ede885de4a0358e
|
||||
@@ -442,7 +442,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"depd@npm:2.0.0, depd@npm:~2.0.0":
|
||||
"depd@npm:~2.0.0":
|
||||
version: 2.0.0
|
||||
resolution: "depd@npm:2.0.0"
|
||||
checksum: 10c0/58bd06ec20e19529b06f7ad07ddab60e504d9e0faca4bd23079fac2d279c3594334d736508dc350e06e510aba5e22e4594483b3a6562ce7c17dd797f4cc4ad2c
|
||||
@@ -577,9 +577,9 @@ __metadata:
|
||||
date-fns: "npm:^4.1.0"
|
||||
generic-pool: "npm:^3.9.0"
|
||||
inflation: "npm:^2.1.0"
|
||||
ioredis: "npm:^5.8.1"
|
||||
playwright: "npm:^1.55.1"
|
||||
raw-body: "npm:^3.0.1"
|
||||
ioredis: "npm:^5.8.2"
|
||||
playwright: "npm:^1.57.0"
|
||||
raw-body: "npm:^3.0.2"
|
||||
source-map-support: "npm:^0.5.21"
|
||||
svgo: "penpot/svgo#v3.1"
|
||||
undici: "npm:^7.16.0"
|
||||
@@ -683,16 +683,16 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"http-errors@npm:2.0.0":
|
||||
version: 2.0.0
|
||||
resolution: "http-errors@npm:2.0.0"
|
||||
"http-errors@npm:~2.0.1":
|
||||
version: 2.0.1
|
||||
resolution: "http-errors@npm:2.0.1"
|
||||
dependencies:
|
||||
depd: "npm:2.0.0"
|
||||
inherits: "npm:2.0.4"
|
||||
setprototypeof: "npm:1.2.0"
|
||||
statuses: "npm:2.0.1"
|
||||
toidentifier: "npm:1.0.1"
|
||||
checksum: 10c0/fc6f2715fe188d091274b5ffc8b3657bd85c63e969daa68ccb77afb05b071a4b62841acb7a21e417b5539014dff2ebf9550f0b14a9ff126f2734a7c1387f8e19
|
||||
depd: "npm:~2.0.0"
|
||||
inherits: "npm:~2.0.4"
|
||||
setprototypeof: "npm:~1.2.0"
|
||||
statuses: "npm:~2.0.2"
|
||||
toidentifier: "npm:~1.0.1"
|
||||
checksum: 10c0/fb38906cef4f5c83952d97661fe14dc156cb59fe54812a42cd448fa57b5c5dfcb38a40a916957737bd6b87aab257c0648d63eb5b6a9ca9f548e105b6072712d4
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -716,15 +716,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"iconv-lite@npm:0.7.0":
|
||||
version: 0.7.0
|
||||
resolution: "iconv-lite@npm:0.7.0"
|
||||
dependencies:
|
||||
safer-buffer: "npm:>= 2.1.2 < 3.0.0"
|
||||
checksum: 10c0/2382400469071c55b6746c531eed5fa4d033e5db6690b7331fb2a5f59a30d7a9782932e92253db26df33c1cf46fa200a3fbe524a2a7c62037c762283f188ec2f
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"iconv-lite@npm:^0.6.2":
|
||||
version: 0.6.3
|
||||
resolution: "iconv-lite@npm:0.6.3"
|
||||
@@ -734,6 +725,15 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"iconv-lite@npm:~0.7.0":
|
||||
version: 0.7.0
|
||||
resolution: "iconv-lite@npm:0.7.0"
|
||||
dependencies:
|
||||
safer-buffer: "npm:>= 2.1.2 < 3.0.0"
|
||||
checksum: 10c0/2382400469071c55b6746c531eed5fa4d033e5db6690b7331fb2a5f59a30d7a9782932e92253db26df33c1cf46fa200a3fbe524a2a7c62037c762283f188ec2f
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"ieee754@npm:^1.2.1":
|
||||
version: 1.2.1
|
||||
resolution: "ieee754@npm:1.2.1"
|
||||
@@ -755,16 +755,16 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"inherits@npm:2.0.4, inherits@npm:~2.0.3":
|
||||
"inherits@npm:~2.0.3, inherits@npm:~2.0.4":
|
||||
version: 2.0.4
|
||||
resolution: "inherits@npm:2.0.4"
|
||||
checksum: 10c0/4e531f648b29039fb7426fb94075e6545faa1eb9fe83c29f0b6d9e7263aceb4289d2d4557db0d428188eeb449cc7c5e77b0a0b2c4e248ff2a65933a0dee49ef2
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"ioredis@npm:^5.8.1":
|
||||
version: 5.8.1
|
||||
resolution: "ioredis@npm:5.8.1"
|
||||
"ioredis@npm:^5.8.2":
|
||||
version: 5.8.2
|
||||
resolution: "ioredis@npm:5.8.2"
|
||||
dependencies:
|
||||
"@ioredis/commands": "npm:1.4.0"
|
||||
cluster-key-slot: "npm:^1.1.0"
|
||||
@@ -775,7 +775,7 @@ __metadata:
|
||||
redis-errors: "npm:^1.2.0"
|
||||
redis-parser: "npm:^3.0.0"
|
||||
standard-as-callback: "npm:^2.1.0"
|
||||
checksum: 10c0/4ed66444017150da027bce940a24bf726994691e2a7b3aa11d52f8aeb37f258068cc171af4d9c61247acafc28eb086fa8a7c79420b8e8d2907d2f74f39584465
|
||||
checksum: 10c0/305e385f811d49908899e32c2de69616cd059f909afd9e0a53e54f596b1a5835ee3449bfc6a3c49afbc5a2fd27990059e316cc78f449c94024957bd34c826d88
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -1106,27 +1106,27 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"playwright-core@npm:1.55.1":
|
||||
version: 1.55.1
|
||||
resolution: "playwright-core@npm:1.55.1"
|
||||
"playwright-core@npm:1.57.0":
|
||||
version: 1.57.0
|
||||
resolution: "playwright-core@npm:1.57.0"
|
||||
bin:
|
||||
playwright-core: cli.js
|
||||
checksum: 10c0/39837a8c1232ec27486eac8c3fcacc0b090acc64310f7f9004b06715370fc426f944e3610fe8c29f17cd3d68280ed72c75f660c02aa5b5cf0eb34bab0031308f
|
||||
checksum: 10c0/798e35d83bf48419a8c73de20bb94d68be5dde68de23f95d80a0ebe401e3b83e29e3e84aea7894d67fa6c79d2d3d40cc5bcde3e166f657ce50987aaa2421b6a9
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"playwright@npm:^1.55.1":
|
||||
version: 1.55.1
|
||||
resolution: "playwright@npm:1.55.1"
|
||||
"playwright@npm:^1.57.0":
|
||||
version: 1.57.0
|
||||
resolution: "playwright@npm:1.57.0"
|
||||
dependencies:
|
||||
fsevents: "npm:2.3.2"
|
||||
playwright-core: "npm:1.55.1"
|
||||
playwright-core: "npm:1.57.0"
|
||||
dependenciesMeta:
|
||||
fsevents:
|
||||
optional: true
|
||||
bin:
|
||||
playwright: cli.js
|
||||
checksum: 10c0/b84a97b0d764403df512f5bbb10c7343974e151a28202cc06f90883a13e8a45f4491a0597f0ae5fb03a026746cbc0d200f0f32195bfaa381aee5ca5770626771
|
||||
checksum: 10c0/ab03c99a67b835bdea9059f516ad3b6e42c21025f9adaa161a4ef6bc7ca716dcba476d287140bb240d06126eb23f889a8933b8f5f1f1a56b80659d92d1358899
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -1161,15 +1161,15 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"raw-body@npm:^3.0.1":
|
||||
version: 3.0.1
|
||||
resolution: "raw-body@npm:3.0.1"
|
||||
"raw-body@npm:^3.0.2":
|
||||
version: 3.0.2
|
||||
resolution: "raw-body@npm:3.0.2"
|
||||
dependencies:
|
||||
bytes: "npm:3.1.2"
|
||||
http-errors: "npm:2.0.0"
|
||||
iconv-lite: "npm:0.7.0"
|
||||
unpipe: "npm:1.0.0"
|
||||
checksum: 10c0/892f4fbd21ecab7e2fed0f045f7af9e16df7e8050879639d4e482784a2f4640aaaa33d916a0e98013f23acb82e09c2e3c57f84ab97104449f728d22f65a7d79a
|
||||
bytes: "npm:~3.1.2"
|
||||
http-errors: "npm:~2.0.1"
|
||||
iconv-lite: "npm:~0.7.0"
|
||||
unpipe: "npm:~1.0.0"
|
||||
checksum: 10c0/d266678d08e1e7abea62c0ce5864344e980fa81c64f6b481e9842c5beaed2cdcf975f658a3ccd67ad35fc919c1f6664ccc106067801850286a6cbe101de89f29
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -1270,7 +1270,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"setprototypeof@npm:1.2.0":
|
||||
"setprototypeof@npm:~1.2.0":
|
||||
version: 1.2.0
|
||||
resolution: "setprototypeof@npm:1.2.0"
|
||||
checksum: 10c0/68733173026766fa0d9ecaeb07f0483f4c2dc70ca376b3b7c40b7cda909f94b0918f6c5ad5ce27a9160bdfb475efaa9d5e705a11d8eaae18f9835d20976028bc
|
||||
@@ -1368,10 +1368,10 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"statuses@npm:2.0.1":
|
||||
version: 2.0.1
|
||||
resolution: "statuses@npm:2.0.1"
|
||||
checksum: 10c0/34378b207a1620a24804ce8b5d230fea0c279f00b18a7209646d5d47e419d1cc23e7cbf33a25a1e51ac38973dc2ac2e1e9c647a8e481ef365f77668d72becfd0
|
||||
"statuses@npm:~2.0.2":
|
||||
version: 2.0.2
|
||||
resolution: "statuses@npm:2.0.2"
|
||||
checksum: 10c0/a9947d98ad60d01f6b26727570f3bcceb6c8fa789da64fe6889908fe2e294d57503b14bf2b5af7605c2d36647259e856635cd4c49eab41667658ec9d0080ec3f
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -1500,7 +1500,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"toidentifier@npm:1.0.1":
|
||||
"toidentifier@npm:~1.0.1":
|
||||
version: 1.0.1
|
||||
resolution: "toidentifier@npm:1.0.1"
|
||||
checksum: 10c0/93937279934bd66cc3270016dd8d0afec14fb7c94a05c72dc57321f8bd1fa97e5bea6d1f7c89e728d077ca31ea125b78320a616a6c6cd0e6b9cb94cb864381c1
|
||||
@@ -1539,7 +1539,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"unpipe@npm:1.0.0":
|
||||
"unpipe@npm:~1.0.0":
|
||||
version: 1.0.0
|
||||
resolution: "unpipe@npm:1.0.0"
|
||||
checksum: 10c0/193400255bd48968e5c5383730344fbb4fa114cdedfab26e329e50dd2d81b134244bb8a72c6ac1b10ab0281a58b363d06405632c9d49ca9dfd5e90cbd7d0f32c
|
||||
|
||||
@@ -8,6 +8,11 @@
|
||||
metosin/reitit-core {:mvn/version "0.9.1"}
|
||||
funcool/okulary {:mvn/version "2022.04.11-16"}
|
||||
|
||||
funcool/tubax
|
||||
{:git/tag "v2025.11.28"
|
||||
:git/sha "2d9a986"
|
||||
:git/url "https://github.com/funcool/tubax.git"}
|
||||
|
||||
funcool/potok2
|
||||
{:git/tag "v2.2"
|
||||
:git/sha "0f7e15a"
|
||||
@@ -45,7 +50,7 @@
|
||||
{thheller/shadow-cljs {:mvn/version "3.2.2"}
|
||||
com.bhauman/rebel-readline {:mvn/version "RELEASE"}
|
||||
org.clojure/tools.namespace {:mvn/version "RELEASE"}
|
||||
criterium/criterium {:mvn/version "RELEASE"}
|
||||
criterium/criterium {:mvn/version "0.4.6"}
|
||||
cider/cider-nrepl {:mvn/version "0.57.0"}}}
|
||||
|
||||
:shadow-cljs
|
||||
|
||||
@@ -53,83 +53,74 @@
|
||||
"watch:storybook:assets": "node ./scripts/watch-storybook.js"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@penpot/draft-js": "portal:./packages/draft-js",
|
||||
"@penpot/mousetrap": "portal:./packages/mousetrap",
|
||||
"@penpot/plugins-runtime": "1.3.2",
|
||||
"@penpot/svgo": "penpot/svgo#v3.2",
|
||||
"@penpot/text-editor": "portal:./text-editor",
|
||||
"@playwright/test": "1.52.0",
|
||||
"@storybook/addon-docs": "10.0.4",
|
||||
"@storybook/addon-themes": "10.0.4",
|
||||
"@storybook/addon-vitest": "10.0.4",
|
||||
"@storybook/react-vite": "10.0.4",
|
||||
"@tokens-studio/sd-transforms": "1.2.11",
|
||||
"@types/node": "^22.15.21",
|
||||
"@vitest/browser": "3.2.4",
|
||||
"@vitest/coverage-v8": "3.2.4",
|
||||
"@zip.js/zip.js": "patch:@zip.js/zip.js@npm%3A2.7.60#~/.yarn/patches/@zip.js-zip.js-npm-2.7.60-b6b814410b.patch",
|
||||
"autoprefixer": "^10.4.21",
|
||||
"compression": "^1.8.1",
|
||||
"concurrently": "^9.2.1",
|
||||
"date-fns": "^4.1.0",
|
||||
"esbuild": "^0.25.9",
|
||||
"eventsource-parser": "^3.0.6",
|
||||
"express": "^5.1.0",
|
||||
"fancy-log": "^2.0.0",
|
||||
"getopts": "^2.3.0",
|
||||
"gettext-parser": "^8.0.0",
|
||||
"gulp-concat": "^2.6.1",
|
||||
"gulp-gzip": "^1.4.2",
|
||||
"gulp-mustache": "^5.0.0",
|
||||
"gulp-postcss": "^10.0.0",
|
||||
"gulp-rename": "^2.0.0",
|
||||
"gulp-sourcemaps": "^3.0.0",
|
||||
"gulp-svg-sprite": "^2.0.3",
|
||||
"highlight.js": "^11.10.0",
|
||||
"js-beautify": "^1.15.4",
|
||||
"jsdom": "^27.0.0",
|
||||
"lodash": "^4.17.21",
|
||||
"lodash.debounce": "^4.0.8",
|
||||
"map-stream": "0.0.7",
|
||||
"marked": "^15.0.12",
|
||||
"mkdirp": "^3.0.1",
|
||||
"mustache": "^4.2.0",
|
||||
"nodemon": "^3.1.10",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"opentype.js": "^1.3.4",
|
||||
"p-limit": "^6.2.0",
|
||||
"playwright": "1.56.1",
|
||||
"postcss": "^8.5.4",
|
||||
"postcss-clean": "^1.2.2",
|
||||
"postcss-modules": "^6.0.1",
|
||||
"prettier": "3.5.3",
|
||||
"pretty-time": "^1.1.0",
|
||||
"prop-types": "^15.8.1",
|
||||
"rimraf": "^6.0.1",
|
||||
"sass": "^1.89.0",
|
||||
"sass-embedded": "^1.89.0",
|
||||
"storybook": "10.0.4",
|
||||
"svg-sprite": "^2.0.4",
|
||||
"typescript": "^5.9.2",
|
||||
"vite": "^6.3.5",
|
||||
"vitest": "^3.2.0",
|
||||
"wasm-pack": "^0.13.1",
|
||||
"watcher": "^2.3.1",
|
||||
"workerpool": "^9.3.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"@penpot/draft-js": "portal:./vendor/draft-js",
|
||||
"@penpot/hljs": "portal:./vendor/hljs",
|
||||
"@penpot/mousetrap": "portal:./vendor/mousetrap",
|
||||
"@penpot/plugins-runtime": "1.3.2",
|
||||
"@penpot/svgo": "penpot/svgo#v3.2",
|
||||
"@penpot/text-editor": "portal:./text-editor",
|
||||
"@tokens-studio/sd-transforms": "1.2.11",
|
||||
"@zip.js/zip.js": "patch:@zip.js/zip.js@npm%3A2.7.60#~/.yarn/patches/@zip.js-zip.js-npm-2.7.60-b6b814410b.patch",
|
||||
"compression": "^1.8.1",
|
||||
"date-fns": "^4.1.0",
|
||||
"eventsource-parser": "^3.0.6",
|
||||
"js-beautify": "^1.15.4",
|
||||
"lodash": "^4.17.21",
|
||||
"lodash.debounce": "^4.0.8",
|
||||
"opentype.js": "^1.3.4",
|
||||
"postcss-modules": "^6.0.1",
|
||||
"randomcolor": "^0.6.2",
|
||||
"react": "19.1.1",
|
||||
"react-dom": "19.1.1",
|
||||
"react-error-boundary": "^6.0.0",
|
||||
"react-virtualized": "^9.22.6",
|
||||
"rimraf": "^6.0.1",
|
||||
"rxjs": "8.0.0-alpha.14",
|
||||
"sass": "^1.89.0",
|
||||
"sass-embedded": "^1.89.0",
|
||||
"sax": "^1.4.1",
|
||||
"source-map-support": "^0.5.21",
|
||||
"storybook": "10.0.4",
|
||||
"style-dictionary": "5.0.0-rc.1",
|
||||
"svg-sprite": "^2.0.4",
|
||||
"tdigest": "^0.1.2",
|
||||
"tinycolor2": "^1.6.0",
|
||||
"typescript": "^5.9.2",
|
||||
"ua-parser-js": "2.0.5",
|
||||
"vite": "^6.3.5",
|
||||
"vitest": "^3.2.0",
|
||||
"wasm-pack": "^0.13.1",
|
||||
"watcher": "^2.3.1",
|
||||
"workerpool": "^9.3.2",
|
||||
"xregexp": "^5.1.2"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,9 @@ export const {
|
||||
RichTextEditorUtil,
|
||||
SelectionState,
|
||||
convertFromRaw,
|
||||
convertToRaw
|
||||
convertToRaw,
|
||||
EditorBlock,
|
||||
Editor
|
||||
} = pkg;
|
||||
|
||||
import DraftPasteProcessor from 'draft-js/lib/DraftPasteProcessor.js';
|
||||
@@ -8,7 +8,8 @@
|
||||
"author": "Andrey Antukh",
|
||||
"license": "MPL-2.0",
|
||||
"dependencies": {
|
||||
"draft-js": "penpot/draft-js.git#4a99b2a6020b2af97f6dc5fa1b4275ec16b559a0"
|
||||
"draft-js": "penpot/draft-js.git#4a99b2a6020b2af97f6dc5fa1b4275ec16b559a0",
|
||||
"immutable": "^5.1.4"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=0.17.0",
|
||||
@@ -173,12 +173,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@penpot/draft-js-wrapper@workspace:.":
|
||||
"@penpot/draft-js@workspace:.":
|
||||
version: 0.0.0-use.local
|
||||
resolution: "@penpot/draft-js-wrapper@workspace:."
|
||||
resolution: "@penpot/draft-js@workspace:."
|
||||
dependencies:
|
||||
draft-js: "penpot/draft-js.git#4a99b2a6020b2af97f6dc5fa1b4275ec16b559a0"
|
||||
esbuild: "npm:^0.24.0"
|
||||
immutable: "npm:^5.1.4"
|
||||
peerDependencies:
|
||||
react: ">=0.17.0"
|
||||
react-dom: ">=0.17.0"
|
||||
@@ -320,6 +321,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"immutable@npm:^5.1.4":
|
||||
version: 5.1.4
|
||||
resolution: "immutable@npm:5.1.4"
|
||||
checksum: 10c0/f1c98382e4cde14a0b218be3b9b2f8441888da8df3b8c064aa756071da55fbed6ad696e5959982508456332419be9fdeaf29b2e58d0eadc45483cc16963c0446
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"immutable@npm:~3.7.4":
|
||||
version: 3.7.6
|
||||
resolution: "immutable@npm:3.7.6"
|
||||
@@ -0,0 +1 @@
|
||||
[]
|
||||
@@ -0,0 +1,47 @@
|
||||
[
|
||||
{
|
||||
"~:id": "~uc7ce0794-0992-8105-8004-38e630f41234",
|
||||
"~:revn": 1,
|
||||
"~:vern": 1,
|
||||
"~:project-id": "~uc7ce0794-0992-8105-8004-38e630f7920b",
|
||||
"~:created-at": "~m1705307400000",
|
||||
"~:modified-at": "~m1732111500000",
|
||||
"~:deleted-at": "~m1732111500000",
|
||||
"~:name": "Deleted Design File 1",
|
||||
"~:is-shared": false,
|
||||
"~:will-be-deleted-at": "~m1732716300000",
|
||||
"~:thumbnail-id": null,
|
||||
"~:row-num": 1,
|
||||
"~:team-id": "~uc7ce0794-0992-8105-8004-38e630f40f6d"
|
||||
},
|
||||
{
|
||||
"~:id": "~uc7ce0794-0992-8105-8004-38e630f41235",
|
||||
"~:revn": 2,
|
||||
"~:vern": 2,
|
||||
"~:project-id": "~uc7ce0794-0992-8105-8004-38e630f7920b",
|
||||
"~:created-at": "~m1704875700000",
|
||||
"~:modified-at": "~m1732025400000",
|
||||
"~:deleted-at": "~m1732025400000",
|
||||
"~:name": "Deleted Design File 2",
|
||||
"~:is-shared": true,
|
||||
"~:will-be-deleted-at": "~m1732630200000",
|
||||
"~:thumbnail-id": null,
|
||||
"~:row-num": 2,
|
||||
"~:team-id": "~uc7ce0794-0992-8105-8004-38e630f40f6d"
|
||||
},
|
||||
{
|
||||
"~:id": "~uc7ce0794-0992-8105-8004-38e630f41236",
|
||||
"~:revn": 3,
|
||||
"~:vern": 3,
|
||||
"~:project-id": "~uc7ce0794-0992-8105-8004-38e630f7920c",
|
||||
"~:created-at": "~m1706792400000",
|
||||
"~:modified-at": "~m1731939600000",
|
||||
"~:deleted-at": "~m1731939600000",
|
||||
"~:name": "Old Project Design",
|
||||
"~:is-shared": false,
|
||||
"~:will-be-deleted-at": "~m1732544400000",
|
||||
"~:thumbnail-id": null,
|
||||
"~:row-num": 3,
|
||||
"~:team-id": "~uc7ce0794-0992-8105-8004-38e630f40f6d"
|
||||
}
|
||||
]
|
||||
@@ -106,6 +106,13 @@ export class DashboardPage extends BaseWebSocketPage {
|
||||
);
|
||||
}
|
||||
|
||||
async setupDeletedFiles() {
|
||||
await this.mockRPC(
|
||||
"get-team-deleted-files?team-id=*",
|
||||
"dashboard/get-team-deleted-files.json",
|
||||
);
|
||||
}
|
||||
|
||||
async setupDrafts() {
|
||||
await this.mockRPC(
|
||||
"get-project-files?project-id=*",
|
||||
@@ -160,6 +167,10 @@ export class DashboardPage extends BaseWebSocketPage {
|
||||
});
|
||||
await this.mockRPC("search-files", "dashboard/search-files.json");
|
||||
await this.mockRPC("get-teams", "logged-in-user/get-teams-complete.json");
|
||||
await this.mockRPC(
|
||||
"get-team-deleted-files?team-id=*",
|
||||
"dashboard/get-team-deleted-files.json",
|
||||
);
|
||||
}
|
||||
|
||||
async setupAccessTokensEmpty() {
|
||||
@@ -289,6 +300,13 @@ export class DashboardPage extends BaseWebSocketPage {
|
||||
await expect(this.mainHeading).toHaveText("Libraries");
|
||||
}
|
||||
|
||||
async goToDeleted() {
|
||||
await this.page.goto(
|
||||
`#/dashboard/deleted?team-id=${DashboardPage.anyTeamId}`,
|
||||
);
|
||||
await expect(this.mainHeading).toHaveText("Projects");
|
||||
}
|
||||
|
||||
async openProfileMenu() {
|
||||
await this.userAccount.click();
|
||||
}
|
||||
|
||||
31
frontend/playwright/ui/specs/dashboard-deleted.spec.js
Normal file
31
frontend/playwright/ui/specs/dashboard-deleted.spec.js
Normal file
@@ -0,0 +1,31 @@
|
||||
import { test, expect } from "@playwright/test";
|
||||
import DashboardPage from "../pages/DashboardPage";
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await DashboardPage.init(page);
|
||||
await DashboardPage.mockRPC(
|
||||
page,
|
||||
"get-profile",
|
||||
"logged-in-user/get-profile-logged-in-no-onboarding.json",
|
||||
);
|
||||
});
|
||||
|
||||
test.describe("Dashboard Deleted Page", () => {
|
||||
test("User can navigate to deleted page", async ({ page }) => {
|
||||
const dashboardPage = new DashboardPage(page);
|
||||
|
||||
// Setup mock for deleted files API
|
||||
await dashboardPage.setupDeletedFiles();
|
||||
|
||||
// Navigate directly to deleted page
|
||||
await dashboardPage.goToDeleted();
|
||||
|
||||
// Check for the restore all and clear trash buttons
|
||||
await expect(
|
||||
page.getByRole("button", { name: "Restore All" }),
|
||||
).toBeVisible();
|
||||
await expect(
|
||||
page.getByRole("button", { name: "Clear trash" }),
|
||||
).toBeVisible();
|
||||
});
|
||||
});
|
||||
@@ -24,6 +24,8 @@
|
||||
|
||||
<link rel="icon" href="images/favicon.png" />
|
||||
|
||||
<script type="importmap">{{& manifest.importmap }}</script>
|
||||
|
||||
<script type="module">
|
||||
globalThis.penpotVersion = "{{& version}}";
|
||||
globalThis.penpotBuildDate = "{{& build_date}}";
|
||||
@@ -33,7 +35,6 @@
|
||||
{{# manifest}}
|
||||
<script src="{{& config}}"></script>
|
||||
<script src="{{& polyfills}}"></script>
|
||||
<script type="importmap">{{& importmap }}</script>
|
||||
{{/manifest}}
|
||||
|
||||
<!--cookie-consent-->
|
||||
@@ -49,7 +50,9 @@
|
||||
<script type="module" src="{{& libs}}"></script>
|
||||
<script type="module">
|
||||
import { init } from "{{& app_main}}";
|
||||
init();
|
||||
import defaultTranslations from "{{& default_translations}}";
|
||||
|
||||
init({defaultTranslations});
|
||||
</script>
|
||||
{{/manifest}}
|
||||
</body>
|
||||
|
||||
@@ -187,7 +187,7 @@ async function readManifestFile(resource) {
|
||||
return JSON.parse(content);
|
||||
}
|
||||
|
||||
async function readShadowManifest() {
|
||||
async function generateManifest() {
|
||||
const index = {
|
||||
app_main: "./js/main.js",
|
||||
render_main: "./js/render.js",
|
||||
@@ -197,6 +197,7 @@ async function readShadowManifest() {
|
||||
polyfills: "./js/polyfills.js?version=" + CURRENT_VERSION,
|
||||
libs: "./js/libs.js?version=" + CURRENT_VERSION,
|
||||
worker_main: "./js/worker/main.js?version=" + CURRENT_VERSION,
|
||||
default_translations: "./js/translation.en.js?version=" + CURRENT_VERSION,
|
||||
|
||||
importmap: JSON.stringify({
|
||||
"imports": {
|
||||
@@ -276,6 +277,7 @@ export async function compileTranslations() {
|
||||
"id",
|
||||
"ru",
|
||||
"tr",
|
||||
"hi",
|
||||
"zh_CN",
|
||||
"zh_Hant",
|
||||
"hr",
|
||||
@@ -391,7 +393,7 @@ async function generateTemplates() {
|
||||
const isDebug = process.env.NODE_ENV !== "production";
|
||||
await fs.mkdir("./resources/public/", { recursive: true });
|
||||
|
||||
const manifest = await readShadowManifest();
|
||||
const manifest = await generateManifest();
|
||||
let content;
|
||||
|
||||
const iconsSprite = await fs.readFile(
|
||||
|
||||
@@ -90,7 +90,10 @@
|
||||
(rx/map #(ws/initialize)))))))
|
||||
|
||||
(defn ^:export init
|
||||
[]
|
||||
[options]
|
||||
(some-> (unchecked-get options "defaultTranslations")
|
||||
(i18n/set-default-translations))
|
||||
|
||||
(mw/init!)
|
||||
(i18n/init)
|
||||
(cur/init-styles)
|
||||
|
||||
@@ -386,3 +386,21 @@
|
||||
(rx/of ::dps/force-persist
|
||||
(rt/nav :viewer params options))))))
|
||||
|
||||
(defn go-to-dashboard-deleted
|
||||
[& {:keys [team-id] :as options}]
|
||||
(ptk/reify ::go-to-dashboard-deleted
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [profile (get state :profile)
|
||||
team-id (cond
|
||||
(= :default team-id)
|
||||
(:default-team-id profile)
|
||||
|
||||
(uuid? team-id)
|
||||
team-id
|
||||
|
||||
:else
|
||||
(:current-team-id state))
|
||||
params {:team-id team-id}]
|
||||
(rx/of (modal/hide)
|
||||
(rt/nav :dashboard-deleted params options))))))
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
[app.main.data.modal :as modal]
|
||||
[app.main.data.websocket :as dws]
|
||||
[app.main.repo :as rp]
|
||||
[app.main.store :as st]
|
||||
[app.util.i18n :as i18n :refer [tr]]
|
||||
[app.util.sse :as sse]
|
||||
[beicon.v2.core :as rx]
|
||||
@@ -76,7 +77,8 @@
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(reduce (fn [state {:keys [id] :as project}]
|
||||
(update-in state [:projects id] merge project))
|
||||
;; Replace completely instead of merge to ensure deleted-at is removed
|
||||
(assoc-in state [:projects id] project))
|
||||
state
|
||||
projects))))
|
||||
|
||||
@@ -152,6 +154,34 @@
|
||||
(->> (rp/cmd! :get-builtin-templates)
|
||||
(rx/map builtin-templates-fetched)))))
|
||||
|
||||
;; --- EVENT: deleted-files
|
||||
|
||||
(defn- deleted-files-fetched
|
||||
[files]
|
||||
(ptk/reify ::deleted-files-fetched
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [now (ct/now)
|
||||
filtered-files (filterv (fn [file]
|
||||
(let [will-be-deleted-at (:will-be-deleted-at file)]
|
||||
(or (nil? will-be-deleted-at)
|
||||
(ct/is-after? will-be-deleted-at now))))
|
||||
files)
|
||||
files (d/index-by :id filtered-files)]
|
||||
(-> state
|
||||
(assoc :deleted-files files)
|
||||
(update :files d/merge files))))))
|
||||
|
||||
(defn fetch-deleted-files
|
||||
([] (fetch-deleted-files nil))
|
||||
([team-id]
|
||||
(ptk/reify ::fetch-deleted-files
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(when-let [team-id (or team-id (:current-team-id state))]
|
||||
(->> (rp/cmd! :get-team-deleted-files {:team-id team-id})
|
||||
(rx/map deleted-files-fetched)))))))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Data Selection
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
@@ -460,6 +490,7 @@
|
||||
(-> state
|
||||
(d/update-in-when [:files file-id] assoc :thumbnail-id thumbnail-id)
|
||||
(d/update-in-when [:recent-files file-id] assoc :thumbnail-id thumbnail-id)
|
||||
(d/update-in-when [:deleted-files file-id] assoc :thumbnail-id thumbnail-id)
|
||||
(d/update-when :dashboard-search-result update-search-files))))))
|
||||
|
||||
;; --- EVENT: create-file
|
||||
@@ -656,3 +687,156 @@
|
||||
:team-role-change (handle-change-team-role msg)
|
||||
:team-membership-change (dcm/team-membership-change msg)
|
||||
nil))
|
||||
|
||||
|
||||
;; --- Delete files immediately
|
||||
|
||||
(defn delete-files-immediately
|
||||
[{:keys [team-id ids] :as params}]
|
||||
(assert (uuid? team-id))
|
||||
(assert (set? ids))
|
||||
(assert (every? uuid? ids))
|
||||
|
||||
(ptk/reify ::delete-files-immediately
|
||||
ev/Event
|
||||
(-data [_]
|
||||
{:team-id team-id
|
||||
:num-files (count ids)})
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [_ _ _]
|
||||
(let [{:keys [on-success on-error]
|
||||
:or {on-success identity
|
||||
on-error rx/throw}} (meta params)]
|
||||
(->> (rp/cmd! :permanently-delete-team-files {:team-id team-id :ids ids})
|
||||
(rx/tap on-success)
|
||||
(rx/catch on-error))))))
|
||||
|
||||
;; --- Restore deleted files immediately
|
||||
|
||||
(defn- initialize-restore-status
|
||||
[files]
|
||||
(ptk/reify ::init-restore-status
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [restore-state {:in-progress true
|
||||
:healthy? true
|
||||
:error false
|
||||
:progress 0
|
||||
:widget-visible true
|
||||
:detail-visible true
|
||||
:files files
|
||||
:last-update (ct/now)
|
||||
:cmd :restore-files}]
|
||||
(assoc state :restore restore-state)))))
|
||||
|
||||
(defn- update-restore-status
|
||||
[{:keys [index total] :as data}]
|
||||
(ptk/reify ::upd-restore-status
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [time-diff (ct/diff-ms (get-in state [:restore :last-update]) (ct/now))
|
||||
healthy? (< time-diff 6000)]
|
||||
(update state :restore assoc
|
||||
:progress index
|
||||
:total total
|
||||
:last-update (ct/now)
|
||||
:healthy? healthy?)))))
|
||||
|
||||
(defn- complete-restore-status
|
||||
[]
|
||||
(ptk/reify ::comp-restore-status
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [total (get-in state [:restore :total])]
|
||||
(update state :restore assoc
|
||||
:in-progress false
|
||||
:progress total ; Ensure progress equals total on completion
|
||||
:last-update (ct/now))))))
|
||||
|
||||
(defn- error-restore-status
|
||||
[error]
|
||||
(ptk/reify ::err-restore-status
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(update state :restore assoc
|
||||
:in-progress false
|
||||
:error error
|
||||
:last-update (ct/now)
|
||||
:healthy? false))))
|
||||
|
||||
(defn toggle-restore-detail-visibility
|
||||
[]
|
||||
(ptk/reify ::toggle-restore-detail
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(update-in state [:restore :detail-visible] not))))
|
||||
|
||||
(defn retry-last-restore
|
||||
[]
|
||||
(ptk/reify ::retry-restore
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
;; Reset restore state for retry - actual retry will be handled by UI
|
||||
(if (get state :restore)
|
||||
(update state :restore assoc :error false :in-progress false)
|
||||
state))))
|
||||
|
||||
(defn clear-restore-state
|
||||
[]
|
||||
(ptk/reify ::clear-restore
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(dissoc state :restore))))
|
||||
|
||||
(defn- projects-restored
|
||||
[team-id]
|
||||
(ptk/reify ::projects-restored
|
||||
ptk/WatchEvent
|
||||
(watch [_ _ _]
|
||||
;; Refetch projects to get the updated state without deleted-at
|
||||
(rx/of (fetch-projects team-id)))))
|
||||
|
||||
(defn restore-files-immediately
|
||||
[{:keys [team-id ids] :as params}]
|
||||
(dm/assert! (uuid? team-id))
|
||||
(dm/assert! (set? ids))
|
||||
(dm/assert! (every? uuid? ids))
|
||||
|
||||
(ptk/reify ::restore-files-immediately
|
||||
ev/Event
|
||||
(-data [_]
|
||||
{:team-id team-id
|
||||
:num-files (count ids)})
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [_ _ _]
|
||||
(let [{:keys [on-success on-error]
|
||||
:or {on-success identity
|
||||
on-error rx/throw}} (meta params)
|
||||
files (mapv #(hash-map :id %) ids)]
|
||||
|
||||
(rx/merge
|
||||
(rx/of (initialize-restore-status files))
|
||||
|
||||
(->> (rp/cmd! ::sse/restore-deleted-team-files {:team-id team-id :ids ids})
|
||||
(rx/tap (fn [event]
|
||||
(let [payload (sse/get-payload event)
|
||||
type (sse/get-type event)]
|
||||
(when (and payload (= type "progress"))
|
||||
(let [{:keys [index total]} payload]
|
||||
(when (and index total)
|
||||
;; Dispatch progress update
|
||||
(st/emit! (update-restore-status {:index index :total total}))))))))
|
||||
(rx/filter sse/end-of-stream?)
|
||||
(rx/map sse/get-payload)
|
||||
(rx/tap on-success)
|
||||
(rx/mapcat (fn [_]
|
||||
(rx/of (complete-restore-status)
|
||||
(projects-restored team-id))))
|
||||
(rx/catch (fn [error]
|
||||
(rx/concat
|
||||
(rx/of (error-restore-status (ex-message error)))
|
||||
(on-error error)))))
|
||||
|
||||
(rx/of (ptk/data-event ::restore-start {:total (count ids)})))))))
|
||||
|
||||
@@ -98,9 +98,7 @@
|
||||
(def context
|
||||
(atom (d/without-nils (collect-context))))
|
||||
|
||||
(add-watch i18n/state "events"
|
||||
(fn [_ _ _ v]
|
||||
(swap! context assoc :locale (get v :locale))))
|
||||
(add-watch i18n/locale "events" #(swap! context assoc :locale %4))
|
||||
|
||||
;; --- EVENT TRANSLATION
|
||||
|
||||
|
||||
@@ -270,8 +270,12 @@
|
||||
(ptk/reify ::process-wasm-object
|
||||
ptk/EffectEvent
|
||||
(effect [_ state _]
|
||||
(let [objects (dsh/lookup-page-objects state)]
|
||||
(wasm.api/process-object (get objects id))))))
|
||||
(let [objects (dsh/lookup-page-objects state)
|
||||
shape (get objects id)]
|
||||
;; Only process objects that exist in the current page
|
||||
;; This prevents errors when processing changes from other pages
|
||||
(when shape
|
||||
(wasm.api/process-object shape))))))
|
||||
|
||||
(defn initialize-workspace
|
||||
[team-id file-id]
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
[app.common.types.fills :as types.fills]
|
||||
[app.common.types.library :as ctl]
|
||||
[app.common.types.shape :as shp]
|
||||
[app.common.types.shape.shadow :refer [check-shadow]]
|
||||
[app.common.types.shape.shadow :as types.shadow]
|
||||
[app.common.types.text :as txt]
|
||||
[app.main.broadcast :as mbc]
|
||||
[app.main.data.helpers :as dsh]
|
||||
@@ -406,30 +406,30 @@
|
||||
|
||||
(defn change-shadow
|
||||
[ids attrs index]
|
||||
(ptk/reify ::change-shadow
|
||||
ptk/WatchEvent
|
||||
(watch [_ _ _]
|
||||
(rx/of (dwsh/update-shapes
|
||||
ids
|
||||
(fn [shape]
|
||||
(let [;; If we try to set a gradient to a shadow (for
|
||||
;; example using the color selection from
|
||||
;; multiple shapes) let's use the first stop
|
||||
;; color
|
||||
attrs (cond-> attrs
|
||||
(:gradient attrs)
|
||||
(dm/get-in [:gradient :stops 0]))
|
||||
(letfn [(update-shadow [shape]
|
||||
(let [;; If we try to set a gradient to a shadow (for
|
||||
;; example using the color selection from
|
||||
;; multiple shapes) let's use the first stop
|
||||
;; color
|
||||
attrs (cond-> attrs
|
||||
(:gradient attrs)
|
||||
(-> (dm/get-in [:gradient :stops 0])
|
||||
(select-keys types.shadow/color-attrs)))
|
||||
|
||||
attrs' (-> (dm/get-in shape [:shadow index :color])
|
||||
(merge attrs)
|
||||
(d/without-nils))]
|
||||
(assoc-in shape [:shadow index :color] attrs'))))))))
|
||||
attrs' (-> (dm/get-in shape [:shadow index :color])
|
||||
(merge attrs)
|
||||
(d/without-nils))]
|
||||
(assoc-in shape [:shadow index :color] attrs')))]
|
||||
(ptk/reify ::change-shadow
|
||||
ptk/WatchEvent
|
||||
(watch [_ _ _]
|
||||
(rx/of (dwsh/update-shapes ids update-shadow))))))
|
||||
|
||||
(defn add-shadow
|
||||
[ids shadow]
|
||||
|
||||
(assert
|
||||
(check-shadow shadow)
|
||||
(types.shadow/check-shadow shadow)
|
||||
"expected a valid shadow struct")
|
||||
|
||||
(assert
|
||||
@@ -1146,16 +1146,16 @@
|
||||
(defn- shadow->color-attr
|
||||
"Given a stroke map enriched with :shape-id, :index, and optionally
|
||||
:has-token-applied / :token-name, returns a color attribute map.
|
||||
|
||||
|
||||
If :has-token-applied is true, adds token metadata to :attrs:
|
||||
{:has-token-applied true
|
||||
:token-name <token-name>}
|
||||
|
||||
|
||||
Args:
|
||||
- stroke: map with stroke info, including :shape-id and :index
|
||||
- file-id: current file UUID
|
||||
- libraries: map of shared color libraries
|
||||
|
||||
|
||||
Returns:
|
||||
A map like:
|
||||
{:attrs {...color data...}
|
||||
@@ -1260,12 +1260,12 @@
|
||||
will include extra attributes in its :attrs map:
|
||||
{:has-token-applied true
|
||||
:token-name <token-name>}
|
||||
|
||||
|
||||
Args:
|
||||
- shapes: vector of shape maps
|
||||
- file-id: current file UUID
|
||||
- libraries: map of shared color libraries
|
||||
|
||||
|
||||
Returns:
|
||||
A vector of color attribute maps with metadata for each shape."
|
||||
[shapes file-id libraries]
|
||||
|
||||
@@ -636,3 +636,6 @@
|
||||
|
||||
(def persistence-state
|
||||
(l/derived (comp :status :persistence) st/state))
|
||||
|
||||
(def restore
|
||||
(l/derived :restore st/state))
|
||||
|
||||
@@ -87,6 +87,9 @@
|
||||
{:stream? true
|
||||
:form-data? true}
|
||||
|
||||
::sse/restore-deleted-team-files
|
||||
{:stream? true}
|
||||
|
||||
:export-binfile {:response-type :blob}
|
||||
:retrieve-list-of-builtin-templates {:query-params :all}})
|
||||
|
||||
|
||||
@@ -224,7 +224,8 @@
|
||||
:dashboard-members
|
||||
:dashboard-invitations
|
||||
:dashboard-webhooks
|
||||
:dashboard-settings)
|
||||
:dashboard-settings
|
||||
:dashboard-deleted)
|
||||
(let [params (get params :query)
|
||||
team-id (some-> params :team-id uuid/parse*)
|
||||
project-id (some-> params :project-id uuid/parse*)
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
[app.main.router :as rt]
|
||||
[app.main.store :as st]
|
||||
[app.main.ui.context :as ctx]
|
||||
[app.main.ui.dashboard.deleted :refer [deleted-section*]]
|
||||
[app.main.ui.dashboard.files :refer [files-section*]]
|
||||
[app.main.ui.dashboard.fonts :refer [fonts-page* font-providers-page*]]
|
||||
[app.main.ui.dashboard.import]
|
||||
@@ -29,6 +30,7 @@
|
||||
[app.main.ui.dashboard.sidebar :refer [sidebar*]]
|
||||
[app.main.ui.dashboard.team :refer [team-settings-page* team-members-page* team-invitations-page* webhooks-page*]]
|
||||
[app.main.ui.dashboard.templates :refer [templates-section*]]
|
||||
[app.main.ui.exports.assets :refer [progress-widget]]
|
||||
[app.main.ui.hooks :as hooks]
|
||||
[app.main.ui.modal :refer [modal-container*]]
|
||||
[app.main.ui.workspace.plugins]
|
||||
@@ -84,6 +86,9 @@
|
||||
[:div {:class (stl/css :dashboard-content)
|
||||
:on-click clear-selected-fn
|
||||
:ref container}
|
||||
|
||||
[:& progress-widget {:operation :restore}]
|
||||
|
||||
(case section
|
||||
:dashboard-recent
|
||||
(when (seq projects)
|
||||
@@ -140,6 +145,11 @@
|
||||
:dashboard-settings
|
||||
[:> team-settings-page* {:team team :profile profile}]
|
||||
|
||||
:dashboard-deleted
|
||||
[:> deleted-section* {:team team
|
||||
:projects projects
|
||||
:profile profile}]
|
||||
|
||||
nil)]))
|
||||
|
||||
(def ref:dashboard-initialized
|
||||
|
||||
331
frontend/src/app/main/ui/dashboard/deleted.cljs
Normal file
331
frontend/src/app/main/ui/dashboard/deleted.cljs
Normal file
@@ -0,0 +1,331 @@
|
||||
;; This Source Code Form is subject to the terms of the Mozilla Public
|
||||
;; License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
;;
|
||||
;; Copyright (c) KALEIDOS INC
|
||||
|
||||
(ns app.main.ui.dashboard.deleted
|
||||
(:require-macros [app.main.style :as stl])
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.geom.point :as gpt]
|
||||
[app.main.data.common :as dcm]
|
||||
[app.main.data.dashboard :as dd]
|
||||
[app.main.data.modal :as modal]
|
||||
[app.main.data.notifications :as ntf]
|
||||
[app.main.refs :as refs]
|
||||
[app.main.store :as st]
|
||||
[app.main.ui.components.context-menu-a11y :refer [context-menu*]]
|
||||
[app.main.ui.dashboard.grid :refer [grid*]]
|
||||
[app.main.ui.ds.buttons.button :refer [button*]]
|
||||
[app.main.ui.ds.product.empty-placeholder :refer [empty-placeholder*]]
|
||||
[app.main.ui.hooks :as hooks]
|
||||
[app.main.ui.icons :as deprecated-icon]
|
||||
[app.util.dom :as dom]
|
||||
[app.util.i18n :as i18n :refer [tr]]
|
||||
[app.util.keyboard :as kbd]
|
||||
[okulary.core :as l]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
|
||||
(def ^:private menu-icon
|
||||
(deprecated-icon/icon-xref :menu (stl/css :menu-icon)))
|
||||
|
||||
(mf/defc header*
|
||||
{::mf/props :obj
|
||||
::mf/private true}
|
||||
[]
|
||||
[:header {:class (stl/css :dashboard-header) :data-testid "dashboard-header"}
|
||||
[:div#dashboard-deleted-title {:class (stl/css :dashboard-title)}
|
||||
[:h1 (tr "dashboard.projects-title")]]])
|
||||
|
||||
(mf/defc deleted-project-menu*
|
||||
[{:keys [project files team-id show on-close top left]}]
|
||||
(let [top (d/nilv top 0)
|
||||
left (d/nilv left 0)
|
||||
|
||||
file-ids
|
||||
(mf/with-memo [files]
|
||||
(into #{} d/xf:map-id files))
|
||||
|
||||
restore-fn
|
||||
(fn [_]
|
||||
(st/emit! (dd/restore-files-immediately
|
||||
(with-meta {:team-id team-id :ids file-ids}
|
||||
{:on-success #(st/emit! (ntf/success (tr "restore-modal.success-restore-immediately" (:name project)))
|
||||
(dd/fetch-projects team-id)
|
||||
(dd/fetch-deleted-files team-id))
|
||||
:on-error #(st/emit! (ntf/error (tr "restore-modal.error-restore-project" (:name project))))}))))
|
||||
|
||||
on-restore-project
|
||||
(fn []
|
||||
(st/emit!
|
||||
(modal/show {:type :confirm
|
||||
:title (tr "restore-modal.restore-project.title")
|
||||
:message (tr "restore-modal.restore-project.description" (:name project))
|
||||
:accept-style :primary
|
||||
:accept-label (tr "labels.continue")
|
||||
:on-accept restore-fn})))
|
||||
|
||||
delete-fn
|
||||
(fn [_]
|
||||
(st/emit! (ntf/success (tr "delete-forever-modal.success-delete-immediately" (:name project)))
|
||||
(dd/delete-files-immediately
|
||||
{:team-id team-id
|
||||
:ids file-ids})
|
||||
(dd/fetch-projects team-id)
|
||||
(dd/fetch-deleted-files team-id)))
|
||||
|
||||
on-delete-project
|
||||
(fn []
|
||||
(st/emit!
|
||||
(modal/show {:type :confirm
|
||||
:title (tr "delete-forever-modal.title")
|
||||
:message (tr "delete-forever-modal.delete-project.description" (:name project))
|
||||
:accept-label (tr "dashboard.deleted.delete-forever")
|
||||
:on-accept delete-fn})))
|
||||
options
|
||||
[{:name (tr "dashboard.deleted.restore-project")
|
||||
:id "project-restore"
|
||||
:handler on-restore-project}
|
||||
{:name (tr "dashboard.deleted.delete-project")
|
||||
:id "project-delete"
|
||||
:handler on-delete-project}]]
|
||||
|
||||
[:> context-menu*
|
||||
{:on-close on-close
|
||||
:show show
|
||||
:fixed (or (not= top 0) (not= left 0))
|
||||
:min-width true
|
||||
:top top
|
||||
:left left
|
||||
:options options}]))
|
||||
|
||||
(mf/defc deleted-project-item*
|
||||
{::mf/props :obj
|
||||
::mf/private true}
|
||||
[{:keys [project team files]}]
|
||||
(let [project-files (filterv #(= (:project-id %) (:id project)) files)
|
||||
|
||||
empty? (empty? project-files)
|
||||
selected-files (mf/deref refs/selected-files)
|
||||
|
||||
dstate (mf/deref refs/dashboard-local)
|
||||
edit-id (:project-for-edit dstate)
|
||||
|
||||
local (mf/use-state
|
||||
#(do {:menu-open false
|
||||
:menu-pos nil
|
||||
:edition (= (:id project) edit-id)}))
|
||||
|
||||
[rowref limit] (hooks/use-dynamic-grid-item-width)
|
||||
|
||||
on-menu-click
|
||||
(mf/use-fn
|
||||
(fn [event]
|
||||
(dom/prevent-default event)
|
||||
|
||||
(let [client-position (dom/get-client-position event)
|
||||
position (if (and (nil? (:y client-position)) (nil? (:x client-position)))
|
||||
(let [target-element (dom/get-target event)
|
||||
points (dom/get-bounding-rect target-element)
|
||||
y (:top points)
|
||||
x (:left points)]
|
||||
(gpt/point x y))
|
||||
client-position)]
|
||||
(swap! local assoc
|
||||
:menu-open true
|
||||
:menu-pos position))))
|
||||
|
||||
on-menu-close
|
||||
(mf/use-fn #(swap! local assoc :menu-open false))
|
||||
|
||||
handle-menu-click
|
||||
(mf/use-callback
|
||||
(mf/deps on-menu-click)
|
||||
(fn [event]
|
||||
(when (kbd/enter? event)
|
||||
(dom/stop-propagation event)
|
||||
(on-menu-click event))))]
|
||||
|
||||
[:article {:class (stl/css-case :dashboard-project-row true)}
|
||||
[:header {:class (stl/css :project)}
|
||||
[:div {:class (stl/css :project-name-wrapper)}
|
||||
[:h2 {:class (stl/css :project-name)
|
||||
:title (:name project)}
|
||||
(:name project)]
|
||||
|
||||
(when (:deleted-at project)
|
||||
[:div {:class (stl/css :info-wrapper)}
|
||||
[:div {:class (stl/css-case :project-actions true)}
|
||||
|
||||
[:button {:class (stl/css :options-btn)
|
||||
:on-click on-menu-click
|
||||
:title (tr "dashboard.options")
|
||||
:aria-label (tr "dashboard.options")
|
||||
:data-testid "project-options"
|
||||
:on-key-down handle-menu-click}
|
||||
menu-icon]]
|
||||
|
||||
(when (:menu-open @local)
|
||||
[:> deleted-project-menu*
|
||||
{:project project
|
||||
:files project-files
|
||||
:team-id (:id team)
|
||||
:show (:menu-open @local)
|
||||
:left (+ 24 (:x (:menu-pos @local)))
|
||||
:top (:y (:menu-pos @local))
|
||||
:on-close on-menu-close}])])]]
|
||||
|
||||
[:div {:class (stl/css :grid-container) :ref rowref}
|
||||
(if ^boolean empty?
|
||||
[:> empty-placeholder* {:title (tr "dashboard.empty-placeholder-files-title")
|
||||
:class (stl/css :placeholder-placement)
|
||||
:type 1
|
||||
:subtitle (tr "dashboard.empty-placeholder-files-subtitle")}]
|
||||
|
||||
[:> grid*
|
||||
{:project project
|
||||
:files project-files
|
||||
:origin :deleted
|
||||
:can-edit false
|
||||
:can-restore true
|
||||
:limit limit
|
||||
:selected-files selected-files}])]]))
|
||||
|
||||
(def ^:private ref:deleted-files
|
||||
(l/derived :deleted-files st/state))
|
||||
|
||||
(mf/defc deleted-section*
|
||||
[{:keys [team projects]}]
|
||||
(let [deleted-map
|
||||
(mf/deref ref:deleted-files)
|
||||
|
||||
projects
|
||||
(mf/with-memo [projects deleted-map]
|
||||
(->> projects
|
||||
(filter (fn [project]
|
||||
(or (:deleted-at project)
|
||||
(when deleted-map
|
||||
(some #(= (:id project) (:project-id %))
|
||||
(vals deleted-map))))))
|
||||
(filter (fn [project]
|
||||
(when deleted-map
|
||||
(some #(= (:id project) (:project-id %))
|
||||
(vals deleted-map)))))
|
||||
(sort-by :modified-at)
|
||||
(reverse)))
|
||||
|
||||
team-id
|
||||
(get team :id)
|
||||
|
||||
;; Calculate deletion days based on team subscription
|
||||
deletion-days
|
||||
(let [subscription (get team :subscription)
|
||||
sub-type (get subscription :type)
|
||||
sub-status (get subscription :status)
|
||||
canceled? (contains? #{"canceled" "unpaid"} sub-status)]
|
||||
(cond
|
||||
(and (= "unlimited" sub-type) (not canceled?)) 30
|
||||
(and (= "enterprise" sub-type) (not canceled?)) 90
|
||||
:else 7))
|
||||
|
||||
on-clear
|
||||
(mf/use-fn
|
||||
(mf/deps team-id deleted-map)
|
||||
(fn []
|
||||
(when deleted-map
|
||||
(let [file-ids (into #{} (keys deleted-map))]
|
||||
(when (seq file-ids)
|
||||
(st/emit!
|
||||
(modal/show {:type :confirm
|
||||
:title (tr "delete-forever-modal.title")
|
||||
:message (tr "delete-forever-modal.delete-all.description" (count file-ids))
|
||||
:accept-label (tr "dashboard.deleted.delete-forever")
|
||||
:on-accept #(st/emit!
|
||||
(dd/delete-files-immediately
|
||||
{:team-id team-id
|
||||
:ids file-ids})
|
||||
(dd/fetch-projects team-id)
|
||||
(dd/fetch-deleted-files team-id))})))))))
|
||||
|
||||
restore-fn
|
||||
(fn [file-ids]
|
||||
(st/emit! (dd/restore-files-immediately
|
||||
(with-meta {:team-id team-id :ids file-ids}
|
||||
{:on-success #(st/emit! (dd/fetch-projects team-id)
|
||||
(dd/fetch-deleted-files team-id))
|
||||
:on-error #(st/emit! (ntf/error (tr "restore-modal.error-restore-files")))}))))
|
||||
|
||||
on-restore-all
|
||||
(mf/use-fn
|
||||
(mf/deps team-id deleted-map)
|
||||
(fn []
|
||||
(when deleted-map
|
||||
(let [file-ids (into #{} (keys deleted-map))]
|
||||
(when (seq file-ids)
|
||||
(st/emit!
|
||||
(modal/show {:type :confirm
|
||||
:title (tr "restore-modal.restore-all.title")
|
||||
:message (tr "restore-modal.restore-all.description" (count file-ids))
|
||||
:accept-label (tr "labels.continue")
|
||||
:accept-style :primary
|
||||
:on-accept #(restore-fn file-ids)})))))))
|
||||
|
||||
on-recent-click
|
||||
(mf/use-fn
|
||||
(mf/deps team-id)
|
||||
(fn []
|
||||
(st/emit! (dcm/go-to-dashboard-recent :team-id team-id))))]
|
||||
|
||||
(mf/with-effect [team-id]
|
||||
(st/emit! (dd/fetch-projects team-id)
|
||||
(dd/fetch-deleted-files team-id)
|
||||
(dd/clear-selected-files)))
|
||||
|
||||
[:*
|
||||
[:> header* {:team team}]
|
||||
[:section {:class (stl/css :dashboard-container :no-bg)}
|
||||
[:*
|
||||
[:div {:class (stl/css :no-bg)}
|
||||
|
||||
[:div {:class (stl/css :nav-options)}
|
||||
[:> button* {:variant "ghost"
|
||||
:data-testid "recent-tab"
|
||||
:type "button"
|
||||
:on-click on-recent-click}
|
||||
(tr "dashboard.labels.recent")]
|
||||
[:div {:class (stl/css :selected)
|
||||
:data-testid "deleted-tab"}
|
||||
(tr "dashboard.labels.deleted")]]
|
||||
|
||||
[:div {:class (stl/css :deleted-content)}
|
||||
[:div {:class (stl/css :deleted-info)}
|
||||
[:div
|
||||
(tr "dashboard.deleted.info-text")
|
||||
[:span {:class (stl/css :info-text-highlight)}
|
||||
(tr "dashboard.deleted.info-days" deletion-days)]
|
||||
(tr "dashboard.deleted.info-text2")]
|
||||
[:div
|
||||
(tr "dashboard.deleted.restore-text")]]
|
||||
[:div {:class (stl/css :deleted-options)}
|
||||
[:> button* {:variant "ghost"
|
||||
:type "button"
|
||||
:on-click on-restore-all}
|
||||
(tr "dashboard.deleted.restore-all")]
|
||||
[:> button* {:variant "destructive"
|
||||
:type "button"
|
||||
:icon "delete"
|
||||
:on-click on-clear}
|
||||
(tr "dashboard.deleted.clear")]]]
|
||||
|
||||
(when (seq projects)
|
||||
(for [{:keys [id] :as project} projects]
|
||||
(let [files (when deleted-map
|
||||
(->> (vals deleted-map)
|
||||
(filterv #(= id (:project-id %)))
|
||||
(sort-by :modified-at #(compare %2 %1))))]
|
||||
[:> deleted-project-item* {:project project
|
||||
:team team
|
||||
:files files
|
||||
:key id}])))]]]]))
|
||||
125
frontend/src/app/main/ui/dashboard/deleted.scss
Normal file
125
frontend/src/app/main/ui/dashboard/deleted.scss
Normal file
@@ -0,0 +1,125 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
//
|
||||
// Copyright (c) KALEIDOS INC
|
||||
|
||||
@use "common/refactor/common-dashboard";
|
||||
@use "../ds/typography.scss" as t;
|
||||
@use "../ds/_borders.scss" as *;
|
||||
@use "../ds/spacing.scss" as *;
|
||||
@use "../ds/_sizes.scss" as *;
|
||||
@use "../ds/z-index.scss" as *;
|
||||
|
||||
.dashboard-container {
|
||||
flex: 1 0 0;
|
||||
width: 100%;
|
||||
margin-inline-end: var(--sp-l);
|
||||
border-top: $b-1 solid var(--panel-border-color);
|
||||
overflow-y: auto;
|
||||
padding-block-end: var(--sp-xxxl);
|
||||
}
|
||||
|
||||
.deleted-content {
|
||||
display: flex;
|
||||
gap: var(--sp-l);
|
||||
justify-content: space-between;
|
||||
margin-inline-start: var(--sp-l);
|
||||
margin-block-start: var(--sp-xxl);
|
||||
}
|
||||
|
||||
.deleted-info {
|
||||
@include t.use-typography("body-medium");
|
||||
color: var(--color-foreground-secondary);
|
||||
}
|
||||
|
||||
.info-text-highlight {
|
||||
color: var(--color-accent-primary);
|
||||
}
|
||||
|
||||
.deleted-options {
|
||||
display: flex;
|
||||
gap: 5px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.nav-options {
|
||||
display: flex;
|
||||
gap: var(--sp-l);
|
||||
justify-content: space-between;
|
||||
border-bottom: $b-1 solid var(--panel-border-color);
|
||||
padding-inline-start: var(--sp-l);
|
||||
background: var(--color-background-default);
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: var(--z-index-panels);
|
||||
}
|
||||
|
||||
.selected {
|
||||
@include t.use-typography("headline-small");
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: var(--color-foreground-primary);
|
||||
border: $b-1 solid transparent;
|
||||
border-bottom: $b-1 solid var(--color-foreground-primary);
|
||||
padding: 0 var(--sp-m);
|
||||
}
|
||||
|
||||
.project {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: var(--sp-s);
|
||||
width: 99%;
|
||||
max-height: $sz-40;
|
||||
padding: var(--sp-s) var(--sp-s) var(--sp-s) var(--sp-l);
|
||||
margin-block-start: var(--sp-l);
|
||||
border-radius: $br-4;
|
||||
}
|
||||
|
||||
.project-name-wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
width: 100%;
|
||||
min-height: var(--sp-xxxl);
|
||||
margin-inline-start: var(--sp-s);
|
||||
}
|
||||
|
||||
.project-name {
|
||||
@include t.use-typography("body-large");
|
||||
width: fit-content;
|
||||
margin-inline-end: var(--sp-m);
|
||||
line-height: 0.8;
|
||||
color: var(--title-foreground-color-hover);
|
||||
height: var(--sp-l);
|
||||
}
|
||||
|
||||
.project-actions {
|
||||
display: flex;
|
||||
opacity: var(--actions-opacity);
|
||||
margin-inline-start: var(--sp-xxxl);
|
||||
}
|
||||
|
||||
.add-file-btn,
|
||||
.options-btn {
|
||||
@extend .button-tertiary;
|
||||
height: var(--sp-xxxl);
|
||||
width: var(--sp-xxxl);
|
||||
margin: 0 var(--sp-s);
|
||||
padding: var(--sp-s);
|
||||
}
|
||||
|
||||
.info-wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--sp-s);
|
||||
}
|
||||
|
||||
.add-icon,
|
||||
.menu-icon {
|
||||
@extend .button-icon;
|
||||
stroke: var(--icon-foreground);
|
||||
}
|
||||
@@ -55,7 +55,7 @@
|
||||
projects))
|
||||
|
||||
(mf/defc file-menu*
|
||||
[{:keys [files on-edit on-close top left navigate origin parent-id can-edit]}]
|
||||
[{:keys [files on-edit on-close top left navigate origin parent-id can-edit can-restore]}]
|
||||
|
||||
(assert (seq files) "missing `files` prop")
|
||||
(assert (fn? on-edit) "missing `on-edit` prop")
|
||||
@@ -187,7 +187,46 @@
|
||||
on-export-binary-files
|
||||
(fn []
|
||||
(st/emit! (-> (fexp/open-export-dialog files)
|
||||
(with-meta {::ev/origin "dashboard"}))))]
|
||||
(with-meta {::ev/origin "dashboard"}))))
|
||||
|
||||
restore-fn
|
||||
(fn [_]
|
||||
(st/emit! (dd/restore-files-immediately
|
||||
(with-meta {:team-id (:id current-team)
|
||||
:ids #{(:id file)}}
|
||||
{:on-success #(st/emit! (ntf/success (tr "restore-modal.success-restore-immediately" (:name file)))
|
||||
(dd/fetch-projects (:id current-team))
|
||||
(dd/fetch-deleted-files (:id current-team)))
|
||||
:on-error #(st/emit! (ntf/error (tr "restore-modal.error-restore-file" (:name file))))}))))
|
||||
|
||||
on-restore-immediately
|
||||
(fn []
|
||||
(st/emit!
|
||||
(modal/show {:type :confirm
|
||||
:title (tr "restore-modal.restore-file.title")
|
||||
:message (tr "restore-modal.restore-file.description" (:name file))
|
||||
:accept-label (tr "labels.continue")
|
||||
:accept-style :primary
|
||||
:on-accept restore-fn})))
|
||||
|
||||
|
||||
delete-fn
|
||||
(fn [_]
|
||||
(st/emit! (ntf/success (tr "delete-forever-modal.success-delete-immediately" (:name file)))
|
||||
(dd/delete-files-immediately
|
||||
{:team-id (:id current-team)
|
||||
:ids #{(:id file)}})
|
||||
(dd/fetch-projects (:id current-team))
|
||||
(dd/fetch-deleted-files (:id current-team))))
|
||||
|
||||
on-delete-immediately
|
||||
(fn []
|
||||
(st/emit!
|
||||
(modal/show {:type :confirm
|
||||
:title (tr "delete-forever-modal.title")
|
||||
:message (tr "delete-forever-modal.delete-file.description" (:name file))
|
||||
:accept-label (tr "delete-forever-modal.title")
|
||||
:on-accept delete-fn})))]
|
||||
|
||||
(mf/with-effect []
|
||||
(->> (rp/cmd! :get-all-projects)
|
||||
@@ -227,76 +266,85 @@
|
||||
(:id sub-project))})})}]))
|
||||
|
||||
options
|
||||
(if multi?
|
||||
[(when can-edit
|
||||
{:name (tr "dashboard.duplicate-multi" file-count)
|
||||
:id "duplicate-multi"
|
||||
:handler on-duplicate})
|
||||
(if can-restore
|
||||
[(when can-restore
|
||||
{:name (tr "dashboard.restore-file")
|
||||
:id "restore-file"
|
||||
:handler on-restore-immediately})
|
||||
(when can-restore
|
||||
{:name (tr "dashboard.delete-file")
|
||||
:id "delete-file"
|
||||
:handler on-delete-immediately})]
|
||||
(if multi?
|
||||
[(when can-edit
|
||||
{:name (tr "dashboard.duplicate-multi" file-count)
|
||||
:id "duplicate-multi"
|
||||
:handler on-duplicate})
|
||||
|
||||
(when (and (or (seq current-projects) (seq other-teams)) can-edit)
|
||||
{:name (tr "dashboard.move-to-multi" file-count)
|
||||
:id "file-move-multi"
|
||||
:options sub-options})
|
||||
(when (and (or (seq current-projects) (seq other-teams)) can-edit)
|
||||
{:name (tr "dashboard.move-to-multi" file-count)
|
||||
:id "file-move-multi"
|
||||
:options sub-options})
|
||||
|
||||
{:name (tr "dashboard.export-binary-multi" file-count)
|
||||
:id "file-binary-export-multi"
|
||||
:handler on-export-binary-files}
|
||||
{:name (tr "dashboard.export-binary-multi" file-count)
|
||||
:id "file-binary-export-multi"
|
||||
:handler on-export-binary-files}
|
||||
|
||||
(when (and (:is-shared file) can-edit)
|
||||
{:name (tr "labels.unpublish-multi-files" file-count)
|
||||
:id "file-unpublish-multi"
|
||||
:handler on-del-shared})
|
||||
(when (and (:is-shared file) can-edit)
|
||||
{:name (tr "labels.unpublish-multi-files" file-count)
|
||||
:id "file-unpublish-multi"
|
||||
:handler on-del-shared})
|
||||
|
||||
(when (and (not is-lib-page?) can-edit)
|
||||
{:name :separator}
|
||||
{:name (tr "labels.delete-multi-files" file-count)
|
||||
:id "file-delete-multi"
|
||||
:handler on-delete})]
|
||||
(when (and (not is-lib-page?) can-edit)
|
||||
{:name :separator}
|
||||
{:name (tr "labels.delete-multi-files" file-count)
|
||||
:id "file-delete-multi"
|
||||
:handler on-delete})]
|
||||
|
||||
[{:name (tr "dashboard.open-in-new-tab")
|
||||
:id "file-open-new-tab"
|
||||
:handler on-new-tab}
|
||||
(when (and (not is-search-page?) can-edit)
|
||||
{:name (tr "labels.rename")
|
||||
:id "file-rename"
|
||||
:handler on-edit})
|
||||
[{:name (tr "dashboard.open-in-new-tab")
|
||||
:id "file-open-new-tab"
|
||||
:handler on-new-tab}
|
||||
(when (and (not is-search-page?) can-edit)
|
||||
{:name (tr "labels.rename")
|
||||
:id "file-rename"
|
||||
:handler on-edit})
|
||||
|
||||
(when (and (not is-search-page?) can-edit)
|
||||
{:name (tr "dashboard.duplicate")
|
||||
:id "file-duplicate"
|
||||
:handler on-duplicate})
|
||||
(when (and (not is-search-page?) can-edit)
|
||||
{:name (tr "dashboard.duplicate")
|
||||
:id "file-duplicate"
|
||||
:handler on-duplicate})
|
||||
|
||||
(when (and (not is-lib-page?)
|
||||
(not is-search-page?)
|
||||
(or (seq current-projects) (seq other-teams))
|
||||
can-edit)
|
||||
{:name (tr "dashboard.move-to")
|
||||
:id "file-move-to"
|
||||
:options sub-options})
|
||||
(when (and (not is-lib-page?)
|
||||
(not is-search-page?)
|
||||
(or (seq current-projects) (seq other-teams))
|
||||
can-edit)
|
||||
{:name (tr "dashboard.move-to")
|
||||
:id "file-move-to"
|
||||
:options sub-options})
|
||||
|
||||
(when (and (not is-search-page?)
|
||||
can-edit)
|
||||
(if (:is-shared file)
|
||||
{:name (tr "dashboard.unpublish-shared")
|
||||
:id "file-del-shared"
|
||||
:handler on-del-shared}
|
||||
{:name (tr "dashboard.add-shared")
|
||||
:id "file-add-shared"
|
||||
:handler on-add-shared}))
|
||||
(when (and (not is-search-page?)
|
||||
can-edit)
|
||||
(if (:is-shared file)
|
||||
{:name (tr "dashboard.unpublish-shared")
|
||||
:id "file-del-shared"
|
||||
:handler on-del-shared}
|
||||
{:name (tr "dashboard.add-shared")
|
||||
:id "file-add-shared"
|
||||
:handler on-add-shared}))
|
||||
|
||||
{:name :separator}
|
||||
{:name :separator}
|
||||
|
||||
{:name (tr "dashboard.download-binary-file")
|
||||
:id "download-binary-file"
|
||||
:handler on-export-binary-files}
|
||||
{:name (tr "dashboard.download-binary-file")
|
||||
:id "download-binary-file"
|
||||
:handler on-export-binary-files}
|
||||
|
||||
(when (and (not is-lib-page?) (not is-search-page?) can-edit)
|
||||
{:name :separator})
|
||||
(when (and (not is-lib-page?) (not is-search-page?) can-edit)
|
||||
{:name :separator})
|
||||
|
||||
(when (and (not is-lib-page?) (not is-search-page?) can-edit)
|
||||
{:name (tr "labels.delete")
|
||||
:id "file-delete"
|
||||
:handler on-delete})])]
|
||||
(when (and (not is-lib-page?) (not is-search-page?) can-edit)
|
||||
{:name (tr "labels.delete")
|
||||
:id "file-delete"
|
||||
:handler on-delete})]))]
|
||||
|
||||
[:> context-menu*
|
||||
{:on-close on-close
|
||||
|
||||
@@ -86,7 +86,7 @@
|
||||
(mf/defc grid-item-thumbnail*
|
||||
{::mf/props :obj
|
||||
::mf/private true}
|
||||
[{:keys [can-edit file]}]
|
||||
[{:keys [can-edit file can-restore]}]
|
||||
(let [file-id (get file :id)
|
||||
revn (get file :revn)
|
||||
thumbnail-id (get file :thumbnail-id)
|
||||
@@ -109,7 +109,8 @@
|
||||
:message (ex-message cause)))))]
|
||||
(partial rx/dispose! subscription))))
|
||||
|
||||
[:div {:class (stl/css :grid-item-th)
|
||||
[:div {:class (stl/css-case :grid-item-th true
|
||||
:deleted-item can-restore)
|
||||
:style {:background-color bg-color}
|
||||
:ref container}
|
||||
(when visible?
|
||||
@@ -131,13 +132,15 @@
|
||||
|
||||
(mf/defc grid-item-library*
|
||||
{::mf/props :obj}
|
||||
[{:keys [file]}]
|
||||
[{:keys [file can-restore]}]
|
||||
(mf/with-effect [file]
|
||||
(when file
|
||||
(let [font-ids (map :font-id (get-in file [:library-summary :typographies :sample] []))]
|
||||
(run! fonts/ensure-loaded! font-ids))))
|
||||
|
||||
[:div {:class (stl/css :grid-item-th :library)}
|
||||
[:div {:class (stl/css-case :grid-item-th true
|
||||
:library true
|
||||
:deleted-item can-restore)}
|
||||
(if (nil? file)
|
||||
[:> loader* {:class (stl/css :grid-loader)
|
||||
:overlay true
|
||||
@@ -250,7 +253,7 @@
|
||||
counter-el))
|
||||
|
||||
(mf/defc grid-item*
|
||||
[{:keys [file origin can-edit selected-files]}]
|
||||
[{:keys [file origin can-edit selected-files can-restore]}]
|
||||
(let [file-id (get file :id)
|
||||
state (mf/deref refs/dashboard-local)
|
||||
|
||||
@@ -289,12 +292,13 @@
|
||||
|
||||
on-navigate
|
||||
(mf/use-fn
|
||||
(mf/deps file-id)
|
||||
(mf/deps file-id can-restore)
|
||||
(fn [event]
|
||||
(let [menu-icon (mf/ref-val menu-ref)
|
||||
target (dom/get-target event)]
|
||||
(when-not (dom/child? target menu-icon)
|
||||
(st/emit! (dcm/go-to-workspace :file-id file-id))))))
|
||||
(when-not can-restore
|
||||
(let [menu-icon (mf/ref-val menu-ref)
|
||||
target (dom/get-target event)]
|
||||
(when-not (dom/child? target menu-icon)
|
||||
(st/emit! (dcm/go-to-workspace :file-id file-id)))))))
|
||||
|
||||
on-drag-start
|
||||
(mf/use-fn
|
||||
@@ -412,8 +416,8 @@
|
||||
[:div {:class (stl/css :overlay)}]
|
||||
|
||||
(if ^boolean is-library-view?
|
||||
[:> grid-item-library* {:file file}]
|
||||
[:> grid-item-thumbnail* {:file file :can-edit can-edit}])
|
||||
[:> grid-item-library* {:file file :can-restore can-restore}]
|
||||
[:> grid-item-thumbnail* {:file file :can-edit can-edit :can-restore can-restore}])
|
||||
|
||||
(when (and (:is-shared file) (not is-library-view?))
|
||||
[:div {:class (stl/css :item-badge)} deprecated-icon/library])
|
||||
@@ -451,11 +455,12 @@
|
||||
:on-edit on-edit
|
||||
:on-close on-menu-close
|
||||
:origin origin
|
||||
:parent-id (dm/str file-id "-action-menu")}]])]]]]]))
|
||||
:parent-id (dm/str file-id "-action-menu")
|
||||
:can-restore can-restore}]])]]]]]))
|
||||
|
||||
(mf/defc grid*
|
||||
{::mf/props :obj}
|
||||
[{:keys [files project origin limit create-fn can-edit selected-files]}]
|
||||
[{:keys [files project origin limit create-fn can-edit selected-files can-restore]}]
|
||||
(let [dragging? (mf/use-state false)
|
||||
project-id (get project :id)
|
||||
team-id (get project :team-id)
|
||||
@@ -535,7 +540,8 @@
|
||||
:key (dm/str (:id item))
|
||||
:origin origin
|
||||
:selected-files selected-files
|
||||
:can-edit can-edit}])])
|
||||
:can-edit can-edit
|
||||
:can-restore can-restore}])])
|
||||
|
||||
:else
|
||||
[:> empty-grid-placeholder*
|
||||
@@ -548,7 +554,7 @@
|
||||
:on-finish-import on-finish-import}])]))
|
||||
|
||||
(mf/defc line-grid-row
|
||||
[{:keys [files selected-files dragging? limit can-edit] :as props}]
|
||||
[{:keys [files selected-files dragging? limit can-edit can-restore] :as props}]
|
||||
(let [elements limit
|
||||
limit (if dragging? (dec limit) limit)]
|
||||
[:ul {:class (stl/css :grid-row :no-wrap)
|
||||
@@ -563,10 +569,11 @@
|
||||
:file item
|
||||
:selected-files selected-files
|
||||
:can-edit can-edit
|
||||
:key (dm/str (:id item))}])]))
|
||||
:key (dm/str (:id item))
|
||||
:can-restore can-restore}])]))
|
||||
|
||||
(mf/defc line-grid
|
||||
[{:keys [project team files limit create-fn can-edit] :as props}]
|
||||
[{:keys [project team files limit create-fn can-edit can-restore] :as props}]
|
||||
(let [dragging? (mf/use-state false)
|
||||
project-id (:id project)
|
||||
team-id (:id team)
|
||||
@@ -664,7 +671,8 @@
|
||||
:selected-files selected-files
|
||||
:dragging? @dragging?
|
||||
:can-edit can-edit
|
||||
:limit limit}]
|
||||
:limit limit
|
||||
:can-restore can-restore}]
|
||||
|
||||
:else
|
||||
[:> empty-grid-placeholder*
|
||||
|
||||
@@ -375,3 +375,7 @@ $thumbnail-default-height: deprecated.$s-168; // Default width
|
||||
.grid-loader {
|
||||
--icon-width: calc(var(--th-width, #{$thumbnail-default-width}) * 0.25);
|
||||
}
|
||||
|
||||
.deleted-item {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
[app.main.ui.dashboard.inline-edition :refer [inline-edition]]
|
||||
[app.main.ui.dashboard.pin-button :refer [pin-button*]]
|
||||
[app.main.ui.dashboard.project-menu :refer [project-menu*]]
|
||||
[app.main.ui.ds.buttons.button :refer [button*]]
|
||||
[app.main.ui.ds.product.empty-placeholder :refer [empty-placeholder*]]
|
||||
[app.main.ui.hooks :as hooks]
|
||||
[app.main.ui.icons :as deprecated-icon]
|
||||
@@ -342,7 +343,13 @@
|
||||
(fn []
|
||||
(reset! show-team-hero* false)
|
||||
(st/emit! (ptk/data-event ::ev/event {::ev/name "dont-show-team-up-hero"
|
||||
::ev/origin "dashboard"}))))]
|
||||
::ev/origin "dashboard"}))))
|
||||
|
||||
on-deleted-click
|
||||
(mf/use-fn
|
||||
(mf/deps team-id)
|
||||
(fn []
|
||||
(st/emit! (dcm/go-to-dashboard-deleted :team-id team-id))))]
|
||||
|
||||
(mf/with-effect [show-team-hero?]
|
||||
(swap! storage/global assoc ::show-team-hero show-team-hero?))
|
||||
@@ -376,6 +383,15 @@
|
||||
(not is-defalt-team?)
|
||||
show-team-hero?
|
||||
can-invite))}
|
||||
[:div {:class (stl/css :nav-options)}
|
||||
[:div {:class (stl/css :selected)
|
||||
:data-testid "recent-tab"}
|
||||
(tr "dashboard.labels.recent")]
|
||||
[:> button* {:variant "ghost"
|
||||
:type "button"
|
||||
:data-testid "deleted-tab"
|
||||
:on-click on-deleted-click}
|
||||
(tr "dashboard.labels.deleted")]]
|
||||
(for [{:keys [id] :as project} projects]
|
||||
;; FIXME: refactor this, looks inneficient
|
||||
(let [files (when recent-map
|
||||
|
||||
@@ -4,16 +4,21 @@
|
||||
//
|
||||
// Copyright (c) KALEIDOS INC
|
||||
|
||||
@use "refactor/common-refactor.scss" as deprecated;
|
||||
@use "common/refactor/common-refactor.scss" as deprecated;
|
||||
@use "common/refactor/common-dashboard";
|
||||
@use "../ds/typography.scss" as t;
|
||||
@use "../ds/_borders.scss" as *;
|
||||
@use "../ds/spacing.scss" as *;
|
||||
@use "../ds/_sizes.scss" as *;
|
||||
@use "../ds/z-index.scss" as *;
|
||||
|
||||
.dashboard-container {
|
||||
flex: 1 0 0;
|
||||
width: 100%;
|
||||
margin-right: deprecated.$s-16;
|
||||
border-top: deprecated.$s-1 solid var(--panel-border-color);
|
||||
margin-inline-end: var(--sp-l);
|
||||
border-top: $b-1 solid var(--panel-border-color);
|
||||
overflow-y: auto;
|
||||
padding-bottom: deprecated.$s-32;
|
||||
padding-bottom: var(--sp-xxxl);
|
||||
}
|
||||
|
||||
.dashboard-projects {
|
||||
@@ -27,16 +32,16 @@
|
||||
|
||||
.dashboard-shared {
|
||||
width: calc(100vw - deprecated.$s-320);
|
||||
margin-right: deprecated.$s-52;
|
||||
margin-inline-end: deprecated.$s-52;
|
||||
}
|
||||
|
||||
.search {
|
||||
margin-top: deprecated.$s-12;
|
||||
margin-block-start: var(--sp-m);
|
||||
}
|
||||
|
||||
.dashboard-project-row {
|
||||
--actions-opacity: 0;
|
||||
margin-bottom: deprecated.$s-24;
|
||||
margin-block-end: var(--sp-xxl);
|
||||
position: relative;
|
||||
|
||||
&:hover,
|
||||
@@ -60,12 +65,12 @@
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: deprecated.$s-8;
|
||||
gap: var(--sp-s);
|
||||
width: 99%;
|
||||
max-height: deprecated.$s-40;
|
||||
padding: deprecated.$s-8 deprecated.$s-8 deprecated.$s-8 deprecated.$s-16;
|
||||
margin-top: deprecated.$s-16;
|
||||
border-radius: deprecated.$br-4;
|
||||
max-height: $sz-40;
|
||||
padding: var(--sp-s) var(--sp-s) var(--sp-s) var(--sp-l);
|
||||
margin-block-start: var(--sp-l);
|
||||
border-radius: $br-4;
|
||||
}
|
||||
|
||||
.project-name-wrapper {
|
||||
@@ -73,30 +78,29 @@
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
width: 100%;
|
||||
min-height: deprecated.$s-32;
|
||||
margin-left: deprecated.$s-8;
|
||||
min-height: var(--sp-xxxl);
|
||||
margin-inline-start: var(--sp-s);
|
||||
}
|
||||
|
||||
.project-name {
|
||||
@include deprecated.bodyLargeTypography;
|
||||
@include deprecated.textEllipsis;
|
||||
@include t.use-typography("body-large");
|
||||
width: fit-content;
|
||||
margin-right: deprecated.$s-12;
|
||||
margin-inline-end: var(--sp-m);
|
||||
line-height: 0.8;
|
||||
color: var(--title-foreground-color-hover);
|
||||
cursor: pointer;
|
||||
height: deprecated.$s-16;
|
||||
height: var(--sp-l);
|
||||
}
|
||||
|
||||
.info-wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: deprecated.$s-8;
|
||||
gap: var(--sp-s);
|
||||
}
|
||||
|
||||
.info,
|
||||
.recent-files-row-title-info {
|
||||
@include deprecated.bodyMediumTypography;
|
||||
@include t.use-typography("body-medium");
|
||||
color: var(--title-foreground-color);
|
||||
@media (max-width: 760px) {
|
||||
display: none;
|
||||
@@ -106,16 +110,16 @@
|
||||
.project-actions {
|
||||
display: flex;
|
||||
opacity: var(--actions-opacity);
|
||||
margin-left: deprecated.$s-32;
|
||||
margin-inline-start: var(--sp-xxxl);
|
||||
}
|
||||
|
||||
.add-file-btn,
|
||||
.options-btn {
|
||||
@extend .button-tertiary;
|
||||
height: deprecated.$s-32;
|
||||
width: deprecated.$s-32;
|
||||
margin: 0 deprecated.$s-8;
|
||||
padding: deprecated.$s-8;
|
||||
height: var(--sp-xxxl);
|
||||
width: var(--sp-xxxl);
|
||||
margin: 0 var(--sp-s);
|
||||
padding: var(--sp-s);
|
||||
}
|
||||
|
||||
.add-icon,
|
||||
@@ -126,24 +130,24 @@
|
||||
|
||||
.grid-container {
|
||||
width: 100%;
|
||||
padding: 0 deprecated.$s-4;
|
||||
padding: 0 var(--sp-xs);
|
||||
}
|
||||
|
||||
.placeholder-placement {
|
||||
margin: deprecated.$s-16 deprecated.$s-32;
|
||||
margin: var(--sp-l) var(--sp-xxxl);
|
||||
}
|
||||
|
||||
.show-more {
|
||||
--show-more-color: var(--button-secondary-foreground-color-rest);
|
||||
@include deprecated.buttonStyle;
|
||||
@include deprecated.bodyMediumTypography;
|
||||
@include t.use-typography("body-medium");
|
||||
position: absolute;
|
||||
top: deprecated.$s-8;
|
||||
top: var(--sp-s);
|
||||
right: deprecated.$s-52;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
column-gap: deprecated.$s-12;
|
||||
column-gap: var(--sp-m);
|
||||
color: var(--show-more-color);
|
||||
|
||||
&:hover {
|
||||
@@ -152,8 +156,8 @@
|
||||
}
|
||||
|
||||
.show-more-icon {
|
||||
height: deprecated.$s-16;
|
||||
width: deprecated.$s-16;
|
||||
height: var(--sp-l);
|
||||
width: var(--sp-l);
|
||||
fill: none;
|
||||
stroke: var(--show-more-color);
|
||||
}
|
||||
@@ -164,13 +168,13 @@
|
||||
border-radius: deprecated.$br-8;
|
||||
border: none;
|
||||
display: flex;
|
||||
margin: deprecated.$s-16;
|
||||
padding: deprecated.$s-8;
|
||||
margin: var(--sp-l);
|
||||
padding: var(--sp-s);
|
||||
position: relative;
|
||||
|
||||
img {
|
||||
border-radius: deprecated.$br-4;
|
||||
height: deprecated.$s-200;
|
||||
border-radius: $br-4;
|
||||
height: var(--sp-xl) 0;
|
||||
width: auto;
|
||||
|
||||
@media (max-width: 1200px) {
|
||||
@@ -185,18 +189,18 @@
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
flex-grow: 1;
|
||||
padding: deprecated.$s-20 deprecated.$s-20;
|
||||
padding: var(--sp-xl) var(--sp-xl);
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: deprecated.$fs-24;
|
||||
font-size: $sz-24;
|
||||
color: var(--color-foreground-primary);
|
||||
font-weight: deprecated.$fw400;
|
||||
}
|
||||
|
||||
.info {
|
||||
flex: 1;
|
||||
font-size: deprecated.$fs-16;
|
||||
font-size: $sz-16;
|
||||
span {
|
||||
color: var(--color-foreground-secondary);
|
||||
display: block;
|
||||
@@ -204,15 +208,15 @@
|
||||
a {
|
||||
color: var(--color-accent-primary);
|
||||
}
|
||||
padding: deprecated.$s-8 0;
|
||||
padding: var(--sp-s) 0;
|
||||
}
|
||||
|
||||
.close {
|
||||
--close-icon-foreground-color: var(--icon-foreground);
|
||||
position: absolute;
|
||||
top: deprecated.$s-20;
|
||||
right: deprecated.$s-24;
|
||||
width: deprecated.$s-24;
|
||||
top: var(--sp-xl);
|
||||
right: var(--sp-xxl);
|
||||
width: var(--sp-xxl);
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
@@ -227,7 +231,7 @@
|
||||
}
|
||||
|
||||
.invite {
|
||||
height: deprecated.$s-32;
|
||||
height: var(--sp-xxxl);
|
||||
width: deprecated.$s-180;
|
||||
}
|
||||
|
||||
@@ -235,8 +239,8 @@
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: deprecated.$s-200;
|
||||
height: deprecated.$s-200;
|
||||
width: var(--sp-xl) 0;
|
||||
height: var(--sp-xl) 0;
|
||||
overflow: hidden;
|
||||
border-radius: deprecated.$br-4;
|
||||
@media (max-width: 1200px) {
|
||||
@@ -244,3 +248,26 @@
|
||||
width: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.nav-options {
|
||||
display: flex;
|
||||
gap: var(--sp-l);
|
||||
justify-content: space-between;
|
||||
border-bottom: $b-1 solid var(--panel-border-color);
|
||||
padding-inline-start: var(--sp-l);
|
||||
background: var(--color-background-default);
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: var(--z-index-panels);
|
||||
}
|
||||
|
||||
.selected {
|
||||
@include t.use-typography("headline-small");
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: var(--color-foreground-primary);
|
||||
border: $b-1 solid transparent;
|
||||
border-bottom: $b-1 solid var(--color-foreground-primary);
|
||||
padding: 0 var(--sp-m);
|
||||
}
|
||||
|
||||
@@ -27,11 +27,11 @@
|
||||
[app.main.ui.dashboard.comments :refer [comments-icon* comments-section]]
|
||||
[app.main.ui.dashboard.inline-edition :refer [inline-edition]]
|
||||
[app.main.ui.dashboard.project-menu :refer [project-menu*]]
|
||||
[app.main.ui.dashboard.subscription :refer [subscription-sidebar*
|
||||
[app.main.ui.dashboard.subscription :refer [dashboard-cta*
|
||||
get-subscription-type
|
||||
menu-team-icon*
|
||||
dashboard-cta*
|
||||
show-subscription-dashboard-banner?
|
||||
get-subscription-type]]
|
||||
subscription-sidebar*]]
|
||||
[app.main.ui.dashboard.team-form]
|
||||
[app.main.ui.ds.foundations.assets.icon :refer [icon*] :as i]
|
||||
[app.main.ui.icons :as deprecated-icon]
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
[app.common.data :as d]
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.types.color :as clr]
|
||||
[app.main.data.dashboard :as dd]
|
||||
[app.main.data.exports.assets :as de]
|
||||
[app.main.data.modal :as modal]
|
||||
[app.main.refs :as refs]
|
||||
@@ -205,10 +206,13 @@
|
||||
:cmd :export-frames
|
||||
:origin origin}]))
|
||||
|
||||
(mf/defc export-progress-widget
|
||||
(mf/defc progress-widget
|
||||
{::mf/wrap [mf/memo]}
|
||||
[]
|
||||
(let [state (mf/deref refs/export)
|
||||
[{:keys [operation] :or {operation :export}}]
|
||||
(let [state (mf/deref (case operation
|
||||
:export refs/export
|
||||
:restore refs/restore
|
||||
refs/export))
|
||||
profile (mf/deref refs/profile)
|
||||
theme (or (:theme profile) theme/default)
|
||||
is-default-theme? (= theme/default theme)
|
||||
@@ -217,11 +221,14 @@
|
||||
detail-visible? (:detail-visible state)
|
||||
widget-visible? (:widget-visible state)
|
||||
progress (:progress state)
|
||||
exports (:exports state)
|
||||
total (count exports)
|
||||
items (case operation
|
||||
:export (:exports state)
|
||||
:restore (:files state)
|
||||
[])
|
||||
total (or (:total state) (count items))
|
||||
complete? (= progress total)
|
||||
circ (* 2 Math/PI 12)
|
||||
pct (- circ (* circ (/ progress total)))
|
||||
pct (if (zero? total) circ (- circ (* circ (/ progress total))))
|
||||
|
||||
pwidth
|
||||
(if error?
|
||||
@@ -243,19 +250,43 @@
|
||||
|
||||
title
|
||||
(cond
|
||||
error? (tr "workspace.options.exporting-object-error")
|
||||
complete? (tr "workspace.options.exporting-complete")
|
||||
healthy? (tr "workspace.options.exporting-object")
|
||||
(not healthy?) (tr "workspace.options.exporting-object-slow"))
|
||||
error? (case operation
|
||||
:export (tr "workspace.options.exporting-object-error")
|
||||
:restore (tr "workspace.options.restoring-object-error")
|
||||
(tr "workspace.options.processing-object-error"))
|
||||
complete? (case operation
|
||||
:export (tr "workspace.options.exporting-complete")
|
||||
:restore (tr "workspace.options.restoring-complete")
|
||||
(tr "workspace.options.processing-complete"))
|
||||
healthy? (case operation
|
||||
:export (tr "workspace.options.exporting-object")
|
||||
:restore (tr "workspace.options.restoring-object")
|
||||
(tr "workspace.options.processing-object"))
|
||||
(not healthy?) (case operation
|
||||
:export (tr "workspace.options.exporting-object-slow")
|
||||
:restore (tr "workspace.options.restoring-object-slow")
|
||||
(tr "workspace.options.processing-object-slow")))
|
||||
|
||||
retry-last-export
|
||||
(mf/use-fn #(st/emit! (de/retry-last-export)))
|
||||
retry-last-operation
|
||||
(mf/use-fn
|
||||
(mf/deps operation)
|
||||
(fn []
|
||||
(case operation
|
||||
:export (st/emit! (de/retry-last-export))
|
||||
:restore (st/emit! (dd/retry-last-restore))
|
||||
nil)))
|
||||
|
||||
toggle-detail-visibility
|
||||
(mf/use-fn #(st/emit! (de/toggle-detail-visibililty)))]
|
||||
(mf/use-fn
|
||||
(mf/deps operation)
|
||||
(fn []
|
||||
(case operation
|
||||
:export (st/emit! (de/toggle-detail-visibililty))
|
||||
:restore (st/emit! (dd/toggle-restore-detail-visibility))
|
||||
nil)))]
|
||||
|
||||
[:*
|
||||
(when widget-visible?
|
||||
(when (and widget-visible? (= operation :export))
|
||||
[:div {:class (stl/css :export-progress-widget)
|
||||
:on-click toggle-detail-visibility}
|
||||
[:svg {:width "24" :height "24"}
|
||||
@@ -283,11 +314,11 @@
|
||||
error-icon
|
||||
neutral-icon)
|
||||
|
||||
[:p {:class (stl/css :export-progress-title)}
|
||||
title
|
||||
[:div {:class (stl/css :export-progress-title)}
|
||||
[:div {:class (stl/css :title-text)} title]
|
||||
(if error?
|
||||
[:button {:class (stl/css :retry-btn)
|
||||
:on-click retry-last-export}
|
||||
:on-click retry-last-operation}
|
||||
(tr "workspace.options.retry")]
|
||||
|
||||
[:span {:class (stl/css :progress)}
|
||||
|
||||
@@ -64,7 +64,8 @@
|
||||
["/fonts" :dashboard-fonts]
|
||||
["/fonts/providers" :dashboard-font-providers]
|
||||
["/libraries" :dashboard-libraries]
|
||||
["/files" :dashboard-files]]
|
||||
["/files" :dashboard-files]
|
||||
["/deleted" :dashboard-deleted]]
|
||||
|
||||
["/dashboard/team/:team-id"
|
||||
["/members" :dashboard-legacy-team-members]
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
[app.main.data.viewer.shortcuts :as sc]
|
||||
[app.main.store :as st]
|
||||
[app.main.ui.components.dropdown :refer [dropdown]]
|
||||
[app.main.ui.exports.assets :refer [export-progress-widget]]
|
||||
[app.main.ui.exports.assets :refer [progress-widget]]
|
||||
[app.main.ui.formats :as fmt]
|
||||
[app.main.ui.icons :as deprecated-icon]
|
||||
[app.main.ui.viewer.comments :refer [comments-menu]]
|
||||
@@ -167,7 +167,7 @@
|
||||
(open-share-dialog)))
|
||||
|
||||
[:div {:class (stl/css :options-zone)}
|
||||
[:& export-progress-widget]
|
||||
[:& progress-widget {:operation :export}]
|
||||
|
||||
(case section
|
||||
:interactions [:*
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
[app.main.ui.dashboard.team]
|
||||
[app.main.ui.ds.buttons.icon-button :refer [icon-button*]]
|
||||
[app.main.ui.ds.foundations.assets.icon :as i]
|
||||
[app.main.ui.exports.assets :refer [export-progress-widget]]
|
||||
[app.main.ui.exports.assets :refer [progress-widget]]
|
||||
[app.main.ui.formats :as fmt]
|
||||
[app.main.ui.icons :as deprecated-icon]
|
||||
[app.main.ui.workspace.presence :refer [active-sessions]]
|
||||
@@ -200,7 +200,7 @@
|
||||
[:div {:class (stl/css :users-section)}
|
||||
[:& active-sessions]]
|
||||
|
||||
[:& export-progress-widget]
|
||||
[:& progress-widget {:operation :export}]
|
||||
|
||||
[:div {:class (stl/css :separator)}]
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
(ns app.main.ui.workspace.shapes.text.editor
|
||||
(:require
|
||||
["draft-js" :as draft]
|
||||
["@penpot/draft-js" :as draft]
|
||||
[app.common.data :as d]
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.geom.point :as gpt]
|
||||
|
||||
@@ -271,8 +271,10 @@
|
||||
:font-variant-id new-variant-id
|
||||
:font-weight (:weight variant)
|
||||
:font-style (:style variant)}))
|
||||
|
||||
(dom/blur! (dom/get-target new-variant-id)))))
|
||||
;; NOTE: the select component we are using does not fire on-blur event
|
||||
;; so we need to call on-blur manually
|
||||
(when (some? on-blur)
|
||||
(on-blur)))))
|
||||
|
||||
on-font-select
|
||||
(mf/use-fn
|
||||
|
||||
@@ -268,8 +268,8 @@
|
||||
:on-click modal/hide!}
|
||||
(tr "labels.cancel")]
|
||||
[:> import-type-dropdown*
|
||||
{:options [{:label (tr "workspace.tokens.import-menu-zip-option") :value :zip}
|
||||
{:label (tr "workspace.tokens.import-menu-json-option") :value :file}
|
||||
{:options [{:label (tr "workspace.tokens.import-menu-json-option") :value :file}
|
||||
{:label (tr "workspace.tokens.import-menu-zip-option") :value :zip}
|
||||
{:label (tr "workspace.tokens.import-menu-folder-option") :value :folder}]
|
||||
:on-click handle-import-action
|
||||
:text-render render-button-text
|
||||
|
||||
@@ -19,5 +19,5 @@
|
||||
}
|
||||
|
||||
.threads {
|
||||
position: fixed;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
@@ -54,6 +54,7 @@
|
||||
[app.plugins.ruler-guides :as rg]
|
||||
[app.plugins.text :as text]
|
||||
[app.plugins.utils :as u]
|
||||
[app.util.http :as http]
|
||||
[app.util.object :as obj]
|
||||
[beicon.v2.core :as rx]
|
||||
[cuerdas.core :as str]))
|
||||
@@ -1195,7 +1196,12 @@
|
||||
(js/Promise.
|
||||
(fn [resolve reject]
|
||||
(->> (rp/cmd! :export payload)
|
||||
(rx/mapcat #(rp/cmd! :export {:cmd :get-resource :wait true :id (:id %) :blob? true}))
|
||||
(rx/mapcat (fn [{:keys [uri]}]
|
||||
(->> (http/send! {:method :get
|
||||
:uri uri
|
||||
:response-type :blob
|
||||
:omit-default-headers true})
|
||||
(rx/map :body))))
|
||||
(rx/mapcat #(.arrayBuffer %))
|
||||
(rx/map #(js/Uint8Array. %))
|
||||
(rx/subs! resolve reject))))))))
|
||||
|
||||
@@ -194,7 +194,12 @@
|
||||
|
||||
:addToken
|
||||
(fn [type-str name value]
|
||||
(let [type (cto/dtcg-token-type->token-type type-str)]
|
||||
(let [type (cto/dtcg-token-type->token-type type-str)
|
||||
value (case type
|
||||
:font-family (ctob/convert-dtcg-font-family (js->clj value))
|
||||
:typography (ctob/convert-dtcg-typography-composite (js->clj value))
|
||||
:shadow (ctob/convert-dtcg-shadow-composite (js->clj value))
|
||||
(js->clj value))]
|
||||
(cond
|
||||
(nil? type)
|
||||
(u/display-not-valid :addTokenType type-str)
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
[app.common.types.path :as path]
|
||||
[app.common.types.path.impl :as path.impl]
|
||||
[app.common.types.shape.layout :as ctl]
|
||||
[app.common.types.text :as txt]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.config :as cf]
|
||||
[app.main.refs :as refs]
|
||||
@@ -964,8 +965,8 @@
|
||||
(set-shape-children children)
|
||||
(set-shape-corners corners)
|
||||
(set-shape-blur blur)
|
||||
(when (and (= type :group) masked)
|
||||
(set-masked masked))
|
||||
(when (= type :group)
|
||||
(set-masked (boolean masked)))
|
||||
(when (= type :bool)
|
||||
(set-shape-bool-type bool-type))
|
||||
(when (and (some? content)
|
||||
@@ -1411,20 +1412,23 @@
|
||||
(get span))
|
||||
text (subs (:text element) start-pos end-pos)]
|
||||
|
||||
{:x x
|
||||
:y (+ y height)
|
||||
:width width
|
||||
:height height
|
||||
:direction (dr/translate-direction direction)
|
||||
:font-family (get element :font-family)
|
||||
:font-size (get element :font-size)
|
||||
:font-weight (get element :font-weight)
|
||||
:text-transform (get element :text-transform)
|
||||
:text-decoration (get element :text-decoration)
|
||||
:letter-spacing (get element :letter-spacing)
|
||||
:font-style (get element :font-style)
|
||||
:fills (get element :fills)
|
||||
:text text}))))]
|
||||
(d/patch-object
|
||||
txt/default-text-attrs
|
||||
(d/without-nils
|
||||
{:x x
|
||||
:y (+ y height)
|
||||
:width width
|
||||
:height height
|
||||
:direction (dr/translate-direction direction)
|
||||
:font-family (get element :font-family)
|
||||
:font-size (get element :font-size)
|
||||
:font-weight (get element :font-weight)
|
||||
:text-transform (get element :text-transform)
|
||||
:text-decoration (get element :text-decoration)
|
||||
:letter-spacing (get element :letter-spacing)
|
||||
:font-style (get element :font-style)
|
||||
:fills (get element :fills)
|
||||
:text text}))))))]
|
||||
(mem/free)
|
||||
|
||||
result)))
|
||||
|
||||
@@ -233,8 +233,8 @@
|
||||
(api/set-shape-shadows (:shadow shape)))
|
||||
|
||||
:masked-group
|
||||
(when (cfh/mask-shape? shape)
|
||||
(api/set-masked (:masked-group shape)))
|
||||
(when (cfh/group-shape? shape)
|
||||
(api/set-masked (boolean (:masked-group shape))))
|
||||
|
||||
:content
|
||||
(cond
|
||||
|
||||
@@ -6,11 +6,11 @@
|
||||
|
||||
(ns app.util.code-highlight
|
||||
(:require
|
||||
["@penpot/hljs" :as hljs]
|
||||
["highlight.js" :as hljs]
|
||||
[app.util.dom :as dom]))
|
||||
|
||||
(defn highlight!
|
||||
{:lazy-loadable true}
|
||||
[node]
|
||||
(dom/set-data! node "highlighted" nil)
|
||||
(hljs/highlightElement node))
|
||||
(.highlightElement hljs/default node))
|
||||
|
||||
@@ -50,6 +50,7 @@
|
||||
{:label "Føroyskt mál (community)" :value "fo"}
|
||||
{:label "Korean (community)" :value "ko"}
|
||||
{:label "עִבְרִית (community)" :value "he"}
|
||||
{:label "आधुनिक मानक हिन्दी (community)" :value "hi"}
|
||||
{:label "عربي/عربى (community)" :value "ar"}
|
||||
{:label "فارسی (community)" :value "fa"}
|
||||
{:label "日本語 (Community)" :value "ja_jp"}
|
||||
@@ -69,7 +70,6 @@
|
||||
(-> (.-language globals/navigator)
|
||||
(parse-locale))))
|
||||
|
||||
|
||||
;; Set initial translation loading state as globaly stored variable;
|
||||
;; this facilitates hot reloading
|
||||
(when-not (exists? (unchecked-get globals/global "penpotTranslations"))
|
||||
@@ -93,14 +93,8 @@
|
||||
(def ^:dynamic *current-locale*
|
||||
(get-current))
|
||||
|
||||
(defonce state
|
||||
(l/atom {:render 0 :locale *current-locale*}))
|
||||
|
||||
(defn- assign-current-locale
|
||||
[state locale]
|
||||
(-> state
|
||||
(update :render inc)
|
||||
(assoc :locale locale)))
|
||||
(defonce locale
|
||||
(l/atom *current-locale*))
|
||||
|
||||
(defn- get-translations
|
||||
"Get globaly stored mutable object with all loaded translations"
|
||||
@@ -114,6 +108,10 @@
|
||||
(unchecked-set translations locale data)
|
||||
nil))
|
||||
|
||||
(defn set-default-translations
|
||||
[data]
|
||||
(set-translations cf/default-language data))
|
||||
|
||||
(defn- load
|
||||
[locale]
|
||||
(let [path (str "./translation." locale ".js?version=" (:full cf/version))]
|
||||
@@ -122,15 +120,14 @@
|
||||
(p/fnly (fn [data cause]
|
||||
(if cause
|
||||
(js/console.error "unexpected error on fetching locale" cause)
|
||||
(do
|
||||
(set! *current-locale* locale)
|
||||
(set-translations locale data)
|
||||
(swap! state assign-current-locale locale))))))))
|
||||
(set-translations locale data)))))))
|
||||
|
||||
(defn init
|
||||
"Initialize the i18n module"
|
||||
[]
|
||||
(load *current-locale*))
|
||||
(load *current-locale*)
|
||||
(when-not (= *current-locale* cf/default-language)
|
||||
(load cf/default-language)))
|
||||
|
||||
(defn set-locale
|
||||
[lname]
|
||||
@@ -145,7 +142,10 @@
|
||||
(recur (rest locales)))
|
||||
cf/default-language))))]
|
||||
|
||||
(load lname)))
|
||||
(->> (load lname)
|
||||
(p/fnly (fn [_r _c]
|
||||
(set! *current-locale* lname)
|
||||
(reset! locale lname))))))
|
||||
|
||||
(deftype C [val]
|
||||
IDeref
|
||||
@@ -206,9 +206,7 @@
|
||||
:className class
|
||||
:on-click on-click}]))
|
||||
|
||||
(add-watch state "common.time"
|
||||
(add-watch locale "common.time"
|
||||
(fn [_ _ pv cv]
|
||||
(let [pv (get pv :locale)
|
||||
cv (get cv :locale)]
|
||||
(when (not= pv cv)
|
||||
(ct/set-default-locale! cv)))))
|
||||
(when (not= pv cv)
|
||||
(ct/set-default-locale cv))))
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"PO-Revision-Date: 2025-11-22 10:51+0000\n"
|
||||
"Last-Translator: jonnysemon <jonnysemon@users.noreply.hosted.weblate.org>\n"
|
||||
"PO-Revision-Date: 2025-12-22 15:34+0000\n"
|
||||
"Last-Translator: Shuaib Zahda <shuaib.zahda@gmail.com>\n"
|
||||
"Language-Team: Arabic <https://hosted.weblate.org/projects/penpot/frontend/"
|
||||
"ar/>\n"
|
||||
"Language: ar\n"
|
||||
@@ -10,7 +10,7 @@ msgstr ""
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 "
|
||||
"&& n%100<=10 ? 3 : n%100>=11 ? 4 : 5;\n"
|
||||
"X-Generator: Weblate 5.15-dev\n"
|
||||
"X-Generator: Weblate 5.15.1\n"
|
||||
|
||||
#: src/app/main/ui/auth/register.cljs:215, src/app/main/ui/static.cljs:159, src/app/main/ui/viewer/login.cljs:100
|
||||
msgid "auth.already-have-account"
|
||||
@@ -402,8 +402,10 @@ msgstr ""
|
||||
"أصولهم*؟"
|
||||
|
||||
#: src/app/main/ui/exports/files.cljs:164
|
||||
#, fuzzy
|
||||
msgid "dashboard.export.options.all.message"
|
||||
msgstr "سيتم ادراج الملفات التي لها مكتبات مشتركة في التصدير، مع الحفاظ على روابطهم."
|
||||
msgstr ""
|
||||
"سيتم ادراج الملفات التي لها مكتبات مشتركة في التصدير، مع الحفاظ على روابطهم."
|
||||
|
||||
#: src/app/main/ui/exports/files.cljs:165
|
||||
msgid "dashboard.export.options.all.title"
|
||||
|
||||
@@ -1575,10 +1575,6 @@ msgstr ""
|
||||
"Pokud se chcete dozvědět více o inspektorovi designu, navštivte centrum "
|
||||
"nápovědy společnosti Penpot"
|
||||
|
||||
#: src/app/main/ui/inspect/right_sidebar.cljs:240
|
||||
msgid "inspect.empty.more-info"
|
||||
msgstr "Více informací o inspektorovi"
|
||||
|
||||
#: src/app/main/ui/inspect/right_sidebar.cljs:232
|
||||
msgid "inspect.empty.select"
|
||||
msgstr ""
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"PO-Revision-Date: 2025-11-03 20:51+0000\n"
|
||||
"Last-Translator: Stas Haas <stas@girafic.de>\n"
|
||||
"Language-Team: German "
|
||||
"<https://hosted.weblate.org/projects/penpot/frontend/de/>\n"
|
||||
"PO-Revision-Date: 2025-12-22 15:34+0000\n"
|
||||
"Last-Translator: Anonymous <noreply@weblate.org>\n"
|
||||
"Language-Team: German <https://hosted.weblate.org/projects/penpot/frontend/"
|
||||
"de/>\n"
|
||||
"Language: de\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||
"X-Generator: Weblate 5.14.1-dev\n"
|
||||
"X-Generator: Weblate 5.15.1\n"
|
||||
|
||||
#: src/app/main/ui/auth/register.cljs:215, src/app/main/ui/static.cljs:159, src/app/main/ui/viewer/login.cljs:100
|
||||
msgid "auth.already-have-account"
|
||||
msgstr "Sie haben schon ein Konto?"
|
||||
msgstr "Sie haben bereits ein Konto?"
|
||||
|
||||
#: src/app/main/ui/auth/recovery_request.cljs:113, src/app/main/ui/auth/register.cljs:238
|
||||
msgid "auth.check-mail"
|
||||
@@ -584,10 +584,11 @@ msgstr ""
|
||||
"machen?"
|
||||
|
||||
#: src/app/main/ui/exports/files.cljs:164
|
||||
#, fuzzy
|
||||
msgid "dashboard.export.options.all.message"
|
||||
msgstr ""
|
||||
"Dateien mit geteilten Bibliotheken werden exportiert, und ihre "
|
||||
"Verknüpfungen bleiben erhalten."
|
||||
"Dateien mit geteilten Bibliotheken werden exportiert, und ihre Verknüpfungen "
|
||||
"bleiben erhalten."
|
||||
|
||||
#: src/app/main/ui/exports/files.cljs:165
|
||||
msgid "dashboard.export.options.all.title"
|
||||
@@ -1799,10 +1800,6 @@ msgstr ""
|
||||
"Für weitere Informationen zum Thema \"Auswerten von "
|
||||
"Design-Spezifikationen\", besuchen Sie bitte das Penpot-Hilfezentrum"
|
||||
|
||||
#: src/app/main/ui/inspect/right_sidebar.cljs:240
|
||||
msgid "inspect.empty.more-info"
|
||||
msgstr "Weitere Informationen zur Inspektion"
|
||||
|
||||
#: src/app/main/ui/inspect/right_sidebar.cljs:232
|
||||
msgid "inspect.empty.select"
|
||||
msgstr ""
|
||||
@@ -1810,6 +1807,7 @@ msgstr ""
|
||||
"Eigenschaften und Code zu überprüfen"
|
||||
|
||||
#: src/app/main/ui/inspect/right_sidebar.cljs:166
|
||||
#, fuzzy
|
||||
msgid "inspect.layer-info"
|
||||
msgstr "Info zur Ebene"
|
||||
|
||||
@@ -2630,7 +2628,7 @@ msgstr "Eigene Schriftarten hochladen"
|
||||
|
||||
#: src/app/main/ui/dashboard/fonts.cljs:252
|
||||
msgid "labels.uploading"
|
||||
msgstr "Hochladen…"
|
||||
msgstr "Lädt hoch…"
|
||||
|
||||
#: src/app/main/ui/inspect/right_sidebar.cljs:65, src/app/main/ui/workspace/sidebar/options/menus/component.cljs:1028
|
||||
msgid "labels.variant"
|
||||
@@ -3907,7 +3905,7 @@ msgstr "Kopieren"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:96
|
||||
msgid "shortcuts.copy-link"
|
||||
msgstr "Link in die Zwischenablage kopieren"
|
||||
msgstr "Link kopieren"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:106
|
||||
#, unused
|
||||
@@ -6705,7 +6703,7 @@ msgstr "Als CSS kopieren (verschachtelte Ebenen)"
|
||||
|
||||
#: src/app/main/ui/workspace/context_menu.cljs:202
|
||||
msgid "workspace.shape.menu.copy-link"
|
||||
msgstr "Link in die Zwischenablage kopieren"
|
||||
msgstr "Link kopieren"
|
||||
|
||||
#: src/app/main/ui/workspace/context_menu.cljs:215
|
||||
msgid "workspace.shape.menu.copy-paste-as"
|
||||
@@ -7504,3 +7502,662 @@ msgstr "Automatisch gespeicherte Versionen werden für %s Tage aufbewahrt."
|
||||
#, unused
|
||||
msgid "workspace.viewport.click-to-close-path"
|
||||
msgstr "Klicken Sie, um den Pfad zu schließen"
|
||||
|
||||
#: src/app/main/ui/dashboard/team.cljs:765
|
||||
msgid "dashboard.invitation-modal.delete"
|
||||
msgstr "Diese Einladungen werden gelöscht:"
|
||||
|
||||
#: src/app/main/ui/dashboard/team.cljs:766
|
||||
msgid "dashboard.invitation-modal.resend"
|
||||
msgstr "Diese Einladungen werden erneut gesendet:"
|
||||
|
||||
#: src/app/main/ui/dashboard/team.cljs:933
|
||||
msgid "team.invitations-selected"
|
||||
msgid_plural "team.invitations-selected"
|
||||
msgstr[0] "Eine Einladung ausgewählt"
|
||||
msgstr[1] "%s Einladungen ausgewählt"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/themes/create_modal.cljs:121
|
||||
msgid "workspace.tokens.themes-description"
|
||||
msgstr ""
|
||||
"Hier können Sie ihre Themes verwalten, ein- oder ausschalten und aktive Sets "
|
||||
"auswählen."
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/management.cljs:143
|
||||
msgid "workspace.tokens.inactive-set"
|
||||
msgstr "Inaktiv"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/themes/create_modal.cljs:174
|
||||
msgid "workspace.tokens.no-active-sets"
|
||||
msgstr "Keine Sets aktiviert"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/themes/create_modal.cljs:173
|
||||
msgid "workspace.tokens.num-active-sets"
|
||||
msgstr "%s aktivierte Sets"
|
||||
|
||||
#: src/app/main/ui/workspace/colorpicker/color_tokens.cljs:35
|
||||
msgid "color-token.empty-state"
|
||||
msgstr ""
|
||||
"Keine Farb-Tokens vorhanden. Aktivieren sie Sets und/oder Themes oder fügen "
|
||||
"Sie neue Tokens hinzu."
|
||||
|
||||
#: src/app/main/ui/ds/controls/numeric_input.cljs:99
|
||||
msgid "ds.inputs.numeric-input.no-applicable-tokens"
|
||||
msgstr ""
|
||||
"Es sind keine passenden Tokens in aktivierten Sets oder Themes vorhanden."
|
||||
|
||||
#: src/app/main/ui/ds/controls/utilities/token_field.cljs:41, src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs:98, src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs:105
|
||||
msgid "ds.inputs.token-field.no-active-token-option"
|
||||
msgstr "Dieser Token ist nicht Teil eines aktiven Sets oder ungültig."
|
||||
|
||||
#: src/app/main/errors.cljs:307
|
||||
msgid "errors.deprecated"
|
||||
msgstr ""
|
||||
"Tut uns leid! Diese Datei beinhaltet veraltete Penpot-Assets und kann "
|
||||
"deshalb nicht geöffnet werden."
|
||||
|
||||
#: src/app/main/errors.cljs:310
|
||||
msgid "errors.deprecated.contact.after"
|
||||
msgstr "damit wir Ihnen helfen können."
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/management/create/border_radius.cljs:52, src/app/main/ui/workspace/tokens/management/create/form.cljs:80
|
||||
msgid "errors.field-max-length"
|
||||
msgstr "Darf maximal %s Zeichen enthalten."
|
||||
|
||||
#: src/app/main/ui/settings/feedback.cljs:143
|
||||
msgid "feedback.other-ways-contact"
|
||||
msgstr "Weitere Möglichkeiten uns zu kontaktieren"
|
||||
|
||||
#: src/app/main/ui/settings/feedback.cljs:122
|
||||
msgid "feedback.description-placeholder"
|
||||
msgstr "Bitte beschreiben Sie ihr Feedback"
|
||||
|
||||
#: src/app/main/ui/settings/feedback.cljs:126
|
||||
msgid "feedback.penpot.link"
|
||||
msgstr ""
|
||||
"Wenn sich Ihr Feedback auf eine Datei oder Projekt bezieht, können Sie einen "
|
||||
"Link hinzufügen:"
|
||||
|
||||
#: src/app/main/ui/settings/feedback.cljs:101
|
||||
msgid "feedback.title-contact-us"
|
||||
msgstr "Kontakt"
|
||||
|
||||
#: src/app/main/ui/settings/feedback.cljs:110, src/app/main/ui/settings/feedback.cljs:111
|
||||
msgid "feedback.type"
|
||||
msgstr "Art"
|
||||
|
||||
#: src/app/main/ui/settings/feedback.cljs:115
|
||||
msgid "feedback.type.doubt"
|
||||
msgstr "Bedenken"
|
||||
|
||||
#: src/app/main/ui/settings/feedback.cljs:113
|
||||
msgid "feedback.type.idea"
|
||||
msgstr "Idee"
|
||||
|
||||
#: src/app/main/ui/settings/feedback.cljs:114
|
||||
msgid "feedback.type.issue"
|
||||
msgstr "Problem"
|
||||
|
||||
#: src/app/main/ui/inspect/styles/rows/color_properties_row.cljs:120
|
||||
msgid "inspect.attributes.image.preview"
|
||||
msgstr "Bildvorschau"
|
||||
|
||||
#: src/app/main/ui/inspect/right_sidebar.cljs:170
|
||||
msgid "inspect.color-space-label"
|
||||
msgstr "Farbraum auswählen"
|
||||
|
||||
#: src/app/main/ui/inspect/styles/style_box.cljs:68
|
||||
msgid "inspect.tabs.styles.copy-shorthand"
|
||||
msgstr "CSS-Stile kopieren"
|
||||
|
||||
#: src/app/main/ui/inspect/styles/style_box.cljs:60, src/app/main/ui/workspace/colorpicker/color_tokens.cljs:179
|
||||
msgid "inspect.tabs.styles.toggle-style"
|
||||
msgstr "%s-Schaltfläche ein-/ausblenden"
|
||||
|
||||
#: src/app/main/ui/inspect/styles/style_box.cljs:21
|
||||
msgid "inspect.tabs.styles.token-panel"
|
||||
msgstr "Token Sets und Themes"
|
||||
|
||||
#: src/app/main/ui/inspect/styles/rows/color_properties_row.cljs:102, src/app/main/ui/inspect/styles/rows/properties_row.cljs:60
|
||||
msgid "inspect.tabs.styles.token-resolved-value"
|
||||
msgstr "Festgelegter Wert:"
|
||||
|
||||
#: src/app/main/ui/inspect/styles/style_box.cljs:26
|
||||
msgid "labels.blur"
|
||||
msgstr "Weichzeichnen"
|
||||
|
||||
#: src/app/main/ui/dashboard/sidebar.cljs:1031
|
||||
msgid "labels.community-contributions"
|
||||
msgstr "Community & Beiträge"
|
||||
|
||||
#: src/app/main/ui/static.cljs:406
|
||||
msgid "labels.contact-support"
|
||||
msgstr "Support kontaktieren"
|
||||
|
||||
#: src/app/main/ui/settings/sidebar.cljs:136
|
||||
msgid "labels.contact-us"
|
||||
msgstr "Kontakt"
|
||||
|
||||
#: src/app/main/ui/static.cljs:68
|
||||
msgid "labels.copyright-period"
|
||||
msgstr "Kaleidos © 2019-heute"
|
||||
|
||||
#: src/app/main/ui/settings/feedback.cljs:134, src/app/main/ui/static.cljs:400
|
||||
msgid "labels.download"
|
||||
msgstr "%s herunterladen"
|
||||
|
||||
#: src/app/main/ui/inspect/styles/style_box.cljs:23
|
||||
msgid "labels.fill"
|
||||
msgstr "Fläche"
|
||||
|
||||
#: src/app/main/ui/dashboard/sidebar.cljs:1020
|
||||
msgid "labels.help-learning"
|
||||
msgstr "Hilfe & Lernen"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:667
|
||||
msgid "labels.reference"
|
||||
msgstr "Referenz"
|
||||
|
||||
#: src/app/main/ui/dashboard/team.cljs:788
|
||||
msgid "labels.resend"
|
||||
msgstr "Erneut senden"
|
||||
|
||||
#: src/app/main/ui/dashboard/sidebar.cljs:873
|
||||
msgid "labels.version-notes"
|
||||
msgstr "Hinweise zu Version %s"
|
||||
|
||||
#: src/app/main/ui/inspect/styles/style_box.cljs:32
|
||||
msgid "labels.visibility"
|
||||
msgstr "Sichtbarkeit"
|
||||
|
||||
#: src/app/main/ui/static.cljs:397
|
||||
msgid "labels.internal-error.desc-message-second"
|
||||
msgstr "Probieren Sie es erneut oder kontaktieren Sie unseren Support."
|
||||
|
||||
#: src/app/main/ui/ds/product/loader.cljs:26
|
||||
msgid "loader.tips.04.title"
|
||||
msgstr ""
|
||||
|
||||
#: src/app/main/ui/dashboard/team.cljs:825
|
||||
msgid "notifications.invitation-deleted"
|
||||
msgstr "Einladung erfolgreich widerrufen"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:97
|
||||
msgid "shortcuts.create-component-variant"
|
||||
msgstr "Komponente / Variante erstellen"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/assets/groups.cljs:81
|
||||
msgid "workspace.assets.component-group-options"
|
||||
msgstr "Optionen für diese Gruppe"
|
||||
|
||||
#: src/app/main/ui/workspace/colorpicker.cljs:427, src/app/main/ui/workspace/colorpicker.cljs:439
|
||||
msgid "workspace.colorpicker.color-tokens"
|
||||
msgstr "Farb-Tokens"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/component.cljs:499
|
||||
msgid "workspace.component.swap.loop-error"
|
||||
msgstr "Komponenten können nicht in sich selbst verschachtelt werden."
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/component.cljs:498
|
||||
msgid "workspace.component.switch.loop-error-multi"
|
||||
msgstr ""
|
||||
"Einige Elemente konnten nicht ausgetauscht werden. Komponenten können nicht "
|
||||
"in sich selbst verschachtelt werden."
|
||||
|
||||
#: src/app/main/ui/workspace/libraries.cljs:107, src/app/main/ui/workspace/libraries.cljs:133
|
||||
msgid "workspace.libraries.colors"
|
||||
msgid_plural "workspace.libraries.colors"
|
||||
msgstr[0] "1 Farbe"
|
||||
msgstr[1] "%s Farben"
|
||||
|
||||
#: src/app/main/ui/workspace/libraries.cljs:101, src/app/main/ui/workspace/libraries.cljs:125
|
||||
msgid "workspace.libraries.components"
|
||||
msgid_plural "workspace.libraries.components"
|
||||
msgstr[0] "1 Komponente"
|
||||
msgstr[1] "%s Komponenten"
|
||||
|
||||
#: src/app/main/ui/workspace/libraries.cljs:104, src/app/main/ui/workspace/libraries.cljs:129
|
||||
msgid "workspace.libraries.graphics"
|
||||
msgid_plural "workspace.libraries.graphics"
|
||||
msgstr[0] "%s Grafik"
|
||||
msgstr[1] "%s Grafiken"
|
||||
|
||||
#: src/app/main/ui/workspace/libraries.cljs:110, src/app/main/ui/workspace/libraries.cljs:137
|
||||
msgid "workspace.libraries.typography"
|
||||
msgid_plural "workspace.libraries.typography"
|
||||
msgstr[0] "1 Textstil"
|
||||
msgstr[1] "%s Textstile"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/component.cljs:1055
|
||||
msgid "workspace.options.component.unlinked"
|
||||
msgstr "Getrennt"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/component.cljs:1330
|
||||
msgid "workspace.options.component.variant.duplicated.group.locate"
|
||||
msgstr "Doppelte Varianten anzeigen"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/component.cljs:1327
|
||||
msgid "workspace.options.component.variant.duplicated.group.title"
|
||||
msgstr "Einige Varianten haben identische Eigenschaften und Werte"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/component.cljs:268
|
||||
msgid "workspace.options.component.variant.duplicated.single.all"
|
||||
msgstr ""
|
||||
"Diese Varianten haben identische Eigenschaften und Werte. Geben Sie jeder "
|
||||
"Variante einen eindeutigen Wert."
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/component.cljs:265
|
||||
msgid "workspace.options.component.variant.duplicated.single.one"
|
||||
msgstr ""
|
||||
"Diese Variante hat die selben Eigenschaften order Werte wie eine andere "
|
||||
"Variante. Geben Sie jeder Variante einen eindeutigen Wert."
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/component.cljs:271
|
||||
msgid "workspace.options.component.variant.duplicated.single.some"
|
||||
msgstr ""
|
||||
"Einige dieser Varianten haben identische Eigenschaften und Werte. Geben Sie "
|
||||
"jeder Variante einen eindeutigen Wert."
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/component.cljs:550
|
||||
msgid "workspace.options.component.variant.malformed.copy"
|
||||
msgstr ""
|
||||
"Diese Komponente hat Varianten mit ungültigen Namen. Stellen Sie sicher, das "
|
||||
"jede Variante korrekt benannt ist."
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/component.cljs:424
|
||||
msgid "workspace.options.component.variant.malformed.structure.title"
|
||||
msgstr "Versuchen Sie diesem Schema zu folgen:"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/variants_help_modal.cljs:54
|
||||
msgid "workspace.options.component.variants-help-modal.intro"
|
||||
msgstr ""
|
||||
"Um Änderungen beizubehalten wenn Sie Varianten wechseln, verbindet Penpot "
|
||||
"Ebenen die:"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/variants_help_modal.cljs:91
|
||||
msgid "workspace.options.component.variants-help-modal.outro"
|
||||
msgstr ""
|
||||
"Jede Änderung (z.B. Ebenen umbenennen oder gruppieren) trennt die "
|
||||
"Verbindung. Änderungen können rückgängig gemacht werden, um die Verbindung "
|
||||
"wiederherzustellen."
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/variants_help_modal.cljs:67
|
||||
msgid "workspace.options.component.variants-help-modal.rule1"
|
||||
msgstr "Den gleichen Namen haben."
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/variants_help_modal.cljs:76
|
||||
msgid "workspace.options.component.variants-help-modal.rule2"
|
||||
msgstr "Vom gleichen Typ sind."
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/variants_help_modal.cljs:77
|
||||
msgid "workspace.options.component.variants-help-modal.rule2.detail"
|
||||
msgstr ""
|
||||
"Rechtecke, Ellipsen, Pfade und boolesche Operationen gelten als der gleiche "
|
||||
"Typ."
|
||||
|
||||
#: src/app/main/data/workspace/tokens/library_edit.cljs:209, src/app/main/data/workspace/tokens/library_edit.cljs:452
|
||||
msgid "workspace.tokens.duplicate-suffix"
|
||||
msgstr "Kopie"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:581
|
||||
msgid "workspace.tokens.edit-token"
|
||||
msgstr "%s Token bearbeiten"
|
||||
|
||||
#: src/app/main/data/workspace/tokens/errors.cljs:41
|
||||
msgid "workspace.tokens.empty-input"
|
||||
msgstr "Der Token-Wert darf nicht leer sein"
|
||||
|
||||
#: src/app/main/data/workspace/tokens/errors.cljs:15
|
||||
msgid "workspace.tokens.error-parse"
|
||||
msgstr "Fehler beim Importieren. JSON konnte nicht verarbeitet werden."
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/export/modal.cljs:49
|
||||
msgid "workspace.tokens.export"
|
||||
msgstr "Export"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/export/modal.cljs:125
|
||||
msgid "workspace.tokens.export-tokens"
|
||||
msgstr "Tokens Exportieren"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/export/modal.cljs:118
|
||||
msgid "workspace.tokens.export.multiple-files"
|
||||
msgstr "Mehrere Dateien"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/export/modal.cljs:38
|
||||
msgid "workspace.tokens.export.no-tokens-themes-sets"
|
||||
msgstr "Es sind keine Tokens, Themes oder Sets zum Exportieren vorhanden."
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/export/modal.cljs:35
|
||||
msgid "workspace.tokens.export.preview"
|
||||
msgstr "Vorschau:"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/export/modal.cljs:116
|
||||
msgid "workspace.tokens.export.single-file"
|
||||
msgstr "Einzeln"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:1339
|
||||
msgid "workspace.tokens.font-size-value-enter"
|
||||
msgstr "Schriftgröße oder {alias}"
|
||||
|
||||
#: src/app/main/data/workspace/tokens/application.cljs:323
|
||||
msgid "workspace.tokens.font-variant-not-found"
|
||||
msgstr ""
|
||||
"Fehler beim Festlegen der Schriftstärke/des Schriftstils. Dieser Schriftstil "
|
||||
"ist in der aktuellen Schriftart nicht vorhanden"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:1328, src/app/main/ui/workspace/tokens/management/create/form.cljs:1343
|
||||
msgid "workspace.tokens.font-weight-value-enter"
|
||||
msgstr "Schriftstärke (300, Fett Kursiv) oder {alias}"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/management/context_menu.cljs:225
|
||||
msgid "workspace.tokens.gaps"
|
||||
msgstr "Zwischenräume"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/style_dictionary.cljs
|
||||
#, unused
|
||||
msgid "workspace.tokens.generic-error"
|
||||
msgstr "Fehler: "
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/themes/create_modal.cljs:129
|
||||
msgid "workspace.tokens.group-name"
|
||||
msgstr "Gruppenname"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/import/modal.cljs:233
|
||||
msgid "workspace.tokens.import-button-prefix"
|
||||
msgstr "%s importieren"
|
||||
|
||||
#: src/app/main/data/workspace/tokens/errors.cljs:32, src/app/main/data/workspace/tokens/errors.cljs:37
|
||||
msgid "workspace.tokens.import-error"
|
||||
msgstr "Fehler beim Import:"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/import/modal.cljs:273
|
||||
msgid "workspace.tokens.import-menu-folder-option"
|
||||
msgstr "Ordner"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/import/modal.cljs:272
|
||||
msgid "workspace.tokens.import-menu-json-option"
|
||||
msgstr "Einzelne JSON-Datei"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/import/modal.cljs:271
|
||||
msgid "workspace.tokens.import-menu-zip-option"
|
||||
msgstr "ZIP-Datei"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/import/modal.cljs:241
|
||||
msgid "workspace.tokens.import-multiple-files"
|
||||
msgstr ""
|
||||
"Bei mehreren Dateien werden die Datei- oder Pfadnamen zum Benennen der Sets "
|
||||
"verwendet."
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/import/modal.cljs:240
|
||||
msgid "workspace.tokens.import-single-file"
|
||||
msgstr ""
|
||||
"Bei einer einzelnen JSON-Datei sollten die Keys der ersten Ebene die Namen "
|
||||
"der Token-Sets sein."
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/import/modal.cljs:237
|
||||
msgid "workspace.tokens.import-tokens"
|
||||
msgstr "Token importieren"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/sidebar.cljs:414, src/app/main/ui/workspace/tokens/sidebar.cljs:415
|
||||
#, unused
|
||||
msgid "workspace.tokens.import-tooltip"
|
||||
msgstr ""
|
||||
"Beim Importieren einer JSON-Datei werden alle bestehenden Tokens, Sets und "
|
||||
"Themes überschrieben"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/import/modal.cljs:247
|
||||
msgid "workspace.tokens.import-warning"
|
||||
msgstr ""
|
||||
"Beim Import werden alle bestehenden Tokens, Sets und Themes überschrieben."
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/management.cljs:134
|
||||
msgid "workspace.tokens.inactive-set-description"
|
||||
msgstr ""
|
||||
"Dieses Set ist nicht aktiv. Ändern Sie das Theme oder aktivieren Sie dieses "
|
||||
"Set, um Änderungen im Anzeigebereich sehen zu können"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:741
|
||||
msgid "workspace.tokens.individual-tokens"
|
||||
msgstr "Einzelne Token verwenden"
|
||||
|
||||
#: src/app/main/data/workspace/tokens/errors.cljs:49
|
||||
msgid "workspace.tokens.invalid-color"
|
||||
msgstr "Ungültiger Farbwert: %s"
|
||||
|
||||
#: src/app/main/data/workspace/tokens/errors.cljs:89
|
||||
msgid "workspace.tokens.invalid-font-weight-token-value"
|
||||
msgstr ""
|
||||
"Ungültiger Wert für die Schriftstärke: Verwenden Sie numerische Werte (100–"
|
||||
"950) oder Standardbezeichnungen (dünn, leicht, normal, fett usw.), optional "
|
||||
"gefolgt von „kursiv”"
|
||||
|
||||
#: src/app/main/data/workspace/tokens/errors.cljs:23
|
||||
msgid "workspace.tokens.invalid-json"
|
||||
msgstr "Fehler beim Importieren: Ihre JSON-Datei enthält ungültige Token-Daten."
|
||||
|
||||
#: src/app/main/data/workspace/tokens/errors.cljs:27
|
||||
msgid "workspace.tokens.invalid-json-token-name"
|
||||
msgstr "Fehler beim Importieren: Ihre JSON-Datei enthält ungültige Token-Namen."
|
||||
|
||||
#: src/app/main/data/workspace/tokens/errors.cljs:28
|
||||
msgid "workspace.tokens.invalid-json-token-name-detail"
|
||||
msgstr ""
|
||||
"„%s“ ist kein gültiger Namen für ein Token.\n"
|
||||
"Token-Namen dürfen nur Buchstaben und Ziffern enthalten, die durch Punkte "
|
||||
"getrennt sind und dürfen nicht mit einem Dollarzeichen beginnen."
|
||||
|
||||
#: src/app/main/data/workspace/tokens/errors.cljs:101
|
||||
msgid "workspace.tokens.invalid-shadow-type-token-value"
|
||||
msgstr ""
|
||||
"Ungültiger Schattentyp: Es werden nur „innerShadow” oder „dropShadow” "
|
||||
"akzeptiert"
|
||||
|
||||
#: src/app/main/data/workspace/tokens/errors.cljs:81
|
||||
msgid "workspace.tokens.invalid-text-case-token-value"
|
||||
msgstr ""
|
||||
"Ungültiger Token-Wert: Es werden nur „none“, „Uppercase“, „Lowercase“ oder „"
|
||||
"Capitalize“ akzeptiert"
|
||||
|
||||
#: src/app/main/data/workspace/tokens/errors.cljs:85
|
||||
msgid "workspace.tokens.invalid-text-decoration-token-value"
|
||||
msgstr ""
|
||||
"Ungültiger Token-Wert: Es werden nur „none“, „underline“ oder „strike-through"
|
||||
"“ akzeptiert"
|
||||
|
||||
#: src/app/main/data/workspace/tokens/errors.cljs:93
|
||||
msgid "workspace.tokens.invalid-token-value-typography"
|
||||
msgstr ""
|
||||
"Ungültiger Wert: Der Wert muss auf ein zusammengesetztes Typografie-Token "
|
||||
"verweisen."
|
||||
|
||||
#: src/app/main/data/workspace/tokens/errors.cljs:61, src/app/main/data/workspace/tokens/errors.cljs:73, src/app/main/data/workspace/tokens/errors.cljs:77
|
||||
msgid "workspace.tokens.invalid-value"
|
||||
msgstr "Ungültiger Token-Wert: %s"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/themes/create_modal.cljs:229
|
||||
msgid "workspace.tokens.label.group-placeholder"
|
||||
msgstr "Gruppe hinzufügen (z. B. „Modus“)"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/themes/create_modal.cljs:236
|
||||
msgid "workspace.tokens.label.theme-placeholder"
|
||||
msgstr "Theme hinzufügen (z. B. „Hell“)"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:1351
|
||||
msgid "workspace.tokens.letter-spacing-value-enter-composite"
|
||||
msgstr "Zeichenabstand oder {alias}"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:1347
|
||||
msgid "workspace.tokens.line-height-value-enter"
|
||||
msgstr "Zeilenabstand (Multiplikator, px, %) oder {alias}"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/management/context_menu.cljs:217
|
||||
msgid "workspace.tokens.margins"
|
||||
msgstr "Abstände"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/management/context_menu.cljs:253
|
||||
msgid "workspace.tokens.max-size"
|
||||
msgstr "Maximale Größe"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/management/context_menu.cljs:247
|
||||
msgid "workspace.tokens.min-size"
|
||||
msgstr "Mindestgröße"
|
||||
|
||||
#: src/app/main/data/workspace/tokens/errors.cljs:57
|
||||
msgid "workspace.tokens.missing-references"
|
||||
msgstr "Fehlende Token-Referenzen: "
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/management/token_pill.cljs:123
|
||||
msgid "workspace.tokens.more-options"
|
||||
msgstr "Rechtsklick, um Optionen anzuzeigen"
|
||||
|
||||
#: src/app/main/data/workspace/tokens/errors.cljs:19
|
||||
msgid "workspace.tokens.no-token-files-found"
|
||||
msgstr "In dieser Datei wurden keine Tokens, Sets oder Themen gefunden."
|
||||
|
||||
#: src/app/main/data/workspace/tokens/errors.cljs:53
|
||||
msgid "workspace.tokens.number-too-large"
|
||||
msgstr "Ungültiger Tokenwert. Der ermittelte Wert ist zu hoch: %s"
|
||||
|
||||
#: src/app/main/data/workspace/tokens/errors.cljs:73, src/app/main/data/workspace/tokens/warnings.cljs:15
|
||||
msgid "workspace.tokens.opacity-range"
|
||||
msgstr ""
|
||||
"Die Deckkraft muss zwischen 0 und 100 % oder zwischen 0 und 1 liegen (z. B. "
|
||||
"50 % oder 0,5)."
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/management/context_menu.cljs:201
|
||||
msgid "workspace.tokens.paddings"
|
||||
msgstr "Innenabstände"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/management/context_menu.cljs:277
|
||||
msgid "workspace.tokens.radius"
|
||||
msgstr "Radius"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:775
|
||||
msgid "workspace.tokens.reference-composite"
|
||||
msgstr "Geben Sie einen Typografie-Alias für diesen Token ein"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/style_dictionary.cljs
|
||||
#, unused
|
||||
msgid "workspace.tokens.reference-error"
|
||||
msgstr "Referenzfehler: "
|
||||
|
||||
#: src/app/main/data/workspace/tokens/errors.cljs:45, src/app/main/ui/workspace/tokens/management/create/border_radius.cljs:55
|
||||
msgid "workspace.tokens.self-reference"
|
||||
msgstr "Der Token referenziert sich selbst"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/sets/lists.cljs:60
|
||||
msgid "workspace.tokens.set-edit-placeholder"
|
||||
msgstr "Namen eingeben (für Gruppen „/“ verwenden)"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/themes/create_modal.cljs:168
|
||||
msgid "workspace.tokens.sets-hint"
|
||||
msgstr "Theme bearbeiten und Sets verwalten"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/settings/menu.cljs:91
|
||||
msgid "workspace.tokens.setting-description"
|
||||
msgstr ""
|
||||
"Hier können Sie die grundlegende Schriftgröße festlegen, die als Wert für "
|
||||
"1rem verwendet wird:"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/settings/menu.cljs:84
|
||||
msgid "workspace.tokens.settings"
|
||||
msgstr "Token-Einstellungen"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:1084
|
||||
msgid "workspace.tokens.shadow-add-shadow"
|
||||
msgstr "Schatten hinzufügen"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:981, src/app/main/ui/workspace/tokens/management/create/form.cljs:982
|
||||
msgid "workspace.tokens.shadow-blur"
|
||||
msgstr "Weichzeichnen"
|
||||
|
||||
#: src/app/main/data/workspace/tokens/errors.cljs:105
|
||||
msgid "workspace.tokens.shadow-blur-range"
|
||||
msgstr "Wert muss größer oder gleich 0 sein."
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:987, src/app/main/ui/workspace/tokens/management/create/form.cljs:988
|
||||
msgid "workspace.tokens.shadow-color"
|
||||
msgstr "Farbe"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:990, src/app/main/ui/workspace/tokens/management/create/form.cljs:991
|
||||
msgid "workspace.tokens.shadow-inset"
|
||||
msgstr "Innerer Schatten"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:1091
|
||||
msgid "workspace.tokens.shadow-remove-shadow"
|
||||
msgstr "Schatten entfernen"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:1215
|
||||
msgid "workspace.tokens.shadow-title"
|
||||
msgstr "Schatten"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:975, src/app/main/ui/workspace/tokens/management/create/form.cljs:976
|
||||
msgid "workspace.tokens.shadow-x"
|
||||
msgstr "X"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:978, src/app/main/ui/workspace/tokens/management/create/form.cljs:979
|
||||
msgid "workspace.tokens.shadow-y"
|
||||
msgstr "Y"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/management/context_menu.cljs:241
|
||||
msgid "workspace.tokens.size"
|
||||
msgstr "Größe"
|
||||
|
||||
#: src/app/main/data/workspace/tokens/errors.cljs:77, src/app/main/data/workspace/tokens/warnings.cljs:19
|
||||
msgid "workspace.tokens.stroke-width-range"
|
||||
msgstr "Die Rahmenbreite muss größer oder gleich 0 sein."
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:1322, src/app/main/ui/workspace/tokens/management/create/form.cljs:1359
|
||||
msgid "workspace.tokens.text-decoration-value-enter"
|
||||
msgstr "none | underline | strike-through oder {alias}"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:1316, src/app/main/ui/workspace/tokens/management/create/form.cljs:1355
|
||||
msgid "workspace.tokens.text-case-value-enter"
|
||||
msgstr "none | uppercase | lowercase | capitalize oder {alias}"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/themes/create_modal.cljs:52
|
||||
msgid "workspace.tokens.theme-name-already-exists"
|
||||
msgstr "Ein Theme mit diesem Namen existiert bereits"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:1283, src/app/main/ui/workspace/tokens/management/create/form.cljs:1335
|
||||
msgid "workspace.tokens.token-font-family-value-enter"
|
||||
msgstr "Schriftfamilie oder eine durch Kommas (,) getrennte Liste von Schriften"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/management/create/border_radius.cljs:44, src/app/main/ui/workspace/tokens/management/create/form.cljs:70
|
||||
msgid "workspace.tokens.token-name-duplication-validation-error"
|
||||
msgstr "Unter diesem Speicherort existiert bereits ein Token: %s"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/management/create/border_radius.cljs:42, src/app/main/ui/workspace/tokens/management/create/form.cljs:68
|
||||
msgid "workspace.tokens.token-name-length-validation-error"
|
||||
msgstr "Der Name muss mindestens 1 Zeichen lang sein"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/style_dictionary.cljs:259
|
||||
#, unused
|
||||
msgid "workspace.tokens.token-not-resolved"
|
||||
msgstr "Das Token mit dem Namen „%s” konnte nicht gefunden werden"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/management/create/border_radius.cljs:185, src/app/main/ui/workspace/tokens/management/create/form.cljs:605
|
||||
msgid "workspace.tokens.token-value-enter"
|
||||
msgstr "Geben Sie einen Wert oder einen Alias mittels {alias} ein"
|
||||
|
||||
#: src/app/main/data/workspace/tokens/import_export.cljs:49
|
||||
msgid "workspace.tokens.unknown-token-type-section"
|
||||
msgstr "„%s“ wird nicht als Datentyp unterstützt (%s)\n"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:745
|
||||
msgid "workspace.tokens.use-reference"
|
||||
msgstr "Referenz verwenden"
|
||||
|
||||
#: src/app/main/data/workspace/tokens/errors.cljs:65
|
||||
msgid "workspace.tokens.value-with-units"
|
||||
msgstr "Ungültiger Wert: Einheiten sind hier nicht zulässig."
|
||||
|
||||
#: src/app/main/ui/workspace/top_toolbar.cljs:129
|
||||
msgid "workspace.toolbar.frame-first-time"
|
||||
msgstr ""
|
||||
"Zeichenfläche erstellen. Zum Festlegen der Größe anklicken und ziehen. (%s)"
|
||||
|
||||
#, unused
|
||||
msgid "workspace.versions.locked-by-other"
|
||||
msgstr ""
|
||||
"Diese Version ist durch %s gesperrt und kann gerade nicht bearbeitet werden"
|
||||
|
||||
@@ -8421,3 +8421,111 @@ msgstr "Autosaved versions will be kept for %s days."
|
||||
#, unused
|
||||
msgid "workspace.viewport.click-to-close-path"
|
||||
msgstr "Click to close the path"
|
||||
|
||||
msgid "dashboard.labels.recent"
|
||||
msgstr "Recent"
|
||||
|
||||
msgid "dashboard.labels.deleted"
|
||||
msgstr "Deleted"
|
||||
|
||||
msgid "dashboard.deleted.restore-all"
|
||||
msgstr "Restore All"
|
||||
|
||||
msgid "dashboard.deleted.clear"
|
||||
msgstr "Clear trash"
|
||||
|
||||
msgid "dashboard.restore-file"
|
||||
msgstr "Restore file"
|
||||
|
||||
msgid "dashboard.delete-file"
|
||||
msgstr "Delete file"
|
||||
|
||||
msgid "dashboard.deleted.restore-project"
|
||||
msgstr "Restore project"
|
||||
|
||||
msgid "dashboard.deleted.delete-project"
|
||||
msgstr "Delete project"
|
||||
|
||||
msgid "dashboard.deleted.info-text"
|
||||
msgstr "Deleted files will remain in the trash for"
|
||||
|
||||
msgid "dashboard.deleted.info-days"
|
||||
msgstr " %s days. "
|
||||
|
||||
msgid "dashboard.deleted.info-text2"
|
||||
msgstr "After that, they will be permanently deleted."
|
||||
|
||||
msgid "dashboard.deleted.restore-text"
|
||||
msgstr "If you change your mind, you can restore them or delete them permanently from each file's menu."
|
||||
|
||||
msgid "dashboard.deleted.delete-forever"
|
||||
msgstr "Delete forever"
|
||||
|
||||
msgid "restore-modal.restore-all.title"
|
||||
msgstr "Restore all projects and files"
|
||||
|
||||
msgid "restore-modal.restore-all.description"
|
||||
msgstr "You're going to restore all your projects and files. This may take a while."
|
||||
|
||||
msgid "restore-modal.restore-file.title"
|
||||
msgstr "Restore file"
|
||||
|
||||
msgid "restore-modal.restore-file.description"
|
||||
msgstr "You're going to restore %s."
|
||||
|
||||
msgid "restore-modal.restore-project.title"
|
||||
msgstr "Restore Project"
|
||||
|
||||
msgid "restore-modal.restore-project.description"
|
||||
msgstr "You're going to restore %s project and all the files contained in it."
|
||||
|
||||
msgid "delete-forever-modal.title"
|
||||
msgstr "Delete forever"
|
||||
|
||||
msgid "delete-forever-modal.delete-all.description"
|
||||
msgstr "Are you sure you want to delete forever all your deleted projects and files? This is a non reversible action."
|
||||
|
||||
msgid "delete-forever-modal.delete-file.description"
|
||||
msgstr "Are you sure you want to delete forever %s? This is a non reversible action."
|
||||
|
||||
msgid "delete-forever-modal.delete-project.description"
|
||||
msgstr "Are you sure you want to delete forever %s project? You're going to delete it forever an all of the files contained in it. This is a non reeversible action."
|
||||
|
||||
msgid "restore-modal.success-restore-immediately"
|
||||
msgstr "%s has been successfully restored."
|
||||
|
||||
msgid "delete-forever-modal.success-delete-immediately"
|
||||
msgstr "%s has been successfully deleted."
|
||||
|
||||
msgid "restore-modal.error-restore-files"
|
||||
msgstr "There was an error while restoring the files."
|
||||
|
||||
msgid "restore-modal.error-restore-file"
|
||||
msgstr "There was an error while restoring the file %s."
|
||||
|
||||
msgid "restore-modal.error-restore-project"
|
||||
msgstr "There was an error while restoring the project %s and its files."
|
||||
|
||||
msgid "restore-modal.normal-progress-label"
|
||||
msgstr "Restoring files…"
|
||||
|
||||
msgid "restore-modal.failed-progress-label"
|
||||
msgstr "Restore failed"
|
||||
|
||||
msgid "restore-modal.slow-progress-label"
|
||||
msgstr "Restore unexpectedly slow"
|
||||
|
||||
msgid "restore-modal.complete-process-label"
|
||||
msgstr "Restore completed"
|
||||
|
||||
msgid "progress-widget.default-normal-progress-label"
|
||||
msgstr "Processing…"
|
||||
|
||||
msgid "progress-widget.default-failed-progress-label"
|
||||
msgstr "Process failed"
|
||||
|
||||
msgid "progress-widget.default-slow-progress-label"
|
||||
msgstr "Process unexpectedly slow"
|
||||
|
||||
msgid "progress-widget.default-complete-progress-label"
|
||||
msgstr "Process completed"
|
||||
@@ -1,15 +1,15 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"PO-Revision-Date: 2025-10-07 16:35+0000\n"
|
||||
"Last-Translator: Deleted User <noreply+94857@weblate.org>\n"
|
||||
"Language-Team: Spanish "
|
||||
"<https://hosted.weblate.org/projects/penpot/frontend/es/>\n"
|
||||
"PO-Revision-Date: 2025-12-22 15:34+0000\n"
|
||||
"Last-Translator: Anonymous <noreply@weblate.org>\n"
|
||||
"Language-Team: Spanish <https://hosted.weblate.org/projects/penpot/frontend/"
|
||||
"es/>\n"
|
||||
"Language: es\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||
"X-Generator: Weblate 5.14-dev\n"
|
||||
"X-Generator: Weblate 5.15.1\n"
|
||||
|
||||
#: src/app/main/ui/auth/register.cljs:215, src/app/main/ui/static.cljs:159, src/app/main/ui/viewer/login.cljs:100
|
||||
msgid "auth.already-have-account"
|
||||
@@ -1843,6 +1843,7 @@ msgid "inspect.empty.select"
|
||||
msgstr "Elige una forma, tablero o grupo para inspeccionar sus propiedades y código"
|
||||
|
||||
#: src/app/main/ui/inspect/right_sidebar.cljs:166
|
||||
#, fuzzy
|
||||
msgid "inspect.layer-info"
|
||||
msgstr "Info. de capa"
|
||||
|
||||
@@ -8276,3 +8277,111 @@ msgstr "Los autoguardados duran %s días."
|
||||
#, unused
|
||||
msgid "workspace.viewport.click-to-close-path"
|
||||
msgstr "Pulsar para cerrar la ruta"
|
||||
|
||||
msgid "dashboard.labels.recent"
|
||||
msgstr "Recientes"
|
||||
|
||||
msgid "dashboard.labels.deleted"
|
||||
msgstr "Eliminados"
|
||||
|
||||
msgid "dashboard.deleted.restore-all"
|
||||
msgstr "Restaurar todo"
|
||||
|
||||
msgid "dashboard.deleted.clear"
|
||||
msgstr "Vaciar papelera"
|
||||
|
||||
msgid "dashboard.restore-file"
|
||||
msgstr "Restaurar archivo"
|
||||
|
||||
msgid "dashboard.delete-file"
|
||||
msgstr "Eliminar archivo"
|
||||
|
||||
msgid "dashboard.deleted.restore-project"
|
||||
msgstr "Restaurar proyecto"
|
||||
|
||||
msgid "dashboard.deleted.delete-project"
|
||||
msgstr "Eliminar proyecto"
|
||||
|
||||
msgid "dashboard.deleted.info-text"
|
||||
msgstr "Los archivos eliminados permanecerán en la papelera durante"
|
||||
|
||||
msgid "dashboard.deleted.info-days"
|
||||
msgstr " %s días. "
|
||||
|
||||
msgid "dashboard.deleted.info-text2"
|
||||
msgstr "Después de eso, serán eliminados permanentemente."
|
||||
|
||||
msgid "dashboard.deleted.restore-text"
|
||||
msgstr "Si cambias de opinión, puedes restaurarlos o eliminarlos permanentemente desde el menú de cada archivo."
|
||||
|
||||
msgid "dashboard.deleted.delete-forever"
|
||||
msgstr "Eliminar para siempre"
|
||||
|
||||
msgid "restore-modal.restore-all.title"
|
||||
msgstr "Restaurar todos los proyectos y archivos"
|
||||
|
||||
msgid "restore-modal.restore-all.description"
|
||||
msgstr "Vas a restaurar todos tus proyectos y archivos. Esto puede tardar un poco."
|
||||
|
||||
msgid "restore-modal.restore-file.title"
|
||||
msgstr "Restaurar archivo"
|
||||
|
||||
msgid "restore-modal.restore-file.description"
|
||||
msgstr "Vas a restaurar %s."
|
||||
|
||||
msgid "restore-modal.restore-project.title"
|
||||
msgstr "Restaurar proyecto"
|
||||
|
||||
msgid "restore-modal.restore-project.description"
|
||||
msgstr "Vas a restaurar el proyecto %s y todos los archivos que contiene."
|
||||
|
||||
msgid "delete-forever-modal.title"
|
||||
msgstr "Eliminar para siempre"
|
||||
|
||||
msgid "delete-forever-modal.delete-all.description"
|
||||
msgstr "¿Estás seguro de que quieres eliminar para siempre todos tus proyectos y archivos eliminados? Esta es una acción irreversible."
|
||||
|
||||
msgid "delete-forever-modal.delete-file.description"
|
||||
msgstr "¿Estás seguro de que quieres eliminar para siempre %s? Esta es una acción irreversible."
|
||||
|
||||
msgid "delete-forever-modal.delete-project.description"
|
||||
msgstr "¿Estás seguro de que quieres eliminar para siempre el proyecto %s? Vas a eliminarlo para siempre junto con todos los archivos que contiene. Esta es una acción irreversible."
|
||||
|
||||
msgid "restore-modal.success-restore-immediately"
|
||||
msgstr "%s ha sido restaurado correctamente."
|
||||
|
||||
msgid "delete-forever-modal.success-delete-immediately"
|
||||
msgstr "%s ha sido eliminado correctamente."
|
||||
|
||||
msgid "restore-modal.error-restore-files"
|
||||
msgstr "Hubo un error al restaurar los archivos."
|
||||
|
||||
msgid "restore-modal.error-restore-file"
|
||||
msgstr "Hubo un error al restaurar el archivo %s."
|
||||
|
||||
msgid "restore-modal.error-restore-project"
|
||||
msgstr "Hubo un error al restaurar el proyecto %s y sus archivos."
|
||||
|
||||
msgid "restore-modal.normal-progress-label"
|
||||
msgstr "Restaurando archivos…"
|
||||
|
||||
msgid "restore-modal.failed-progress-label"
|
||||
msgstr "Falló la restauración"
|
||||
|
||||
msgid "restore-modal.slow-progress-label"
|
||||
msgstr "Restauración lenta"
|
||||
|
||||
msgid "restore-modal.complete-process-label"
|
||||
msgstr "Restauración completada"
|
||||
|
||||
msgid "progress-widget.default-normal-progress-label"
|
||||
msgstr "Procesando…"
|
||||
|
||||
msgid "progress-widget.default-failed-progress-label"
|
||||
msgstr "Falló el procesamiento"
|
||||
|
||||
msgid "progress-widget.default-slow-progress-label"
|
||||
msgstr "Procesamiento lento"
|
||||
|
||||
msgid "progress-widget.default-complete-progress-label"
|
||||
msgstr "Procesamiento completado"
|
||||
@@ -1,15 +1,15 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"PO-Revision-Date: 2024-06-17 08:07+0000\n"
|
||||
"Last-Translator: Anonymous <noreply@weblate.org>\n"
|
||||
"Language-Team: Spanish (Latin America) "
|
||||
"<https://hosted.weblate.org/projects/penpot/frontend/es_419/>\n"
|
||||
"PO-Revision-Date: 2025-12-22 15:34+0000\n"
|
||||
"Last-Translator: Yessenia Villarte Vaca <yesseniavillarte@gmail.com>\n"
|
||||
"Language-Team: Spanish (Latin America) <https://hosted.weblate.org/projects/"
|
||||
"penpot/frontend/es_419/>\n"
|
||||
"Language: es_419\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||
"X-Generator: Weblate 5.6-dev\n"
|
||||
"X-Generator: Weblate 5.15.1\n"
|
||||
|
||||
#: src/app/main/ui/auth/register.cljs:215, src/app/main/ui/static.cljs:159, src/app/main/ui/viewer/login.cljs:100
|
||||
msgid "auth.already-have-account"
|
||||
@@ -454,6 +454,7 @@ msgstr ""
|
||||
"¿Qué quiere hacer con sus activos*?"
|
||||
|
||||
#: src/app/main/ui/exports/files.cljs:164
|
||||
#, fuzzy
|
||||
msgid "dashboard.export.options.all.message"
|
||||
msgstr ""
|
||||
"Los archivos con bibliotecas compartidas se incluirán en la exportación, "
|
||||
|
||||
@@ -1188,10 +1188,6 @@ msgstr ""
|
||||
"Diseinua ikuskatzeari buruz gehiago jakin nahi baduzu zoaz Penpoten "
|
||||
"laguntza zentrora"
|
||||
|
||||
#: src/app/main/ui/inspect/right_sidebar.cljs:240
|
||||
msgid "inspect.empty.more-info"
|
||||
msgstr "Informazio gehiago ikuskatzeari buruz"
|
||||
|
||||
#: src/app/main/ui/inspect/right_sidebar.cljs:232
|
||||
msgid "inspect.empty.select"
|
||||
msgstr ""
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"PO-Revision-Date: 2025-11-10 07:51+0000\n"
|
||||
"PO-Revision-Date: 2025-12-22 15:34+0000\n"
|
||||
"Last-Translator: Ahmad HosseinBor <123hozeifeh@gmail.com>\n"
|
||||
"Language-Team: Persian "
|
||||
"<https://hosted.weblate.org/projects/penpot/frontend/fa/>\n"
|
||||
"Language-Team: Persian <https://hosted.weblate.org/projects/penpot/frontend/"
|
||||
"fa/>\n"
|
||||
"Language: fa\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=n > 1;\n"
|
||||
"X-Generator: Weblate 5.15-dev\n"
|
||||
"X-Generator: Weblate 5.15.1\n"
|
||||
|
||||
#: src/app/main/ui/auth/register.cljs:215, src/app/main/ui/static.cljs:159, src/app/main/ui/viewer/login.cljs:100
|
||||
msgid "auth.already-have-account"
|
||||
@@ -501,10 +501,11 @@ msgstr ""
|
||||
"میکنند. با داراییهای آنها چه میخواهید بکنید*؟"
|
||||
|
||||
#: src/app/main/ui/exports/files.cljs:164
|
||||
#, fuzzy
|
||||
msgid "dashboard.export.options.all.message"
|
||||
msgstr ""
|
||||
"فایلهای دارای کتابخانههای مشترک در اکسپورت گنجانده میشوند و پیوند خود را "
|
||||
"حفظ میکنند."
|
||||
"فایلهای دارای کتابخانههای مشترک در اکسپورت گنجانده میشوند و پیوند خود را حفظ "
|
||||
"میکنند."
|
||||
|
||||
#: src/app/main/ui/exports/files.cljs:165
|
||||
msgid "dashboard.export.options.all.title"
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"PO-Revision-Date: 2025-10-27 12:02+0000\n"
|
||||
"Last-Translator: Ingrid Pigueron <ingridp.uxr@gmail.com>\n"
|
||||
"Language-Team: French "
|
||||
"<https://hosted.weblate.org/projects/penpot/frontend/fr/>\n"
|
||||
"PO-Revision-Date: 2025-12-22 15:34+0000\n"
|
||||
"Last-Translator: Anonymous <noreply@weblate.org>\n"
|
||||
"Language-Team: French <https://hosted.weblate.org/projects/penpot/frontend/"
|
||||
"fr/>\n"
|
||||
"Language: fr\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n!=1);\n"
|
||||
"X-Generator: Weblate 5.14.1-dev\n"
|
||||
"X-Generator: Weblate 5.15.1\n"
|
||||
|
||||
#: src/app/main/ui/auth/register.cljs:215, src/app/main/ui/static.cljs:159, src/app/main/ui/viewer/login.cljs:100
|
||||
msgid "auth.already-have-account"
|
||||
@@ -585,6 +585,7 @@ msgstr ""
|
||||
"bibliothèques partagées. Que voulez-vous faire avec leurs ressources ?"
|
||||
|
||||
#: src/app/main/ui/exports/files.cljs:164
|
||||
#, fuzzy
|
||||
msgid "dashboard.export.options.all.message"
|
||||
msgstr ""
|
||||
"Les fichiers avec des bibliothèques partagées seront inclus dans "
|
||||
@@ -1840,10 +1841,6 @@ msgstr "Propriétés des variantes"
|
||||
msgid "inspect.empty.help"
|
||||
msgstr "Pour en savoir plus sur l'inspection, visitez le centre d'aide de Penpot"
|
||||
|
||||
#: src/app/main/ui/inspect/right_sidebar.cljs:240
|
||||
msgid "inspect.empty.more-info"
|
||||
msgstr "Plus d'informations sur l'inspection"
|
||||
|
||||
#: src/app/main/ui/inspect/right_sidebar.cljs:232
|
||||
msgid "inspect.empty.select"
|
||||
msgstr ""
|
||||
@@ -1851,6 +1848,7 @@ msgstr ""
|
||||
"leurs propriétés et le code"
|
||||
|
||||
#: src/app/main/ui/inspect/right_sidebar.cljs:166
|
||||
#, fuzzy
|
||||
msgid "inspect.layer-info"
|
||||
msgstr "Info sur la couche"
|
||||
|
||||
@@ -8228,3 +8226,86 @@ msgstr "Les versions auto-enregistrées seront gardées %s jours."
|
||||
#, unused
|
||||
msgid "workspace.viewport.click-to-close-path"
|
||||
msgstr "Cliquez pour fermer le chemin"
|
||||
|
||||
#: src/app/main/ui/settings/feedback.cljs:122
|
||||
msgid "feedback.description-placeholder"
|
||||
msgstr "Décrivez la raison de votre commentaire"
|
||||
|
||||
#: src/app/main/ui/settings/feedback.cljs:143
|
||||
msgid "feedback.other-ways-contact"
|
||||
msgstr "Autres méthodes de contact"
|
||||
|
||||
#: src/app/main/ui/settings/feedback.cljs:126
|
||||
msgid "feedback.penpot.link"
|
||||
msgstr ""
|
||||
"Si le commentaire concerne un fichier ou un projet, ajoutez le lien penpot "
|
||||
"ici :"
|
||||
|
||||
#: src/app/main/ui/settings/feedback.cljs:110, src/app/main/ui/settings/feedback.cljs:111
|
||||
#, fuzzy
|
||||
msgid "feedback.type"
|
||||
msgstr "Type"
|
||||
|
||||
#: src/app/main/ui/settings/feedback.cljs:113
|
||||
msgid "feedback.type.idea"
|
||||
msgstr "Idée"
|
||||
|
||||
#: src/app/main/ui/inspect/styles/rows/color_properties_row.cljs:120
|
||||
msgid "inspect.attributes.image.preview"
|
||||
msgstr "Aperçu de l'image de remplissage de la forme"
|
||||
|
||||
#: src/app/main/ui/static.cljs:68
|
||||
msgid "labels.copyright-period"
|
||||
msgstr "Kaleidos © depuis 2019"
|
||||
|
||||
#: src/app/main/ui/settings/feedback.cljs:134, src/app/main/ui/static.cljs:400
|
||||
msgid "labels.download"
|
||||
msgstr "Télécharger %s"
|
||||
|
||||
#: src/app/main/ui/dashboard/sidebar.cljs:1020
|
||||
msgid "labels.help-learning"
|
||||
msgstr "Aide et formation"
|
||||
|
||||
#: src/app/main/ui/static.cljs:396
|
||||
msgid "labels.internal-error.desc-message-first"
|
||||
msgstr "Un incident est survenu."
|
||||
|
||||
#: src/app/main/ui/static.cljs:397
|
||||
msgid "labels.internal-error.desc-message-second"
|
||||
msgstr ""
|
||||
"Vous pouvez réessayer d'effectuer l'opération ou contacter l'assistance "
|
||||
"technique pour signaler l'erreur."
|
||||
|
||||
#: src/app/main/ui/dashboard/sidebar.cljs:799
|
||||
msgid "labels.learning-center"
|
||||
msgstr "Centre de formation"
|
||||
|
||||
#: src/app/main/ui/settings/feedback.cljs:101
|
||||
msgid "feedback.title-contact-us"
|
||||
msgstr "Contact"
|
||||
|
||||
#: src/app/main/ui/inspect/right_sidebar.cljs:170
|
||||
msgid "inspect.color-space-label"
|
||||
msgstr "Sélectionner un espace de couleur"
|
||||
|
||||
#: src/app/main/ui/static.cljs:406
|
||||
msgid "labels.contact-support"
|
||||
msgstr "Contacter l'assistance technique"
|
||||
|
||||
#: src/app/main/ui/settings/sidebar.cljs:136
|
||||
msgid "labels.contact-us"
|
||||
msgstr "Contact"
|
||||
|
||||
#: src/app/main/ui/dashboard/subscription.cljs:83
|
||||
msgid "subscription.dashboard.power-up.professional.bottom-description"
|
||||
msgstr ""
|
||||
"Bénéficiez de stockage supplémentaire, de la récupération de fichiers et de "
|
||||
"bien plus encore pour vos équipes."
|
||||
|
||||
#: src/app/main/ui/dashboard/subscription.cljs:101
|
||||
#, markdown
|
||||
msgid "subscription.dashboard.power-up.unlimited.bottom-text"
|
||||
msgstr ""
|
||||
"Bénéficiez d'un stockage illimité, de la récupération de fichier étendue et "
|
||||
"d'un nombre illimité d'éditeurs pour toutes vos équipes à un tarif fixe. "
|
||||
"[Consultez le forfait Entreprise.|target:self](%s)"
|
||||
|
||||
@@ -1244,10 +1244,6 @@ msgstr "manyan baqaqe"
|
||||
msgid "inspect.empty.help"
|
||||
msgstr "domin neman qarin bayani game da fenfot a tuntubi sashen agaji"
|
||||
|
||||
#: src/app/main/ui/inspect/right_sidebar.cljs:240
|
||||
msgid "inspect.empty.more-info"
|
||||
msgstr "qarin bayani a fagen lura"
|
||||
|
||||
#: src/app/main/ui/inspect/right_sidebar.cljs:232
|
||||
msgid "inspect.empty.select"
|
||||
msgstr "zabar zubi, hukumar masu sa ido akan bangarorinsu da lambobinsu"
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"PO-Revision-Date: 2025-10-14 17:07+0000\n"
|
||||
"PO-Revision-Date: 2025-12-22 15:34+0000\n"
|
||||
"Last-Translator: Yaron Shahrabani <sh.yaron@gmail.com>\n"
|
||||
"Language-Team: Hebrew "
|
||||
"<https://hosted.weblate.org/projects/penpot/frontend/he/>\n"
|
||||
"Language-Team: Hebrew <https://hosted.weblate.org/projects/penpot/frontend/"
|
||||
"he/>\n"
|
||||
"Language: he\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=4; plural=(n == 1) ? 0 : ((n == 2) ? 1 : ((n > 10 && "
|
||||
"n % 10 == 0) ? 2 : 3));\n"
|
||||
"X-Generator: Weblate 5.14-dev\n"
|
||||
"X-Generator: Weblate 5.15.1\n"
|
||||
|
||||
#: src/app/main/ui/auth/register.cljs:215, src/app/main/ui/static.cljs:159, src/app/main/ui/viewer/login.cljs:100
|
||||
msgid "auth.already-have-account"
|
||||
@@ -564,6 +564,7 @@ msgstr ""
|
||||
"המשאבים שלהן*?"
|
||||
|
||||
#: src/app/main/ui/exports/files.cljs:164
|
||||
#, fuzzy
|
||||
msgid "dashboard.export.options.all.message"
|
||||
msgstr "קבצים עם ספריות משותפות יצורפו לייצוא, תוך שימור הקישוריות שלהם."
|
||||
|
||||
@@ -1769,17 +1770,14 @@ msgstr "מאפייני הגוונים"
|
||||
msgid "inspect.empty.help"
|
||||
msgstr "למידע נוסף על חקירת עיצוב אפשר לבקר במרכז העזרה של Penpot"
|
||||
|
||||
#: src/app/main/ui/inspect/right_sidebar.cljs:240
|
||||
msgid "inspect.empty.more-info"
|
||||
msgstr "מידע נוסף על חקירה"
|
||||
|
||||
#: src/app/main/ui/inspect/right_sidebar.cljs:232
|
||||
msgid "inspect.empty.select"
|
||||
msgstr "ניתן לבחור צורה, לוח או קבוצה ולראות את המאפיינים והקוד שלהם"
|
||||
|
||||
#: src/app/main/ui/inspect/right_sidebar.cljs:166
|
||||
#, fuzzy
|
||||
msgid "inspect.layer-info"
|
||||
msgstr "פרטי שכבה"
|
||||
msgstr "בחירת לשונית חקירה"
|
||||
|
||||
#: src/app/main/ui/inspect/right_sidebar.cljs:137
|
||||
msgid "inspect.multiple-selected"
|
||||
@@ -2194,7 +2192,7 @@ msgstr "בלתי פעיל"
|
||||
|
||||
#: src/app/main/ui/inspect/right_sidebar.cljs:114
|
||||
msgid "labels.info"
|
||||
msgstr "מידע"
|
||||
msgstr "פירוט"
|
||||
|
||||
#: src/app/main/ui/dashboard/fonts.cljs:428
|
||||
msgid "labels.installed-fonts"
|
||||
@@ -4663,7 +4661,6 @@ msgid "subscription.settings.sucess.dialog.title"
|
||||
msgstr "התוכנית שלך היא %s!"
|
||||
|
||||
#: src/app/main/ui/settings/subscription.cljs:440
|
||||
#, fuzzy
|
||||
msgid "subscription.settings.support-us-since"
|
||||
msgstr "תמכת בנו עם התוכנית הזאת מאז: %s"
|
||||
|
||||
@@ -7583,7 +7580,7 @@ msgstr "הוספת ערכת עיצוב (למשל: בהירה)"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:1351
|
||||
msgid "workspace.tokens.letter-spacing-value-enter-composite"
|
||||
msgstr "הוספת ריווח תווים או {alias}"
|
||||
msgstr "ריווח תווים או {alias}"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/management/context_menu.cljs:217
|
||||
msgid "workspace.tokens.margins"
|
||||
@@ -7654,7 +7651,6 @@ msgid "workspace.tokens.opacity-range"
|
||||
msgstr "שקיפות צריכה להיות בין 0 ל־100% או 0 ו־1 (כלומר 50% או 0.5)."
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/management/token_pill.cljs:120
|
||||
#, fuzzy
|
||||
msgid "workspace.tokens.original-value"
|
||||
msgstr "ערך מקורי: %s"
|
||||
|
||||
@@ -7680,7 +7676,6 @@ msgid "workspace.tokens.reference-error"
|
||||
msgstr "שגיאות הפניה: "
|
||||
|
||||
#: src/app/main/data/workspace/tokens/warnings.cljs:15, src/app/main/data/workspace/tokens/warnings.cljs:19, src/app/main/ui/workspace/colorpicker/color_tokens.cljs:56, src/app/main/ui/workspace/colorpicker/color_tokens.cljs:84, src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs:102, src/app/main/ui/workspace/tokens/management/create/form_input_token.cljs:109, src/app/main/ui/workspace/tokens/management/create/input_tokens_value.cljs:41, src/app/main/ui/workspace/tokens/management/create/input_tokens_value.cljs:46, src/app/main/ui/workspace/tokens/management/token_pill.cljs:121
|
||||
#, fuzzy
|
||||
msgid "workspace.tokens.resolved-value"
|
||||
msgstr "ערך פתור: %s"
|
||||
|
||||
@@ -7744,7 +7739,6 @@ msgid "workspace.tokens.themes-list"
|
||||
msgstr "רשימת ערכות עיצוב"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/management/create/border_radius.cljs:194, src/app/main/ui/workspace/tokens/management/create/border_radius.cljs:195, src/app/main/ui/workspace/tokens/management/create/form.cljs:629, src/app/main/ui/workspace/tokens/management/create/form.cljs:630
|
||||
#, fuzzy
|
||||
msgid "workspace.tokens.token-description"
|
||||
msgstr "תיאור"
|
||||
|
||||
@@ -8147,3 +8141,214 @@ msgstr "גרסאות שנשמרו אוטומטית תישמרנה למשך %s י
|
||||
#, unused
|
||||
msgid "workspace.viewport.click-to-close-path"
|
||||
msgstr "לחיצה תסגור את הנתיב"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/management/create/border_radius.cljs:52, src/app/main/ui/workspace/tokens/management/create/form.cljs:80
|
||||
msgid "errors.field-max-length"
|
||||
msgstr "חייב להכיל עד %s תווים."
|
||||
|
||||
#: src/app/main/ui/settings/feedback.cljs:122
|
||||
msgid "feedback.description-placeholder"
|
||||
msgstr "נא לתאר את הסיבה למשוב שלך"
|
||||
|
||||
#: src/app/main/ui/settings/feedback.cljs:143
|
||||
msgid "feedback.other-ways-contact"
|
||||
msgstr "דרכים אחרות ליצור איתנו קשר"
|
||||
|
||||
#: src/app/main/ui/settings/feedback.cljs:126
|
||||
msgid "feedback.penpot.link"
|
||||
msgstr ""
|
||||
"אם המשוב הוא משהו שקשור לקובץ או למיזם, יש להוסיף את קישור ה־penpot לכאן:"
|
||||
|
||||
#: src/app/main/ui/settings/feedback.cljs:101
|
||||
msgid "feedback.title-contact-us"
|
||||
msgstr "ליצור איתנו קשר"
|
||||
|
||||
#: src/app/main/ui/settings/feedback.cljs:110, src/app/main/ui/settings/feedback.cljs:111
|
||||
msgid "feedback.type"
|
||||
msgstr "סוג"
|
||||
|
||||
#: src/app/main/ui/settings/feedback.cljs:115
|
||||
msgid "feedback.type.doubt"
|
||||
msgstr "ספק"
|
||||
|
||||
#: src/app/main/ui/settings/feedback.cljs:113
|
||||
msgid "feedback.type.idea"
|
||||
msgstr "רעיון"
|
||||
|
||||
#: src/app/main/ui/settings/feedback.cljs:114
|
||||
msgid "feedback.type.issue"
|
||||
msgstr "בעיה"
|
||||
|
||||
#: src/app/main/ui/inspect/styles/rows/color_properties_row.cljs:120
|
||||
msgid "inspect.attributes.image.preview"
|
||||
msgstr "תצוגה מקדימה של תמונת מילוי הצורה"
|
||||
|
||||
#: src/app/main/ui/inspect/right_sidebar.cljs:170
|
||||
msgid "inspect.color-space-label"
|
||||
msgstr "בחירת מרחב צבע"
|
||||
|
||||
#: src/app/main/ui/inspect/styles/style_box.cljs:68
|
||||
msgid "inspect.tabs.styles.copy-shorthand"
|
||||
msgstr "העתקת קיצור CSS ללוח הגזירים"
|
||||
|
||||
#: src/app/main/ui/static.cljs:406
|
||||
msgid "labels.contact-support"
|
||||
msgstr "יצירת קשר עם התמיכה"
|
||||
|
||||
#: src/app/main/ui/settings/sidebar.cljs:136
|
||||
msgid "labels.contact-us"
|
||||
msgstr "יצירת קשר איתנו"
|
||||
|
||||
#: src/app/main/ui/static.cljs:68
|
||||
msgid "labels.copyright-period"
|
||||
msgstr "Kaleidos © 2019-עכשיו"
|
||||
|
||||
#: src/app/main/ui/settings/feedback.cljs:134, src/app/main/ui/static.cljs:400
|
||||
msgid "labels.download"
|
||||
msgstr "הורדת %s"
|
||||
|
||||
#: src/app/main/ui/static.cljs:396
|
||||
msgid "labels.internal-error.desc-message-first"
|
||||
msgstr "משהו גרוע התרחש."
|
||||
|
||||
#: src/app/main/ui/static.cljs:397
|
||||
msgid "labels.internal-error.desc-message-second"
|
||||
msgstr ""
|
||||
"אפשר לנסות לבצע את הפעולה שוב או ליצור קשר עם התמיכה כדי לדווח על השגיאה."
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/rows/stroke_row.cljs:229
|
||||
msgid "labels.switch"
|
||||
msgstr "החלפה"
|
||||
|
||||
#: src/app/main/ui/dashboard/subscription.cljs:84
|
||||
msgid "subscription.dashboard.power-up.professional.bottom-button"
|
||||
msgstr "עליית מדרגה!"
|
||||
|
||||
#: src/app/main/ui/dashboard/subscription.cljs:83
|
||||
msgid "subscription.dashboard.power-up.professional.bottom-description"
|
||||
msgstr "קבלת אחסון נוסף, שחזור קבצים ועוד למען הצוותים שלך."
|
||||
|
||||
msgid "subscription.settings.management-dialog.step-2-title"
|
||||
msgstr "נשמח לסיוע בצמיחה ולהפוך את ההתנסות שלך לפשוטה יותר"
|
||||
|
||||
msgid "subscription.settings.management-dialog.step-2-skip-button"
|
||||
msgstr "לדלג לבינתיים ולהתחיל בהתנסות"
|
||||
|
||||
msgid "subscription.settings.management-dialog.step-2-add-payment-button"
|
||||
msgstr "הוספת פרטי תשלום"
|
||||
|
||||
#: src/app/main/ui/settings/subscription.cljs:209
|
||||
msgid "subscription.settings.management.dialog.unlimited-capped-warning"
|
||||
msgstr ""
|
||||
"עצה: אפשר להגדיל את כמות המושבים שלך כעת ולהקדים את ההזמנות. עם יותר מ־25 "
|
||||
"עורכים על פני הצוותים, אנו מציעים 175$ לחודש בלי חיובים נוספים."
|
||||
|
||||
#: src/app/main/ui/settings/subscription.cljs:50
|
||||
msgid "subscription.settings.recommended"
|
||||
msgstr "מומלץ"
|
||||
|
||||
#: src/app/main/ui/dashboard/team.cljs:933
|
||||
msgid "team.invitations-selected"
|
||||
msgid_plural "team.invitations-selected"
|
||||
msgstr[0] "הזמנה נבחרה"
|
||||
msgstr[1] "שתי הזמנות נבחרו"
|
||||
msgstr[2] "%s הזמנות נבחרו"
|
||||
msgstr[3] "%s הזמנות נבחרו"
|
||||
|
||||
#: src/app/main/ui/workspace/libraries.cljs:110, src/app/main/ui/workspace/libraries.cljs:137
|
||||
msgid "workspace.libraries.typography"
|
||||
msgid_plural "workspace.libraries.typography"
|
||||
msgstr[0] "טיפוגרפיה אחת"
|
||||
msgstr[1] "שתי טיפוגרפיות"
|
||||
msgstr[2] "%s טיפוגרפיות"
|
||||
msgstr[3] "%s טיפוגרפיות"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/color_selection.cljs:264
|
||||
msgid "workspace.options.more-token-colors"
|
||||
msgstr "עוד אסימוני צבע"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:1339
|
||||
msgid "workspace.tokens.font-size-value-enter"
|
||||
msgstr "גודל גופן או {כינוי}"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:1328, src/app/main/ui/workspace/tokens/management/create/form.cljs:1343
|
||||
msgid "workspace.tokens.font-weight-value-enter"
|
||||
msgstr "משקל גופן (300, מודגש נטוי…) או {כינוי}"
|
||||
|
||||
#: src/app/main/data/workspace/tokens/errors.cljs:89
|
||||
msgid "workspace.tokens.invalid-font-weight-token-value"
|
||||
msgstr ""
|
||||
"ערך משקל גופן שגוי: יש להשתמש בערכים מספריים (100-950) או שמות תקניים (thin, "
|
||||
"light, regular, bold ועוד), אפשר גם לצרף בסוף ‚Italic’ (נטוי) במקרה הצורך"
|
||||
|
||||
#: src/app/main/data/workspace/tokens/errors.cljs:101
|
||||
msgid "workspace.tokens.invalid-shadow-type-token-value"
|
||||
msgstr "סוג הצללה שגוי: רק ‚innerShadow’ או ‚dropShadow’ מורשים"
|
||||
|
||||
#: src/app/main/data/workspace/tokens/errors.cljs:81
|
||||
msgid "workspace.tokens.invalid-text-case-token-value"
|
||||
msgstr "ערך אסימון שגוי: רק none, Uppercase, Lowercase או Capitalize מורשים"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:1347
|
||||
msgid "workspace.tokens.line-height-value-enter"
|
||||
msgstr "גובה שורה (מכפיל, פיקסלים, %) או {כינוי}"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:1084
|
||||
msgid "workspace.tokens.shadow-add-shadow"
|
||||
msgstr "הוספת הצללה"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:981, src/app/main/ui/workspace/tokens/management/create/form.cljs:982
|
||||
msgid "workspace.tokens.shadow-blur"
|
||||
msgstr "טשטוש"
|
||||
|
||||
#: src/app/main/data/workspace/tokens/errors.cljs:105
|
||||
msgid "workspace.tokens.shadow-blur-range"
|
||||
msgstr "טשטוש הצל חייב להיות גדול או שווה ל־0."
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:987, src/app/main/ui/workspace/tokens/management/create/form.cljs:988
|
||||
msgid "workspace.tokens.shadow-color"
|
||||
msgstr "צבע"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:990, src/app/main/ui/workspace/tokens/management/create/form.cljs:991
|
||||
msgid "workspace.tokens.shadow-inset"
|
||||
msgstr "כיווץ פנימה"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:1091
|
||||
msgid "workspace.tokens.shadow-remove-shadow"
|
||||
msgstr "הסרת הצללה"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:984, src/app/main/ui/workspace/tokens/management/create/form.cljs:985
|
||||
msgid "workspace.tokens.shadow-spread"
|
||||
msgstr "התפרסות"
|
||||
|
||||
#: src/app/main/data/workspace/tokens/errors.cljs:109
|
||||
msgid "workspace.tokens.shadow-spread-range"
|
||||
msgstr "התפרסות ההצללה חייב להיות גדולה או שווה ל־0."
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:1215
|
||||
msgid "workspace.tokens.shadow-title"
|
||||
msgstr "הצללות"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:975, src/app/main/ui/workspace/tokens/management/create/form.cljs:976
|
||||
msgid "workspace.tokens.shadow-x"
|
||||
msgstr "X"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:978, src/app/main/ui/workspace/tokens/management/create/form.cljs:979
|
||||
msgid "workspace.tokens.shadow-y"
|
||||
msgstr "Y"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/themes/create_modal.cljs:52
|
||||
msgid "workspace.tokens.theme-name-already-exists"
|
||||
msgstr "כבר קיימת ערכת עיצוב בשם הזה"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/management/create/border_radius.cljs:44, src/app/main/ui/workspace/tokens/management/create/form.cljs:70
|
||||
msgid "workspace.tokens.token-name-duplication-validation-error"
|
||||
msgstr "כבר קיים אסימון בנתיב: %s"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/management/create/border_radius.cljs:42, src/app/main/ui/workspace/tokens/management/create/form.cljs:68
|
||||
msgid "workspace.tokens.token-name-length-validation-error"
|
||||
msgstr "אורך השם חייב להיות תו אחד לפחות"
|
||||
|
||||
#: src/app/main/data/workspace/tokens/errors.cljs:85
|
||||
msgid "workspace.tokens.invalid-text-decoration-token-value"
|
||||
msgstr "ערך אסימון שגוי: מותר רק none, underline ו־strike-through"
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"PO-Revision-Date: 2025-10-13 09:26+0000\n"
|
||||
"PO-Revision-Date: 2025-12-22 15:34+0000\n"
|
||||
"Last-Translator: VKing9 <vaibhavrathod2282@gmail.com>\n"
|
||||
"Language-Team: Hindi "
|
||||
"<https://hosted.weblate.org/projects/penpot/frontend/hi/>\n"
|
||||
"Language-Team: Hindi <https://hosted.weblate.org/projects/penpot/frontend/"
|
||||
"hi/>\n"
|
||||
"Language: hi\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=n > 1;\n"
|
||||
"X-Generator: Weblate 5.14-dev\n"
|
||||
"X-Generator: Weblate 5.15.1\n"
|
||||
|
||||
#: src/app/main/ui/auth/register.cljs:215, src/app/main/ui/static.cljs:159, src/app/main/ui/viewer/login.cljs:100
|
||||
msgid "auth.already-have-account"
|
||||
@@ -569,10 +569,11 @@ msgstr ""
|
||||
"लाइब्रेरीज़ का उपयोग कर रही हैं। आप उनके एसेट्स के साथ क्या करना चाहते हैं?"
|
||||
|
||||
#: src/app/main/ui/exports/files.cljs:164
|
||||
#, fuzzy
|
||||
msgid "dashboard.export.options.all.message"
|
||||
msgstr ""
|
||||
"साझा की गई लाइब्रेरीज़ वाली फ़ाइलें निर्यात में शामिल की जाएँगी, और उनका "
|
||||
"लिंक बनाए रखा जाएगा।"
|
||||
"साझा की गई लाइब्रेरीज़ वाली फ़ाइलें निर्यात में शामिल की जाएँगी, और उनका लिंक बनाए रखा "
|
||||
"जाएगा।"
|
||||
|
||||
#: src/app/main/ui/exports/files.cljs:165
|
||||
msgid "dashboard.export.options.all.title"
|
||||
@@ -1726,10 +1727,6 @@ msgstr ""
|
||||
"यदि आप डिजाइन निरीक्षण के बारे में अधिक जानना चाहते हैं, तो कृपया पेनपॉट के "
|
||||
"हेल्प सेंटर पर जाएं"
|
||||
|
||||
#: src/app/main/ui/inspect/right_sidebar.cljs:240
|
||||
msgid "inspect.empty.more-info"
|
||||
msgstr "निरीक्षण के बारे में अधिक जानकारी"
|
||||
|
||||
#: src/app/main/ui/inspect/right_sidebar.cljs:232
|
||||
msgid "inspect.empty.select"
|
||||
msgstr "उनके गुणधर्म और कोड का निरीक्षण करने के लिए कोई आकृति, बोर्ड या समूह चुनें"
|
||||
@@ -4321,7 +4318,7 @@ msgstr ""
|
||||
|
||||
#: src/app/main/ui/settings/subscription.cljs:202
|
||||
msgid "subscription.settings.management.dialog.payment-explanation"
|
||||
msgstr "(अभी कोई भुगतान नहीं किया जाएगा)"
|
||||
msgstr "परीक्षण के बाद शुल्क लिया जाएगा। अभी क्रेडिट कार्ड की आवश्यकता नहीं है।"
|
||||
|
||||
#: src/app/main/ui/settings/subscription.cljs:195, src/app/main/ui/settings/subscription.cljs:199
|
||||
#, markdown
|
||||
@@ -4383,9 +4380,8 @@ msgid "subscription.settings.sucess.dialog.title"
|
||||
msgstr "आप %s हैं!"
|
||||
|
||||
#: src/app/main/ui/settings/subscription.cljs:440
|
||||
#, fuzzy
|
||||
msgid "subscription.settings.support-us-since"
|
||||
msgstr "आप इस योजना के साथ %s से हमारा समर्थन कर रहे हैं"
|
||||
msgstr "आप इस योजना में हमारा समर्थन तब से कर रहे हैं: %s"
|
||||
|
||||
#: src/app/main/ui/settings/subscription.cljs:472, src/app/main/ui/settings/subscription.cljs:488
|
||||
msgid "subscription.settings.try-it-free"
|
||||
@@ -7169,7 +7165,6 @@ msgid "workspace.tokens.opacity-range"
|
||||
msgstr "अपारदर्शिता 0 और 100% या 0 और 1 (जैसे 50% या 0.5) के बीच होनी चाहिए।"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/management/token_pill.cljs:120
|
||||
#, fuzzy
|
||||
msgid "workspace.tokens.original-value"
|
||||
msgstr "मूल मान: %s"
|
||||
|
||||
@@ -7191,9 +7186,8 @@ msgid "workspace.tokens.reference-error"
|
||||
msgstr "संदर्भ त्रुटियाँ: "
|
||||
|
||||
#: src/app/main/data/workspace/tokens/warnings.cljs:15, src/app/main/data/workspace/tokens/warnings.cljs:19, src/app/main/ui/workspace/colorpicker/color_tokens.cljs:56, src/app/main/ui/workspace/colorpicker/color_tokens.cljs:84, src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs:102, src/app/main/ui/workspace/tokens/management/create/form_input_token.cljs:109, src/app/main/ui/workspace/tokens/management/create/input_tokens_value.cljs:41, src/app/main/ui/workspace/tokens/management/create/input_tokens_value.cljs:46, src/app/main/ui/workspace/tokens/management/token_pill.cljs:121
|
||||
#, fuzzy
|
||||
msgid "workspace.tokens.resolved-value"
|
||||
msgstr "समाधानित मान: %s"
|
||||
msgstr "हल किया गया मान: %s"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/themes/create_modal.cljs:272
|
||||
msgid "workspace.tokens.save-theme"
|
||||
@@ -7259,7 +7253,6 @@ msgid "workspace.tokens.themes-list"
|
||||
msgstr "थीम्स सूची"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/management/create/border_radius.cljs:194, src/app/main/ui/workspace/tokens/management/create/border_radius.cljs:195, src/app/main/ui/workspace/tokens/management/create/form.cljs:629, src/app/main/ui/workspace/tokens/management/create/form.cljs:630
|
||||
#, fuzzy
|
||||
msgid "workspace.tokens.token-description"
|
||||
msgstr "वर्णन"
|
||||
|
||||
@@ -7628,3 +7621,826 @@ msgstr "स्वतः सहेजे गए संस्करण %s दि
|
||||
#, unused
|
||||
msgid "workspace.viewport.click-to-close-path"
|
||||
msgstr "पथ बंद करने के लिए क्लिक करें"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs:100, src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs:107
|
||||
msgid "color-row.token-color-row.deleted-token"
|
||||
msgstr "यह token मौजूद नहीं है या हटा दिया गया है।"
|
||||
|
||||
#: src/app/main/ui/workspace/colorpicker/color_tokens.cljs:35
|
||||
msgid "color-token.empty-state"
|
||||
msgstr "कोई रंग tokens उपलब्ध नहीं है। सक्रिय सेट/थीम देखें या नए टोकन जोड़ें।"
|
||||
|
||||
#: src/app/main/ui/dashboard/team.cljs:765
|
||||
msgid "dashboard.invitation-modal.delete"
|
||||
msgstr "आप निम्न आमंत्रणों को हटाने जा रहे हैं:"
|
||||
|
||||
#: src/app/main/ui/dashboard/team.cljs:766
|
||||
msgid "dashboard.invitation-modal.resend"
|
||||
msgstr "आप निम्नलिखित को पुनः निमंत्रण भेजने जा रहे हैं:"
|
||||
|
||||
#: src/app/main/ui/dashboard/team.cljs:756
|
||||
msgid "dashboard.invitation-modal.title.delete-invitations"
|
||||
msgstr "निमंत्रण हटाएँ"
|
||||
|
||||
#: src/app/main/ui/dashboard/team.cljs:757
|
||||
msgid "dashboard.invitation-modal.title.resend-invitations"
|
||||
msgstr "निमंत्रण पुनः भेजें"
|
||||
|
||||
#: src/app/main/ui/dashboard/team.cljs:949
|
||||
msgid "dashboard.order-invitations-by-role"
|
||||
msgstr "भूमिका के अनुसार क्रमबद्ध करें"
|
||||
|
||||
#: src/app/main/ui/dashboard/team.cljs:958
|
||||
msgid "dashboard.order-invitations-by-status"
|
||||
msgstr "स्थिति के अनुसार क्रमबद्ध करें"
|
||||
|
||||
#: src/app/main/ui/ds/controls/numeric_input.cljs:99
|
||||
msgid "ds.inputs.numeric-input.no-applicable-tokens"
|
||||
msgstr "सक्रिय सेट या थीम में कोई लागू tokens नहीं।"
|
||||
|
||||
#: src/app/main/ui/ds/controls/numeric_input.cljs:100
|
||||
msgid "ds.inputs.numeric-input.no-matches"
|
||||
msgstr "कोई मेल नहीं मिले।"
|
||||
|
||||
#: src/app/main/ui/ds/controls/numeric_input.cljs:650, src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs:140
|
||||
msgid "ds.inputs.numeric-input.open-token-list-dropdown"
|
||||
msgstr "token सूची खोलें"
|
||||
|
||||
#: src/app/main/ui/ds/controls/utilities/token_field.cljs:87, src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs:135
|
||||
msgid "ds.inputs.token-field.detach-token"
|
||||
msgstr "token अलग करें"
|
||||
|
||||
#: src/app/main/ui/ds/controls/utilities/token_field.cljs:41, src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs:98, src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs:105
|
||||
msgid "ds.inputs.token-field.no-active-token-option"
|
||||
msgstr "यह token किसी भी सक्रिय सेट में नहीं है या इसका मान अमान्य है।"
|
||||
|
||||
#: src/app/main/ui/auth/register.cljs:89
|
||||
msgid "errors.email-does-not-match-invitation"
|
||||
msgstr "ईमेल आमंत्रण से मेल नहीं खाता।"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/management/create/border_radius.cljs:52, src/app/main/ui/workspace/tokens/management/create/form.cljs:80
|
||||
msgid "errors.field-max-length"
|
||||
msgstr "इसमें अधिकतम %s वर्ण होने चाहिए।"
|
||||
|
||||
#: src/app/main/ui/dashboard/team.cljs:853
|
||||
msgid "errors.max-quote-reached"
|
||||
msgstr "|"
|
||||
|
||||
#: src/app/main/errors.cljs:167
|
||||
msgid "errors.only-creator-can-lock"
|
||||
msgstr "केवल संस्करण निर्माता ही इसे लॉक कर सकता है"
|
||||
|
||||
#: src/app/main/errors.cljs:175
|
||||
msgid "errors.only-creator-can-unlock"
|
||||
msgstr "केवल संस्करण निर्माता ही इसे अनलॉक कर सकता है"
|
||||
|
||||
#: src/app/main/errors.cljs:183
|
||||
msgid "errors.version-already-locked"
|
||||
msgstr "यह संस्करण पहले से ही लॉक है"
|
||||
|
||||
#: src/app/main/errors.cljs:159
|
||||
msgid "errors.version-locked"
|
||||
msgstr "यह संस्करण लॉक है और इसे अन्य लोग हटा नहीं सकते"
|
||||
|
||||
#: src/app/main/ui/settings/feedback.cljs:122
|
||||
msgid "feedback.description-placeholder"
|
||||
msgstr "कृपया अपनी प्रतिक्रिया का कारण बताएँ"
|
||||
|
||||
#: src/app/main/ui/settings/feedback.cljs:143
|
||||
msgid "feedback.other-ways-contact"
|
||||
msgstr "हमसे संपर्क करने के अन्य तरीके"
|
||||
|
||||
#: src/app/main/ui/settings/feedback.cljs:126
|
||||
msgid "feedback.penpot.link"
|
||||
msgstr ""
|
||||
"यदि फीडबैक किसी फ़ाइल या प्रोजेक्ट से संबंधित है, तो यहां पेनपॉट लिंक जोड़ें:"
|
||||
|
||||
#: src/app/main/ui/settings/feedback.cljs:101
|
||||
msgid "feedback.title-contact-us"
|
||||
msgstr "हमसे संपर्क करें"
|
||||
|
||||
#: src/app/main/ui/settings/feedback.cljs:110, src/app/main/ui/settings/feedback.cljs:111
|
||||
msgid "feedback.type"
|
||||
msgstr "प्रकार"
|
||||
|
||||
#: src/app/main/ui/settings/feedback.cljs:115
|
||||
msgid "feedback.type.doubt"
|
||||
msgstr "संदेह"
|
||||
|
||||
#: src/app/main/ui/settings/feedback.cljs:113
|
||||
msgid "feedback.type.idea"
|
||||
msgstr "विचार"
|
||||
|
||||
#: src/app/main/ui/settings/feedback.cljs:114
|
||||
msgid "feedback.type.issue"
|
||||
msgstr "मुद्दा"
|
||||
|
||||
#: src/app/main/ui/inspect/styles/rows/color_properties_row.cljs:120
|
||||
msgid "inspect.attributes.image.preview"
|
||||
msgstr "आकृति की भरण छवि का पूर्वावलोकन"
|
||||
|
||||
#, unused
|
||||
msgid "inspect.attributes.typography.text-decoration.line-through"
|
||||
msgstr "स्ट्राइकथ्रू"
|
||||
|
||||
#: src/app/main/ui/inspect/attributes/text.cljs:125, src/app/main/ui/workspace/sidebar/options/menus/typography.cljs:429
|
||||
msgid "inspect.attributes.typography.text-transform.capitalize"
|
||||
msgstr "प्रमुख अक्षर करना"
|
||||
|
||||
#: src/app/main/ui/inspect/right_sidebar.cljs:170
|
||||
msgid "inspect.color-space-label"
|
||||
msgstr "रंग स्थान चुनें"
|
||||
|
||||
#: src/app/main/ui/inspect/right_sidebar.cljs:166
|
||||
#, fuzzy
|
||||
msgid "inspect.layer-info"
|
||||
msgstr "निरीक्षण टैब चुनें"
|
||||
|
||||
#: src/app/main/ui/inspect/styles/panels/tokens_panel.cljs:26
|
||||
msgid "inspect.tabs.styles.active-sets"
|
||||
msgstr "सक्रिय सेट"
|
||||
|
||||
#: src/app/main/ui/inspect/styles/panels/tokens_panel.cljs:21
|
||||
msgid "inspect.tabs.styles.active-themes"
|
||||
msgstr "सक्रिय थीम"
|
||||
|
||||
#: src/app/main/ui/inspect/styles/style_box.cljs:68
|
||||
msgid "inspect.tabs.styles.copy-shorthand"
|
||||
msgstr "CSS शॉर्टहैंड को क्लिपबोर्ड पर कॉपी करें"
|
||||
|
||||
#: src/app/main/ui/inspect/styles/property_detail_copiable.cljs:51
|
||||
msgid "inspect.tabs.styles.copy-to-clipboard"
|
||||
msgstr "क्लिपबोर्ड पर कॉपी करें"
|
||||
|
||||
#: src/app/main/ui/inspect/styles/style_box.cljs:22
|
||||
msgid "inspect.tabs.styles.geometry-panel"
|
||||
msgstr "आकार & स्थिति"
|
||||
|
||||
#: src/app/main/ui/inspect/styles/style_box.cljs:60, src/app/main/ui/workspace/colorpicker/color_tokens.cljs:179
|
||||
msgid "inspect.tabs.styles.toggle-style"
|
||||
msgstr "टॉगल पैनल %s"
|
||||
|
||||
#: src/app/main/ui/inspect/styles/style_box.cljs:21
|
||||
msgid "inspect.tabs.styles.token-panel"
|
||||
msgstr "Token सेट और थीम"
|
||||
|
||||
#: src/app/main/ui/inspect/styles/rows/color_properties_row.cljs:102, src/app/main/ui/inspect/styles/rows/properties_row.cljs:60
|
||||
msgid "inspect.tabs.styles.token-resolved-value"
|
||||
msgstr "हल किया गया मान:"
|
||||
|
||||
#: src/app/main/ui/inspect/styles/style_box.cljs:20
|
||||
msgid "inspect.tabs.styles.variants-panel"
|
||||
msgstr "भिन्न गुण"
|
||||
|
||||
#: src/app/main/ui/dashboard/sidebar.cljs:1044
|
||||
msgid "labels.about-penpot"
|
||||
msgstr "पेनपोट के बारे में"
|
||||
|
||||
#: src/app/main/ui/inspect/styles/style_box.cljs:26
|
||||
msgid "labels.blur"
|
||||
msgstr "धुंधला"
|
||||
|
||||
#: src/app/main/ui/workspace/colorpicker.cljs:423
|
||||
msgid "labels.color"
|
||||
msgstr "रंग"
|
||||
|
||||
#: src/app/main/ui/dashboard/sidebar.cljs:1031
|
||||
msgid "labels.community-contributions"
|
||||
msgstr "समुदाय & योगदान"
|
||||
|
||||
#: src/app/main/ui/inspect/right_sidebar.cljs:109
|
||||
msgid "labels.computed"
|
||||
msgstr "परिकलित"
|
||||
|
||||
#: src/app/main/ui/static.cljs:406
|
||||
msgid "labels.contact-support"
|
||||
msgstr "समर्थन से संपर्क करें"
|
||||
|
||||
#: src/app/main/ui/settings/sidebar.cljs:136
|
||||
msgid "labels.contact-us"
|
||||
msgstr "हमसे संपर्क करें"
|
||||
|
||||
#: src/app/main/ui/static.cljs:68
|
||||
msgid "labels.copyright-period"
|
||||
msgstr "कैलिडोस © 2019-वर्तमान"
|
||||
|
||||
#: src/app/main/ui/settings/feedback.cljs:134, src/app/main/ui/static.cljs:400
|
||||
msgid "labels.download"
|
||||
msgstr "%s डाउनलोड करें"
|
||||
|
||||
#: src/app/main/ui/inspect/styles/style_box.cljs:23
|
||||
msgid "labels.fill"
|
||||
msgstr "भरना"
|
||||
|
||||
#: src/app/main/ui/dashboard/sidebar.cljs:1020
|
||||
msgid "labels.help-learning"
|
||||
msgstr "मदद & सीखना"
|
||||
|
||||
#: src/app/main/ui/static.cljs:396
|
||||
msgid "labels.internal-error.desc-message-first"
|
||||
msgstr "कुछ बुरा हुआ।"
|
||||
|
||||
#: src/app/main/ui/static.cljs:397
|
||||
msgid "labels.internal-error.desc-message-second"
|
||||
msgstr ""
|
||||
"आप ऑपरेशन पुनः प्रयास कर सकते हैं या त्रुटि की रिपोर्ट करने के लिए समर्थन से संपर्क कर सकते हैं"
|
||||
"।"
|
||||
|
||||
#: src/app/main/ui/inspect/styles/style_box.cljs:28
|
||||
msgid "labels.layout"
|
||||
msgstr "लेआउट"
|
||||
|
||||
#: src/app/main/ui/dashboard/sidebar.cljs:799
|
||||
msgid "labels.learning-center"
|
||||
msgstr "अध्ययन केन्द्र"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/versions.cljs:209
|
||||
msgid "labels.lock"
|
||||
msgstr "ताला"
|
||||
|
||||
#: src/app/main/ui/ds/controls/numeric_input.cljs:628
|
||||
msgid "labels.mixed-values"
|
||||
msgstr "मिश्रित"
|
||||
|
||||
#: src/app/main/ui/dashboard/sidebar.cljs:879
|
||||
msgid "labels.penpot-changelog"
|
||||
msgstr "पेनपॉट चेंजलॉग"
|
||||
|
||||
#: src/app/main/ui/dashboard/sidebar.cljs:805
|
||||
msgid "labels.penpot-hub"
|
||||
msgstr "पेनपॉट हब"
|
||||
|
||||
#: src/app/main/ui/dashboard/sidebar.cljs:752
|
||||
msgid "labels.pinned-projects"
|
||||
msgstr "पिन किए गए प्रोजेक्ट"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:667
|
||||
msgid "labels.reference"
|
||||
msgstr "संदर्भ"
|
||||
|
||||
#: src/app/main/ui/dashboard/team.cljs:788
|
||||
msgid "labels.resend"
|
||||
msgstr "पुन: भेजें"
|
||||
|
||||
#: src/app/main/ui/inspect/styles/style_box.cljs:27
|
||||
msgid "labels.shadow"
|
||||
msgstr "छाया"
|
||||
|
||||
#: src/app/main/ui/dashboard/sidebar.cljs:731
|
||||
msgid "labels.sources"
|
||||
msgstr "स्त्रोत"
|
||||
|
||||
#: src/app/main/ui/inspect/styles/style_box.cljs:24, src/app/main/ui/workspace/sidebar/options/menus/stroke.cljs:46
|
||||
msgid "labels.stroke"
|
||||
msgstr "स्ट्रोक"
|
||||
|
||||
#: src/app/main/ui/inspect/right_sidebar.cljs:107, src/app/main/ui/inspect/styles.cljs:134
|
||||
msgid "labels.styles"
|
||||
msgstr "शैलियों"
|
||||
|
||||
#: src/app/main/ui/inspect/styles/style_box.cljs:33
|
||||
msgid "labels.svg"
|
||||
msgstr "SVG"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/rows/stroke_row.cljs:229
|
||||
msgid "labels.switch"
|
||||
msgstr "बदलना"
|
||||
|
||||
#: src/app/main/ui/inspect/styles/style_box.cljs:25
|
||||
msgid "labels.text"
|
||||
msgstr "मूलपाठ"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:1452
|
||||
msgid "labels.typography"
|
||||
msgstr "अक्षर विन्यास"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/versions.cljs:203
|
||||
msgid "labels.unlock"
|
||||
msgstr "अनलॉक"
|
||||
|
||||
#: src/app/main/ui/inspect/right_sidebar.cljs:65, src/app/main/ui/workspace/sidebar/options/menus/component.cljs:1028
|
||||
msgid "labels.variant"
|
||||
msgstr "रूपांतर"
|
||||
|
||||
#: src/app/main/ui/dashboard/sidebar.cljs:873
|
||||
msgid "labels.version-notes"
|
||||
msgstr "संस्करण %s नोट्स"
|
||||
|
||||
#: src/app/main/ui/inspect/styles/style_box.cljs:32
|
||||
msgid "labels.visibility"
|
||||
msgstr "दृश्यता"
|
||||
|
||||
#: src/app/main/ui/dashboard/team.cljs:825
|
||||
msgid "notifications.invitation-deleted"
|
||||
msgstr "आमंत्रण सफलतापूर्वक हटा दिया गया"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:97
|
||||
msgid "shortcuts.create-component-variant"
|
||||
msgstr "घटक/संस्करण बनाएं"
|
||||
|
||||
#: src/app/main/ui/dashboard/subscription.cljs:109
|
||||
msgid "subscription.dashboard.power-up.enterprise-trial.top-title"
|
||||
msgstr "एंटरप्राइज़ योजना (परीक्षण)"
|
||||
|
||||
#: src/app/main/ui/dashboard/subscription.cljs:84
|
||||
msgid "subscription.dashboard.power-up.professional.bottom-button"
|
||||
msgstr "शक्तिप्रापक!"
|
||||
|
||||
#: src/app/main/ui/dashboard/subscription.cljs:83
|
||||
msgid "subscription.dashboard.power-up.professional.bottom-description"
|
||||
msgstr ""
|
||||
"अपनी टीमों के लिए अतिरिक्त संग्रहण, फ़ाइल पुनर्प्राप्ति और बहुत कुछ प्राप्त करें।"
|
||||
|
||||
#: src/app/main/ui/dashboard/subscription.cljs:101
|
||||
#, markdown
|
||||
msgid "subscription.dashboard.power-up.unlimited.bottom-text"
|
||||
msgstr ""
|
||||
"अपनी सभी टीमों के लिए एक निश्चित कीमत पर असीमित स्टोरेज, विस्तारित फ़ाइल रिकवरी और "
|
||||
"असीमित एडिटर प्राप्त करें। [एंटरप्राइज़ प्लान देखें।|target:self](%s)"
|
||||
|
||||
#: src/app/main/ui/dashboard/subscription.cljs:194
|
||||
msgid "subscription.dashboard.professional-dashboard-cta-title"
|
||||
msgstr ""
|
||||
"आपकी स्वामित्व वाली टीमों में %s संपादक हैं, जबकि आपकी व्यावसायिक योजना 8 तक को कवर "
|
||||
"करती है।"
|
||||
|
||||
#: src/app/main/ui/dashboard/subscription.cljs:202
|
||||
#, markdown
|
||||
msgid "subscription.dashboard.professional-dashboard-cta-upgrade-owner"
|
||||
msgstr ""
|
||||
"कृपया ज़्यादा एडिटर, स्टोरेज और फ़ाइल रिकवरी के लिए अभी अनलिमिटेड या एंटरप्राइज़ में "
|
||||
"अपग्रेड करें। [अभी सब्सक्राइब करें।|target:self](%s)"
|
||||
|
||||
#: src/app/main/ui/dashboard/subscription.cljs:197
|
||||
msgid "subscription.dashboard.unlimited-dashboard-cta-title"
|
||||
msgstr ""
|
||||
"आपकी टीम बढ़ती जा रही है! आपकी अनलिमिटेड योजना में %s संपादकों तक की सेवाएँ शामिल हैं, "
|
||||
"लेकिन अब आपके पास %s हैं।"
|
||||
|
||||
#: src/app/main/ui/dashboard/subscription.cljs:205
|
||||
#, markdown
|
||||
msgid "subscription.dashboard.unlimited-dashboard-cta-upgrade-owner"
|
||||
msgstr ""
|
||||
"कृपया अपनी वर्तमान संपादक संख्या से मेल खाने के लिए अभी अपग्रेड करें। [अभी सदस्यता लें"
|
||||
"।|target:self](%s)"
|
||||
|
||||
#: src/app/main/ui/dashboard/subscription.cljs:182
|
||||
msgid "subscription.dashboard.unlimited-members-extra-editors-cta-text"
|
||||
msgstr ""
|
||||
"आपकी स्वामित्व वाली टीमों के केवल नए संपादक ही भविष्य के बिलिंग में शामिल होंगे। 25+ "
|
||||
"संपादकों के लिए अभी भी $175/माह का एक समान शुल्क लागू है।"
|
||||
|
||||
#: src/app/main/ui/dashboard/subscription.cljs:178
|
||||
msgid "subscription.dashboard.unlimited-members-extra-editors-cta-title"
|
||||
msgstr "असीमित योजना के दौरान लोगों को आमंत्रित करना"
|
||||
|
||||
#: src/app/main/ui/settings/subscription.cljs:53
|
||||
msgid "subscription.settings.editors"
|
||||
msgstr "(x %s संपादक)"
|
||||
|
||||
#: src/app/main/ui/settings/subscription.cljs:418, src/app/main/ui/settings/subscription.cljs:428, src/app/main/ui/settings/subscription.cljs:486
|
||||
msgid "subscription.settings.enterprise.autosave"
|
||||
msgstr "90-दिन के ऑटोसेव संस्करण और फ़ाइल पुनर्प्राप्ति"
|
||||
|
||||
#: src/app/main/ui/settings/subscription.cljs:419, src/app/main/ui/settings/subscription.cljs:429, src/app/main/ui/settings/subscription.cljs:487
|
||||
msgid "subscription.settings.enterprise.capped-bill"
|
||||
msgstr "फ्लैट मासिक बिल"
|
||||
|
||||
#: src/app/main/ui/settings/subscription.cljs:417, src/app/main/ui/settings/subscription.cljs:427, src/app/main/ui/settings/subscription.cljs:485
|
||||
msgid "subscription.settings.enterprise.unlimited-storage-benefit"
|
||||
msgstr "असीमित भंडारण"
|
||||
|
||||
#: src/app/main/ui/settings/subscription.cljs:154
|
||||
msgid "subscription.settings.management.dialog.currently-editors-title"
|
||||
msgid_plural "subscription.settings.management.dialog.currently-editors-title"
|
||||
msgstr[0] "वर्तमान में, आपकी टीम में %s व्यक्ति हैं जो संपादन कर सकते हैं।"
|
||||
msgstr[1] "वर्तमान में, आपकी टीम में %s लोग हैं जो संपादन कर सकते हैं।"
|
||||
|
||||
#: src/app/main/ui/inspect/attributes/text.cljs:112
|
||||
msgid "inspect.attributes.typography.text-decoration.strikethrough"
|
||||
msgstr " "
|
||||
|
||||
#: src/app/main/ui/inspect/right_sidebar.cljs:177
|
||||
msgid "inspect.tabs-switcher-label"
|
||||
msgstr " "
|
||||
|
||||
#: src/app/main/ui/settings/subscription.cljs:156
|
||||
msgid "subscription.settings.management.dialog.editors"
|
||||
msgstr "संपादनकर्ता"
|
||||
|
||||
#: src/app/main/ui/settings/subscription.cljs:163
|
||||
msgid "subscription.settings.management.dialog.editors-explanation"
|
||||
msgstr "(स्वामी, व्यवस्थापक और संपादक। दर्शकों को संपादक नहीं माना जाएगा)"
|
||||
|
||||
#: src/app/main/ui/settings/subscription.cljs:206
|
||||
msgid "subscription.settings.management.dialog.input-error"
|
||||
msgstr ""
|
||||
"आप मौजूदा संपादकों की संख्या से कम संपादक नहीं सेट कर सकते। टीम सेटिंग में उन लोगों की "
|
||||
"भूमिका (संपादक/व्यवस्थापक से दर्शक) बदलें जो वास्तव में फ़ाइलें संपादित नहीं करते हैं।"
|
||||
|
||||
msgid "subscription.settings.management-dialog.step-2-title"
|
||||
msgstr "हमें आगे बढ़ने में मदद करें और अपने परीक्षण को आसान बनाएं"
|
||||
|
||||
msgid "subscription.settings.management-dialog.step-2-description"
|
||||
msgstr ""
|
||||
"परीक्षण अवधि के बाद अपनी सदस्यता को सुचारू रूप से जारी रखने और हमारे ओपन-सोर्स प्रोजेक्ट "
|
||||
"का समर्थन जारी रखने के लिए अभी अपनी भुगतान जानकारी जोड़ें। आपसे अभी कोई शुल्क नहीं लिया "
|
||||
"जाएगा।"
|
||||
|
||||
msgid "subscription.settings.management-dialog.step-2-skip-button"
|
||||
msgstr "अभी छोड़ें और परीक्षण शुरू करें"
|
||||
|
||||
msgid "subscription.settings.management-dialog.step-2-add-payment-button"
|
||||
msgstr "भुगतान विवरण जोड़ें"
|
||||
|
||||
#: src/app/main/ui/settings/subscription.cljs:209
|
||||
msgid "subscription.settings.management.dialog.unlimited-capped-warning"
|
||||
msgstr ""
|
||||
"सुझाव: आमंत्रणों से आगे रहने के लिए आप अभी अपनी सीटों की संख्या बढ़ा सकते हैं। 25+ संपादकों "
|
||||
"वाली टीमों में, आपको प्रति माह ₹175 का एकमुश्त शुल्क मिलेगा।"
|
||||
|
||||
#: src/app/main/ui/settings/subscription.cljs:385, src/app/main/ui/settings/subscription.cljs:456
|
||||
msgid "subscription.settings.professional.autosave-benefit"
|
||||
msgstr "7-दिन का स्वतः सहेजा गया संस्करण और फ़ाइल पुनर्प्राप्ति"
|
||||
|
||||
#: src/app/main/ui/settings/subscription.cljs:384, src/app/main/ui/settings/subscription.cljs:455
|
||||
msgid "subscription.settings.professional.storage-benefit"
|
||||
msgstr "10GB स्टोरेज"
|
||||
|
||||
#: src/app/main/ui/settings/subscription.cljs:386, src/app/main/ui/settings/subscription.cljs:457
|
||||
msgid "subscription.settings.professional.teams-editors-benefit"
|
||||
msgstr "असीमित टीमें। आपकी स्वामित्व वाली टीमों में अधिकतम 8 संपादक।"
|
||||
|
||||
#: src/app/main/ui/settings/subscription.cljs:50
|
||||
msgid "subscription.settings.recommended"
|
||||
msgstr "अनुशंसित"
|
||||
|
||||
#: src/app/main/ui/settings/subscription.cljs:263
|
||||
msgid "subscription.settings.success.dialog.thanks"
|
||||
msgstr "पेनपोट %s योजना चुनने के लिए धन्यवाद!"
|
||||
|
||||
#: src/app/main/ui/settings/subscription.cljs:394, src/app/main/ui/settings/subscription.cljs:406, src/app/main/ui/settings/subscription.cljs:470
|
||||
msgid "subscription.settings.unlimited.autosave-benefit"
|
||||
msgstr "30-दिन का स्वतः सहेजा गया संस्करण और फ़ाइल पुनर्प्राप्ति"
|
||||
|
||||
#: src/app/main/ui/settings/subscription.cljs:393, src/app/main/ui/settings/subscription.cljs:405, src/app/main/ui/settings/subscription.cljs:469
|
||||
msgid "subscription.settings.unlimited.storage-benefit"
|
||||
msgstr "25GB स्टोरेज"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/versions.cljs:56
|
||||
#, markdown
|
||||
msgid "subscription.workspace.versions.warning.enterprise.subtext-owner"
|
||||
msgstr "यदि आप इस सीमा को बढ़ाना चाहते हैं, तो हमें [%s](mailto) पर लिखें"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/versions.cljs:58
|
||||
#, markdown
|
||||
msgid "subscription.workspace.versions.warning.subtext-member"
|
||||
msgstr ""
|
||||
"यदि आप इस सीमा को बढ़ाना चाहते हैं, तो टीम के मालिक से संपर्क करें: [%s](mailto)"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/versions.cljs:57
|
||||
#, markdown
|
||||
msgid "subscription.workspace.versions.warning.subtext-owner"
|
||||
msgstr ""
|
||||
"यदि आप इस सीमा को बढ़ाना चाहते हैं, तो [अपना प्लान अपग्रेड करें|target:self](%s)"
|
||||
|
||||
#: src/app/main/ui/dashboard/team.cljs:933
|
||||
msgid "team.invitations-selected"
|
||||
msgid_plural "team.invitations-selected"
|
||||
msgstr[0] "1 आमंत्रण चयनित"
|
||||
msgstr[1] "%s आमंत्रण चयनित"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/assets/groups.cljs:81
|
||||
msgid "workspace.assets.component-group-options"
|
||||
msgstr "घटक समूह विकल्प"
|
||||
|
||||
#: src/app/main/ui/workspace/colorpicker.cljs:427, src/app/main/ui/workspace/colorpicker.cljs:439
|
||||
msgid "workspace.colorpicker.color-tokens"
|
||||
msgstr "रंग टोकन"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/component.cljs:499
|
||||
msgid "workspace.component.swap.loop-error"
|
||||
msgstr "घटकों को अपने अंदर नहीं रखा जा सकता।"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/component.cljs:498
|
||||
msgid "workspace.component.switch.loop-error-multi"
|
||||
msgstr ""
|
||||
"कुछ प्रतियों को स्विच नहीं किया जा सका। घटकों को आपस में नेस्ट नहीं किया जा सकता।"
|
||||
|
||||
#: src/app/main/ui/workspace/libraries.cljs:107, src/app/main/ui/workspace/libraries.cljs:133
|
||||
msgid "workspace.libraries.colors"
|
||||
msgid_plural "workspace.libraries.colors"
|
||||
msgstr[0] "1 रंग"
|
||||
msgstr[1] "%s रंग"
|
||||
|
||||
#: src/app/main/ui/workspace/libraries.cljs:101, src/app/main/ui/workspace/libraries.cljs:125
|
||||
msgid "workspace.libraries.components"
|
||||
msgid_plural "workspace.libraries.components"
|
||||
msgstr[0] "1 घटक"
|
||||
msgstr[1] "%s घटक"
|
||||
|
||||
#: src/app/main/ui/workspace/libraries.cljs:349
|
||||
msgid "workspace.libraries.connected-to"
|
||||
msgstr "से जुड़ा"
|
||||
|
||||
#: src/app/main/ui/workspace/libraries.cljs:104, src/app/main/ui/workspace/libraries.cljs:129
|
||||
msgid "workspace.libraries.graphics"
|
||||
msgid_plural "workspace.libraries.graphics"
|
||||
msgstr[0] "1 ग्राफ़िक"
|
||||
msgstr[1] "%s ग्राफ़िक्स"
|
||||
|
||||
#: src/app/main/ui/workspace/libraries.cljs:110, src/app/main/ui/workspace/libraries.cljs:137
|
||||
msgid "workspace.libraries.typography"
|
||||
msgid_plural "workspace.libraries.typography"
|
||||
msgstr[0] "1 अक्षर विन्यास"
|
||||
msgstr[1] "%s अक्षर विन्यास"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/component.cljs:563
|
||||
msgid "workspace.options.component.variant.duplicated.copy.locate"
|
||||
msgstr "परस्पर विरोधी वेरिएंट का पता लगाएं"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/component.cljs:560
|
||||
msgid "workspace.options.component.variant.duplicated.copy.title"
|
||||
msgstr ""
|
||||
"इस घटक में परस्पर विरोधी वैरिएंट हैं। सुनिश्चित करें कि प्रत्येक वैरिएंट में गुण मानों का एक "
|
||||
"विशिष्ट सेट हो।"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/component.cljs:1330
|
||||
msgid "workspace.options.component.variant.duplicated.group.locate"
|
||||
msgstr "डुप्लिकेट वेरिएंट का पता लगाएँ"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/component.cljs:1327
|
||||
msgid "workspace.options.component.variant.duplicated.group.title"
|
||||
msgstr "कुछ वेरिएंट में समान गुण और मूल्य होते हैं"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/component.cljs:268
|
||||
msgid "workspace.options.component.variant.duplicated.single.all"
|
||||
msgstr ""
|
||||
"इन वेरिएंट के गुण और मान समान हैं। मानों को समायोजित करें ताकि उन्हें पुनर्प्राप्त किया जा सके"
|
||||
"।"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/component.cljs:265
|
||||
msgid "workspace.options.component.variant.duplicated.single.one"
|
||||
msgstr ""
|
||||
"इस संस्करण के गुण और मान दूसरे संस्करण के समान हैं। मानों को समायोजित करें ताकि उन्हें "
|
||||
"पुनर्प्राप्त किया जा सके।"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/component.cljs:271
|
||||
msgid "workspace.options.component.variant.duplicated.single.some"
|
||||
msgstr ""
|
||||
"इनमें से कुछ वेरिएंट के गुण और मान समान हैं। मानों को समायोजित करें ताकि उन्हें पुनर्प्राप्त "
|
||||
"किया जा सके।"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/component.cljs:550
|
||||
msgid "workspace.options.component.variant.malformed.copy"
|
||||
msgstr ""
|
||||
"इस घटक के कुछ वेरिएंट अमान्य नामों वाले हैं। सुनिश्चित करें कि प्रत्येक वेरिएंट सही संरचना का "
|
||||
"पालन कर रहा है।"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/component.cljs:553
|
||||
msgid "workspace.options.component.variant.malformed.locate"
|
||||
msgstr "अमान्य वेरिएंट का पता लगाएं"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/variants_help_modal.cljs:54
|
||||
msgid "workspace.options.component.variants-help-modal.intro"
|
||||
msgstr ""
|
||||
"वेरिएंट के बीच स्विच करते समय परिवर्तनों को बनाए रखने के लिए, पेनपॉट उन परतों को जोड़ता "
|
||||
"है जो:"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/variants_help_modal.cljs:91
|
||||
msgid "workspace.options.component.variants-help-modal.outro"
|
||||
msgstr ""
|
||||
"इनमें से किसी भी परिवर्तन (जैसे, परत का नाम बदलना या समूह बनाना) से कनेक्शन टूट जाता है, "
|
||||
"लेकिन परिवर्तन को पूर्ववत करने से यह पुनः स्थापित हो जाएगा।"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/variants_help_modal.cljs:67
|
||||
msgid "workspace.options.component.variants-help-modal.rule1"
|
||||
msgstr "एक ही नाम साझा करें।"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/variants_help_modal.cljs:76
|
||||
msgid "workspace.options.component.variants-help-modal.rule2"
|
||||
msgstr "एक ही प्रकार के हैं।"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/variants_help_modal.cljs:77
|
||||
msgid "workspace.options.component.variants-help-modal.rule2.detail"
|
||||
msgstr "आयत, दीर्घवृत्त, पथ और बूलियन ऑपरेशन एक ही प्रकार के माने जाते हैं।"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/variants_help_modal.cljs:87
|
||||
msgid "workspace.options.component.variants-help-modal.rule3"
|
||||
msgstr "समान पदानुक्रम स्तर रखें।"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/variants_help_modal.cljs:88
|
||||
msgid "workspace.options.component.variants-help-modal.rule3.detail"
|
||||
msgstr "समूह, बोर्ड और लेआउट को समतुल्य माना जाता है।"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/component.cljs:1034, src/app/main/ui/workspace/sidebar/options/menus/component.cljs:1278, src/app/main/ui/workspace/sidebar/options/menus/variants_help_modal.cljs:47
|
||||
msgid "workspace.options.component.variants-help-modal.title"
|
||||
msgstr "वेरिएंट कैसे जुड़े रहते हैं"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/color_selection.cljs:264
|
||||
msgid "workspace.options.more-token-colors"
|
||||
msgstr "अधिक रंग के टोकन"
|
||||
|
||||
#: src/app/main/ui/workspace/plugins.cljs:287
|
||||
msgid "workspace.plugins.permissions.allow-localstorage"
|
||||
msgstr "ब्राउज़र में डेटा संग्रहीत करें।"
|
||||
|
||||
#: src/app/main/ui/workspace/context_menu.cljs:617, src/app/main/ui/workspace/sidebar/assets/components.cljs:634, src/app/main/ui/workspace/sidebar/assets/groups.cljs:75, src/app/main/ui/workspace/sidebar/options/menus/component.cljs:1095
|
||||
msgid "workspace.shape.menu.combine-as-variants"
|
||||
msgstr "वैरिएंट के रूप में संयोजित करें"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/assets/components.cljs:636
|
||||
msgid "workspace.shape.menu.combine-as-variants-error"
|
||||
msgstr "घटकों को एक ही पृष्ठ पर होना आवश्यक है"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/component.cljs:1145
|
||||
msgid "workspace.shape.menu.remove-variant-property.last-property"
|
||||
msgstr "वैरिएंट में कम से कम एक प्रॉपर्टी होनी चाहिए"
|
||||
|
||||
#: src/app/main/data/workspace/tokens/errors.cljs:97
|
||||
msgid "workspace.tokens.composite-line-height-needs-font-size"
|
||||
msgstr ""
|
||||
"पंक्ति की ऊँचाई फ़ॉन्ट आकार पर निर्भर करती है। हल किया गया मान प्राप्त करने के लिए फ़ॉन्ट "
|
||||
"आकार जोड़ें।"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:581
|
||||
msgid "workspace.tokens.edit-token"
|
||||
msgstr "%s token संपादित करें"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:1339
|
||||
msgid "workspace.tokens.font-size-value-enter"
|
||||
msgstr "फ़ॉन्ट आकार या {उपनाम}"
|
||||
|
||||
#: src/app/main/data/workspace/tokens/application.cljs:323
|
||||
msgid "workspace.tokens.font-variant-not-found"
|
||||
msgstr ""
|
||||
"फ़ॉन्ट वज़न/शैली सेट करते समय त्रुटि हुई। यह फ़ॉन्ट शैली वर्तमान फ़ॉन्ट में मौजूद नहीं है"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:1328, src/app/main/ui/workspace/tokens/management/create/form.cljs:1343
|
||||
msgid "workspace.tokens.font-weight-value-enter"
|
||||
msgstr "फ़ॉन्ट वज़न (300, बोल्ड इटैलिक...) या {उपनाम}"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/import/modal.cljs:233
|
||||
msgid "workspace.tokens.import-button-prefix"
|
||||
msgstr "%s आयात करें"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/import/modal.cljs:273
|
||||
msgid "workspace.tokens.import-menu-folder-option"
|
||||
msgstr "फ़ोल्डर"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/import/modal.cljs:272
|
||||
msgid "workspace.tokens.import-menu-json-option"
|
||||
msgstr "एकल JSON फ़ाइल"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/import/modal.cljs:271
|
||||
msgid "workspace.tokens.import-menu-zip-option"
|
||||
msgstr "ज़िप फ़ाइल"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:741
|
||||
msgid "workspace.tokens.individual-tokens"
|
||||
msgstr "व्यक्तिगत टोकन का प्रयोग करें"
|
||||
|
||||
#: src/app/main/data/workspace/tokens/errors.cljs:89
|
||||
msgid "workspace.tokens.invalid-font-weight-token-value"
|
||||
msgstr ""
|
||||
"अमान्य फ़ॉन्ट भार मान: संख्यात्मक मान (100-950) या मानक नाम (पतला, हल्का, नियमित, "
|
||||
"बोल्ड, आदि) का उपयोग करें, वैकल्पिक रूप से उसके बाद 'इटैलिक' लिखें"
|
||||
|
||||
#: src/app/main/data/workspace/tokens/errors.cljs:101
|
||||
msgid "workspace.tokens.invalid-shadow-type-token-value"
|
||||
msgstr ""
|
||||
"अमान्य छाया प्रकार: केवल 'innerShadow' या 'dropShadow' स्वीकार किए जाते हैं"
|
||||
|
||||
#: src/app/main/data/workspace/tokens/errors.cljs:81
|
||||
msgid "workspace.tokens.invalid-text-case-token-value"
|
||||
msgstr ""
|
||||
"अमान्य token मान: केवल कोई नहीं, अपरकेस, लोअरकेस या कैपिटलाइज़ स्वीकार किए जाते हैं"
|
||||
|
||||
#: src/app/main/data/workspace/tokens/errors.cljs:85
|
||||
msgid "workspace.tokens.invalid-text-decoration-token-value"
|
||||
msgstr ""
|
||||
"अमान्य token मान: केवल कोई नहीं, रेखांकित और स्ट्राइक-थ्रू स्वीकार किए जाते हैं"
|
||||
|
||||
#: src/app/main/data/workspace/tokens/errors.cljs:93
|
||||
msgid "workspace.tokens.invalid-token-value-typography"
|
||||
msgstr "अमान्य मान: एक संयुक्त टाइपोग्राफी token का संदर्भ होना चाहिए।"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:1351
|
||||
msgid "workspace.tokens.letter-spacing-value-enter-composite"
|
||||
msgstr "अक्षर रिक्ति या {उपनाम}"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:1347
|
||||
msgid "workspace.tokens.line-height-value-enter"
|
||||
msgstr "पंक्ति ऊँचाई (गुणक, पिक्सेल, %) या {उपनाम}"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/management/token_pill.cljs:123
|
||||
msgid "workspace.tokens.more-options"
|
||||
msgstr "विकल्प देखने के लिए राइट क्लिक करें"
|
||||
|
||||
#: src/app/main/data/workspace/tokens/errors.cljs:19
|
||||
msgid "workspace.tokens.no-token-files-found"
|
||||
msgstr "इस फ़ाइल में कोई टोकन, सेट या थीम नहीं मिला।"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:775
|
||||
msgid "workspace.tokens.reference-composite"
|
||||
msgstr "token टाइपोग्राफी उपनाम दर्ज करें"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:1084
|
||||
msgid "workspace.tokens.shadow-add-shadow"
|
||||
msgstr "छाया जोड़ें"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:981, src/app/main/ui/workspace/tokens/management/create/form.cljs:982
|
||||
msgid "workspace.tokens.shadow-blur"
|
||||
msgstr "धुंधला"
|
||||
|
||||
#: src/app/main/data/workspace/tokens/errors.cljs:105
|
||||
msgid "workspace.tokens.shadow-blur-range"
|
||||
msgstr "छाया धुंधलापन 0 से अधिक या उसके बराबर होना चाहिए।"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:987, src/app/main/ui/workspace/tokens/management/create/form.cljs:988
|
||||
msgid "workspace.tokens.shadow-color"
|
||||
msgstr "रंग"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:990, src/app/main/ui/workspace/tokens/management/create/form.cljs:991
|
||||
msgid "workspace.tokens.shadow-inset"
|
||||
msgstr "अंतर्भूत"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:1091
|
||||
msgid "workspace.tokens.shadow-remove-shadow"
|
||||
msgstr "छाया हटाएँ"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:984, src/app/main/ui/workspace/tokens/management/create/form.cljs:985
|
||||
msgid "workspace.tokens.shadow-spread"
|
||||
msgstr "फैलाना"
|
||||
|
||||
#: src/app/main/data/workspace/tokens/errors.cljs:109
|
||||
msgid "workspace.tokens.shadow-spread-range"
|
||||
msgstr "छाया प्रसार 0 से अधिक या उसके बराबर होना चाहिए।"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:1215
|
||||
msgid "workspace.tokens.shadow-title"
|
||||
msgstr "छायाएँ"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:975, src/app/main/ui/workspace/tokens/management/create/form.cljs:976
|
||||
msgid "workspace.tokens.shadow-x"
|
||||
msgstr "X"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:978, src/app/main/ui/workspace/tokens/management/create/form.cljs:979
|
||||
msgid "workspace.tokens.shadow-y"
|
||||
msgstr "Y"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:1316, src/app/main/ui/workspace/tokens/management/create/form.cljs:1355
|
||||
msgid "workspace.tokens.text-case-value-enter"
|
||||
msgstr "कोई नहीं | अपरकेस | लोअरकेस | कैपिटलाइज़ या {उपनाम}"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:1322, src/app/main/ui/workspace/tokens/management/create/form.cljs:1359
|
||||
msgid "workspace.tokens.text-decoration-value-enter"
|
||||
msgstr "कोई नहीं | रेखांकित | स्ट्राइक-थ्रू या {उपनाम}"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/themes/create_modal.cljs:52
|
||||
msgid "workspace.tokens.theme-name-already-exists"
|
||||
msgstr "इस नाम वाली थीम पहले से मौजूद है"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:1277
|
||||
msgid "workspace.tokens.token-font-family-select"
|
||||
msgstr "फ़ॉन्ट परिवार चुनें"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:1333
|
||||
msgid "workspace.tokens.token-font-family-value"
|
||||
msgstr "फॉन्ट परिवार"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:1283, src/app/main/ui/workspace/tokens/management/create/form.cljs:1335
|
||||
msgid "workspace.tokens.token-font-family-value-enter"
|
||||
msgstr "फ़ॉन्ट परिवार या अल्पविराम (,) द्वारा अलग किए गए फ़ॉन्ट की सूची"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/management/create/border_radius.cljs:44, src/app/main/ui/workspace/tokens/management/create/form.cljs:70
|
||||
msgid "workspace.tokens.token-name-duplication-validation-error"
|
||||
msgstr "पथ पर एक token पहले से मौजूद है: %s"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/management/create/border_radius.cljs:42, src/app/main/ui/workspace/tokens/management/create/form.cljs:68
|
||||
msgid "workspace.tokens.token-name-length-validation-error"
|
||||
msgstr "नाम कम से कम 1 अक्षर का होना चाहिए"
|
||||
|
||||
#: src/app/main/data/workspace/tokens/import_export.cljs:47
|
||||
msgid "workspace.tokens.unknown-token-type-message"
|
||||
msgstr "आयात सफल रहा। कुछ टोकन शामिल नहीं किए गए।"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:745
|
||||
msgid "workspace.tokens.use-reference"
|
||||
msgstr "एक संदर्भ का प्रयोग करें"
|
||||
|
||||
#: src/app/main/data/workspace/tokens/errors.cljs:69
|
||||
msgid "workspace.tokens.value-with-percent"
|
||||
msgstr "अमान्य मान: % की अनुमति नहीं है।"
|
||||
|
||||
#, unused
|
||||
msgid "workspace.versions.locked-by-other"
|
||||
msgstr "यह संस्करण %s द्वारा लॉक किया गया है और इसे संशोधित नहीं किया जा सकता"
|
||||
|
||||
#, unused
|
||||
msgid "workspace.versions.locked-by-you"
|
||||
msgstr "यह संस्करण आपके द्वारा लॉक किया गया है"
|
||||
|
||||
#, unused
|
||||
msgid "workspace.versions.tooltip.locked-version"
|
||||
msgstr "लॉक किया गया संस्करण - केवल निर्माता ही इसे संशोधित कर सकता है"
|
||||
|
||||
@@ -1569,10 +1569,6 @@ msgstr ""
|
||||
"Ako želite saznati više o pregledu dizajna, posjetite Penpotov centar za "
|
||||
"pomoć"
|
||||
|
||||
#: src/app/main/ui/inspect/right_sidebar.cljs:240
|
||||
msgid "inspect.empty.more-info"
|
||||
msgstr "Više informacija o inspekciji"
|
||||
|
||||
#: src/app/main/ui/inspect/right_sidebar.cljs:232
|
||||
msgid "inspect.empty.select"
|
||||
msgstr "Odaberite oblik, ploču ili grupu da provjerite njihova svojstva i kod"
|
||||
|
||||
@@ -1653,10 +1653,6 @@ msgstr ""
|
||||
"Jika Anda ingin mengetahui lebih lanjut tentang inspeksi desain kunjungi "
|
||||
"pusat bantuan Penpot"
|
||||
|
||||
#: src/app/main/ui/inspect/right_sidebar.cljs:240
|
||||
msgid "inspect.empty.more-info"
|
||||
msgstr "Lebih banyak info tentang inspeksi"
|
||||
|
||||
#: src/app/main/ui/inspect/right_sidebar.cljs:232
|
||||
msgid "inspect.empty.select"
|
||||
msgstr "Pilih bentuk, papan, atau grup untuk menginskpeksi properti dan kodenya"
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"PO-Revision-Date: 2025-10-07 16:35+0000\n"
|
||||
"Last-Translator: Anonymous <noreply@weblate.org>\n"
|
||||
"Language-Team: Igbo "
|
||||
"<https://hosted.weblate.org/projects/penpot/frontend/ig/>\n"
|
||||
"PO-Revision-Date: 2025-12-22 15:34+0000\n"
|
||||
"Last-Translator: Alejandro Alonso <alejandro.alonso@kaleidos.net>\n"
|
||||
"Language-Team: Igbo <https://hosted.weblate.org/projects/penpot/frontend/ig/>"
|
||||
"\n"
|
||||
"Language: ig\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||
"X-Generator: Weblate 5.14-dev\n"
|
||||
"X-Generator: Weblate 5.15.1\n"
|
||||
|
||||
#: src/app/main/ui/auth/register.cljs:277
|
||||
#, unused
|
||||
@@ -402,6 +402,7 @@ msgid "dashboard.export.detail"
|
||||
msgstr "* Nwere Ike ịgụnye ngwa , esereese gasị, agwụgwara na/ma ọ bụ akara nkụpụta."
|
||||
|
||||
#: src/app/main/ui/exports/files.cljs:164
|
||||
#, fuzzy
|
||||
msgid "dashboard.export.options.all.message"
|
||||
msgstr ""
|
||||
"A ga-atinye ederede nwere ọba ederede nkekọrịta ma gụnyere mbupu , ma "
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"PO-Revision-Date: 2025-11-23 12:51+0000\n"
|
||||
"Last-Translator: Nicola Bortoletto <nicola.bortoletto@live.com>\n"
|
||||
"PO-Revision-Date: 2025-12-22 15:34+0000\n"
|
||||
"Last-Translator: Anonymous <noreply@weblate.org>\n"
|
||||
"Language-Team: Italian <https://hosted.weblate.org/projects/penpot/frontend/"
|
||||
"it/>\n"
|
||||
"Language: it\n"
|
||||
@@ -9,7 +9,7 @@ msgstr ""
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||
"X-Generator: Weblate 5.15-dev\n"
|
||||
"X-Generator: Weblate 5.15.1\n"
|
||||
|
||||
#: src/app/main/ui/auth/register.cljs:215, src/app/main/ui/static.cljs:159, src/app/main/ui/viewer/login.cljs:100
|
||||
msgid "auth.already-have-account"
|
||||
@@ -582,10 +582,11 @@ msgstr ""
|
||||
"cosa desideri fare con le loro risorse*?"
|
||||
|
||||
#: src/app/main/ui/exports/files.cljs:164
|
||||
#, fuzzy
|
||||
msgid "dashboard.export.options.all.message"
|
||||
msgstr ""
|
||||
"I file con librerie condivise verranno inclusi nell'esportazione, "
|
||||
"mantenendo il loro collegamento."
|
||||
"I file con librerie condivise verranno inclusi nell'esportazione, mantenendo "
|
||||
"il loro collegamento."
|
||||
|
||||
#: src/app/main/ui/exports/files.cljs:165
|
||||
msgid "dashboard.export.options.all.title"
|
||||
@@ -1824,10 +1825,6 @@ msgstr ""
|
||||
"Per ulteriori informazioni su l'ispezione, visita il centro di supporto di "
|
||||
"Penpot"
|
||||
|
||||
#: src/app/main/ui/inspect/right_sidebar.cljs:240
|
||||
msgid "inspect.empty.more-info"
|
||||
msgstr "Maggiori informazioni sull'ispezione"
|
||||
|
||||
#: src/app/main/ui/inspect/right_sidebar.cljs:232
|
||||
msgid "inspect.empty.select"
|
||||
msgstr ""
|
||||
@@ -1835,6 +1832,7 @@ msgstr ""
|
||||
"loro proprietà e il loro codice"
|
||||
|
||||
#: src/app/main/ui/inspect/right_sidebar.cljs:166
|
||||
#, fuzzy
|
||||
msgid "inspect.layer-info"
|
||||
msgstr "Informazioni livello"
|
||||
|
||||
@@ -4743,9 +4741,8 @@ msgid "subscription.settings.sucess.dialog.title"
|
||||
msgstr "Sei %s!"
|
||||
|
||||
#: src/app/main/ui/settings/subscription.cljs:440
|
||||
#, fuzzy
|
||||
msgid "subscription.settings.support-us-since"
|
||||
msgstr "Ci supporti con questo piano dal %s"
|
||||
msgstr "Ci stai supportando con questo piano dal %s"
|
||||
|
||||
#: src/app/main/ui/settings/subscription.cljs:472, src/app/main/ui/settings/subscription.cljs:488
|
||||
msgid "subscription.settings.try-it-free"
|
||||
@@ -7772,7 +7769,6 @@ msgstr ""
|
||||
"0.5)."
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/management/token_pill.cljs:120
|
||||
#, fuzzy
|
||||
msgid "workspace.tokens.original-value"
|
||||
msgstr "Valore originale: %s"
|
||||
|
||||
@@ -7798,7 +7794,6 @@ msgid "workspace.tokens.reference-error"
|
||||
msgstr "Errori di riferimento: "
|
||||
|
||||
#: src/app/main/data/workspace/tokens/warnings.cljs:15, src/app/main/data/workspace/tokens/warnings.cljs:19, src/app/main/ui/workspace/colorpicker/color_tokens.cljs:56, src/app/main/ui/workspace/colorpicker/color_tokens.cljs:84, src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs:102, src/app/main/ui/workspace/tokens/management/create/form_input_token.cljs:109, src/app/main/ui/workspace/tokens/management/create/input_tokens_value.cljs:41, src/app/main/ui/workspace/tokens/management/create/input_tokens_value.cljs:46, src/app/main/ui/workspace/tokens/management/token_pill.cljs:121
|
||||
#, fuzzy
|
||||
msgid "workspace.tokens.resolved-value"
|
||||
msgstr "Valore risolto: %"
|
||||
|
||||
@@ -7872,7 +7867,6 @@ msgid "workspace.tokens.themes-list"
|
||||
msgstr "Elenco temi"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/management/create/border_radius.cljs:194, src/app/main/ui/workspace/tokens/management/create/border_radius.cljs:195, src/app/main/ui/workspace/tokens/management/create/form.cljs:629, src/app/main/ui/workspace/tokens/management/create/form.cljs:630
|
||||
#, fuzzy
|
||||
msgid "workspace.tokens.token-description"
|
||||
msgstr "Descrizione"
|
||||
|
||||
@@ -8419,3 +8413,96 @@ msgstr "Esiste già un tema con questo nome"
|
||||
#: src/app/main/ui/workspace/tokens/management/create/border_radius.cljs:44, src/app/main/ui/workspace/tokens/management/create/form.cljs:70
|
||||
msgid "workspace.tokens.token-name-duplication-validation-error"
|
||||
msgstr "Un token con questo nome esiste già nel percorso: %s"
|
||||
|
||||
#: src/app/main/ui/static.cljs:396
|
||||
msgid "labels.internal-error.desc-message-first"
|
||||
msgstr "Qualcosa è andato storto."
|
||||
|
||||
#: src/app/main/ui/static.cljs:397
|
||||
msgid "labels.internal-error.desc-message-second"
|
||||
msgstr ""
|
||||
"Puoi riprovare l’operazione oppure contattare il supporto per segnalare "
|
||||
"l’errore."
|
||||
|
||||
#: src/app/main/ui/dashboard/subscription.cljs:84
|
||||
msgid "subscription.dashboard.power-up.professional.bottom-button"
|
||||
msgstr "Potenzia!"
|
||||
|
||||
#: src/app/main/ui/dashboard/subscription.cljs:83
|
||||
msgid "subscription.dashboard.power-up.professional.bottom-description"
|
||||
msgstr ""
|
||||
"Ottieni spazio aggiuntivo, recupero dei file e altro ancora per i tuoi team."
|
||||
|
||||
msgid "subscription.settings.management-dialog.step-2-title"
|
||||
msgstr "Aiutaci a crescere e rendi la tua prova ancora più semplice"
|
||||
|
||||
msgid "subscription.settings.management-dialog.step-2-description"
|
||||
msgstr ""
|
||||
"Aggiungi subito i tuoi dati di pagamento per mantenere attiva la "
|
||||
"sottoscrizione dopo il periodo di prova e continuare a supportare il nostro "
|
||||
"progetto open-source. Non ti verrà ancora addebitato nulla."
|
||||
|
||||
#: src/app/main/ui/inspect/styles/style_box.cljs:68
|
||||
msgid "inspect.tabs.styles.copy-shorthand"
|
||||
msgstr "Copia l'abbreviazione CSS negli appunti"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/rows/stroke_row.cljs:229
|
||||
msgid "labels.switch"
|
||||
msgstr "Cambia"
|
||||
|
||||
msgid "subscription.settings.management-dialog.step-2-add-payment-button"
|
||||
msgstr "Aggiungi dettagli di pagamento"
|
||||
|
||||
#: src/app/main/ui/settings/subscription.cljs:50
|
||||
msgid "subscription.settings.recommended"
|
||||
msgstr "Consigliato"
|
||||
|
||||
#: src/app/main/ui/dashboard/team.cljs:933
|
||||
msgid "team.invitations-selected"
|
||||
msgid_plural "team.invitations-selected"
|
||||
msgstr[0] "1 invito selezionato"
|
||||
msgstr[1] "%s inviti selezionati"
|
||||
|
||||
#: src/app/main/ui/workspace/libraries.cljs:107, src/app/main/ui/workspace/libraries.cljs:133
|
||||
msgid "workspace.libraries.colors"
|
||||
msgid_plural "workspace.libraries.colors"
|
||||
msgstr[0] "1 colore"
|
||||
msgstr[1] "%s colori"
|
||||
|
||||
#: src/app/main/ui/workspace/libraries.cljs:101, src/app/main/ui/workspace/libraries.cljs:125
|
||||
msgid "workspace.libraries.components"
|
||||
msgid_plural "workspace.libraries.components"
|
||||
msgstr[0] "1 componente"
|
||||
msgstr[1] "%s componenti"
|
||||
|
||||
#: src/app/main/ui/workspace/libraries.cljs:104, src/app/main/ui/workspace/libraries.cljs:129
|
||||
msgid "workspace.libraries.graphics"
|
||||
msgid_plural "workspace.libraries.graphics"
|
||||
msgstr[0] "1 grafica"
|
||||
msgstr[1] "%s grafiche"
|
||||
|
||||
#: src/app/main/ui/workspace/libraries.cljs:110, src/app/main/ui/workspace/libraries.cljs:137
|
||||
msgid "workspace.libraries.typography"
|
||||
msgid_plural "workspace.libraries.typography"
|
||||
msgstr[0] "1 tipografia"
|
||||
msgstr[1] "%s tipografie"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/color_selection.cljs:264
|
||||
msgid "workspace.options.more-token-colors"
|
||||
msgstr "Altri token colore"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/management/create/form.cljs:1339
|
||||
msgid "workspace.tokens.font-size-value-enter"
|
||||
msgstr "Dimensione carattere o {alias}"
|
||||
|
||||
#: src/app/main/data/workspace/tokens/errors.cljs:101
|
||||
msgid "workspace.tokens.invalid-shadow-type-token-value"
|
||||
msgstr ""
|
||||
"Tipologia ombra non valida: sono consentite solo 'innerShadow' o 'dropShadow'"
|
||||
|
||||
#: src/app/main/ui/workspace/tokens/management/create/border_radius.cljs:42, src/app/main/ui/workspace/tokens/management/create/form.cljs:68
|
||||
msgid "workspace.tokens.token-name-length-validation-error"
|
||||
msgstr "Il nome deve essere di almeno 1 carattere"
|
||||
|
||||
msgid "subscription.settings.management-dialog.step-2-skip-button"
|
||||
msgstr "Salta per ora e inizia la prova"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"PO-Revision-Date: 2025-11-23 12:51+0000\n"
|
||||
"PO-Revision-Date: 2025-11-25 16:51+0000\n"
|
||||
"Last-Translator: Edgars Andersons <Edgars+Weblate@gaitenis.id.lv>\n"
|
||||
"Language-Team: Latvian <https://hosted.weblate.org/projects/penpot/frontend/"
|
||||
"lv/>\n"
|
||||
@@ -1809,10 +1809,6 @@ msgstr ""
|
||||
"Ja ir vēlme uzzināt vairāk par dizaina apskati, jāapmeklē Penpot palīdzības "
|
||||
"centrs"
|
||||
|
||||
#: src/app/main/ui/inspect/right_sidebar.cljs:240
|
||||
msgid "inspect.empty.more-info"
|
||||
msgstr "Vairāk informācijas par apskatīšanu"
|
||||
|
||||
#: src/app/main/ui/inspect/right_sidebar.cljs:232
|
||||
msgid "inspect.empty.select"
|
||||
msgstr "Jāatlasa apveids, plātne vai kopa, lai apskatītu to īpašības un kodu"
|
||||
@@ -7966,3 +7962,12 @@ msgstr "Ierosinājums"
|
||||
#: src/app/main/ui/settings/feedback.cljs:114
|
||||
msgid "feedback.type.issue"
|
||||
msgstr "Sarežģījums"
|
||||
|
||||
msgid "subscription.settings.management-dialog.step-2-title"
|
||||
msgstr "Palīdzi mums attīstīties un padarīt Tavu izmēģinājumu vienkāršāku"
|
||||
|
||||
msgid "subscription.settings.management-dialog.step-2-skip-button"
|
||||
msgstr "Pagaidām izlaist un uzsākt izmēģinājumu"
|
||||
|
||||
msgid "subscription.settings.management-dialog.step-2-add-payment-button"
|
||||
msgstr "Pievienot maksājumu informāciju"
|
||||
|
||||
@@ -1297,10 +1297,6 @@ msgstr ""
|
||||
"Jika anda ingin mengetahui lebih lanjut tentang pemeriksaan reka bentuk, "
|
||||
"lawati pusat bantuan Penpot"
|
||||
|
||||
#: src/app/main/ui/inspect/right_sidebar.cljs:240
|
||||
msgid "inspect.empty.more-info"
|
||||
msgstr "Maklumat lanjut tentang inspect"
|
||||
|
||||
#: src/app/main/ui/inspect/right_sidebar.cljs:232
|
||||
msgid "inspect.empty.select"
|
||||
msgstr "Pilih bentuk, papan atau kumpulan untuk memeriksa sifat dan kod mereka"
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"PO-Revision-Date: 2025-11-22 10:51+0000\n"
|
||||
"Last-Translator: Keunes <keunes@mailbox.org>\n"
|
||||
"Language-Team: Dutch <https://hosted.weblate.org/projects/penpot/frontend/nl/"
|
||||
">\n"
|
||||
"PO-Revision-Date: 2025-12-22 15:34+0000\n"
|
||||
"Last-Translator: Anonymous <noreply@weblate.org>\n"
|
||||
"Language-Team: Dutch <https://hosted.weblate.org/projects/penpot/frontend/"
|
||||
"nl/>\n"
|
||||
"Language: nl\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||
"X-Generator: Weblate 5.15-dev\n"
|
||||
"X-Generator: Weblate 5.15.1\n"
|
||||
|
||||
#: src/app/main/ui/auth/register.cljs:215, src/app/main/ui/static.cljs:159, src/app/main/ui/viewer/login.cljs:100
|
||||
msgid "auth.already-have-account"
|
||||
@@ -580,6 +580,7 @@ msgstr ""
|
||||
"bibliotheken. Wat wil je doen met hun assets*?"
|
||||
|
||||
#: src/app/main/ui/exports/files.cljs:164
|
||||
#, fuzzy
|
||||
msgid "dashboard.export.options.all.message"
|
||||
msgstr ""
|
||||
"Bestanden met gedeelde bibliotheken worden opgenomen in de export en hun "
|
||||
@@ -1825,10 +1826,6 @@ msgstr ""
|
||||
"Als je meer wilt weten over ontwerpinspectie, ga dan naar het helpcentrum "
|
||||
"van Penpot"
|
||||
|
||||
#: src/app/main/ui/inspect/right_sidebar.cljs:240
|
||||
msgid "inspect.empty.more-info"
|
||||
msgstr "Meer info over inspecteren"
|
||||
|
||||
#: src/app/main/ui/inspect/right_sidebar.cljs:232
|
||||
msgid "inspect.empty.select"
|
||||
msgstr ""
|
||||
@@ -1836,6 +1833,7 @@ msgstr ""
|
||||
"inspecteren"
|
||||
|
||||
#: src/app/main/ui/inspect/right_sidebar.cljs:166
|
||||
#, fuzzy
|
||||
msgid "inspect.layer-info"
|
||||
msgstr "Laaginfo"
|
||||
|
||||
@@ -8384,7 +8382,7 @@ msgstr "Schakelaar"
|
||||
|
||||
#: src/app/main/ui/dashboard/subscription.cljs:84
|
||||
msgid "subscription.dashboard.power-up.professional.bottom-button"
|
||||
msgstr "Inschakelen!"
|
||||
msgstr "Gas geven!"
|
||||
|
||||
#: src/app/main/ui/dashboard/subscription.cljs:83
|
||||
#, markdown
|
||||
@@ -8474,3 +8472,18 @@ msgstr "Naam moet minimaal 1 teken zijn"
|
||||
#: src/app/main/ui/inspect/styles/style_box.cljs:68
|
||||
msgid "inspect.tabs.styles.copy-shorthand"
|
||||
msgstr "CSS-code kopiëren naar klembord"
|
||||
|
||||
msgid "subscription.settings.management-dialog.step-2-title"
|
||||
msgstr "Help ons groeien en maak je proefperiode eenvoudiger"
|
||||
|
||||
msgid "subscription.settings.management-dialog.step-2-description"
|
||||
msgstr ""
|
||||
"Voeg nu je betalingsgegevens toe om je abonnement na de proefperiode soepel "
|
||||
"te laten verlopen en ons open-sourceproject te blijven ondersteunen. Er "
|
||||
"worden nog geen kosten in rekening gebracht."
|
||||
|
||||
msgid "subscription.settings.management-dialog.step-2-skip-button"
|
||||
msgstr "Nu overslaan en proefperiode starten"
|
||||
|
||||
msgid "subscription.settings.management-dialog.step-2-add-payment-button"
|
||||
msgstr "Betalingsgegevens toevoegen"
|
||||
|
||||
@@ -1170,10 +1170,6 @@ msgstr ""
|
||||
"Jeśli chcesz dowiedzieć się więcej o inspekcji projektu, odwiedź centrum "
|
||||
"pomocy Penpot"
|
||||
|
||||
#: src/app/main/ui/inspect/right_sidebar.cljs:240
|
||||
msgid "inspect.empty.more-info"
|
||||
msgstr "Więcej informacji o inspekcji"
|
||||
|
||||
#: src/app/main/ui/inspect/right_sidebar.cljs:232
|
||||
msgid "inspect.empty.select"
|
||||
msgstr "Wybierz kształt, tablicę lub grupę, aby sprawdzić ich właściwości i kod"
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"PO-Revision-Date: 2025-11-18 13:51+0000\n"
|
||||
"Last-Translator: Tiago José <soutiagojose@outlook.com>\n"
|
||||
"Language-Team: Portuguese (Brazil) "
|
||||
"<https://hosted.weblate.org/projects/penpot/frontend/pt_BR/>\n"
|
||||
"PO-Revision-Date: 2025-12-22 15:34+0000\n"
|
||||
"Last-Translator: Anonymous <noreply@weblate.org>\n"
|
||||
"Language-Team: Portuguese (Brazil) <https://hosted.weblate.org/projects/"
|
||||
"penpot/frontend/pt_BR/>\n"
|
||||
"Language: pt_BR\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=n > 1;\n"
|
||||
"X-Generator: Weblate 5.15-dev\n"
|
||||
"X-Generator: Weblate 5.15.1\n"
|
||||
|
||||
#: src/app/main/ui/auth/register.cljs:215, src/app/main/ui/static.cljs:159, src/app/main/ui/viewer/login.cljs:100
|
||||
msgid "auth.already-have-account"
|
||||
@@ -1812,10 +1812,6 @@ msgstr ""
|
||||
"Se quiser saber mais sobre inspecionar o design, visite a central de ajuda "
|
||||
"do Penpot"
|
||||
|
||||
#: src/app/main/ui/inspect/right_sidebar.cljs:240
|
||||
msgid "inspect.empty.more-info"
|
||||
msgstr "Mais informações sobre inspecionar"
|
||||
|
||||
#: src/app/main/ui/inspect/right_sidebar.cljs:232
|
||||
msgid "inspect.empty.select"
|
||||
msgstr ""
|
||||
@@ -1823,6 +1819,7 @@ msgstr ""
|
||||
"código"
|
||||
|
||||
#: src/app/main/ui/inspect/right_sidebar.cljs:166
|
||||
#, fuzzy
|
||||
msgid "inspect.layer-info"
|
||||
msgstr "Informações da camada"
|
||||
|
||||
|
||||
@@ -1576,10 +1576,6 @@ msgstr "Maiúsculas"
|
||||
msgid "inspect.empty.help"
|
||||
msgstr "Se quiseres saber mais sobre a inspeção, visita o centro de ajuda do Penpot"
|
||||
|
||||
#: src/app/main/ui/inspect/right_sidebar.cljs:240
|
||||
msgid "inspect.empty.more-info"
|
||||
msgstr "Mais informações sobre a inspeção"
|
||||
|
||||
#: src/app/main/ui/inspect/right_sidebar.cljs:232
|
||||
msgid "inspect.empty.select"
|
||||
msgstr ""
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"PO-Revision-Date: 2025-10-17 11:07+0000\n"
|
||||
"Last-Translator: AlexTECPlayz <alextecplayz@vantainteractive.com>\n"
|
||||
"Language-Team: Romanian "
|
||||
"<https://hosted.weblate.org/projects/penpot/frontend/ro/>\n"
|
||||
"PO-Revision-Date: 2025-12-22 15:34+0000\n"
|
||||
"Last-Translator: Anonymous <noreply@weblate.org>\n"
|
||||
"Language-Team: Romanian <https://hosted.weblate.org/projects/penpot/frontend/"
|
||||
"ro/>\n"
|
||||
"Language: ro\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=3; plural=n==1 ? 0 : (n==0 || (n%100 > 0 && n%100 < "
|
||||
"20)) ? 1 : 2;\n"
|
||||
"X-Generator: Weblate 5.14-dev\n"
|
||||
"X-Generator: Weblate 5.15.1\n"
|
||||
|
||||
#: src/app/main/ui/auth/register.cljs:215, src/app/main/ui/static.cljs:159, src/app/main/ui/viewer/login.cljs:100
|
||||
msgid "auth.already-have-account"
|
||||
@@ -1821,10 +1821,6 @@ msgstr ""
|
||||
"Dacă dorești să afli mai multe despre inspectorul de design, vizitează "
|
||||
"centrul de ajutor Penpot"
|
||||
|
||||
#: src/app/main/ui/inspect/right_sidebar.cljs:240
|
||||
msgid "inspect.empty.more-info"
|
||||
msgstr "Mai multe informații despre inspector"
|
||||
|
||||
#: src/app/main/ui/inspect/right_sidebar.cljs:232
|
||||
msgid "inspect.empty.select"
|
||||
msgstr ""
|
||||
@@ -1832,6 +1828,7 @@ msgstr ""
|
||||
"și codul"
|
||||
|
||||
#: src/app/main/ui/inspect/right_sidebar.cljs:166
|
||||
#, fuzzy
|
||||
msgid "inspect.layer-info"
|
||||
msgstr "Informație strat"
|
||||
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"PO-Revision-Date: 2025-10-14 17:07+0000\n"
|
||||
"Last-Translator: \"Roman D.\" <williampuh@gmail.com>\n"
|
||||
"Language-Team: Russian "
|
||||
"<https://hosted.weblate.org/projects/penpot/frontend/ru/>\n"
|
||||
"PO-Revision-Date: 2025-12-22 15:34+0000\n"
|
||||
"Last-Translator: Anonymous <noreply@weblate.org>\n"
|
||||
"Language-Team: Russian <https://hosted.weblate.org/projects/penpot/frontend/"
|
||||
"ru/>\n"
|
||||
"Language: ru\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Generator: Weblate 5.14-dev\n"
|
||||
"X-Generator: Weblate 5.15.1\n"
|
||||
|
||||
#: src/app/main/ui/auth/register.cljs:215, src/app/main/ui/static.cljs:159, src/app/main/ui/viewer/login.cljs:100
|
||||
msgid "auth.already-have-account"
|
||||
@@ -573,8 +573,10 @@ msgstr ""
|
||||
"сделать с их ресурсами*?"
|
||||
|
||||
#: src/app/main/ui/exports/files.cljs:164
|
||||
#, fuzzy
|
||||
msgid "dashboard.export.options.all.message"
|
||||
msgstr "Файлы с общих библиотек будут включены в экспорт, сохраняя свою привязку."
|
||||
msgstr ""
|
||||
"Файлы с общих библиотек будут включены в экспорт, сохраняя свою привязку."
|
||||
|
||||
#: src/app/main/ui/exports/files.cljs:165
|
||||
msgid "dashboard.export.options.all.title"
|
||||
@@ -1779,15 +1781,12 @@ msgstr ""
|
||||
"Если вы хотите узнать больше о осмотре дизайна, посетите справочный центр "
|
||||
"Penpot"
|
||||
|
||||
#: src/app/main/ui/inspect/right_sidebar.cljs:240
|
||||
msgid "inspect.empty.more-info"
|
||||
msgstr "Подробнее об осмотре"
|
||||
|
||||
#: src/app/main/ui/inspect/right_sidebar.cljs:232
|
||||
msgid "inspect.empty.select"
|
||||
msgstr "Выберите фигуру, доску или группу, чтобы просмотреть свойства и код"
|
||||
|
||||
#: src/app/main/ui/inspect/right_sidebar.cljs:166
|
||||
#, fuzzy
|
||||
msgid "inspect.layer-info"
|
||||
msgstr "Информация о слое"
|
||||
|
||||
|
||||
@@ -1348,10 +1348,6 @@ msgstr ""
|
||||
"Ако желите да сазнате више о прегледу дизајна, посетите Помоћни центар "
|
||||
"Penpot-а"
|
||||
|
||||
#: src/app/main/ui/inspect/right_sidebar.cljs:240
|
||||
msgid "inspect.empty.more-info"
|
||||
msgstr "Више информација о прегледу"
|
||||
|
||||
#: src/app/main/ui/inspect/right_sidebar.cljs:232
|
||||
msgid "inspect.empty.select"
|
||||
msgstr "Изаберите облик, таблу или групу да бисте прегледали њихова својства и код"
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user