diff --git a/CHANGES.md b/CHANGES.md index 2f0dbac7d3..5631282a05 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -11,6 +11,7 @@ ### :sparkles: New features - New gradients UI with multi-stop support. +- Shareable link pointing to an specific board. ### :bug: Bugs fixed @@ -46,6 +47,8 @@ ### :bug: Bugs fixed - Fix problem with some texts desynchronization [Taiga #9379](https://tree.taiga.io/project/penpot/issue/9379) +- Fix problem with reoder grid layers [#5446](https://github.com/penpot/penpot/issues/5446) +- Fix problem with swap component style [#9542](https://tree.taiga.io/project/penpot/issue/9542) ## 2.3.3 diff --git a/backend/resources/app/email/comment-mention/en.html b/backend/resources/app/email/comment-mention/en.html new file mode 100644 index 0000000000..fa45cab25e --- /dev/null +++ b/backend/resources/app/email/comment-mention/en.html @@ -0,0 +1,244 @@ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ +
+ + + + +
+ + + + + + +
+ +
+
+
+ +
+
+ +
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + + +
+
+ Hello {{name|abbreviate:25}}!
+
+
+ {{ source-user }} has mentioned you on a comment at "{{ comment-reference }}".
+
+
+ {{ comment-content }} +
+
+ + + + +
+ GO TO THE COMMENT +
+
+
+ The Penpot team.
+
+
+ +
+
+ + {% include "app/email/includes/footer.html" %} + +
+ + + diff --git a/backend/resources/app/email/comment-mention/en.subj b/backend/resources/app/email/comment-mention/en.subj new file mode 100644 index 0000000000..c3f027d5d5 --- /dev/null +++ b/backend/resources/app/email/comment-mention/en.subj @@ -0,0 +1 @@ +Mentioned in comment diff --git a/backend/resources/app/email/comment-mention/en.txt b/backend/resources/app/email/comment-mention/en.txt new file mode 100644 index 0000000000..32a15a4d58 --- /dev/null +++ b/backend/resources/app/email/comment-mention/en.txt @@ -0,0 +1,13 @@ +Hello {{name|abbreviate:25}}! + +{{ source-user }} has mentioned you on a comment at "{{ comment-reference }}". + +-- + +{{ comment-content }} + +-- + +{{ comment-url }} + +The Penpot team. diff --git a/backend/resources/app/email/comment-notification/en.html b/backend/resources/app/email/comment-notification/en.html new file mode 100644 index 0000000000..595c6b53da --- /dev/null +++ b/backend/resources/app/email/comment-notification/en.html @@ -0,0 +1,244 @@ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ +
+ + + + +
+ + + + + + +
+ +
+
+
+ +
+
+ +
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + + +
+
+ Hello {{name|abbreviate:25}}!
+
+
+ {{ source-user }} has commented at "{{ comment-reference }}".
+
+
+ {{ comment-content }} +
+
+ + + + +
+ GO TO THE COMMENT +
+
+
+ The Penpot team.
+
+
+ +
+
+ + {% include "app/email/includes/footer.html" %} + +
+ + + diff --git a/backend/resources/app/email/comment-notification/en.subj b/backend/resources/app/email/comment-notification/en.subj new file mode 100644 index 0000000000..94a261f310 --- /dev/null +++ b/backend/resources/app/email/comment-notification/en.subj @@ -0,0 +1 @@ +New comment diff --git a/backend/resources/app/email/comment-notification/en.txt b/backend/resources/app/email/comment-notification/en.txt new file mode 100644 index 0000000000..166ffc14bb --- /dev/null +++ b/backend/resources/app/email/comment-notification/en.txt @@ -0,0 +1,13 @@ +Hello {{name|abbreviate:25}}! + +{{ source-user }} has commented at "{{ comment-reference }}". + +-- + +{{ comment-content }} + +-- + +{{ comment-url }} + +The Penpot team. diff --git a/backend/resources/app/email/comment-thread/en.html b/backend/resources/app/email/comment-thread/en.html new file mode 100644 index 0000000000..8676a35291 --- /dev/null +++ b/backend/resources/app/email/comment-thread/en.html @@ -0,0 +1,244 @@ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ +
+ + + + +
+ + + + + + +
+ +
+
+
+ +
+
+ +
+ + + + + + +
+ +
+ + + + + + + + + + + + + + + + +
+
+ Hello {{name|abbreviate:25}}!
+
+
+ {{ source-user }} has created a comment in a thread you've been mentioned at "{{ comment-reference }}".
+
+
+ {{ comment-content }} +
+
+ + + + +
+ GO TO THE COMMENT +
+
+
+ The Penpot team.
+
+
+ +
+
+ + {% include "app/email/includes/footer.html" %} + +
+ + + diff --git a/backend/resources/app/email/comment-thread/en.subj b/backend/resources/app/email/comment-thread/en.subj new file mode 100644 index 0000000000..5477605728 --- /dev/null +++ b/backend/resources/app/email/comment-thread/en.subj @@ -0,0 +1 @@ +New response in comment diff --git a/backend/resources/app/email/comment-thread/en.txt b/backend/resources/app/email/comment-thread/en.txt new file mode 100644 index 0000000000..52d79de54c --- /dev/null +++ b/backend/resources/app/email/comment-thread/en.txt @@ -0,0 +1,13 @@ +Hello {{name|abbreviate:25}}! + +{{ source-user }} has created a comment in a thread you've been mentioned at "{{ comment-reference }}". + +-- + +{{ comment-content }} + +-- + +{{ comment-url }} + +The Penpot team. diff --git a/backend/src/app/email.clj b/backend/src/app/email.clj index 5bcf741f1c..75365fe75c 100644 --- a/backend/src/app/email.clj +++ b/backend/src/app/email.clj @@ -449,6 +449,45 @@ :id ::request-team-access :schema schema:request-team-access)) +(def ^:private schema:comment-mention + [:map + [:name ::sm/text] + [:source-user ::sm/text] + [:comment-reference ::sm/text] + [:comment-content ::sm/text] + [:comment-url ::sm/text]]) + +(def comment-mention + (template-factory + :id ::comment-mention + :schema schema:comment-mention)) + +(def ^:private schema:comment-thread + [:map + [:name ::sm/text] + [:source-user ::sm/text] + [:comment-reference ::sm/text] + [:comment-content ::sm/text] + [:comment-url ::sm/text]]) + +(def comment-thread + (template-factory + :id ::comment-thread + :schema schema:comment-thread)) + +(def ^:private schema:comment-notification + [:map + [:name ::sm/text] + [:source-user ::sm/text] + [:comment-reference ::sm/text] + [:comment-content ::sm/text] + [:comment-url ::sm/text]]) + +(def comment-notification + (template-factory + :id ::comment-notification + :schema schema:comment-notification)) + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; BOUNCE/COMPLAINS HELPERS ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; diff --git a/backend/src/app/migrations.clj b/backend/src/app/migrations.clj index 566095a19e..cefa94b65c 100644 --- a/backend/src/app/migrations.clj +++ b/backend/src/app/migrations.clj @@ -426,7 +426,10 @@ :fn (mg/resource "app/migrations/sql/0134-mod-file-change-table.sql")} {:name "0135-mod-team-invitation-table.sql" - :fn (mg/resource "app/migrations/sql/0135-mod-team-invitation-table.sql")}]) + :fn (mg/resource "app/migrations/sql/0135-mod-team-invitation-table.sql")} + + {:name "0136-mod-comments-mentions.sql" + :fn (mg/resource "app/migrations/sql/0136-mod-comments-mentions.sql")}]) (defn apply-migrations! [pool name migrations] diff --git a/backend/src/app/migrations/sql/0136-mod-comments-mentions.sql b/backend/src/app/migrations/sql/0136-mod-comments-mentions.sql new file mode 100644 index 0000000000..f5a8cf9f0e --- /dev/null +++ b/backend/src/app/migrations/sql/0136-mod-comments-mentions.sql @@ -0,0 +1,3 @@ +ALTER TABLE comment ADD COLUMN mentions uuid[] NULL DEFAULT '{}'; + +ALTER TABLE comment_thread ADD COLUMN mentions uuid[] NULL DEFAULT '{}'; diff --git a/backend/src/app/rpc/commands/auth.clj b/backend/src/app/rpc/commands/auth.clj index 062436dbe6..cf9db7762f 100644 --- a/backend/src/app/rpc/commands/auth.clj +++ b/backend/src/app/rpc/commands/auth.clj @@ -273,7 +273,8 @@ (merge {:viewed-tutorial? false :viewed-walkthrough? false :nudge {:big 10 :small 1} - :v2-info-shown true}) + :v2-info-shown true + :release-notes-viewed (:main cf/version)}) (db/tjson)) password (or (:password params) "!") diff --git a/backend/src/app/rpc/commands/comments.clj b/backend/src/app/rpc/commands/comments.clj index fafecd8b87..f649f577b5 100644 --- a/backend/src/app/rpc/commands/comments.clj +++ b/backend/src/app/rpc/commands/comments.clj @@ -6,40 +6,165 @@ (ns app.rpc.commands.comments (:require + [app.common.data :as d] [app.common.data.macros :as dm] [app.common.exceptions :as ex] [app.common.geom.point :as gpt] [app.common.schema :as sm] + [app.common.uri :as uri] [app.common.uuid :as uuid] + [app.config :as cf] [app.db :as db] [app.db.sql :as sql] + [app.email :as eml] [app.features.fdata :as feat.fdata] [app.loggers.audit :as-alias audit] [app.loggers.webhooks :as-alias webhooks] [app.rpc :as-alias rpc] [app.rpc.commands.files :as files] + [app.rpc.commands.profile :as profile] [app.rpc.commands.teams :as teams] [app.rpc.doc :as-alias doc] [app.rpc.quotes :as quotes] [app.rpc.retry :as rtry] [app.util.pointer-map :as pmap] [app.util.services :as sv] - [app.util.time :as dt])) + [app.util.time :as dt] + [clojure.set :as set] + [cuerdas.core :as str])) ;; --- GENERAL PURPOSE INTERNAL HELPERS +(def r-mentions-split #"@\[[^\]]*\]\([^\)]*\)") +(def r-mentions #"@\[([^\]]*)\]\(([^\)]*)\)") + +(defn- format-comment + [{:keys [content]}] + (->> (d/interleave-all + (str/split content r-mentions-split) + (->> (re-seq r-mentions content) + (map (fn [[_ user _]] user)))) + (str/join ""))) + +(defn- format-comment-url + [{:keys [team-id file-id page-id]}] + (str/ffmt "%/#/workspace?%" + (cf/get :public-uri) + (uri/map->query-string + {:file-id file-id + :page-id page-id + :team-id team-id}))) + +(defn- format-comment-ref + [{:keys [seqn]} {:keys [file-name page-name]}] + (str/ffmt "#%, %, %" seqn file-name page-name)) + +(defn get-team-users + [conn team-id] + (->> (teams/get-users+props conn team-id) + (map profile/decode-row) + (d/index-by :id))) + +(defn- resolve-profile-name + [conn profile-id] + (-> (db/get conn :profile {:id profile-id} + {::sql/columns [:fullname]}) + (get :fullname))) + +(defn- notification-email? + [profile-id owner-id props] + (if (= profile-id owner-id) + (not= :none (-> props :notifications :email-comments)) + (= :all (-> props :notifications :email-comments)))) + +(defn- mention-email? + [props] + (not= :none (-> props :notifications :email-comments))) + +(defn send-comment-emails! + [conn {:keys [profile-id team-id] :as params} comment thread] + + (let [team-users (get-team-users conn team-id) + source-user (resolve-profile-name conn profile-id) + + comment-reference (format-comment-ref thread params) + comment-content (format-comment comment) + comment-url (format-comment-url params) + + ;; Users mentioned in this comment + comment-mentions + (-> (:mentions comment) + (set/difference #{profile-id})) + + ;; Users mentioned in this thread + thread-mentions + (-> (:mentions thread) + ;; Remove the mentions in the thread because we're already sending a + ;; notification + (set/difference comment-mentions) + (disj profile-id)) + + ;; All users + notificate-users-ids + (-> (set (keys team-users)) + (set/difference comment-mentions) + (set/difference thread-mentions) + (disj profile-id))] + + (doseq [mention comment-mentions] + (let [{:keys [fullname email props]} (get team-users mention)] + (when (mention-email? props) + (eml/send! + {::eml/conn conn + ::eml/factory eml/comment-mention + :to email + :name fullname + :source-user source-user + :comment-reference comment-reference + :comment-content comment-content + :comment-url comment-url})))) + + ;; Send to the thread users + (doseq [mention thread-mentions] + (let [{:keys [fullname email props]} (get team-users mention)] + (when (mention-email? props) + (eml/send! + {::eml/conn conn + ::eml/factory eml/comment-thread + :to email + :name fullname + :source-user source-user + :comment-reference comment-reference + :comment-content comment-content + :comment-url comment-url})))) + + ;; Send to users with the "all" flag activated + (doseq [user-id notificate-users-ids] + (let [{:keys [id fullname email props]} (get team-users user-id)] + (when (notification-email? id (:owner-id thread) props) + (eml/send! + {::eml/conn conn + ::eml/factory eml/comment-notification + :to email + :name fullname + :source-user source-user + :comment-reference comment-reference + :comment-content comment-content + :comment-url comment-url})))))) + (defn- decode-row - [{:keys [participants position] :as row}] + [{:keys [participants position mentions] :as row}] (cond-> row (db/pgpoint? position) (assoc :position (db/decode-pgpoint position)) - (db/pgobject? participants) (assoc :participants (db/decode-transit-pgobject participants)))) + (db/pgobject? participants) (assoc :participants (db/decode-transit-pgobject participants)) + (db/pgarray? mentions) (assoc :mentions (db/decode-pgarray mentions #{})))) (def xf-decode-row (map decode-row)) -(def ^:privateqpage-name +(def ^:private sql:get-file - "select f.id, f.modified_at, f.revn, f.features, + "select f.id, f.modified_at, f.revn, f.features, f.name, f.project_id, p.team_id, f.data from file as f join project as p on (p.id = f.project_id) @@ -91,7 +216,7 @@ (defn upsert-comment-thread-status! ([conn profile-id thread-id] - (upsert-comment-thread-status! conn profile-id thread-id (dt/now))) + (upsert-comment-thread-status! conn profile-id thread-id (dt/in-future "1s"))) ([conn profile-id thread-id mod-at] (db/exec-one! conn [sql:upsert-comment-thread-status thread-id profile-id mod-at mod-at]))) @@ -116,36 +241,38 @@ {::doc/added "1.15" ::sm/params schema:get-comment-threads} [cfg {:keys [::rpc/profile-id file-id share-id] :as params}] - (db/run! cfg (fn [{:keys [::db/conn]}] (files/check-comment-permissions! conn profile-id file-id share-id) (get-comment-threads conn profile-id file-id)))) (def ^:private sql:comment-threads - "select distinct on (ct.id) + "SELECT DISTINCT ON (ct.id) ct.*, - f.name as file_name, - f.project_id as project_id, - first_value(c.content) over w as content, - (select count(1) - from comment as c - where c.thread_id = ct.id) as count_comments, - (select count(1) - from comment as c - where c.thread_id = ct.id - and c.created_at >= coalesce(cts.modified_at, ct.created_at)) as count_unread_comments - from comment_thread as ct - inner join comment as c on (c.thread_id = ct.id) - inner join file as f on (f.id = ct.file_id) - left join comment_thread_status as cts - on (cts.thread_id = ct.id and - cts.profile_id = ?) - where ct.file_id = ? - window w as (partition by c.thread_id order by c.created_at asc)") + p.team_id AS team_id, + f.name AS file_name, + f.project_id AS project_id, + first_value(c.content) OVER w AS content, + (SELECT count(1) + FROM comment AS c + WHERE c.thread_id = ct.id) AS count_comments, + (SELECT count(1) + FROM comment AS c + WHERE c.thread_id = ct.id + AND c.created_at >= coalesce(cts.modified_at, ct.created_at)) AS count_unread_comments + FROM comment_thread AS ct + INNER JOIN comment AS c ON (c.thread_id = ct.id) + INNER JOIN file AS f ON (f.id = ct.file_id) + INNER JOIN project AS p ON (p.id = f.project_id) + LEFT JOIN comment_thread_status AS cts ON (cts.thread_id = ct.id AND cts.profile_id = ?) + WINDOW w AS (PARTITION BY c.thread_id ORDER BY c.created_at ASC)") + +(def ^:private sql:comment-threads-by-file-id + (str "WITH threads AS (" sql:comment-threads ")" + "SELECT * FROM threads WHERE file_id = ?")) (defn- get-comment-threads [conn profile-id file-id] - (->> (db/exec! conn [sql:comment-threads profile-id file-id]) + (->> (db/exec! conn [sql:comment-threads-by-file-id profile-id file-id]) (into [] xf-decode-row))) ;; --- COMMAND: Get Unread Comment Threads @@ -161,41 +288,41 @@ {::doc/added "1.15" ::sm/params schema:get-unread-comment-threads} [cfg {:keys [::rpc/profile-id team-id] :as params}] - (db/run! cfg (fn [{:keys [::db/conn]}] - (teams/check-read-permissions! conn profile-id team-id) - (get-unread-comment-threads conn profile-id team-id)))) + (db/run! + cfg + (fn [{:keys [::db/conn]}] + (teams/check-read-permissions! conn profile-id team-id) + (get-unread-comment-threads conn profile-id team-id)))) -(def sql:comment-threads-by-team - "select distinct on (ct.id) - ct.*, - f.name as file_name, - f.project_id as project_id, - first_value(c.content) over w as content, - (select count(1) - from comment as c - where c.thread_id = ct.id) as count_comments, - (select count(1) - from comment as c - where c.thread_id = ct.id - and c.created_at >= coalesce(cts.modified_at, ct.created_at)) as count_unread_comments - from comment_thread as ct - inner join comment as c on (c.thread_id = ct.id) - inner join file as f on (f.id = ct.file_id) - inner join project as p on (p.id = f.project_id) - left join comment_thread_status as cts - on (cts.thread_id = ct.id and - cts.profile_id = ?) - where p.team_id = ? - window w as (partition by c.thread_id order by c.created_at asc)") +(def sql:unread-all-comment-threads-by-team + (str "WITH threads AS (" sql:comment-threads ")" + "SELECT * FROM threads WHERE count_unread_comments > 0 AND team_id = ?")) -(def sql:unread-comment-threads-by-team - (str "with threads as (" sql:comment-threads-by-team ")" - "select * from threads where count_unread_comments > 0")) +;; The partial configuration will retrieve only comments created by the user and +;; threads that have a mention to the user. +(def sql:unread-partial-comment-threads-by-team + (str "WITH threads AS (" sql:comment-threads ")" + "SELECT * FROM threads + WHERE count_unread_comments > 0 + AND team_id = ? + AND (owner_id = ? OR ? = ANY(mentions))")) (defn- get-unread-comment-threads [conn profile-id team-id] - (->> (db/exec! conn [sql:unread-comment-threads-by-team profile-id team-id]) - (into [] xf-decode-row))) + (let [profile (-> (db/get conn :profile {:id profile-id}) + (profile/decode-row)) + notify (or (-> profile :props :notifications :dashboard-comments) :all)] + + (case notify + :all + (->> (db/exec! conn [sql:unread-all-comment-threads-by-team profile-id team-id]) + (into [] xf-decode-row)) + + :partial + (->> (db/exec! conn [sql:unread-partial-comment-threads-by-team profile-id team-id profile-id profile-id]) + (into [] xf-decode-row)) + + []))) ;; --- COMMAND: Get Single Comment Thread @@ -212,9 +339,9 @@ [cfg {:keys [::rpc/profile-id file-id id share-id] :as params}] (db/run! cfg (fn [{:keys [::db/conn]}] (files/check-comment-permissions! conn profile-id file-id share-id) - (let [sql (str "with threads as (" sql:comment-threads ")" - "select * from threads where id = ?")] - (-> (db/exec-one! conn [sql profile-id file-id id]) + (let [sql (str "WITH threads AS (" sql:comment-threads ")" + "SELECT * FROM threads WHERE id = ? AND file_id = ?")] + (-> (db/exec-one! conn [sql profile-id id file-id]) (decode-row)))))) ;; --- COMMAND: Retrieve Comments @@ -300,7 +427,8 @@ [:content [:string {:max 750}]] [:page-id ::sm/uuid] [:frame-id ::sm/uuid] - [:share-id {:optional true} [:maybe ::sm/uuid]]]) + [:share-id {:optional true} [:maybe ::sm/uuid]] + [:mentions {:optional true} [:vector ::sm/uuid]]]) (sv/defmethod ::create-comment-thread {::doc/added "1.15" @@ -308,11 +436,10 @@ ::rtry/enabled true ::rtry/when rtry/conflict-exception? ::sm/params schema:create-comment-thread} - [cfg {:keys [::rpc/profile-id ::rpc/request-at file-id page-id share-id position content frame-id]}] + [cfg {:keys [::rpc/profile-id ::rpc/request-at file-id page-id share-id mentions position content frame-id]}] (files/check-comment-permissions! cfg profile-id file-id share-id) - (let [{:keys [team-id project-id page-name]} (get-file cfg file-id page-id)] - + (let [{:keys [team-id project-id page-name name]} (get-file cfg file-id page-id)] (-> cfg (assoc ::quotes/profile-id profile-id) (assoc ::quotes/team-id team-id) @@ -324,18 +451,23 @@ (let [params {:created-at request-at :profile-id profile-id :file-id file-id + :file-name name :page-id page-id :page-name page-name :position position :content content - :frame-id frame-id} - thread (db/tx-run! cfg create-comment-thread params)] + :frame-id frame-id + :team-id team-id + :project-id project-id + :mentions mentions} + thread (-> (db/tx-run! cfg create-comment-thread params) + (decode-row))] (vary-meta thread assoc ::audit/props thread)))) (defn- create-comment-thread [{:keys [::db/conn] :as cfg} - {:keys [profile-id file-id page-id page-name created-at position content frame-id]}] + {:keys [profile-id file-id page-id page-name created-at position content mentions frame-id] :as params}] (let [;; NOTE: we take the next seq number from a separate query ;; because we need to lock the file for avoid race conditions @@ -348,25 +480,29 @@ seqn (get-next-seqn conn file-id) thread-id (uuid/next) - thread (db/insert! conn :comment-thread - {:id thread-id - :file-id file-id - :owner-id profile-id - :participants (db/tjson #{profile-id}) - :page-name page-name - :page-id page-id - :created-at created-at - :modified-at created-at - :seqn seqn - :position (db/pgpoint position) - :frame-id frame-id}) - comment (db/insert! conn :comment - {:id (uuid/next) - :thread-id thread-id - :owner-id profile-id - :created-at created-at - :modified-at created-at - :content content})] + thread (-> (db/insert! conn :comment-thread + {:id thread-id + :file-id file-id + :owner-id profile-id + :participants (db/tjson #{profile-id}) + :page-name page-name + :page-id page-id + :created-at created-at + :modified-at created-at + :seqn seqn + :position (db/pgpoint position) + :frame-id frame-id + :mentions (db/encode-pgarray mentions conn "uuid")}) + (decode-row)) + comment (-> (db/insert! conn :comment + {:id (uuid/next) + :thread-id thread-id + :owner-id profile-id + :created-at created-at + :modified-at created-at + :mentions (db/encode-pgarray mentions conn "uuid") + :content content}) + (decode-row))] ;; Make the current thread as read. (upsert-comment-thread-status! conn profile-id thread-id created-at) @@ -377,8 +513,11 @@ {:id file-id} {::db/return-keys false}) + ;; Send mentions emails + (send-comment-emails! conn params comment thread) + (-> thread - (select-keys [:id :file-id :page-id]) + (select-keys [:id :file-id :page-id :mentions]) (assoc :comment-id (:id comment))))) ;; --- COMMAND: Update Comment Thread Status @@ -391,12 +530,12 @@ (sv/defmethod ::update-comment-thread-status {::doc/added "1.15" - ::sm/params schema:update-comment-thread-status} - [cfg {:keys [::rpc/profile-id id share-id]}] - (db/tx-run! cfg (fn [{:keys [::db/conn]}] - (let [{:keys [file-id] :as thread} (get-comment-thread conn id ::sql/for-update true)] - (files/check-comment-permissions! conn profile-id file-id share-id) - (upsert-comment-thread-status! conn profile-id id))))) + ::sm/params schema:update-comment-thread-status + ::db/transaction true} + [{:keys [::db/conn]} {:keys [::rpc/profile-id id share-id]}] + (let [{:keys [file-id] :as thread} (get-comment-thread conn id ::sql/for-update true)] + (files/check-comment-permissions! conn profile-id file-id share-id) + (upsert-comment-thread-status! conn profile-id id))) ;; --- COMMAND: Update Comment Thread @@ -409,16 +548,15 @@ (sv/defmethod ::update-comment-thread {::doc/added "1.15" - ::sm/params schema:update-comment-thread} - [cfg {:keys [::rpc/profile-id id is-resolved share-id]}] - (db/tx-run! cfg (fn [{:keys [::db/conn]}] - (let [{:keys [file-id] :as thread} (get-comment-thread conn id ::sql/for-update true)] - (files/check-comment-permissions! conn profile-id file-id share-id) - (db/update! conn :comment-thread - {:is-resolved is-resolved} - {:id id}) - nil)))) - + ::sm/params schema:update-comment-thread + ::db/transaction true} + [{:keys [::db/conn]} {:keys [::rpc/profile-id id is-resolved share-id]}] + (let [{:keys [file-id] :as thread} (get-comment-thread conn id ::sql/for-update true)] + (files/check-comment-permissions! conn profile-id file-id share-id) + (db/update! conn :comment-thread + {:is-resolved is-resolved} + {:id id}) + nil)) ;; --- COMMAND: Add Comment @@ -429,56 +567,74 @@ [:map {:title "create-comment"} [:thread-id ::sm/uuid] [:content [:string {:max 250}]] - [:share-id {:optional true} [:maybe ::sm/uuid]]]) + [:share-id {:optional true} [:maybe ::sm/uuid]] + [:mentions {:optional true} [:vector ::sm/uuid]]]) (sv/defmethod ::create-comment {::doc/added "1.15" ::webhooks/event? true - ::sm/params schema:create-comment} - [cfg {:keys [::rpc/profile-id ::rpc/request-at thread-id share-id content]}] - (db/tx-run! cfg - (fn [{:keys [::db/conn] :as cfg}] - (let [{:keys [file-id page-id] :as thread} (get-comment-thread conn thread-id ::sql/for-update true) - {:keys [team-id project-id page-name] :as file} (get-file cfg file-id page-id)] + ::sm/params schema:create-comment + ::db/transaction true} + [{:keys [::db/conn] :as cfg} {:keys [::rpc/profile-id ::rpc/request-at thread-id share-id content mentions]}] + (let [{:keys [file-id page-id] :as thread} (get-comment-thread conn thread-id ::sql/for-update true) + {file-name :name :keys [team-id project-id page-name] :as file} (get-file cfg file-id page-id)] - (files/check-comment-permissions! conn profile-id file-id share-id) - (quotes/check! cfg {::quotes/id ::quotes/comments-per-file - ::quotes/profile-id profile-id - ::quotes/team-id team-id - ::quotes/project-id project-id - ::quotes/file-id file-id}) + (files/check-comment-permissions! conn profile-id file-id share-id) + (quotes/check! cfg {::quotes/id ::quotes/comments-per-file + ::quotes/profile-id profile-id + ::quotes/team-id team-id + ::quotes/project-id project-id + ::quotes/file-id file-id}) - ;; Update the page-name cached attribute on comment thread table. - (when (not= page-name (:page-name thread)) - (db/update! conn :comment-thread - {:page-name page-name} - {:id thread-id})) + ;; Update the page-name cached attribute on comment thread table. + (when (not= page-name (:page-name thread)) + (db/update! conn :comment-thread + {:page-name page-name} + {:id thread-id})) - (let [comment (db/insert! conn :comment - {:id (uuid/next) - :created-at request-at - :modified-at request-at - :thread-id thread-id - :owner-id profile-id - :content content}) - props {:file-id file-id - :share-id nil}] + (let [comment (-> (db/insert! + conn :comment + {:id (uuid/next) + :created-at request-at + :modified-at request-at + :thread-id thread-id + :owner-id profile-id + :content content + :mentions + (-> mentions + (set) + (db/encode-pgarray conn "uuid"))}) + (decode-row)) + props {:file-id file-id + :share-id nil}] - ;; Update thread modified-at attribute and assoc the current - ;; profile to the participant set. - (db/update! conn :comment-thread - {:modified-at request-at - :participants (-> (:participants thread #{}) - (conj profile-id) - (db/tjson))} - {:id thread-id}) + ;; Update thread modified-at attribute and assoc the current + ;; profile to the participant set. + (db/update! conn :comment-thread + {:modified-at request-at + :participants (-> (:participants thread #{}) + (conj profile-id) + (db/tjson)) + :mentions (-> (:mentions thread) + (set) + (into mentions) + (db/encode-pgarray conn "uuid"))} + {:id thread-id}) - ;; Update the current profile status in relation to the - ;; current thread. - (upsert-comment-thread-status! conn profile-id thread-id request-at) + ;; Update the current profile status in relation to the + ;; current thread. + (upsert-comment-thread-status! conn profile-id thread-id) - (vary-meta comment assoc ::audit/props props)))))) + (let [params {:project-id project-id + :profile-id profile-id + :team-id team-id + :file-id (:file-id thread) + :page-id (:page-id thread) + :file-name file-name + :page-name page-name}] + (send-comment-emails! conn params comment thread)) + (vary-meta comment assoc ::audit/props props)))) ;; --- COMMAND: Update Comment @@ -487,35 +643,42 @@ [:map {:title "update-comment"} [:id ::sm/uuid] [:content [:string {:max 250}]] - [:share-id {:optional true} [:maybe ::sm/uuid]]]) + [:share-id {:optional true} [:maybe ::sm/uuid]] + [:mentions {:optional true} [:vector ::sm/uuid]]]) +;; TODO Check if there are new mentions, if there are send the new emails. (sv/defmethod ::update-comment {::doc/added "1.15" - ::sm/params schema:update-comment} - [cfg {:keys [::rpc/profile-id ::rpc/request-at id share-id content]}] - (db/tx-run! cfg - (fn [{:keys [::db/conn] :as cfg}] - (let [{:keys [thread-id owner-id] :as comment} (get-comment conn id ::sql/for-update true) - {:keys [file-id page-id] :as thread} (get-comment-thread conn thread-id ::sql/for-update true)] + ::sm/params schema:update-comment + ::db/transaction true} + [{:keys [::db/conn] :as cfg} {:keys [::rpc/profile-id ::rpc/request-at id share-id content mentions]}] + (let [{:keys [thread-id owner-id] :as comment} (get-comment conn id ::sql/for-update true) + {:keys [file-id page-id] :as thread} (get-comment-thread conn thread-id ::sql/for-update true)] - (files/check-comment-permissions! conn profile-id file-id share-id) + (files/check-comment-permissions! conn profile-id file-id share-id) - ;; Don't allow edit comments to not owners - (when-not (= owner-id profile-id) - (ex/raise :type :validation - :code :not-allowed)) + ;; Don't allow edit comments to not owners + (when-not (= owner-id profile-id) + (ex/raise :type :validation + :code :not-allowed)) - (let [{:keys [page-name]} (get-file cfg file-id page-id)] - (db/update! conn :comment - {:content content - :modified-at request-at} - {:id id}) + (let [{:keys [page-name]} (get-file cfg file-id page-id)] + (db/update! conn :comment + {:content content + :modified-at request-at + :mentions (db/encode-pgarray mentions conn "uuid")} + {:id id}) - (db/update! conn :comment-thread - {:modified-at request-at - :page-name page-name} - {:id thread-id}) - nil))))) + (db/update! conn :comment-thread + {:modified-at request-at + :page-name page-name + :mentions + (-> (:mentions thread) + (set) + (into mentions) + (db/encode-pgarray conn "uuid"))} + {:id thread-id}) + nil))) ;; --- COMMAND: Delete Comment Thread @@ -527,17 +690,17 @@ (sv/defmethod ::delete-comment-thread {::doc/added "1.15" - ::sm/params schema:delete-comment-thread} - [cfg {:keys [::rpc/profile-id id share-id]}] - (db/tx-run! cfg (fn [{:keys [::db/conn]}] - (let [{:keys [owner-id file-id] :as thread} (get-comment-thread conn id ::sql/for-update true)] - (files/check-comment-permissions! conn profile-id file-id share-id) - (when-not (= owner-id profile-id) - (ex/raise :type :validation - :code :not-allowed)) + ::sm/params schema:delete-comment-thread + ::db/transaction true} + [{:keys [::db/conn]} {:keys [::rpc/profile-id id share-id]}] + (let [{:keys [owner-id file-id] :as thread} (get-comment-thread conn id ::sql/for-update true)] + (files/check-comment-permissions! conn profile-id file-id share-id) + (when-not (= owner-id profile-id) + (ex/raise :type :validation + :code :not-allowed)) - (db/delete! conn :comment-thread {:id id}) - nil)))) + (db/delete! conn :comment-thread {:id id}) + nil)) ;; --- COMMAND: Delete comment @@ -549,17 +712,17 @@ (sv/defmethod ::delete-comment {::doc/added "1.15" - ::sm/params schema:delete-comment} - [cfg {:keys [::rpc/profile-id id share-id]}] - (db/tx-run! cfg (fn [{:keys [::db/conn]}] - (let [{:keys [owner-id thread-id] :as comment} (get-comment conn id ::sql/for-update true) - {:keys [file-id] :as thread} (get-comment-thread conn thread-id)] - (files/check-comment-permissions! conn profile-id file-id share-id) - (when-not (= owner-id profile-id) - (ex/raise :type :validation - :code :not-allowed)) - (db/delete! conn :comment {:id id}) - nil)))) + ::sm/params schema:delete-comment + ::db/transaction true} + [{:keys [::db/conn]} {:keys [::rpc/profile-id id share-id]}] + (let [{:keys [owner-id thread-id] :as comment} (get-comment conn id ::sql/for-update true) + {:keys [file-id] :as thread} (get-comment-thread conn thread-id)] + (files/check-comment-permissions! conn profile-id file-id share-id) + (when-not (= owner-id profile-id) + (ex/raise :type :validation + :code :not-allowed)) + (db/delete! conn :comment {:id id}) + nil)) ;; --- COMMAND: Update comment thread position @@ -573,17 +736,17 @@ (sv/defmethod ::update-comment-thread-position {::doc/added "1.15" - ::sm/params schema:update-comment-thread-position} - [cfg {:keys [::rpc/profile-id ::rpc/request-at id position frame-id share-id]}] - (db/tx-run! cfg (fn [{:keys [::db/conn]}] - (let [{:keys [file-id] :as thread} (get-comment-thread conn id ::sql/for-update true)] - (files/check-comment-permissions! conn profile-id file-id share-id) - (db/update! conn :comment-thread - {:modified-at request-at - :position (db/pgpoint position) - :frame-id frame-id} - {:id (:id thread)}) - nil)))) + ::sm/params schema:update-comment-thread-position + ::db/transaction true} + [{:keys [::db/conn]} {:keys [::rpc/profile-id ::rpc/request-at id position frame-id share-id]}] + (let [{:keys [file-id] :as thread} (get-comment-thread conn id ::sql/for-update true)] + (files/check-comment-permissions! conn profile-id file-id share-id) + (db/update! conn :comment-thread + {:modified-at request-at + :position (db/pgpoint position) + :frame-id frame-id} + {:id (:id thread)}) + nil)) ;; --- COMMAND: Update comment frame @@ -596,13 +759,13 @@ (sv/defmethod ::update-comment-thread-frame {::doc/added "1.15" - ::sm/params schema:update-comment-thread-frame} - [cfg {:keys [::rpc/profile-id ::rpc/request-at id frame-id share-id]}] - (db/tx-run! cfg (fn [{:keys [::db/conn]}] - (let [{:keys [file-id] :as thread} (get-comment-thread conn id ::sql/for-update true)] - (files/check-comment-permissions! conn profile-id file-id share-id) - (db/update! conn :comment-thread - {:modified-at request-at - :frame-id frame-id} - {:id id}) - nil)))) + ::sm/params schema:update-comment-thread-frame + ::db/transaction true} + [{:keys [::db/conn]} {:keys [::rpc/profile-id ::rpc/request-at id frame-id share-id]}] + (let [{:keys [file-id] :as thread} (get-comment-thread conn id ::sql/for-update true)] + (files/check-comment-permissions! conn profile-id file-id share-id) + (db/update! conn :comment-thread + {:modified-at request-at + :frame-id frame-id} + {:id id}) + nil)) diff --git a/backend/src/app/rpc/commands/files_thumbnails.clj b/backend/src/app/rpc/commands/files_thumbnails.clj index eb7bf3c169..c3a5cb5d47 100644 --- a/backend/src/app/rpc/commands/files_thumbnails.clj +++ b/backend/src/app/rpc/commands/files_thumbnails.clj @@ -402,7 +402,10 @@ [cfg {:keys [::rpc/profile-id file-id] :as params}] (db/tx-run! cfg (fn [{:keys [::db/conn] :as cfg}] - (files/check-edition-permissions! conn profile-id file-id) + ;; TODO For now we check read permissions instead of write, + ;; to allow viewer users to update thumbnails. We might + ;; 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)] {:uri (files/resolve-public-uri (:id media)) diff --git a/backend/src/app/rpc/commands/profile.clj b/backend/src/app/rpc/commands/profile.clj index 7c7ca33399..7760c96b5f 100644 --- a/backend/src/app/rpc/commands/profile.clj +++ b/backend/src/app/rpc/commands/profile.clj @@ -41,6 +41,12 @@ (declare strip-private-attrs) (declare verify-password) +(def schema:props-notifications + [:map {:title "props-notifications"} + [:dashboard-comments [::sm/one-of #{:all :partial :none}]] + [:email-comments [::sm/one-of #{:all :partial :none}]] + [:email-invites [::sm/one-of #{:all :none}]]]) + (def schema:props [:map {:title "ProfileProps"} [:plugins {:optional true} schema:plugin-registry] @@ -51,7 +57,8 @@ [:v2-info-shown {:optional true} ::sm/boolean] [:welcome-file-id {:optional true} [:maybe ::sm/boolean]] [:release-notes-viewed {:optional true} - [::sm/text {:max 100}]]]) + [::sm/text {:max 100}]] + [:notifications {:optional true} schema:props-notifications]]) (def schema:profile [:map {:title "Profile"} @@ -200,6 +207,44 @@ {:id id}) nil)) + +;; --- MUTATION: Update notifications + +(def ^:private + schema:update-profile-notifications + [:map {:title "update-profile-notifications"} + [:dashboard-comments [::sm/one-of #{:all :partial :none}]] + [:email-comments [::sm/one-of #{:all :partial :none}]] + [:email-invites [::sm/one-of #{:all :none}]]]) + +(declare update-notifications!) + +(sv/defmethod ::update-profile-notifications + {::doc/added "2.4.0" + ::sm/params schema:update-profile-notifications + ::climit/id :auth/global} + [cfg {:keys [::rpc/profile-id] :as params}] + (db/tx-run! cfg update-notifications! (assoc params :profile-id profile-id))) + +(defn- update-notifications! + [{:keys [::db/conn] :as cfg} {:keys [profile-id dashboard-comments email-comments email-invites]}] + (let [profile (get-profile conn profile-id) + + notifications + {:dashboard-comments dashboard-comments + :email-comments email-comments + :email-invites email-invites}] + + (db/update! + conn :profile + {:props + (-> (:props profile) + (assoc :notifications notifications) + (db/tjson))} + {:id (:id profile)}) + + nil)) + ;; --- MUTATION: Update Photo (declare upload-photo) diff --git a/backend/src/app/rpc/commands/teams.clj b/backend/src/app/rpc/commands/teams.clj index f111b11846..7e4d0c2610 100644 --- a/backend/src/app/rpc/commands/teams.clj +++ b/backend/src/app/rpc/commands/teams.clj @@ -286,18 +286,18 @@ ;; implemented in UI) (def sql:team-users - "select pf.id, pf.fullname, pf.photo_id + "select pf.id, pf.fullname, pf.photo_id, pf.email from profile as pf inner join team_profile_rel as tpr on (tpr.profile_id = pf.id) where tpr.team_id = ? union - select pf.id, pf.fullname, pf.photo_id + select pf.id, pf.fullname, pf.photo_id, pf.email from profile as pf inner join project_profile_rel as ppr on (ppr.profile_id = pf.id) inner join project as p on (ppr.project_id = p.id) where p.team_id = ? union - select pf.id, pf.fullname, pf.photo_id + select pf.id, pf.fullname, pf.photo_id, pf.email from profile as pf inner join file_profile_rel as fpr on (fpr.profile_id = pf.id) inner join file as f on (fpr.file_id = f.id) @@ -308,6 +308,30 @@ [conn team-id] (db/exec! conn [sql:team-users team-id team-id team-id])) +;; Get the users but add the props property +(def sql:team-users+props + "select pf.id, pf.fullname, pf.photo_id, pf.email, pf.props + from profile as pf + inner join team_profile_rel as tpr on (tpr.profile_id = pf.id) + where tpr.team_id = ? + union + select pf.id, pf.fullname, pf.photo_id, pf.email, pf.props + from profile as pf + inner join project_profile_rel as ppr on (ppr.profile_id = pf.id) + inner join project as p on (ppr.project_id = p.id) + where p.team_id = ? + union + select pf.id, pf.fullname, pf.photo_id, pf.email, pf.props + from profile as pf + inner join file_profile_rel as fpr on (fpr.profile_id = pf.id) + inner join file as f on (fpr.file_id = f.id) + inner join project as p on (f.project_id = p.id) + where p.team_id = ?") + +(defn get-users+props + [conn team-id] + (db/exec! conn [sql:team-users+props team-id team-id team-id])) + (def sql:get-team-by-file "SELECT t.* FROM team AS t diff --git a/backend/src/app/rpc/commands/verify_token.clj b/backend/src/app/rpc/commands/verify_token.clj index d725ceda2e..27679536ef 100644 --- a/backend/src/app/rpc/commands/verify_token.clj +++ b/backend/src/app/rpc/commands/verify_token.clj @@ -166,23 +166,26 @@ ;; invited team. (let [props {:team-id (:team-id claims) :role (:role claims) - :invitation-id (:id invitation)} + :invitation-id (:id invitation)}] - accept-invitation-event - (-> (audit/event-from-rpc-params params) - (assoc ::audit/name "accept-team-invitation") - (assoc ::audit/props props)) + (audit/submit! + cfg + (-> (audit/event-from-rpc-params params) + (assoc ::audit/name "accept-team-invitation") + (assoc ::audit/props props))) - accept-invitation-from-event - (-> (audit/event-from-rpc-params params) - (assoc ::audit/profile-id (:created-by invitation)) - (assoc ::audit/name "accept-team-invitation-from") - (assoc ::audit/props (assoc props - :profile-id (:id profile) - :email (:email profile))))] - - (audit/submit! cfg accept-invitation-event) - (audit/submit! cfg accept-invitation-from-event) + ;; NOTE: Backward compatibility; old invitations can + ;; have the `created-by` to be nil; so in this case we + ;; don't submit this event to the audit-log + (when-let [created-by (:created-by invitation)] + (audit/submit! + cfg + (-> (audit/event-from-rpc-params params) + (assoc ::audit/profile-id created-by) + (assoc ::audit/name "accept-team-invitation-from") + (assoc ::audit/props (assoc props + :profile-id (:id profile) + :email (:email profile)))))) (accept-invitation cfg claims invitation profile) (assoc claims :state :created)) diff --git a/backend/src/app/rpc/commands/viewer.clj b/backend/src/app/rpc/commands/viewer.clj index 641d564af6..b258420ee1 100644 --- a/backend/src/app/rpc/commands/viewer.clj +++ b/backend/src/app/rpc/commands/viewer.clj @@ -12,7 +12,6 @@ [app.config :as cf] [app.db :as db] [app.rpc :as-alias rpc] - [app.rpc.commands.comments :as comments] [app.rpc.commands.files :as files] [app.rpc.commands.teams :as teams] [app.rpc.cond :as-alias cond] @@ -38,10 +37,10 @@ team (-> (db/get conn :team {:id (:team-id project)}) (teams/decode-row)) - members (into #{} (->> (teams/get-team-members conn (:team-id project)) - (map :id))) + members (teams/get-team-members conn (:team-id project)) + member-ids (into #{} (map :id) members) - perms (assoc perms :in-team (contains? members profile-id)) + perms (assoc perms :in-team (contains? member-ids profile-id)) _ (-> (cfeat/get-team-enabled-features cf/flags team) (cfeat/check-client-features! (:features params)) @@ -55,7 +54,6 @@ (update :data select-keys [:id :options :pages :pages-index :components])) libs (files/get-file-libraries conn file-id) - users (comments/get-file-comments-users conn file-id profile-id) links (->> (db/query conn :share-link {:file-id file-id}) (mapv (fn [row] (-> row @@ -71,7 +69,7 @@ {:team-id (:id team) :deleted-at nil})] - {:users users + {:users members :fonts fonts :project project :share-links links diff --git a/backend/test/backend_tests/rpc_comment_test.clj b/backend/test/backend_tests/rpc_comment_test.clj index 9e0f864742..d500352b3f 100644 --- a/backend/test/backend_tests/rpc_comment_test.clj +++ b/backend/test/backend_tests/rpc_comment_test.clj @@ -177,7 +177,7 @@ ;; (th/print-result! out) (t/is (th/success? out)) (let [[thread :as result] (:result out)] - (t/is (= 1 (count result))))) + (t/is (= 0 (count result))))) (let [data {::th/type :update-comment-thread-status ::rpc/profile-id (:id profile-1) diff --git a/common/src/app/common/data.cljc b/common/src/app/common/data.cljc index 0f59271f85..2465a9e98a 100644 --- a/common/src/app/common/data.cljc +++ b/common/src/app/common/data.cljc @@ -653,6 +653,28 @@ (into new-elems) (into (drop index coll)))) +(defn interleave-all + "Like interleave, but stops when the longest seq is done, instead of the shortest." + ([] ()) + ([c1] (lazy-seq c1)) + ([c1 c2] + (lazy-seq + (let [s1 (seq c1) s2 (seq c2)] + (cond + ;; Interleave as it + (and s1 s2) + (cons (first s1) + (cons (first s2) + (interleave-all (rest s1) (rest s2)))) + ;; s2 is empty, we return s1 + s1 s1 + ;; s1 is empty + s2 s2)))) + ([c1 c2 & colls] + (lazy-seq + (let [ss (filter identity (map seq (conj colls c2 c1)))] + (c/concat (map first ss) (apply interleave-all (map rest ss))))))) + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Data Parsing / Conversion ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; diff --git a/common/src/app/common/logic/shapes.cljc b/common/src/app/common/logic/shapes.cljc index a3dee69609..2d9dd4464e 100644 --- a/common/src/app/common/logic/shapes.cljc +++ b/common/src/app/common/logic/shapes.cljc @@ -304,7 +304,9 @@ (->> ids (mapcat #(ctn/get-child-heads objects %)) (map :id))) - cell (or cell (ctl/get-cell-by-index parent to-index))] + + index-cell-data (when to-index (ctl/get-cell-by-index parent to-index)) + cell (or cell (and index-cell-data [(:row index-cell-data) (:column index-cell-data)]))] (-> changes (pcb/with-page-id page-id) diff --git a/common/src/app/common/types/shape/layout.cljc b/common/src/app/common/types/shape/layout.cljc index 1101fd55ac..84a8f0000b 100644 --- a/common/src/app/common/types/shape/layout.cljc +++ b/common/src/app/common/types/shape/layout.cljc @@ -1479,7 +1479,7 @@ (defn get-cell-by-index [parent to-index] (let [cells (get-cells parent {:sort? true :remove-empty? true}) - to-index (- (count cells) to-index)] + to-index (- (count cells) to-index 1)] (nth cells to-index nil))) (defn add-children-to-index diff --git a/docker/devenv/files/nginx.conf b/docker/devenv/files/nginx.conf index 961b3a4fb4..1777f8a88e 100644 --- a/docker/devenv/files/nginx.conf +++ b/docker/devenv/files/nginx.conf @@ -90,6 +90,7 @@ http { proxy_hide_header x-amz-meta-server-side-encryption; proxy_hide_header x-amz-server-side-encryption; proxy_pass $redirect_uri; + proxy_ssl_server_name on; add_header x-internal-redirect "$redirect_uri"; add_header x-cache-control "$redirect_cache_control"; diff --git a/docker/images/files/nginx.conf b/docker/images/files/nginx.conf index ee2f641750..e03f7ef0b2 100644 --- a/docker/images/files/nginx.conf +++ b/docker/images/files/nginx.conf @@ -92,6 +92,7 @@ http { proxy_hide_header x-amz-request-id; proxy_hide_header x-amz-meta-server-side-encryption; proxy_hide_header x-amz-server-side-encryption; + proxy_ssl_server_name on; proxy_pass $redirect_uri; add_header x-internal-redirect "$redirect_uri"; diff --git a/docs/plugins/deployment.md b/docs/plugins/deployment.md index 5b8951dd6b..a225d0a58f 100644 --- a/docs/plugins/deployment.md +++ b/docs/plugins/deployment.md @@ -216,3 +216,9 @@ Success! - Published to example-plugin-penpot.surge.sh ``` 5. Done! + +## 3.5. Submitting to Penpot + +To make your finished plugin available in our catalog, submit in on the [plugin submission page](https://penpot.app/penpothub/plugins/create-plugin). Once it becomes available any Penpot user will be able to install and use it. + + diff --git a/docs/technical-guide/developer/ui.md b/docs/technical-guide/developer/ui.md index fbcf300ca8..db958e2cd6 100644 --- a/docs/technical-guide/developer/ui.md +++ b/docs/technical-guide/developer/ui.md @@ -84,7 +84,7 @@ However, we might want to control the aspect of the icons, or limit which icons [{:keys [icon children] :rest props}] (assert (or (nil? icon) (contains? valid-icon-list icon) "expected valid icon id")) [:> "button" props - (when icon [:> icon* {:id icon :size "m"}]) + (when icon [:> icon* {:icon-id icon :size "m"}]) children]) ``` @@ -160,7 +160,7 @@ Nested styles for DOM elements that are not instantiated by our component should [{:keys [icon children class] :rest props}] (let [props (mf/spread-props props {:class (stl/css :button)})] [:> "button" props - (when icon [:> icon* {:id icon :size "m"}]) + (when icon [:> icon* {:icon-id icon :size "m"}]) [:span {:class (stl/css :label-wrapper)} children]])) ;; later in code diff --git a/docs/user-guide/workspace-basics/index.njk b/docs/user-guide/workspace-basics/index.njk index dfb5bee2a4..09fb5a07e8 100644 --- a/docs/user-guide/workspace-basics/index.njk +++ b/docs/user-guide/workspace-basics/index.njk @@ -250,11 +250,6 @@ geometric structure. In Penpot there are three types of guides:

Navigate actions

To navigate through the actions press Ctrl/⌘ + Z to go backwards and Ctrl/⌘ + Shift/⇧ + Z to go forward.

You can also press any item of the actions list to get to this specific state.

-
- -

Comments

Comments allow the team to have one priceless conversation getting and providing feedback right over the designs and prototypes.

diff --git a/frontend/deps.edn b/frontend/deps.edn index 8febd1edd0..a64a3d5ba1 100644 --- a/frontend/deps.edn +++ b/frontend/deps.edn @@ -9,8 +9,8 @@ funcool/okulary {:mvn/version "2022.04.11-16"} funcool/potok2 - {:git/tag "v2.1" - :git/sha "84c97b9" + {:git/tag "v2.2" + :git/sha "0f7e15a" :git/url "https://github.com/funcool/potok.git" :exclusions [funcool/beicon2]} @@ -20,8 +20,8 @@ :git/url "https://github.com/funcool/beicon.git"} funcool/rumext - {:git/tag "v2.15" - :git/sha "28783a7" + {:git/tag "v2.18" + :git/sha "b6e8f45" :git/url "https://github.com/funcool/rumext.git"} instaparse/instaparse {:mvn/version "1.5.0"} diff --git a/frontend/externs/main.txt b/frontend/externs/main.txt new file mode 100644 index 0000000000..cb9613622a --- /dev/null +++ b/frontend/externs/main.txt @@ -0,0 +1,3392 @@ +a +b +c +d +e +f +g +h +i +j +k +l +m +n +o +p +q +r +s +t +u +v +w +x +y +z +A +B +C +D +E +F +G +H +I +J +K +L +M +N +O +P +Q +R +S +T +U +V +W +X +Y +Z +$ +aa +ab +ac +ad +ae +af +ag +ah +ai +aj +ak +al +am +an +ao +ap +aq +ar +as +at +au +av +aw +ax +ay +az +aA +aB +aC +aD +aE +aF +aG +aH +aI +aJ +aK +aL +aM +aN +aO +aP +aQ +aR +aS +aT +aU +aV +aW +aX +aY +aZ +a$ +a0 +a1 +a2 +a3 +a4 +a5 +a6 +a7 +a8 +a9 +ba +bb +bc +bd +be +bf +bg +bh +bi +bj +bk +bl +bm +bn +bo +bp +bq +br +bs +bt +bu +bv +bw +bx +by +bz +bA +bB +bC +bD +bE +bF +bG +bH +bI +bJ +bK +bL +bM +bN +bO +bP +bQ +bR +bS +bT +bU +bV +bW +bX +bY +bZ +b$ +b0 +b1 +b2 +b3 +b4 +b5 +b6 +b7 +b8 +b9 +ca +cb +cc +cd +ce +cf +cg +ch +ci +cj +ck +cl +cm +cn +co +cp +cq +cr +cs +ct +cu +cv +cw +cx +cy +cz +cA +cB +cC +cD +cE +cF +cG +cH +cI +cJ +cK +cL +cM +cN +cO +cP +cQ +cR +cS +cT +cU +cV +cW +cX +cY +cZ +c$ +c0 +c1 +c2 +c3 +c4 +c5 +c6 +c7 +c8 +c9 +da +db +dc +dd +de +df +dg +dh +di +dj +dk +dl +dm +dn +do +dp +dq +dr +ds +dt +du +dv +dw +dx +dy +dz +dA +dB +dC +dD +dE +dF +dG +dH +dI +dJ +dK +dL +dM +dN +dO +dP +dQ +dR +dS +dT +dU +dV +dW +dX +dY +dZ +d$ +d0 +d1 +d2 +d3 +d4 +d5 +d6 +d7 +d8 +d9 +ea +eb +ec +ed +ee +ef +eg +eh +ei +ej +ek +el +em +en +eo +ep +eq +er +es +et +eu +ev +ew +ex +ey +ez +eA +eB +eC +eD +eE +eF +eG +eH +eI +eJ +eK +eL +eM +eN +eO +eP +eQ +eR +eS +eT +eU +eV +eW +eX +eY +eZ +e$ +e0 +e1 +e2 +e3 +e4 +e5 +e6 +e7 +e8 +e9 +fa +fb +fc +fd +fe +ff +fg +fh +fi +fj +fk +fl +fm +fn +fo +fp +fq +fr +fs +ft +fu +fv +fw +fx +fy +fz +fA +fB +fC +fD +fE +fF +fG +fH +fI +fJ +fK +fL +fM +fN +fO +fP +fQ +fR +fS +fT +fU +fV +fW +fX +fY +fZ +f$ +f0 +f1 +f2 +f3 +f4 +f5 +f6 +f7 +f8 +f9 +ga +gb +gc +gd +ge +gf +gg +gh +gi +gj +gk +gl +gm +gn +go +gp +gq +gr +gs +gt +gu +gv +gw +gx +gy +gz +gA +gB +gC +gD +gE +gF +gG +gH +gI +gJ +gK +gL +gM +gN +gO +gP +gQ +gR +gS +gT +gU +gV +gW +gX +gY +gZ +g$ +g0 +g1 +g2 +g3 +g4 +g5 +g6 +g7 +g8 +g9 +ha +hb +hc +hd +he +hf +hg +hh +hi +hj +hk +hl +hm +hn +ho +hp +hq +hr +hs +ht +hu +hv +hw +hx +hy +hz +hA +hB +hC +hD +hE +hF +hG +hH +hI +hJ +hK +hL +hM +hN +hO +hP +hQ +hR +hS +hT +hU +hV +hW +hX +hY +hZ +h$ +h0 +h1 +h2 +h3 +h4 +h5 +h6 +h7 +h8 +h9 +ia +ib +ic +id +ie +if +ig +ih +ii +ij +ik +il +im +in +io +ip +iq +ir +is +it +iu +iv +iw +ix +iy +iz +iA +iB +iC +iD +iE +iF +iG +iH +iI +iJ +iK +iL +iM +iN +iO +iP +iQ +iR +iS +iT +iU +iV +iW +iX +iY +iZ +i$ +i0 +i1 +i2 +i3 +i4 +i5 +i6 +i7 +i8 +i9 +ja +jb +jc +jd +je +jf +jg +jh +ji +jj +jk +jl +jm +jn +jo +jp +jq +jr +js +jt +ju +jv +jw +jx +jy +jz +jA +jB +jC +jD +jE +jF +jG +jH +jI +jJ +jK +jL +jM +jN +jO +jP +jQ +jR +jS +jT +jU +jV +jW +jX +jY +jZ +j$ +j0 +j1 +j2 +j3 +j4 +j5 +j6 +j7 +j8 +j9 +ka +kb +kc +kd +ke +kf +kg +kh +ki +kj +kk +kl +km +kn +ko +kp +kq +kr +ks +kt +ku +kv +kw +kx +ky +kz +kA +kB +kC +kD +kE +kF +kG +kH +kI +kJ +kK +kL +kM +kN +kO +kP +kQ +kR +kS +kT +kU +kV +kW +kX +kY +kZ +k$ +k0 +k1 +k2 +k3 +k4 +k5 +k6 +k7 +k8 +k9 +la +lb +lc +ld +le +lf +lg +lh +li +lj +lk +ll +lm +ln +lo +lp +lq +lr +ls +lt +lu +lv +lw +lx +ly +lz +lA +lB +lC +lD +lE +lF +lG +lH +lI +lJ +lK +lL +lM +lN +lO +lP +lQ +lR +lS +lT +lU +lV +lW +lX +lY +lZ +l$ +l0 +l1 +l2 +l3 +l4 +l5 +l6 +l7 +l8 +l9 +ma +mb +mc +md +me +mf +mg +mh +mi +mj +mk +ml +mm +mn +mo +mp +mq +mr +ms +mt +mu +mv +mw +mx +my +mz +mA +mB +mC +mD +mE +mF +mG +mH +mI +mJ +mK +mL +mM +mN +mO +mP +mQ +mR +mS +mT +mU +mV +mW +mX +mY +mZ +m$ +m0 +m1 +m2 +m3 +m4 +m5 +m6 +m7 +m8 +m9 +na +nb +nc +nd +ne +nf +ng +nh +ni +nj +nk +nl +nm +nn +no +np +nq +nr +ns +nt +nu +nv +nw +nx +ny +nz +nA +nB +nC +nD +nE +nF +nG +nH +nI +nJ +nK +nL +nM +nN +nO +nP +nQ +nR +nS +nT +nU +nV +nW +nX +nY +nZ +n$ +n0 +n1 +n2 +n3 +n4 +n5 +n6 +n7 +n8 +n9 +oa +ob +oc +od +oe +of +og +oh +oi +oj +ok +ol +om +on +oo +op +oq +or +os +ot +ou +ov +ow +ox +oy +oz +oA +oB +oC +oD +oE +oF +oG +oH +oI +oJ +oK +oL +oM +oN +oO +oP +oQ +oR +oS +oT +oU +oV +oW +oX +oY +oZ +o$ +o0 +o1 +o2 +o3 +o4 +o5 +o6 +o7 +o8 +o9 +pa +pb +pc +pd +pe +pf +pg +ph +pi +pj +pk +pl +pm +pn +po +pp +pq +pr +ps +pt +pu +pv +pw +px +py +pz +pA +pB +pC +pD +pE +pF +pG +pH +pI +pJ +pK +pL +pM +pN +pO +pP +pQ +pR +pS +pT +pU +pV +pW +pX +pY +pZ +p$ +p0 +p1 +p2 +p3 +p4 +p5 +p6 +p7 +p8 +p9 +qa +qb +qc +qd +qe +qf +qg +qh +qi +qj +qk +ql +qm +qn +qo +qp +qq +qr +qs +qt +qu +qv +qw +qx +qy +qz +qA +qB +qC +qD +qE +qF +qG +qH +qI +qJ +qK +qL +qM +qN +qO +qP +qQ +qR +qS +qT +qU +qV +qW +qX +qY +qZ +q$ +q0 +q1 +q2 +q3 +q4 +q5 +q6 +q7 +q8 +q9 +ra +rb +rc +rd +re +rf +rg +rh +ri +rj +rk +rl +rm +rn +ro +rp +rq +rr +rs +rt +ru +rv +rw +rx +ry +rz +rA +rB +rC +rD +rE +rF +rG +rH +rI +rJ +rK +rL +rM +rN +rO +rP +rQ +rR +rS +rT +rU +rV +rW +rX +rY +rZ +r$ +r0 +r1 +r2 +r3 +r4 +r5 +r6 +r7 +r8 +r9 +sa +sb +sc +sd +se +sf +sg +sh +si +sj +sk +sl +sm +sn +so +sp +sq +sr +ss +st +su +sv +sw +sx +sy +sz +sA +sB +sC +sD +sE +sF +sG +sH +sI +sJ +sK +sL +sM +sN +sO +sP +sQ +sR +sS +sT +sU +sV +sW +sX +sY +sZ +s$ +s0 +s1 +s2 +s3 +s4 +s5 +s6 +s7 +s8 +s9 +ta +tb +tc +td +te +tf +tg +th +ti +tj +tk +tl +tm +tn +to +tp +tq +tr +ts +tt +tu +tv +tw +tx +ty +tz +tA +tB +tC +tD +tE +tF +tG +tH +tI +tJ +tK +tL +tM +tN +tO +tP +tQ +tR +tS +tT +tU +tV +tW +tX +tY +tZ +t$ +t0 +t1 +t2 +t3 +t4 +t5 +t6 +t7 +t8 +t9 +ua +ub +uc +ud +ue +uf +ug +uh +ui +uj +uk +ul +um +un +uo +up +uq +ur +us +ut +uu +uv +uw +ux +uy +uz +uA +uB +uC +uD +uE +uF +uG +uH +uI +uJ +uK +uL +uM +uN +uO +uP +uQ +uR +uS +uT +uU +uV +uW +uX +uY +uZ +u$ +u0 +u1 +u2 +u3 +u4 +u5 +u6 +u7 +u8 +u9 +va +vb +vc +vd +ve +vf +vg +vh +vi +vj +vk +vl +vm +vn +vo +vp +vq +vr +vs +vt +vu +vv +vw +vx +vy +vz +vA +vB +vC +vD +vE +vF +vG +vH +vI +vJ +vK +vL +vM +vN +vO +vP +vQ +vR +vS +vT +vU +vV +vW +vX +vY +vZ +v$ +v0 +v1 +v2 +v3 +v4 +v5 +v6 +v7 +v8 +v9 +wa +wb +wc +wd +we +wf +wg +wh +wi +wj +wk +wl +wm +wn +wo +wp +wq +wr +ws +wt +wu +wv +ww +wx +wy +wz +wA +wB +wC +wD +wE +wF +wG +wH +wI +wJ +wK +wL +wM +wN +wO +wP +wQ +wR +wS +wT +wU +wV +wW +wX +wY +wZ +w$ +w0 +w1 +w2 +w3 +w4 +w5 +w6 +w7 +w8 +w9 +xa +xb +xc +xd +xe +xf +xg +xh +xi +xj +xk +xl +xm +xn +xo +xp +xq +xr +xs +xt +xu +xv +xw +xx +xy +xz +xA +xB +xC +xD +xE +xF +xG +xH +xI +xJ +xK +xL +xM +xN +xO +xP +xQ +xR +xS +xT +xU +xV +xW +xX +xY +xZ +x$ +x0 +x1 +x2 +x3 +x4 +x5 +x6 +x7 +x8 +x9 +ya +yb +yc +yd +ye +yf +yg +yh +yi +yj +yk +yl +ym +yn +yo +yp +yq +yr +ys +yt +yu +yv +yw +yx +yy +yz +yA +yB +yC +yD +yE +yF +yG +yH +yI +yJ +yK +yL +yM +yN +yO +yP +yQ +yR +yS +yT +yU +yV +yW +yX +yY +yZ +y$ +y0 +y1 +y2 +y3 +y4 +y5 +y6 +y7 +y8 +y9 +za +zb +zc +zd +ze +zf +zg +zh +zi +zj +zk +zl +zm +zn +zo +zp +zq +zr +zs +zt +zu +zv +zw +zx +zy +zz +zA +zB +zC +zD +zE +zF +zG +zH +zI +zJ +zK +zL +zM +zN +zO +zP +zQ +zR +zS +zT +zU +zV +zW +zX +zY +zZ +z$ +z0 +z1 +z2 +z3 +z4 +z5 +z6 +z7 +z8 +z9 +Aa +Ab +Ac +Ad +Ae +Af +Ag +Ah +Ai +Aj +Ak +Al +Am +An +Ao +Ap +Aq +Ar +As +At +Au +Av +Aw +Ax +Ay +Az +AA +AB +AC +AD +AE +AF +AG +AH +AI +AJ +AK +AL +AM +AN +AO +AP +AQ +AR +AS +AT +AU +AV +AW +AX +AY +AZ +A$ +A0 +A1 +A2 +A3 +A4 +A5 +A6 +A7 +A8 +A9 +Ba +Bb +Bc +Bd +Be +Bf +Bg +Bh +Bi +Bj +Bk +Bl +Bm +Bn +Bo +Bp +Bq +Br +Bs +Bt +Bu +Bv +Bw +Bx +By +Bz +BA +BB +BC +BD +BE +BF +BG +BH +BI +BJ +BK +BL +BM +BN +BO +BP +BQ +BR +BS +BT +BU +BV +BW +BX +BY +BZ +B$ +B0 +B1 +B2 +B3 +B4 +B5 +B6 +B7 +B8 +B9 +Ca +Cb +Cc +Cd +Ce +Cf +Cg +Ch +Ci +Cj +Ck +Cl +Cm +Cn +Co +Cp +Cq +Cr +Cs +Ct +Cu +Cv +Cw +Cx +Cy +Cz +CA +CB +CC +CD +CE +CF +CG +CH +CI +CJ +CK +CL +CM +CN +CO +CP +CQ +CR +CS +CT +CU +CV +CW +CX +CY +CZ +C$ +C0 +C1 +C2 +C3 +C4 +C5 +C6 +C7 +C8 +C9 +Da +Db +Dc +Dd +De +Df +Dg +Dh +Di +Dj +Dk +Dl +Dm +Dn +Do +Dp +Dq +Dr +Ds +Dt +Du +Dv +Dw +Dx +Dy +Dz +DA +DB +DC +DD +DE +DF +DG +DH +DI +DJ +DK +DL +DM +DN +DO +DP +DQ +DR +DS +DT +DU +DV +DW +DX +DY +DZ +D$ +D0 +D1 +D2 +D3 +D4 +D5 +D6 +D7 +D8 +D9 +Ea +Eb +Ec +Ed +Ee +Ef +Eg +Eh +Ei +Ej +Ek +El +Em +En +Eo +Ep +Eq +Er +Es +Et +Eu +Ev +Ew +Ex +Ey +Ez +EA +EB +EC +ED +EE +EF +EG +EH +EI +EJ +EK +EL +EM +EN +EO +EP +EQ +ER +ES +ET +EU +EV +EW +EX +EY +EZ +E$ +E0 +E1 +E2 +E3 +E4 +E5 +E6 +E7 +E8 +E9 +Fa +Fb +Fc +Fd +Fe +Ff +Fg +Fh +Fi +Fj +Fk +Fl +Fm +Fn +Fo +Fp +Fq +Fr +Fs +Ft +Fu +Fv +Fw +Fx +Fy +Fz +FA +FB +FC +FD +FE +FF +FG +FH +FI +FJ +FK +FL +FM +FN +FO +FP +FQ +FR +FS +FT +FU +FV +FW +FX +FY +FZ +F$ +F0 +F1 +F2 +F3 +F4 +F5 +F6 +F7 +F8 +F9 +Ga +Gb +Gc +Gd +Ge +Gf +Gg +Gh +Gi +Gj +Gk +Gl +Gm +Gn +Go +Gp +Gq +Gr +Gs +Gt +Gu +Gv +Gw +Gx +Gy +Gz +GA +GB +GC +GD +GE +GF +GG +GH +GI +GJ +GK +GL +GM +GN +GO +GP +GQ +GR +GS +GT +GU +GV +GW +GX +GY +GZ +G$ +G0 +G1 +G2 +G3 +G4 +G5 +G6 +G7 +G8 +G9 +Ha +Hb +Hc +Hd +He +Hf +Hg +Hh +Hi +Hj +Hk +Hl +Hm +Hn +Ho +Hp +Hq +Hr +Hs +Ht +Hu +Hv +Hw +Hx +Hy +Hz +HA +HB +HC +HD +HE +HF +HG +HH +HI +HJ +HK +HL +HM +HN +HO +HP +HQ +HR +HS +HT +HU +HV +HW +HX +HY +HZ +H$ +H0 +H1 +H2 +H3 +H4 +H5 +H6 +H7 +H8 +H9 +Ia +Ib +Ic +Id +Ie +If +Ig +Ih +Ii +Ij +Ik +Il +Im +In +Io +Ip +Iq +Ir +Is +It +Iu +Iv +Iw +Ix +Iy +Iz +IA +IB +IC +ID +IE +IF +IG +IH +II +IJ +IK +IL +IM +IN +IO +IP +IQ +IR +IS +IT +IU +IV +IW +IX +IY +IZ +I$ +I0 +I1 +I2 +I3 +I4 +I5 +I6 +I7 +I8 +I9 +Ja +Jb +Jc +Jd +Je +Jf +Jg +Jh +Ji +Jj +Jk +Jl +Jm +Jn +Jo +Jp +Jq +Jr +Js +Jt +Ju +Jv +Jw +Jx +Jy +Jz +JA +JB +JC +JD +JE +JF +JG +JH +JI +JJ +JK +JL +JM +JN +JO +JP +JQ +JR +JS +JT +JU +JV +JW +JX +JY +JZ +J$ +J0 +J1 +J2 +J3 +J4 +J5 +J6 +J7 +J8 +J9 +Ka +Kb +Kc +Kd +Ke +Kf +Kg +Kh +Ki +Kj +Kk +Kl +Km +Kn +Ko +Kp +Kq +Kr +Ks +Kt +Ku +Kv +Kw +Kx +Ky +Kz +KA +KB +KC +KD +KE +KF +KG +KH +KI +KJ +KK +KL +KM +KN +KO +KP +KQ +KR +KS +KT +KU +KV +KW +KX +KY +KZ +K$ +K0 +K1 +K2 +K3 +K4 +K5 +K6 +K7 +K8 +K9 +La +Lb +Lc +Ld +Le +Lf +Lg +Lh +Li +Lj +Lk +Ll +Lm +Ln +Lo +Lp +Lq +Lr +Ls +Lt +Lu +Lv +Lw +Lx +Ly +Lz +LA +LB +LC +LD +LE +LF +LG +LH +LI +LJ +LK +LL +LM +LN +LO +LP +LQ +LR +LS +LT +LU +LV +LW +LX +LY +LZ +L$ +L0 +L1 +L2 +L3 +L4 +L5 +L6 +L7 +L8 +L9 +Ma +Mb +Mc +Md +Me +Mf +Mg +Mh +Mi +Mj +Mk +Ml +Mm +Mn +Mo +Mp +Mq +Mr +Ms +Mt +Mu +Mv +Mw +Mx +My +Mz +MA +MB +MC +MD +ME +MF +MG +MH +MI +MJ +MK +ML +MM +MN +MO +MP +MQ +MR +MS +MT +MU +MV +MW +MX +MY +MZ +M$ +M0 +M1 +M2 +M3 +M4 +M5 +M6 +M7 +M8 +M9 +Na +Nb +Nc +Nd +Ne +Nf +Ng +Nh +Ni +Nj +Nk +Nl +Nm +Nn +No +Np +Nq +Nr +Ns +Nt +Nu +Nv +Nw +Nx +Ny +Nz +NA +NB +NC +ND +NE +NF +NG +NH +NI +NJ +NK +NL +NM +NN +NO +NP +NQ +NR +NS +NT +NU +NV +NW +NX +NY +NZ +N$ +N0 +N1 +N2 +N3 +N4 +N5 +N6 +N7 +N8 +N9 +Oa +Ob +Oc +Od +Oe +Of +Og +Oh +Oi +Oj +Ok +Ol +Om +On +Oo +Op +Oq +Or +Os +Ot +Ou +Ov +Ow +Ox +Oy +Oz +OA +OB +OC +OD +OE +OF +OG +OH +OI +OJ +OK +OL +OM +ON +OO +OP +OQ +OR +OS +OT +OU +OV +OW +OX +OY +OZ +O$ +O0 +O1 +O2 +O3 +O4 +O5 +O6 +O7 +O8 +O9 +Pa +Pb +Pc +Pd +Pe +Pf +Pg +Ph +Pi +Pj +Pk +Pl +Pm +Pn +Po +Pp +Pq +Pr +Ps +Pt +Pu +Pv +Pw +Px +Py +Pz +PA +PB +PC +PD +PE +PF +PG +PH +PI +PJ +PK +PL +PM +PN +PO +PP +PQ +PR +PS +PT +PU +PV +PW +PX +PY +PZ +P$ +P0 +P1 +P2 +P3 +P4 +P5 +P6 +P7 +P8 +P9 +Qa +Qb +Qc +Qd +Qe +Qf +Qg +Qh +Qi +Qj +Qk +Ql +Qm +Qn +Qo +Qp +Qq +Qr +Qs +Qt +Qu +Qv +Qw +Qx +Qy +Qz +QA +QB +QC +QD +QE +QF +QG +QH +QI +QJ +QK +QL +QM +QN +QO +QP +QQ +QR +QS +QT +QU +QV +QW +QX +QY +QZ +Q$ +Q0 +Q1 +Q2 +Q3 +Q4 +Q5 +Q6 +Q7 +Q8 +Q9 +Ra +Rb +Rc +Rd +Re +Rf +Rg +Rh +Ri +Rj +Rk +Rl +Rm +Rn +Ro +Rp +Rq +Rr +Rs +Rt +Ru +Rv +Rw +Rx +Ry +Rz +RA +RB +RC +RD +RE +RF +RG +RH +RI +RJ +RK +RL +RM +RN +RO +RP +RQ +RR +RS +RT +RU +RV +RW +RX +RY +RZ +R$ +R0 +R1 +R2 +R3 +R4 +R5 +R6 +R7 +R8 +R9 +Sa +Sb +Sc +Sd +Se +Sf +Sg +Sh +Si +Sj +Sk +Sl +Sm +Sn +So +Sp +Sq +Sr +Ss +St +Su +Sv +Sw +Sx +Sy +Sz +SA +SB +SC +SD +SE +SF +SG +SH +SI +SJ +SK +SL +SM +SN +SO +SP +SQ +SR +SS +ST +SU +SV +SW +SX +SY +SZ +S$ +S0 +S1 +S2 +S3 +S4 +S5 +S6 +S7 +S8 +S9 +Ta +Tb +Tc +Td +Te +Tf +Tg +Th +Ti +Tj +Tk +Tl +Tm +Tn +To +Tp +Tq +Tr +Ts +Tt +Tu +Tv +Tw +Tx +Ty +Tz +TA +TB +TC +TD +TE +TF +TG +TH +TI +TJ +TK +TL +TM +TN +TO +TP +TQ +TR +TS +TT +TU +TV +TW +TX +TY +TZ +T$ +T0 +T1 +T2 +T3 +T4 +T5 +T6 +T7 +T8 +T9 +Ua +Ub +Uc +Ud +Ue +Uf +Ug +Uh +Ui +Uj +Uk +Ul +Um +Un +Uo +Up +Uq +Ur +Us +Ut +Uu +Uv +Uw +Ux +Uy +Uz +UA +UB +UC +UD +UE +UF +UG +UH +UI +UJ +UK +UL +UM +UN +UO +UP +UQ +UR +US +UT +UU +UV +UW +UX +UY +UZ +U$ +U0 +U1 +U2 +U3 +U4 +U5 +U6 +U7 +U8 +U9 +Va +Vb +Vc +Vd +Ve +Vf +Vg +Vh +Vi +Vj +Vk +Vl +Vm +Vn +Vo +Vp +Vq +Vr +Vs +Vt +Vu +Vv +Vw +Vx +Vy +Vz +VA +VB +VC +VD +VE +VF +VG +VH +VI +VJ +VK +VL +VM +VN +VO +VP +VQ +VR +VS +VT +VU +VV +VW +VX +VY +VZ +V$ +V0 +V1 +V2 +V3 +V4 +V5 +V6 +V7 +V8 +V9 +Wa +Wb +Wc +Wd +We +Wf +Wg +Wh +Wi +Wj +Wk +Wl +Wm +Wn +Wo +Wp +Wq +Wr +Ws +Wt +Wu +Wv +Ww +Wx +Wy +Wz +WA +WB +WC +WD +WE +WF +WG +WH +WI +WJ +WK +WL +WM +WN +WO +WP +WQ +WR +WS +WT +WU +WV +WW +WX +WY +WZ +W$ +W0 +W1 +W2 +W3 +W4 +W5 +W6 +W7 +W8 +W9 +Xa +Xb +Xc +Xd +Xe +Xf +Xg +Xh +Xi +Xj +Xk +Xl +Xm +Xn +Xo +Xp +Xq +Xr +Xs +Xt +Xu +Xv +Xw +Xx +Xy +Xz +XA +XB +XC +XD +XE +XF +XG +XH +XI +XJ +XK +XL +XM +XN +XO +XP +XQ +XR +XS +XT +XU +XV +XW +XX +XY +XZ +X$ +X0 +X1 +X2 +X3 +X4 +X5 +X6 +X7 +X8 +X9 +Ya +Yb +Yc +Yd +Ye +Yf +Yg +Yh +Yi +Yj +Yk +Yl +Ym +Yn +Yo +Yp +Yq +Yr +Ys +Yt +Yu +Yv +Yw +Yx +Yy +Yz +YA +YB +YC +YD +YE +YF +YG +YH +YI +YJ +YK +YL +YM +YN +YO +YP +YQ +YR +YS +YT +YU +YV +YW +YX +YY +YZ +Y$ +Y0 +Y1 +Y2 +Y3 +Y4 +Y5 +Y6 +Y7 +Y8 +Y9 +Za +Zb +Zc +Zd +Ze +Zf +Zg +Zh +Zi +Zj +Zk +Zl +Zm +Zn +Zo +Zp +Zq +Zr +Zs +Zt +Zu +Zv +Zw +Zx +Zy +Zz +ZA +ZB +ZC +ZD +ZE +ZF +ZG +ZH +ZI +ZJ +ZK +ZL +ZM +ZN +ZO +ZP +ZQ +ZR +ZS +ZT +ZU +ZV +ZW +ZX +ZY +ZZ +Z$ +Z0 +Z1 +Z2 +Z3 +Z4 +Z5 +Z6 +Z7 +Z8 +Z9 +$a +$b +$c +$d +$e +$f +$g +$h +$i +$j +$k +$l +$m +$n +$o +$p +$q +$r +$s +$t +$u +$v +$w +$x +$y +$z +$A +$B +$C +$D +$E +$F +$G +$H +$I +$J +$K +$L +$M +$N +$O +$P +$Q +$R +$S +$T +$U +$V +$W +$X +$Y +$Z +$$ +$0 +$1 +$2 +$3 +$4 +$5 +$6 +$7 +$8 +$9 diff --git a/frontend/externs/worker.txt b/frontend/externs/worker.txt new file mode 120000 index 0000000000..f446a60e65 --- /dev/null +++ b/frontend/externs/worker.txt @@ -0,0 +1 @@ +main.txt \ No newline at end of file diff --git a/frontend/playwright/ui/pages/ViewerPage.js b/frontend/playwright/ui/pages/ViewerPage.js index 311c0c45ff..7a2a96bcef 100644 --- a/frontend/playwright/ui/pages/ViewerPage.js +++ b/frontend/playwright/ui/pages/ViewerPage.js @@ -104,8 +104,7 @@ export class ViewerPage extends BaseWebSocketPage { async showCommentsThread(number, clickOptions = {}) { await this.page - .getByTestId("floating-thread-bubble") - .filter({ hasText: number.toString() }) + .getByTestId(`floating-thread-bubble-${number.toString()}`) .click(clickOptions); } diff --git a/frontend/playwright/ui/specs/viewer-comments.spec.js b/frontend/playwright/ui/specs/viewer-comments.spec.js index 4ed32135a3..5e923ef6ae 100644 --- a/frontend/playwright/ui/specs/viewer-comments.spec.js +++ b/frontend/playwright/ui/specs/viewer-comments.spec.js @@ -19,12 +19,8 @@ test("Comment is shown with scroll and valid position", async ({ page }) => { }); await viewer.showComments(); await viewer.showCommentsThread(1); - await expect( - viewer.page.getByRole("textbox", { name: "Reply" }), - ).toBeVisible(); + await expect(viewer.page.getByRole("textbox")).toBeVisible(); await viewer.showCommentsThread(1); await viewer.showCommentsThread(2); - await expect( - viewer.page.getByRole("textbox", { name: "Reply" }), - ).toBeVisible(); + await expect(viewer.page.getByRole("textbox")).toBeVisible(); }); diff --git a/frontend/resources/images/icons/at.svg b/frontend/resources/images/icons/at.svg new file mode 100644 index 0000000000..72e5ff01db --- /dev/null +++ b/frontend/resources/images/icons/at.svg @@ -0,0 +1 @@ + diff --git a/frontend/resources/styles/common/refactor/basic-rules.scss b/frontend/resources/styles/common/refactor/basic-rules.scss index 5096ecd6a5..8b43750ab2 100644 --- a/frontend/resources/styles/common/refactor/basic-rules.scss +++ b/frontend/resources/styles/common/refactor/basic-rules.scss @@ -810,28 +810,6 @@ } } -.comment-bubbles { - @include bodySmallTypography; - @include flexCenter; - height: $s-32; - width: $s-32; - border-radius: $br-circle; - background-color: var(--comment-bullet-background-color-rest); - border: $s-1 solid var(--comment-bullet-border-color-rest); - color: var(--comment-bullet-foreground-color-rest); -} - -.resolved-comment-bubble { - background-color: var(--comment-bullet-background-color-resolved); - border: $s-1 solid var(--comment-bullet-border-color-resolved); - color: var(--comment-bullet-foreground-color-resolved); -} -.unread-comment-bubble { - background-color: var(--comment-bullet-background-color-unread); - border: $s-1 solid var(--comment-bullet-border-color-unread); - color: var(--comment-bullet-foreground-color-unread); -} - // SELECTS AND DROPDOWNS .menu-dropdown { @include menuShadow; diff --git a/frontend/src/app/config.cljs b/frontend/src/app/config.cljs index f481303bb8..37d28e0541 100644 --- a/frontend/src/app/config.cljs +++ b/frontend/src/app/config.cljs @@ -143,6 +143,11 @@ (let [f (obj/get global "externalSessionId")] (when (fn? f) (f)))) +(defn external-context-info + [] + (let [f (obj/get global "externalContextInfo")] + (when (fn? f) (f)))) + ;; --- Helper Functions (defn ^boolean check-browser? [candidate] diff --git a/frontend/src/app/main/data/auth.cljs b/frontend/src/app/main/data/auth.cljs index c1ba640b51..740946b24a 100644 --- a/frontend/src/app/main/data/auth.cljs +++ b/frontend/src/app/main/data/auth.cljs @@ -39,24 +39,26 @@ accepting invitation, or third party auth signup or singin." [{:keys [props] :as profile}] (letfn [(get-redirect-events [teams] - (if-let [redirect-href (:login-redirect storage/session)] - (binding [storage/*sync* true] - (swap! storage/session dissoc :login-redirect) - (if (= redirect-href (rt/get-current-href)) - (rx/of (rt/reload true)) - (rx/of (rt/nav-raw :href redirect-href)))) - (if-let [file-id (get props :welcome-file-id)] - (rx/of (dcm/go-to-workspace - :file-id file-id - :team-id (:default-team-id profile)) - (dp/update-profile-props {:welcome-file-id nil})) + (if-let [token (:invitation-token profile)] + (rx/of (rt/nav :auth-verify-token {:token token})) + (if-let [redirect-href (:login-redirect storage/session)] + (binding [storage/*sync* true] + (swap! storage/session dissoc :login-redirect) + (if (= redirect-href (rt/get-current-href)) + (rx/of (rt/reload true)) + (rx/of (rt/nav-raw :href redirect-href)))) + (if-let [file-id (get props :welcome-file-id)] + (rx/of (dcm/go-to-workspace + :file-id file-id + :team-id (:default-team-id profile)) + (dp/update-profile-props {:welcome-file-id nil})) - (let [teams (into #{} (map :id) teams) - team-id (dtm/get-last-team-id) - team-id (if (and team-id (contains? teams team-id)) - team-id - (:default-team-id profile))] - (rx/of (dcm/go-to-dashboard-recent {:team-id team-id}))))))] + (let [teams (into #{} (map :id) teams) + team-id (dtm/get-last-team-id) + team-id (if (and team-id (contains? teams team-id)) + team-id + (:default-team-id profile))] + (rx/of (dcm/go-to-dashboard-recent {:team-id team-id})))))))] (ptk/reify ::logged-in ev/Event diff --git a/frontend/src/app/main/data/comments.cljs b/frontend/src/app/main/data/comments.cljs index 3dc86b5a33..73d8a4c0fc 100644 --- a/frontend/src/app/main/data/comments.cljs +++ b/frontend/src/app/main/data/comments.cljs @@ -25,7 +25,7 @@ [:file-id ::sm/uuid] [:project-id ::sm/uuid] [:owner-id ::sm/uuid] - [:page-name :string] + [:page-name {:optional true} :string] [:file-name :string] [:seqn :int] [:content :string] @@ -55,6 +55,19 @@ (declare retrieve-comment-threads) (declare refresh-comment-thread) +(def r-mentions #"@\[([^\]]*)\]\(([^\)]*)\)") + +(defn extract-mentions + "Retrieves the mentions in the content as an array of uuids" + [content] + (->> (re-seq r-mentions content) + (mapv (fn [[_ _ id]] (uuid/uuid id))))) + +(defn update-mentions + "Updates the params object with the mentiosn" + [{:keys [content] :as props}] + (assoc props :mentions (extract-mentions content))) + (defn created-thread-on-workspace ([params] (created-thread-on-workspace params true)) @@ -103,7 +116,9 @@ (let [page-id (:current-page-id state) objects (wsh/lookup-page-objects state page-id) frame-id (ctst/get-frame-id-by-position objects (:position params)) - params (assoc params :frame-id frame-id)] + params (-> params + (update-mentions) + (assoc :frame-id frame-id))] (->> (rp/cmd! :create-comment-thread params) (rx/mapcat #(rp/cmd! :get-comment-thread {:file-id (:file-id %) :id (:id %)})) (rx/tap on-thread-created) @@ -156,7 +171,9 @@ (watch [_ state _] (let [share-id (-> state :viewer-local :share-id) frame-id (:frame-id params) - params (assoc params :share-id share-id :frame-id frame-id)] + params (-> params + (update-mentions) + (assoc :share-id share-id :frame-id frame-id))] (->> (rp/cmd! :create-comment-thread params) (rx/mapcat #(rp/cmd! :get-comment-thread {:file-id (:file-id %) :id (:id %) :share-id share-id})) (rx/map created-thread-on-viewer) @@ -228,9 +245,15 @@ (watch [_ state _] (let [share-id (-> state :viewer-local :share-id) created (fn [comment state] - (update-in state [:comments (:id thread)] assoc (:id comment) comment))] + (update-in state [:comments (:id thread)] assoc (:id comment) comment)) + + params + (-> {:thread-id (:id thread) + :content content + :share-id share-id} + (update-mentions))] (rx/concat - (->> (rp/cmd! :create-comment {:thread-id (:id thread) :content content :share-id share-id}) + (->> (rp/cmd! :create-comment params) (rx/map (fn [comment] (partial created comment))) (rx/catch (fn [{:keys [type code] :as cause}] (if (and (= type :restriction) @@ -260,8 +283,10 @@ ptk/WatchEvent (watch [_ state _] (let [file-id (:current-file-id state) - share-id (-> state :viewer-local :share-id)] - (->> (rp/cmd! :update-comment {:id id :content content :share-id share-id}) + share-id (-> state :viewer-local :share-id) + params (-> {:id id :content content :share-id share-id} + (update-mentions))] + (->> (rp/cmd! :update-comment params) (rx/catch #(rx/throw {:type :comment-error})) (rx/map #(retrieve-comment-threads file-id))))))) @@ -502,11 +527,11 @@ (d/update-in-when [:comments-local :draft] merge data))))) (defn toggle-comment-options - [comment] + [comment-id] (ptk/reify ::toggle-comment-options ptk/UpdateEvent (update [_ state] - (update-in state [:comments-local :options] #(if (= (:id comment) %) nil (:id comment)))))) + (update-in state [:comments-local :options] #(if (= comment-id %) nil comment-id))))) (defn hide-comment-options [] @@ -559,7 +584,10 @@ (filter (comp not :is-resolved)) (= :yours mode) - (filter #(contains? (:participants %) (:id profile)))))) + (filter #(contains? (:participants %) (:id profile))) + + (= :mentions mode) + (filter #(contains? (set (:mentions %)) (:id profile)))))) (defn update-comment-thread-frame ([thread] diff --git a/frontend/src/app/main/data/common.cljs b/frontend/src/app/main/data/common.cljs index 925c314677..0036824b14 100644 --- a/frontend/src/app/main/data/common.cljs +++ b/frontend/src/app/main/data/common.cljs @@ -307,7 +307,7 @@ ptk/WatchEvent (watch [_ state _] (let [team-id (or team-id (:current-team-id state))] - (rx/of (rt/nav :dashboard-libraries {:team-id team-id})))))) + (rx/of (rt/nav :dashboard-fonts {:team-id team-id})))))) (defn go-to-dashboard-recent [& {:keys [team-id] :as options}] @@ -367,14 +367,14 @@ (watch [_ state _] (let [team-id (or team-id (:current-team-id state)) file-id (or file-id (:current-file-id state)) - ;: FIXME: why not :current-page-id - page-id (or page-id + page-id (or page-id (:current-page-id state) (dm/get-in state [:workspace-data :pages 0])) + params (-> (rt/get-params state) (assoc :team-id team-id) (assoc :file-id file-id) (assoc :page-id page-id) - (assoc :layout layout) + (update :layout #(or layout %)) (d/without-nils))] (rx/of (rt/nav :workspace params options)))))) diff --git a/frontend/src/app/main/data/dashboard.cljs b/frontend/src/app/main/data/dashboard.cljs index 49756a5592..54f64e9656 100644 --- a/frontend/src/app/main/data/dashboard.cljs +++ b/frontend/src/app/main/data/dashboard.cljs @@ -361,7 +361,7 @@ ;; --- EVENT: delete-file (defn file-deleted - [_team-id project-id] + [project-id] (ptk/reify ::file-deleted ptk/UpdateEvent (update [_ state] @@ -378,10 +378,9 @@ (d/update-when :recent-files dissoc id))) ptk/WatchEvent - (watch [_ state _] - (let [team-id (uuid/uuid (get-in state [:route :path-params :team-id]))] - (->> (rp/cmd! :delete-file {:id id}) - (rx/map #(file-deleted team-id project-id))))))) + (watch [_ _ _] + (->> (rp/cmd! :delete-file {:id id}) + (rx/map (partial file-deleted project-id)))))) ;; --- Rename File diff --git a/frontend/src/app/main/data/event.cljs b/frontend/src/app/main/data/event.cljs index ff5250be7e..51d59b6f97 100644 --- a/frontend/src/app/main/data/event.cljs +++ b/frontend/src/app/main/data/event.cljs @@ -8,6 +8,7 @@ (:require ["ua-parser-js" :as ua] [app.common.data :as d] + [app.common.json :as json] [app.common.logging :as l] [app.config :as cf] [app.main.repo :as rp] @@ -93,6 +94,11 @@ data data)) +(defn add-external-context-info + [context] + (let [external-context-info (json/->clj (cf/external-context-info))] + (merge context external-context-info))) + (defn- process-event-by-proto [event] (let [data (d/deep-merge (-data event) (meta event)) @@ -102,6 +108,7 @@ (assoc :event-origin (::origin data)) (assoc :event-namespace (namespace type)) (assoc :event-symbol ev-name) + (add-external-context-info) (d/without-nils)) props (-> data d/without-qualified simplify-props)] @@ -119,6 +126,7 @@ (let [type (::type data "action") context (-> (::context data) (assoc :event-origin (::origin data)) + (add-external-context-info) (d/without-nils)) props (-> data d/without-qualified simplify-props)] {:type type diff --git a/frontend/src/app/main/data/profile.cljs b/frontend/src/app/main/data/profile.cljs index 6ae1641694..2a22ad57eb 100644 --- a/frontend/src/app/main/data/profile.cljs +++ b/frontend/src/app/main/data/profile.cljs @@ -208,7 +208,6 @@ ;; Social registered users don't have old-password [:password-old {:optional true} [:maybe :string]]]) - (defn update-password [data] (dm/assert! @@ -233,6 +232,32 @@ (rx/empty))) (rx/ignore)))))) +(def ^:private schema:update-notifications + [:map {:title "NotificationsForm"} + [:dashboard-comments [::sm/one-of #{:all :partial :none}]] + [:email-comments [::sm/one-of #{:all :partial :none}]] + [:email-invites [::sm/one-of #{:all :none}]]]) + +(defn update-notifications + [data] + (dm/assert! + "expected valid parameters" + (sm/check schema:update-notifications data)) + + (ptk/reify ::update-notifications + ev/Event + (-data [_] {}) + + ptk/WatchEvent + (watch [_ _ _] + (let [{:keys [on-error on-success] + :or {on-error identity + on-success identity}} (meta data)] + (->> (rp/cmd! :update-profile-notifications data) + (rx/tap on-success) + (rx/catch #(do (on-error %) (rx/empty))) + (rx/ignore)))))) + (defn update-profile-props [props] (ptk/reify ::update-profile-props diff --git a/frontend/src/app/main/data/workspace.cljs b/frontend/src/app/main/data/workspace.cljs index c289ec5ca9..05353ffdf2 100644 --- a/frontend/src/app/main/data/workspace.cljs +++ b/frontend/src/app/main/data/workspace.cljs @@ -254,6 +254,22 @@ (dwsl/initialize-shape-layout) (fetch-libraries file-id)))))) +(defn zoom-to-frame + [] + (ptk/reify ::zoom-to-frame + ptk/WatchEvent + (watch [_ state _] + (let [params (rt/get-params state) + board-id (get params :board-id) + board-id (cond + (vector? board-id) board-id + (string? board-id) [board-id]) + frames-id (->> board-id + (map uuid/uuid) + (into (d/ordered-set)))] + (rx/of (dws/select-shapes frames-id) + dwz/zoom-to-selected-shape))))) + (defn- fetch-bundle "Multi-stage file bundle fetch coordinator" [file-id] @@ -290,7 +306,6 @@ :features features :thumbnails thumbnails}))))) (rx/map bundle-fetched))) - (rx/take-until stopper-s)))))) (defn initialize-workspace @@ -334,6 +349,13 @@ (rx/take 1) (rx/map #(dwl/go-to-local-component :id component-id)))) + (when (:board-id rparams) + (->> stream + (rx/filter (ptk/type? ::workspace-initialized)) + (rx/observe-on :async) + (rx/take 1) + (rx/map zoom-to-frame))) + (->> stream (rx/filter dch/commit?) (rx/map deref) @@ -1913,6 +1935,13 @@ (update [_ state] (assoc-in state [:workspace-global :show-distances?] value)))) +(defn copy-link-to-clipboard + [] + (ptk/reify ::copy-link-to-clipboard + ptk/WatchEvent + (watch [_ _ _] + (wapi/write-to-clipboard (rt/get-current-href))))) + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Interactions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; diff --git a/frontend/src/app/main/data/workspace/comments.cljs b/frontend/src/app/main/data/workspace/comments.cljs index d1b250cc1d..1688ec3322 100644 --- a/frontend/src/app/main/data/workspace/comments.cljs +++ b/frontend/src/app/main/data/workspace/comments.cljs @@ -151,11 +151,13 @@ (pcb/with-page page) (pcb/set-comment-thread-position thread))] - (rx/merge - (rx/of (dch/commit-changes changes)) - (->> (rp/cmd! :update-comment-thread-position thread) - (rx/catch #(rx/throw {:type :update-comment-thread-position})) - (rx/ignore)))))))) + (rx/concat + (rx/merge + (rx/of (dch/commit-changes changes)) + (->> (rp/cmd! :update-comment-thread-position thread) + (rx/catch #(rx/throw {:type :update-comment-thread-position})) + (rx/ignore))) + (rx/of (dcmt/refresh-comment-thread thread)))))))) ;; Move comment threads that are inside a frame when that frame is moved" (defmethod ptk/resolve ::move-frame-comment-threads diff --git a/frontend/src/app/main/data/workspace/selection.cljs b/frontend/src/app/main/data/workspace/selection.cljs index 7125453b58..2fdd28d01e 100644 --- a/frontend/src/app/main/data/workspace/selection.cljs +++ b/frontend/src/app/main/data/workspace/selection.cljs @@ -26,6 +26,7 @@ [app.main.data.workspace.undo :as dwu] [app.main.data.workspace.zoom :as dwz] [app.main.refs :as refs] + [app.main.router :as rt] [app.main.streams :as ms] [app.main.worker :as uw] [app.util.mouse :as mse] @@ -138,12 +139,25 @@ ptk/WatchEvent (watch [_ state _] - (let [page-id (:current-page-id state) - objects (wsh/lookup-page-objects state page-id)] + (let [page-id (:current-page-id state) + objects (wsh/lookup-page-objects state page-id) + selected-id (wsh/lookup-selected state) + selected (wsh/lookup-shapes state selected-id) + frame-ids (map (fn [item] (let [parent (cfh/get-frame objects (:id item))] + (:id parent))) selected) + params-without-board (-> (rt/get-params state) + (dissoc :board-id)) + params-board (-> (rt/get-params state) + (assoc :board-id frame-ids))] + (rx/of (dwc/expand-all-parents [id] objects) :interrupt - ::dwsp/interrupt)))))) + ::dwsp/interrupt) + + (if (some #(= % uuid/zero) frame-ids) + (rx/of (rt/nav :workspace params-without-board {::rt/replace true})) + (rx/of (rt/nav :workspace params-board {::rt/replace true})))))))) (defn select-prev-shape ([] @@ -290,8 +304,11 @@ ([check-modal] (ptk/reify ::deselect-all ptk/WatchEvent - (watch [_ _ _] - (rx/of ::dwsp/interrupt)) + (watch [_ state _] + (let [params-without-board (-> (rt/get-params state) + (dissoc :board-id))] + (rx/of ::dwsp/interrupt) + (rx/of (rt/nav :workspace params-without-board {::rt/replace true})))) ptk/UpdateEvent (update [_ state] diff --git a/frontend/src/app/main/data/workspace/shortcuts.cljs b/frontend/src/app/main/data/workspace/shortcuts.cljs index 40879477ec..3a41175bd3 100644 --- a/frontend/src/app/main/data/workspace/shortcuts.cljs +++ b/frontend/src/app/main/data/workspace/shortcuts.cljs @@ -85,6 +85,11 @@ :subsections [:edit] :fn #(st/emit! (dw/copy-selected))} + :copy-link {:tooltip (ds/meta (ds/alt "C")) + :command (ds/c-mod "alt+c") + :subsections [:edit] + :fn #(st/emit! (dw/copy-link-to-clipboard))} + :cut {:tooltip (ds/meta "X") :command (ds/c-mod "x") :subsections [:edit] diff --git a/frontend/src/app/main/data/workspace/thumbnails.cljs b/frontend/src/app/main/data/workspace/thumbnails.cljs index 0d2ef2239f..132db9156a 100644 --- a/frontend/src/app/main/data/workspace/thumbnails.cljs +++ b/frontend/src/app/main/data/workspace/thumbnails.cljs @@ -52,6 +52,11 @@ (defonce queue (q/create find-request (/ 1000 30))) +(defn clear-queue! + [] + (l/dbg :hint "clearing thumbnail queue") + (q/clear! queue)) + ;; This function first renders the HTML calling `render/render-frame` that ;; returns HTML as a string, then we send that data to the iframe rasterizer ;; that returns the image as a Blob. Finally we create a URI for that blob. diff --git a/frontend/src/app/main/data/workspace/versions.cljs b/frontend/src/app/main/data/workspace/versions.cljs index 3a8243c63e..250d13deb6 100644 --- a/frontend/src/app/main/data/workspace/versions.cljs +++ b/frontend/src/app/main/data/workspace/versions.cljs @@ -12,6 +12,7 @@ [app.main.data.event :as ev] [app.main.data.persistence :as dwp] [app.main.data.workspace :as dw] + [app.main.data.workspace.thumbnails :as th] [app.main.refs :as refs] [app.main.repo :as rp] [app.util.time :as dt] @@ -100,19 +101,23 @@ (rx/concat (rx/of ::dwp/force-persist (dw/remove-layout-flag :document-history)) - - ;; FIXME: we should abstract this (->> (rx/from-atom refs/persistence-state {:emit-current-value? true}) (rx/filter #(or (nil? %) (= :saved %))) (rx/take 1) (rx/mapcat #(rp/cmd! :restore-file-snapshot {:file-id file-id :id id})) + (rx/tap #(th/clear-queue!)) (rx/map #(dw/initialize-workspace file-id))) + (case origin + :version + (rx/of (ptk/event ::ev/event {::ev/name "restore-pin-version"})) - (when-let [name (case origin - :version "restore-pin-version" - :snapshot "restore-autosave" - nil)] - (rx/of (ptk/event ::ev/event {::ev/name name})))))))) + :snapshot + (rx/of (ptk/event ::ev/event {::ev/name "restore-autosave"})) + + :plugin + (rx/of (ptk/event ::ev/event {::ev/name "restore-version-plugin"})) + + (rx/empty))))))) (defn delete-version [id] diff --git a/frontend/src/app/main/refs.cljs b/frontend/src/app/main/refs.cljs index 88f8383f83..04a099208f 100644 --- a/frontend/src/app/main/refs.cljs +++ b/frontend/src/app/main/refs.cljs @@ -267,9 +267,9 @@ (def workspace-page-flows (l/derived #(-> % :flows not-empty) workspace-page)) -(defn workspace-page-objects-by-id - [page-id] - (l/derived #(wsh/lookup-page-objects % page-id) st/state =)) +(defn workspace-page-object-by-id + [page-id shape-id] + (l/derived #(wsh/lookup-shape % page-id shape-id) st/state =)) ;; TODO: Looks like using the `=` comparator can be pretty expensive ;; on large pages, we are using this for some reason? diff --git a/frontend/src/app/main/ui.cljs b/frontend/src/app/main/ui.cljs index 95f42507b5..ee962d4b6b 100644 --- a/frontend/src/app/main/ui.cljs +++ b/frontend/src/app/main/ui.cljs @@ -149,6 +149,7 @@ (let [{:keys [data params]} route props (get profile :props) section (get data :name) + team (mf/deref refs/team) show-question-modal? @@ -166,10 +167,12 @@ (and (contains? cf/flags :onboarding) (not (:onboarding-viewed props)) (not (contains? props :onboarding-team-id)) - (contains? props :newsletter-updates)) + (contains? props :newsletter-updates) + (:is-default team)) show-release-modal? (and (contains? cf/flags :onboarding) + (not (contains? cf/flags :hide-release-modal)) (:onboarding-viewed props) (not= (:release-notes-viewed props) (:main cf/version)) (not= "0.0" (:main cf/version)))] @@ -191,7 +194,8 @@ :settings-password :settings-options :settings-feedback - :settings-access-tokens) + :settings-access-tokens + :settings-notifications) [:? [:& settings-page {:route route}]] :debug-icons-preview diff --git a/frontend/src/app/main/ui/auth/login.cljs b/frontend/src/app/main/ui/auth/login.cljs index e30b259577..10bf80d3b5 100644 --- a/frontend/src/app/main/ui/auth/login.cljs +++ b/frontend/src/app/main/ui/auth/login.cljs @@ -120,17 +120,10 @@ :else (reset! error (tr "errors.generic"))))) - on-success-default - (mf/use-fn - (fn [data] - (when-let [token (:invitation-token data)] - (st/emit! (rt/nav :auth-verify-token {:token token}))))) - on-success (fn [data] - (if (nil? on-success-callback) - (on-success-default data) - (on-success-callback))) + (when (fn? on-success-callback) + (on-success-callback data))) on-submit (mf/use-callback diff --git a/frontend/src/app/main/ui/comments.cljs b/frontend/src/app/main/ui/comments.cljs index 643c35d23c..942ee27ac6 100644 --- a/frontend/src/app/main/ui/comments.cljs +++ b/frontend/src/app/main/ui/comments.cljs @@ -9,7 +9,10 @@ (:require [app.common.data :as d] [app.common.data.macros :as dm] + [app.common.files.helpers :as cfh] [app.common.geom.point :as gpt] + [app.common.math :as mth] + [app.common.uuid :as uuid] [app.config :as cfg] [app.main.data.comments :as dcm] [app.main.data.modal :as modal] @@ -17,65 +20,380 @@ [app.main.refs :as refs] [app.main.store :as st] [app.main.ui.components.dropdown :refer [dropdown]] + [app.main.ui.ds.buttons.button :refer [button*]] [app.main.ui.ds.buttons.icon-button :refer [icon-button*]] + [app.main.ui.ds.foundations.assets.icon :refer [icon*]] + [app.main.ui.hooks :as h] [app.main.ui.icons :as i] [app.util.dom :as dom] [app.util.i18n :as i18n :refer [tr]] [app.util.keyboard :as kbd] + [app.util.object :as obj] [app.util.time :as dt] + [app.util.webapi :as wapi] + [beicon.v2.core :as rx] + [clojure.math :refer [floor]] [cuerdas.core :as str] [okulary.core :as l] [rumext.v2 :as mf])) (def comments-local-options (l/derived :options refs/comments-local)) -(mf/defc resizing-textarea +(def mentions-context (mf/create-context nil)) + +(def r-mentions-split #"@\[[^\]]*\]\([^\)]*\)") +(def r-mentions #"@\[([^\]]*)\]\(([^\)]*)\)") + + +(defn- parse-comment + "Parse a comment into its elements (texts and mentions)" + [comment] + (d/interleave-all + (->> (str/split comment r-mentions-split) + (map #(hash-map :type :text :content %))) + + (->> (re-seq r-mentions comment) + (map (fn [[_ user id]] + {:type :mention + :content user + :data {:id id}}))))) + +(defn parse-nodes + "Parse the nodes to format a comment" + [node] + (->> (dom/get-children node) + (map + (fn [node] + (cond + (and (instance? js/HTMLElement node) (dom/get-data node "user-id")) + (str/ffmt "@[%](%)" (.-textContent node) (dom/get-data node "user-id")) + + :else + (.-textContent node)))) + (str/join ""))) + + +(defn create-text-node + "Creates a text-only node" + ([] + (create-text-node "")) + ([text] + (-> (dom/create-element "span") + (dom/set-data! "type" "text") + (dom/set-html! (if (empty? text) "​" text))))) + +(defn create-mention-node + "Creates a mention node" + [id fullname] + (-> (dom/create-element "span") + (dom/set-data! "type" "mention") + (dom/set-data! "user-id" (dm/str id)) + (dom/set-data! "fullname" fullname) + (obj/set! "textContent" fullname))) + +(defn current-text-node + "Retrieves the text node and the offset that the cursor is positioned on" + [node] + + (let [selection (wapi/get-selection) + range (wapi/get-range selection 0) + anchor-node (wapi/range-start-container range) + anchor-offset (wapi/range-start-offset range)] + (when (and node (.contains node anchor-node)) + (let [span-node + (if (instance? js/Text anchor-node) + (dom/get-parent anchor-node) + anchor-node) + container (dom/get-parent span-node)] + (when (= node container) + [span-node anchor-offset]))))) + +(defn absolute-offset + [node child offset] + (loop [nodes (seq (dom/get-children node)) + acc 0] + (if-let [head (first nodes)] + (if (= head child) + (+ acc offset) + (recur (rest nodes) (+ acc (.-length (.-textContent head))))) + nil))) + +(defn get-prev-node + [parent node] + (->> (d/with-prev (dom/get-children parent)) + (d/seek (fn [[it _]] (= node it))) + (second))) + +;; Component that renders the component content +(mf/defc comment-content + [{:keys [content]}] + (let [comment-elements (mf/use-memo (mf/deps content) #(parse-comment content))] + (for [[idx {:keys [type content]}] (d/enumerate comment-elements)] + (case type + [:span + {:key idx + :class (stl/css-case + :comment-text (= type :text) + :comment-mention (= type :mention))} + content])))) + +;; Input text for comments with mentions +(mf/defc comment-input {::mf/wrap-props false} [props] + (let [value (d/nilv (unchecked-get props "value") "") + prev-value (h/use-previous value) + + local-ref (mf/use-ref nil) + mentions-str (mf/use-ctx mentions-context) + cur-mention (mf/use-var nil) + + prev-selection (mf/use-var nil) + on-focus (unchecked-get props "on-focus") on-blur (unchecked-get props "on-blur") placeholder (unchecked-get props "placeholder") - max-length (unchecked-get props "max-length") on-change (unchecked-get props "on-change") on-esc (unchecked-get props "on-esc") on-ctrl-enter (unchecked-get props "on-ctrl-enter") + max-length (unchecked-get props "max-length") autofocus? (unchecked-get props "autofocus") - select-on-focus? (unchecked-get props "select-on-focus") - local-ref (mf/use-ref) + init-input + (mf/use-callback + (fn [node] + (mf/set-ref-val! local-ref node) + (when node + (doseq [{:keys [type content data]} (parse-comment value)] + (case type + :text (dom/append-child! node (create-text-node content)) + :mention (dom/append-child! node (create-mention-node (:id data) content)) + nil))))) - on-change* - (mf/use-fn + handle-input + (mf/use-callback (mf/deps on-change) - (fn [event] - (let [content (dom/get-target-val event)] - (on-change content)))) + (fn [] + (let [node (mf/ref-val local-ref) + children (dom/get-children node)] - on-key-down + (doseq [child-node children] + ;; Remove nodes that are not span. This can happen if the user copy/pastes + (when (not= (.-tagName child-node) "SPAN") + (.remove child-node)) + + ;; If a node is empty we set the content to "empty" + (when (and (= (dom/get-data child-node "type") "text") + (empty? (dom/get-text child-node))) + (dom/set-html! child-node "​")) + + ;; Remove mentions that have been modified + (when (and (= (dom/get-data child-node "type") "mention") + (not= (dom/get-data child-node "fullname") + (dom/get-text child-node))) + (.remove child-node))) + + ;; If there are no nodes we need to create an empty node + (when (= 0 (.-length children)) + (dom/append-child! node (create-text-node))) + + (let [new-input (parse-nodes node)] + (when (and on-change (<= (count new-input) max-length)) + (on-change new-input)))))) + + handle-select + (mf/use-callback + (fn [] + (let [node (mf/ref-val local-ref) + selection (wapi/get-selection) + range (wapi/get-range selection 0) + anchor-node (wapi/range-start-container range)] + (when (and (= node anchor-node) (.-collapsed range)) + (wapi/set-cursor-after! anchor-node))) + + (let [node (mf/ref-val local-ref) + [span-node offset] (current-text-node node) + [prev-span prev-offset] @prev-selection] + + (reset! prev-selection #js [span-node offset]) + + (when (= (dom/get-data span-node "type") "mention") + (let [from-offset (absolute-offset node prev-span prev-offset) + to-offset (absolute-offset node span-node offset) + + [_ prev next] + (->> node + (dom/seq-nodes) + (d/with-prev-next) + (filter (fn [[elem _ _]] (= elem span-node))) + (first))] + + (if (> from-offset to-offset) + (wapi/set-cursor-after! prev) + (wapi/set-cursor-before! next)))) + + (when span-node + (let [node-text (subs (dom/get-text span-node) 0 offset) + + current-at-symbol + (str/last-index-of (subs node-text 0 offset) "@") + + mention-text + (subs node-text current-at-symbol)] + + (if (re-matches #"@\w*" mention-text) + (do + (reset! cur-mention mention-text) + (rx/push! mentions-str {:type :display-mentions}) + (let [mention (subs mention-text 1)] + (when (d/not-empty? mention) + (rx/push! mentions-str {:type :filter-mentions :data mention})))) + (do + (reset! cur-mention nil) + (rx/push! mentions-str {:type :hide-mentions})))))))) + + handle-focus + (mf/use-callback + (fn [event] + (dom/prevent-default event) + (dom/set-css-property! (mf/ref-val local-ref) "--placeholder" "") + (when on-focus + (on-focus event)))) + + handle-blur + (mf/use-callback + (mf/deps value) + (fn [event] + (when (empty? value) + (let [node (mf/ref-val local-ref)] + (dom/set-css-property! node "--placeholder" (dm/str "\"" placeholder "\"")))) + + (when on-blur + (on-blur event)))) + + handle-insert-mention + (fn [data] + (let [node (mf/ref-val local-ref) + [span-node offset] (current-text-node node)] + (when span-node + (let [node-text + (dom/get-text span-node) + + current-at-symbol + (or (str/last-index-of (subs node-text 0 offset) "@") + (absolute-offset node span-node offset)) + + mention + (re-find #"@\w*" (subs node-text current-at-symbol)) + + prefix + (subs node-text 0 current-at-symbol) + + suffix + (subs node-text (+ current-at-symbol (count mention))) + + mention-span (create-mention-node (-> data :user :id) (-> data :user :fullname)) + after-span (create-text-node (dm/str " " suffix)) + sel (wapi/get-selection)] + + (dom/set-html! span-node (if (empty? prefix) "​" prefix)) + (dom/insert-after! node span-node mention-span) + (dom/insert-after! node mention-span after-span) + (wapi/set-cursor-after! after-span) + (wapi/collapse-end! sel) + + (when on-change + (on-change (parse-nodes node))))))) + + handle-key-down (mf/use-fn - (mf/deps on-esc on-ctrl-enter on-change*) + (mf/deps on-esc on-ctrl-enter handle-select handle-input) (fn [event] - (cond - (and (kbd/esc? event) (fn? on-esc)) (on-esc event) - (and (kbd/mod? event) (kbd/enter? event) (fn? on-ctrl-enter)) - (do - (on-change* event) - (on-ctrl-enter event))))) + (handle-select event) - on-focus* - (mf/use-fn - (mf/deps select-on-focus? on-focus) - (fn [event] - (when (fn? on-focus) - (on-focus event)) + (let [node (mf/ref-val local-ref) + [span-node offset] (current-text-node node)] - (when ^boolean select-on-focus? - (let [target (dom/get-target event)] - (dom/select-text! target) - ;; In webkit browsers the mouseup event will be called after the on-focus causing and unselect - (.addEventListener target "mouseup" dom/prevent-default #js {:once true})))))] + (cond + (and @cur-mention (kbd/enter? event)) + (do (dom/prevent-default event) + (dom/stop-propagation event) + (rx/push! mentions-str {:type :insert-selected-mention})) + (and @cur-mention (kbd/down-arrow? event)) + (do (dom/prevent-default event) + (dom/stop-propagation event) + (rx/push! mentions-str {:type :insert-next-mention})) + + (and @cur-mention (kbd/up-arrow? event)) + (do (dom/prevent-default event) + (dom/stop-propagation event) + (rx/push! mentions-str {:type :insert-prev-mention})) + + (and @cur-mention (kbd/esc? event)) + (do (dom/prevent-default event) + (dom/stop-propagation event) + (rx/push! mentions-str {:type :hide-mentions})) + + (and (kbd/esc? event) (fn? on-esc)) + (on-esc event) + + (and (kbd/mod? event) (kbd/enter? event) (fn? on-ctrl-enter)) + (on-ctrl-enter event) + + (kbd/enter? event) + (let [sel (wapi/get-selection) + range (.getRangeAt sel 0)] + (dom/prevent-default event) + (dom/stop-propagation event) + (let [[span-node offset] (current-text-node node)] + (.deleteContents range) + (handle-input) + + (when span-node + (let [txt (.-textContent span-node)] + (dom/set-html! span-node (dm/str (subs txt 0 offset) "\n​" (subs txt offset))) + (wapi/set-cursor! span-node (inc offset)) + (handle-input))))) + + (kbd/backspace? event) + (let [prev-node (get-prev-node node span-node)] + (when (and (some? prev-node) + (= "mention" (dom/get-data prev-node "type")) + (= offset 1)) + (dom/prevent-default event) + (dom/stop-propagation event) + (.remove prev-node)))))))] + + (mf/use-layout-effect + (mf/deps autofocus?) + (fn [] + (when autofocus? + (dom/focus! (mf/ref-val local-ref))))) + + ;; Creates the handlers for selection + (mf/use-effect + (mf/deps handle-select) + (fn [] + (let [handle-select* handle-select] + (js/document.addEventListener "selectionchange" handle-select*) + #(js/document.removeEventListener "selectionchange" handle-select*)))) + + ;; Effect to communicate with the mentions panel + (mf/use-effect + (fn [] + (when mentions-str + (->> mentions-str + (rx/subs! + (fn [{:keys [type data]}] + (case type + :insert-mention + (handle-insert-mention data) + + nil))))))) + + ;; Auto resize input to display the comment (mf/use-layout-effect nil (fn [] @@ -83,18 +401,219 @@ (set! (.-height (.-style node)) "0") (set! (.-height (.-style node)) (str (+ 2 (.-scrollHeight node)) "px"))))) - [:textarea {:ref local-ref - :auto-focus autofocus? - :on-key-down on-key-down - :on-focus on-focus* - :on-blur on-blur - :value value - :placeholder placeholder - :on-change on-change* - :max-length max-length}])) + (mf/use-effect + (mf/deps value prev-value) + (fn [] + (let [node (mf/ref-val local-ref)] + (cond + (and (d/not-empty? prev-value) (empty? value)) + (do (dom/set-html! node "") + (dom/append-child! node (create-text-node)) + (dom/set-css-property! node "--placeholder" "") + (dom/focus! node)) -(mf/defc reply-form - [{:keys [thread] :as props}] + (and (some? node) (empty? value) (not (dom/focus? node))) + (dom/set-css-property! node "--placeholder" (dm/str "\"" placeholder "\"")) + + (some? node) + (dom/set-css-property! node "--placeholder" ""))))) + + [:div + {:role "textbox" + :class (stl/css :comment-input) + :content-editable "true" + :suppress-content-editable-warning true + :on-input handle-input + :ref init-input + :on-key-down handle-key-down + :on-focus handle-focus + :on-blur handle-blur}])) + +(mf/defc mentions-panel + [{:keys [profiles]}] + + (let [mentions-str (mf/use-ctx mentions-context) + + profile (mf/deref refs/profile) + + mention-state + (mf/use-state {:display? false + :mention-filter "" + :selected 0}) + + {:keys [display? mention-filter selected]} @mention-state + + mentions-users + (mf/use-memo + (mf/deps mention-filter) + #(->> (vals profiles) + (filter + (fn [{:keys [id fullname email]}] + (and + (not= id (:id profile)) + (or (not mention-filter) + (empty? mention-filter) + (str/includes? (str/lower fullname) (str/lower mention-filter)) + (str/includes? (str/lower email) (str/lower mention-filter)))))) + (take 4) + (into []))) + + selected (mth/clamp selected 0 (dec (count mentions-users))) + + handle-click-mention + (mf/use-callback + (fn [event] + (dom/prevent-default event) + (dom/stop-propagation event) + (let [id (-> (dom/get-current-target event) + (dom/get-data "user-id") + (uuid/uuid))] + (rx/push! mentions-str {:type :insert-mention + :data {:user (get profiles id)}}))))] + + (mf/use-effect + (mf/deps mentions-users selected) + (fn [] + (let [sub + (->> mentions-str + (rx/subs! + (fn [{:keys [type data]}] + (case type + ;; Display the mentions dialog + :display-mentions + (swap! mention-state assoc :display? true) + + ;; Hide mentions + :hide-mentions + (swap! mention-state assoc :display? false :mention-filter "") + + ;; Filter the metions by some characters + :filter-mentions + (swap! mention-state assoc :mention-filter data) + + :insert-selected-mention + (rx/push! mentions-str {:type :insert-mention + :data {:user (get mentions-users selected)}}) + + :insert-next-mention + (swap! mention-state update :selected #(mth/clamp (inc %) 0 (dec (count mentions-users)))) + + :insert-prev-mention + (swap! mention-state update :selected #(mth/clamp (dec %) 0 (dec (count mentions-users)))) + + ;; + nil))))] + #(rx/dispose! sub)))) + + (when display? + [:div {:class (stl/css :comments-mentions-choice)} + (if (empty? mentions-users) + [:div {:class (stl/css :comments-mentions-empty)} + (tr "comments.mentions.not-found" mention-filter)] + + (for [[idx {:keys [id fullname email] :as user}] (d/enumerate mentions-users)] + [:div {:key id + :on-pointer-down handle-click-mention + :data-user-id (dm/str id) + :class (stl/css-case :comments-mentions-entry true + :is-selected (= selected idx))} + [:img {:class (stl/css :comments-mentions-avatar) + :src (cfg/resolve-profile-photo-url user)}] + [:div {:class (stl/css :comments-mentions-name)} fullname] + [:div {:class (stl/css :comments-mentions-email)} email]]))]))) + +(mf/defc mentions-button + [] + (let [mentions-str (mf/use-ctx mentions-context) + display-mentions* (mf/use-state false) + + handle-mouse-down + (mf/use-callback + (fn [event] + (dom/prevent-default event) + (dom/stop-propagation event) + (rx/push! mentions-str {:type :display-mentions})))] + + (mf/use-effect + (fn [] + (let [sub + (rx/subs! + (fn [{:keys [type _]}] + (case type + :display-mentions (reset! display-mentions* true) + :hide-mentions (reset! display-mentions* false) + nil)) + mentions-str)] + #(rx/dispose! sub)))) + + [:> icon-button* + {:variant "ghost" + :aria-label (tr "labels.options") + :on-pointer-down handle-mouse-down + :icon-class (stl/css-case :open-mentions-button true + :is-toggled @display-mentions*) + :icon "at"}])) + +(def ^:private schema:comment-avatar + [:map + [:class {:optional true} :string] + [:image :string] + [:variant {:optional true} + [:maybe [:enum "read" "unread" "solved"]]]]) + +(mf/defc comment-avatar* + {::mf/props :obj + ::mf/schema schema:comment-avatar} + [{:keys [image variant class] :rest props}] + (let [variant (or variant "read") + class (dm/str class " " (stl/css-case :avatar true + :avatar-read (= variant "read") + :avatar-unread (= variant "unread") + :avatar-solved (= variant "solved"))) + props (mf/spread-props props {:class class})] + [:> :div props + [:img {:src image + :class (stl/css :avatar-image)}] + [:div {:class (stl/css-case :avatar-mask true + :avatar-darken (= variant "solved"))}]])) + +(mf/defc comment-info* + {::mf/props :obj + ::mf/private true} + [{:keys [item profile]}] + [:* + [:div {:class (stl/css :author)} + [:> comment-avatar* {:image (cfg/resolve-profile-photo-url profile) + :class (stl/css :avatar-lg) + :variant (cond (:is-resolved item) "solved" + (pos? (:count-unread-comments item)) "unread" + :else "read")}] + [:div {:class (stl/css :author-identity)} + [:div {:class (stl/css :author-fullname)} (:fullname profile)] + [:div {:class (stl/css :author-timeago)} (dt/timeago (:modified-at item))]]] + + [:div {:class (stl/css :item)} + [:> comment-content {:content (:content item)}]] + + [:div {:class (stl/css :replies)} + (let [total-comments (:count-comments item 1) + total-replies (dec total-comments) + unread-replies (:count-unread-comments item 0)] + [:* + (when (> total-replies 0) + (if (= total-replies 1) + [:span {:class (stl/css :replies-total)} (str total-replies " " (tr "labels.reply"))] + [:span {:class (stl/css :replies-total)} (str total-replies " " (tr "labels.replies"))])) + + (when (and (> total-replies 0) (> unread-replies 0)) + (if (= unread-replies 1) + [:span {:class (stl/css :replies-unread)} (str unread-replies " " (tr "labels.reply.new"))] + [:span {:class (stl/css :replies-unread)} (str unread-replies " " (tr "labels.replies.new"))]))])]]) + +(mf/defc comment-reply-form* + {::mf/props :obj + ::mf/private true} + [{:keys [thread]}] (let [show-buttons? (mf/use-state false) content (mf/use-state "") @@ -124,39 +643,79 @@ (fn [] (st/emit! (dcm/add-comment thread @content)) (on-cancel)))] - [:div {:class (stl/css :reply-form)} - [:& resizing-textarea {:value @content - :placeholder "Reply" - :on-blur on-blur - :on-focus on-focus - :select-on-focus? false - :on-ctrl-enter on-submit - :on-change on-change - :max-length 750}] + [:div {:class (stl/css :form)} + [:& comment-input + {:value @content + :placeholder (tr "labels.reply.thread") + :autofocus true + :on-blur on-blur + :on-focus on-focus + :select-on-focus? false + :on-ctrl-enter on-submit + :on-change on-change + :max-length 750}] (when (or @show-buttons? (seq @content)) - [:div {:class (stl/css :buttons-wrapper)} - [:input.btn-secondary - {:type "button" - :class (stl/css :cancel-btn) - :value "Cancel" - :on-click on-cancel}] - [:input - {:type "button" - :class (stl/css-case :post-btn true - :global/disabled disabled?) - :value "Post" - :on-click on-submit - :disabled disabled?}]])])) + [:div {:class (stl/css :form-buttons-wrapper)} + [:> mentions-button] + [:> button* {:variant "ghost" + :on-click on-cancel} + (tr "ds.confirm-cancel")] + [:> button* {:variant "primary" + :on-click on-submit + :disabled disabled?} + (tr "labels.post")]])])) -(mf/defc draft-thread - [{:keys [draft zoom on-cancel on-submit position-modifier]}] - (let [position (cond-> (:position draft) - (some? position-modifier) - (gpt/transform position-modifier)) - content (:content draft) +(mf/defc comment-edit-form* + {::mf/props :obj + ::mf/private true} + [{:keys [content on-submit on-cancel]}] + (let [content (mf/use-state content) - pos-x (* (:x position) zoom) - pos-y (* (:y position) zoom) + on-change + (mf/use-fn + #(reset! content %)) + + on-submit* + (mf/use-fn + (mf/deps @content) + (fn [] (on-submit @content))) + + disabled? (or (str/blank? @content) + (str/empty? @content))] + + [:div {:class (stl/css :form)} + [:& comment-input + {:value @content + :autofocus true + :select-on-focus true + :select-on-focus? false + :on-ctrl-enter on-submit* + :on-change on-change + :max-length 750}] + [:div {:class (stl/css :form-buttons-wrapper)} + [:> mentions-button] + [:> button* {:variant "ghost" + :on-click on-cancel} + (tr "ds.confirm-cancel")] + [:> button* {:variant "primary" + :on-click on-submit* + :disabled disabled?} + (tr "labels.post")]]])) + +(mf/defc comment-floating-thread-draft* + {::mf/props :obj} + [{:keys [draft zoom on-cancel on-submit position-modifier profiles]}] + (let [profile (mf/deref refs/profile) + + mentions-str (mf/use-memo #(rx/subject)) + + position (cond-> (:position draft) + (some? position-modifier) + (gpt/transform position-modifier)) + content (:content draft) + + pos-x (* (:x position) zoom) + pos-y (* (:y position) zoom) disabled? (or (str/blank? content) (str/empty? content)) @@ -181,79 +740,116 @@ (mf/deps draft) (partial on-submit draft))] - [:* + [:& (mf/provider mentions-context) {:value mentions-str} [:div - {:class (stl/css :floating-thread-bubble) + {:class (stl/css :floating-preview-wrapper) :data-testid "floating-thread-bubble" :style {:top (str pos-y "px") :left (str pos-x "px")} :on-click dom/stop-propagation} - "?"] - [:div {:class (stl/css :thread-content) + [:> comment-avatar* {:class (stl/css :avatar-lg) + :image (cfg/resolve-profile-photo-url profile)}]] + [:div {:class (stl/css :floating-thread-wrapper) :style {:top (str (- pos-y 24) "px") :left (str (+ pos-x 28) "px")} :on-click dom/stop-propagation} - [:div {:class (stl/css :reply-form)} - [:& resizing-textarea {:placeholder (tr "labels.write-new-comment") - :value (or content "") - :autofocus true - :select-on-focus? false - :on-esc on-esc - :on-change on-change - :on-ctrl-enter on-submit - :max-length 750}] - [:div {:class (stl/css :buttons-wrapper)} + [:div {:class (stl/css :form)} + [:& comment-input + {:placeholder (tr "labels.write-new-comment") + :value (or content "") + :autofocus true + :select-on-focus? false + :on-esc on-esc + :on-change on-change + :on-ctrl-enter on-submit + :max-length 750}] - [:input {:on-click on-esc - :class (stl/css :cancel-btn) - :type "button" - :value "Cancel"}] + [:div {:class (stl/css :form-buttons-wrapper)} + [:> mentions-button] + [:> button* {:variant "ghost" + :on-click on-esc} + (tr "ds.confirm-cancel")] + [:> button* {:variant "primary" + :on-click on-submit + :disabled disabled?} + (tr "labels.post")]]] - [:input {:on-click on-submit - :type "button" - :value "Post" - :class (stl/css-case :post-btn true - :global/disabled disabled?) - :disabled disabled?}]]]]])) + [:& mentions-panel {:profiles profiles}]]])) -(mf/defc edit-form - [{:keys [content on-submit on-cancel] :as props}] - (let [content (mf/use-state content) +(mf/defc comment-floating-thread-header* + {::mf/props :obj + ::mf/private true} + [{:keys [profiles thread origin]}] + (let [owner (get profiles (:owner-id thread)) + profile (mf/deref refs/profile) + options (mf/deref comments-local-options) - on-change + toggle-resolved (mf/use-fn - #(reset! content %)) + (mf/deps thread) + (fn [event] + (dom/stop-propagation event) + (st/emit! (dcm/update-comment-thread (update thread :is-resolved not))))) - on-submit* + on-toggle-options (mf/use-fn - (mf/deps @content) - (fn [] (on-submit @content))) + (fn [event] + (dom/stop-propagation event) + (st/emit! (dcm/toggle-comment-options uuid/zero)))) - disabled? (or (str/blank? @content) - (str/empty? @content))] + delete-thread + (mf/use-fn + (fn [] + (st/emit! (dcm/close-thread) + (if (= origin :viewer) + (dcm/delete-comment-thread-on-viewer thread) + (dcm/delete-comment-thread-on-workspace thread))))) - [:div {:class (stl/css :edit-form)} - [:& resizing-textarea {:value @content - :autofocus true - :select-on-focus true - :select-on-focus? false - :on-ctrl-enter on-submit* - :on-change on-change - :max-length 750}] - [:div {:class (stl/css :buttons-wrapper)} - [:input {:type "button" - :value "Cancel" - :class (stl/css :cancel-btn) - :on-click on-cancel}] - [:input {:type "button" - :class (stl/css-case :post-btn true - :global/disabled disabled?) - :value "Post" - :on-click on-submit* - :disabled disabled?}]]])) + on-delete-thread + (mf/use-fn + (fn [event] + (dom/stop-propagation event) + (st/emit! (dcm/hide-comment-options)) + (st/emit! (modal/show + {:type :confirm + :title (tr "modals.delete-comment-thread.title") + :message (tr "modals.delete-comment-thread.message") + :accept-label (tr "modals.delete-comment-thread.accept") + :on-accept delete-thread})))) -(mf/defc comment-item - [{:keys [comment thread profiles origin] :as props}] + on-hide-options + (mf/use-fn + (mf/deps options) + (fn [event] + (dom/stop-propagation event) + (st/emit! (dcm/hide-comment-options))))] + + [:* + [:div {:class (stl/css :floating-thread-header-left)} + (tr "labels.comment") " " [:span {:class (stl/css :grayed-text)} "#" (:seqn thread)]] + [:div {:class (stl/css :floating-thread-header-right)} + (when (some? thread) + [:div {:class (stl/css :checkbox-wrapper) + :title (tr "labels.comment.mark-as-solved") + :on-click toggle-resolved} + [:span {:class (stl/css-case :checkbox true + :global/checked (:is-resolved thread))} i/tick]]) + (when (= (:id profile) (:id owner)) + [:> icon-button* {:variant "ghost" + :aria-label (tr "labels.options") + :on-click on-toggle-options + :icon "menu"}])] + [:& dropdown {:show (= options uuid/zero) + :on-close on-hide-options} + [:ul {:class (stl/css :dropdown-menu)} + [:li {:class (stl/css :dropdown-menu-option) + :on-click on-delete-thread} + (tr "labels.delete-comment-thread")]]]])) + +(mf/defc comment-floating-thread-item* + {::mf/props :obj + ::mf/private true} + [{:keys [comment thread profiles]}] (let [owner (get profiles (:owner-id comment)) profile (mf/deref refs/profile) options (mf/deref comments-local-options) @@ -264,7 +860,7 @@ (mf/deps options) (fn [event] (dom/stop-propagation event) - (st/emit! (dcm/toggle-comment-options comment)))) + (st/emit! (dcm/toggle-comment-options (:id comment))))) on-hide-options (mf/use-fn @@ -285,24 +881,6 @@ (mf/deps comment) #(st/emit! (dcm/delete-comment comment))) - delete-thread - (mf/use-fn - (mf/deps thread) - #(st/emit! (dcm/close-thread) - (if (= origin :viewer) - (dcm/delete-comment-thread-on-viewer thread) - (dcm/delete-comment-thread-on-workspace thread)))) - - on-delete-thread - (mf/use-fn - (mf/deps thread) - #(st/emit! (modal/show - {:type :confirm - :title (tr "modals.delete-comment-thread.title") - :message (tr "modals.delete-comment-thread.message") - :accept-label (tr "modals.delete-comment-thread.accept") - :on-accept delete-thread}))) - on-submit (mf/use-fn (mf/deps comment thread) @@ -311,29 +889,15 @@ (st/emit! (dcm/update-comment (assoc comment :content content))))) on-cancel - (mf/use-fn #(reset! edition? false)) + (mf/use-fn #(reset! edition? false))] - toggle-resolved - (mf/use-fn - (mf/deps thread) - (fn [event] - (dom/stop-propagation event) - (st/emit! (dcm/update-comment-thread (update thread :is-resolved not)))))] - - [:div {:class (stl/css :comment-container)} - [:div {:class (stl/css :comment)} + [:div {:class (stl/css :floating-thread-item-wrapper)} + [:div {:class (stl/css :floating-thread-item)} [:div {:class (stl/css :author)} - [:div {:class (stl/css :avatar)} - [:img {:src (cfg/resolve-profile-photo-url owner)}]] - [:div {:class (stl/css :name)} - [:div {:class (stl/css :fullname)} (:fullname owner)] - [:div {:class (stl/css :timeago)} (dt/timeago (:modified-at comment))]] - - (when (some? thread) - [:div {:class (stl/css :options-resolve-wrapper) - :on-click toggle-resolved} - [:span {:class (stl/css-case :options-resolve true - :global/checked (:is-resolved thread))} i/tick]]) + [:> comment-avatar* {:image (cfg/resolve-profile-photo-url owner)}] + [:div {:class (stl/css :author-identity)} + [:div {:class (stl/css :author-fullname)} (:fullname owner)] + [:div {:class (stl/css :author-timeago)} (dt/timeago (:modified-at comment))]] (when (= (:id profile) (:id owner)) [:> icon-button* {:variant "ghost" @@ -341,24 +905,22 @@ :on-click on-toggle-options :icon "menu"}])] - [:div {:class (stl/css :content)} + [:div {:class (stl/css :item)} (if @edition? - [:& edit-form {:content (:content comment) - :on-submit on-submit - :on-cancel on-cancel}] - [:span {:class (stl/css :text)} (:content comment)])]] + [:> comment-edit-form* {:content (:content comment) + :on-submit on-submit + :on-cancel on-cancel}] + [:span {:class (stl/css :text)} + [:> comment-content {:content (:content comment)}]])]] [:& dropdown {:show (= options (:id comment)) :on-close on-hide-options} - [:ul {:class (stl/css :comment-options-dropdown)} - [:li {:class (stl/css :context-menu-option) + [:ul {:class (stl/css :dropdown-menu)} + [:li {:class (stl/css :dropdown-menu-option) :on-click on-edit-clicked} (tr "labels.edit")] - (if thread - [:li {:class (stl/css :context-menu-option) - :on-click on-delete-thread} - (tr "labels.delete-comment-thread")] - [:li {:class (stl/css :context-menu-option) + (when-not thread + [:li {:class (stl/css :dropdown-menu-option) :on-click on-delete-comment} (tr "labels.delete-comment")])]]])) @@ -370,48 +932,56 @@ (let [viewport (or viewport {:offset-x 0 :offset-y 0 :width 0 :height 0}) base-x (+ (* (:x position) zoom) (:offset-x viewport)) base-y (+ (* (:y position) zoom) (:offset-y viewport)) + + x (:x position) + y (:y position) + w (:width viewport) h (:height viewport) + comment-width 284 ;; TODO: this is the width set via CSS in an outer container… ;; We should probably do this in a different way. + orientation-left? (>= (+ base-x comment-width (:x bubble-margin)) w) - orientation-top? (>= base-y (/ h 2)) + orientation-top? (>= base-y (/ h 2)) + h-dir (if orientation-left? :left :right) - v-dir (if orientation-top? :top :bottom) - x (:x position) - y (:y position)] + v-dir (if orientation-top? :top :bottom)] {:x x :y y :h-dir h-dir :v-dir v-dir})) -(mf/defc thread-comments - {::mf/wrap [mf/memo]} +(mf/defc comment-floating-thread* + {::mf/props :obj + ::mf/wrap [mf/memo]} [{:keys [thread zoom profiles origin position-modifier viewport]}] - (let [ref (mf/use-ref) - thread-id (:id thread) - thread-pos (:position thread) + (let [ref (mf/use-ref) + mentions-str (mf/use-memo #(rx/subject)) + thread-id (:id thread) + thread-pos (:position thread) - base-pos (cond-> thread-pos - (some? position-modifier) - (gpt/transform position-modifier)) + base-pos (cond-> thread-pos + (some? position-modifier) + (gpt/transform position-modifier)) - max-height (when (some? viewport) (int (* (:height viewport) 0.75))) - ;; We should probably look for a better way of doing this. - bubble-margin {:x 24 :y 0} - pos (offset-position base-pos viewport zoom bubble-margin) + max-height (when (some? viewport) (int (* (obj/get viewport "height") 0.75))) - margin-x (* (:x bubble-margin) (if (= (:h-dir pos) :left) -1 1)) - margin-y (* (:y bubble-margin) (if (= (:v-dir pos) :top) -1 1)) - pos-x (+ (* (:x pos) zoom) margin-x) - pos-y (- (* (:y pos) zoom) margin-y) + ;; We should probably look for a better way of doing this. + bubble-margin {:x 24 :y 24} + pos (offset-position base-pos viewport zoom bubble-margin) - comments-ref (mf/with-memo [thread-id] - (make-comments-ref thread-id)) - comments-map (mf/deref comments-ref) + margin-x (* (:x bubble-margin) (if (= (:h-dir pos) :left) -1 1)) + margin-y (* (:y bubble-margin) (if (= (:v-dir pos) :top) -1 1)) + pos-x (+ (* (:x pos) zoom) margin-x) + pos-y (- (* (:y pos) zoom) margin-y) - comments (mf/with-memo [comments-map] - (->> (vals comments-map) - (sort-by :created-at))) + comments-ref (mf/with-memo [thread-id] + (make-comments-ref thread-id)) + comments-map (mf/deref comments-ref) - comment (first comments)] + comments (mf/with-memo [comments-map] + (->> (vals comments-map) + (sort-by :created-at))) + + first-comment (first comments)] (mf/with-effect [thread-id] (st/emit! (dcm/retrieve-comments thread-id))) @@ -423,158 +993,172 @@ (when-let [node (mf/ref-val ref)] (dom/scroll-into-view-if-needed! node))) - (when (some? comment) - [:div {:class (stl/css-case :thread-content true - :thread-content-left (= (:h-dir pos) :left) - :thread-content-top (= (:v-dir pos) :top)) - :id (str "thread-" thread-id) - :style {:left (str pos-x "px") - :top (str pos-y "px") - :max-height max-height} - :on-click dom/stop-propagation} + [:& (mf/provider mentions-context) {:value mentions-str} + (when (some? first-comment) + [:div {:class (stl/css-case :floating-thread-wrapper true + :left (= (:h-dir pos) :left) + :top (= (:v-dir pos) :top)) + :id (str "thread-" thread-id) + :style {:left (str pos-x "px") + :top (str pos-y "px") + :max-height max-height} + :on-click dom/stop-propagation} - [:div {:class (stl/css :comments)} - [:& comment-item {:comment comment - :profiles profiles - :thread thread - :origin origin}] - (for [item (rest comments)] - [:* {:key (dm/str (:id item))} - [:& comment-item {:comment item - :profiles profiles - :origin origin}]])] - [:& reply-form {:thread thread}] - [:div {:ref ref}]]))) + [:div {:class (stl/css :floating-thread-header)} + [:> comment-floating-thread-header* {:profiles profiles + :thread thread + :origin origin}]] -(defn use-buble - [zoom {:keys [position frame-id]}] - (let [dragging-ref (mf/use-ref false) + [:div {:class (stl/css :floating-thread-main)} + [:> comment-floating-thread-item* {:comment first-comment + :profiles profiles + :thread thread}] + (for [item (rest comments)] + [:* {:key (dm/str (:id item))} + [:> comment-floating-thread-item* {:comment item + :profiles profiles}]])] + + [:> comment-reply-form* {:thread thread}] + + [:& mentions-panel {:profiles profiles}]])])) + +(mf/defc comment-floating-bubble* + {::mf/props :obj + ::mf/wrap [mf/memo]} + [{:keys [thread profiles zoom is-open on-click origin position-modifier]}] + (let [owner (get profiles (:owner-id thread)) + + base-pos (cond-> (:position thread) + (some? position-modifier) + (gpt/transform position-modifier)) + + drag? (mf/use-ref nil) + was-open? (mf/use-ref nil) + + dragging-ref (mf/use-ref false) start-ref (mf/use-ref nil) - state (mf/use-state {:hover false + position (:position thread) + frame-id (:frame-id thread) + + state (mf/use-state {:hover? false + :grabbing? false :new-position-x nil :new-position-y nil :new-frame-id frame-id}) + pos-x (floor (* (or (:new-position-x @state) (:x base-pos)) zoom)) + pos-y (floor (* (or (:new-position-y @state) (:y base-pos)) zoom)) + on-pointer-down (mf/use-fn + (mf/deps origin was-open? is-open drag?) (fn [event] - (dom/capture-pointer event) - (mf/set-ref-val! dragging-ref true) - (mf/set-ref-val! start-ref (dom/get-client-position event)))) + (when (not= origin :viewer) + (swap! state assoc :grabbing? true) + (mf/set-ref-val! was-open? is-open) + (when is-open (st/emit! (dcm/close-thread))) + (mf/set-ref-val! drag? false) + (dom/stop-propagation event) + (dom/capture-pointer event) + (mf/set-ref-val! dragging-ref true) + (mf/set-ref-val! start-ref (dom/get-client-position event))))) on-pointer-up (mf/use-fn - (mf/deps (select-keys @state [:new-position-x :new-position-y :new-frame-id])) - (fn [_ thread] - (when (and - (some? (:new-position-x @state)) - (some? (:new-position-y @state))) - (st/emit! (dwcm/update-comment-thread-position thread [(:new-position-x @state) (:new-position-y @state)]))))) - - on-lost-pointer-capture - (mf/use-fn + (mf/deps origin thread (select-keys @state [:new-position-x :new-position-y :new-frame-id])) (fn [event] - (dom/release-pointer event) - (mf/set-ref-val! dragging-ref false) - (mf/set-ref-val! start-ref nil) - (swap! state assoc :new-position-x nil) - (swap! state assoc :new-position-y nil))) + (when (not= origin :viewer) + (swap! state assoc :grabbing? false) + (dom/stop-propagation event) + (dom/release-pointer event) + (mf/set-ref-val! dragging-ref false) + (mf/set-ref-val! start-ref nil) + (when (and + (some? (:new-position-x @state)) + (some? (:new-position-y @state))) + (st/emit! (dwcm/update-comment-thread-position thread [(:new-position-x @state) + (:new-position-y @state)])) + (swap! state assoc + :new-position-x nil + :new-position-y nil))))) on-pointer-move (mf/use-fn - (mf/deps position zoom) - (fn [event] - (when-let [_ (mf/ref-val dragging-ref)] - (let [start-pt (mf/ref-val start-ref) - current-pt (dom/get-client-position event) - delta-x (/ (- (:x current-pt) (:x start-pt)) zoom) - delta-y (/ (- (:y current-pt) (:y start-pt)) zoom)] - (swap! state assoc - :new-position-x (+ (:x position) delta-x) - :new-position-y (+ (:y position) delta-y))))))] - - {:on-pointer-down on-pointer-down - :on-pointer-up on-pointer-up - :on-pointer-move on-pointer-move - :on-lost-pointer-capture on-lost-pointer-capture - :state state})) - -(mf/defc thread-bubble - {::mf/wrap [mf/memo]} - [{:keys [thread zoom open? on-click origin position-modifier]}] - (let [pos (cond-> (:position thread) - (some? position-modifier) - (gpt/transform position-modifier)) - - drag? (mf/use-ref nil) - was-open? (mf/use-ref nil) - - {:keys [on-pointer-down - on-pointer-up - on-pointer-move - state - on-lost-pointer-capture]} (use-buble zoom thread) - - pos-x (* (or (:new-position-x @state) (:x pos)) zoom) - pos-y (* (or (:new-position-y @state) (:y pos)) zoom) - - on-pointer-down* - (mf/use-fn - (mf/deps origin was-open? open? drag? on-pointer-down) - (fn [event] - (when (not= origin :viewer) - (mf/set-ref-val! was-open? open?) - (when open? (st/emit! (dcm/close-thread))) - (mf/set-ref-val! drag? false) - (dom/stop-propagation event) - (on-pointer-down event)))) - - on-pointer-up* - (mf/use-fn - (mf/deps origin thread was-open? drag? on-pointer-up) - (fn [event] - (when (not= origin :viewer) - (dom/stop-propagation event) - (on-pointer-up event thread) - - (when (or (and (mf/ref-val was-open?) (mf/ref-val drag?)) - (and (not (mf/ref-val was-open?)) (not (mf/ref-val drag?)))) - (st/emit! (dcm/open-thread thread)))))) - - on-pointer-move* - (mf/use-fn - (mf/deps origin drag? on-pointer-move) + (mf/deps origin drag? position zoom) (fn [event] (when (not= origin :viewer) (mf/set-ref-val! drag? true) (dom/stop-propagation event) - (on-pointer-move event)))) + (when-let [_ (mf/ref-val dragging-ref)] + (let [start-pt (mf/ref-val start-ref) + current-pt (dom/get-client-position event) + delta-x (/ (- (:x current-pt) (:x start-pt)) zoom) + delta-y (/ (- (:y current-pt) (:y start-pt)) zoom)] + (swap! state assoc + :new-position-x (+ (:x position) delta-x) + :new-position-y (+ (:y position) delta-y))))))) + + on-pointer-enter + (mf/use-fn + (mf/deps is-open) + (fn [event] + (dom/stop-propagation event) + (when (false? is-open) + (swap! state assoc :hover? true)))) + + on-pointer-leave + (mf/use-fn + (fn [event] + (dom/stop-propagation event) + (swap! state assoc :hover? false))) on-click* (mf/use-fn - (mf/deps origin thread on-click) + (mf/deps origin thread on-click was-open? drag? (select-keys @state [:hover?])) (fn [event] (dom/stop-propagation event) + (when (or (and (mf/ref-val was-open?) (mf/ref-val drag?)) + (and (not (mf/ref-val was-open?)) (not (mf/ref-val drag?)))) + (swap! state assoc :hover? false) + (st/emit! (dcm/open-thread thread))) (when (= origin :viewer) (on-click thread))))] + [:div {:style {:top (str pos-y "px") :left (str pos-x "px")} - :on-pointer-down on-pointer-down* - :on-pointer-up on-pointer-up* - :on-pointer-move on-pointer-move* + :on-pointer-down on-pointer-down + :on-pointer-up on-pointer-up + :on-pointer-move on-pointer-move + :on-pointer-enter on-pointer-enter + :on-pointer-leave on-pointer-leave :on-click on-click* - :on-lost-pointer-capture on-lost-pointer-capture - :data-testid "floating-thread-bubble" - :class (stl/css-case - :floating-thread-bubble true - :resolved (:is-resolved thread) - :unread (pos? (:count-unread-comments thread)))} - [:span (:seqn thread)]])) + :class (stl/css-case :floating-preview-wrapper true + :floating-preview-bubble (false? (:hover? @state)) + :grabbing (true? (:grabbing? @state)))} -(mf/defc comment-thread + (if (:hover? @state) + [:div {:class (stl/css :floating-thread-wrapper :floating-preview-displacement)} + [:div {:class (stl/css :floating-thread-item-wrapper)} + [:div {:class (stl/css :floating-thread-item)} + [:> comment-info* {:item thread + :profile owner}]]]] + + [:> comment-avatar* {:image (cfg/resolve-profile-photo-url owner) + :class (stl/css :avatar-lg) + :data-testid (str "floating-thread-bubble-" (:seqn thread)) + :variant (cond (:is-resolved thread) "solved" + (pos? (:count-unread-comments thread)) "unread" + :else "read")}])])) + +(mf/defc comment-sidebar-thread-item* + {::mf/props :obj + ::mf/private true} [{:keys [item profiles on-click]}] (let [owner (get profiles (:owner-id item)) + + frame (mf/deref (refs/workspace-page-object-by-id (:page-id item) (:frame-id item))) + on-click* (mf/use-fn (mf/deps item) @@ -584,52 +1168,64 @@ (when (fn? on-click) (on-click item))))] - [:div {:class (stl/css :comment) + [:div {:class (stl/css :cover) :on-click on-click*} - [:div {:class (stl/css :author)} - [:div {:class (stl/css-case :thread-bubble true - :resolved (:is-resolved item) - :unread (pos? (:count-unread-comments item)))} - (:seqn item)] - [:div {:class (stl/css :avatar)} - [:img {:src (cfg/resolve-profile-photo-url owner)}]] - [:div {:class (stl/css :name)} - [:div {:class (stl/css :fullname)} (:fullname owner)] - [:div {:class (stl/css :timeago)} (dt/timeago (:modified-at item))]]] - [:div {:class (stl/css :content)} - (:content item)] - [:div {:class (stl/css :replies)} - (let [unread (:count-unread-comments item ::none) - total (:count-comments item 1)] - [:* - (when (> total 1) - (if (= total 2) - [:span {:class (stl/css :total-replies)} "1 reply"] - [:span {:class (stl/css :total-replies)} (str (dec total) " replies")])) + [:div {:class (stl/css :location)} + [:div {:class (stl/css :location-text)} + (str "#" (:seqn item)) + (str " - " (:page-name item)) + (when (and (some? frame) (not (cfh/root? frame))) + (str " - " (:name frame)))]] - (when (and (> total 1) (> unread 0)) - (if (= unread 1) - [:span {:class (stl/css :new-replies)} "1 new reply"] - [:span {:class (stl/css :new-replies)} (str unread " new replies")]))])]])) + [:> comment-info* {:item item + :profile owner}]])) -(mf/defc comment-thread-group +(mf/defc comment-sidebar-thread-group* + {::mf/props :obj} [{:keys [group profiles on-thread-click]}] - [:div {:class (stl/css :thread-group)} - (if (:file-name group) - [:div {:class (stl/css :section-title) - :title (str (:file-name group) ", " (:page-name group))} - [:span {:class (stl/css :file-name)} (:file-name group) ", "] - [:span {:class (stl/css :page-name)} (:page-name group)]] + [:div + (for [item (:items group)] + [:> comment-sidebar-thread-item* + {:item item + :on-click on-thread-click + :profiles profiles + :key (:id item)}])]) - [:div {:class (stl/css :section-title) - :title (:page-name group)} - [:span {:class (stl/css :icon)} i/document] - [:span {:class (stl/css :page-name)} (:page-name group)]]) +(mf/defc comment-dashboard-thread-item* + {::mf/props :obj + ::mf/private true} + [{:keys [item profiles on-click]}] + (let [owner (get profiles (:owner-id item)) - [:div {:class (stl/css :threads)} - (for [item (:items group)] - [:& comment-thread - {:item item - :on-click on-thread-click - :profiles profiles - :key (:id item)}])]]) + on-click* + (mf/use-fn + (mf/deps item) + (fn [event] + (dom/stop-propagation event) + (dom/prevent-default event) + (when (fn? on-click) + (on-click item))))] + + [:div {:class (stl/css :cover) + :on-click on-click*} + [:div {:class (stl/css :location)} + [:> icon* {:icon-id "comments" + :class (stl/css :location-icon)}] + [:div {:class (stl/css :location-text)} + (str "#" (:seqn item)) + (str " " (:file-name item)) + (str ", " (:page-name item))]] + + [:> comment-info* {:item item + :profile owner}]])) + +(mf/defc comment-dashboard-thread-group* + {::mf/props :obj} + [{:keys [group profiles on-thread-click]}] + [:div + (for [item (:items group)] + [:> comment-dashboard-thread-item* + {:item item + :on-click on-thread-click + :profiles profiles + :key (:id item)}])]) diff --git a/frontend/src/app/main/ui/comments.scss b/frontend/src/app/main/ui/comments.scss index d90a158ddd..f02df3bd16 100644 --- a/frontend/src/app/main/ui/comments.scss +++ b/frontend/src/app/main/ui/comments.scss @@ -6,103 +6,98 @@ @import "refactor/common-refactor.scss"; -// Comment-thread-group -.thread-group { - padding: 0 $s-12; - cursor: pointer; - border-radius: $br-8; - padding: $s-8 $s-16; - - &:hover { - background: var(--comment-thread-background-color-hover); - } -} - -.section-title { - display: grid; - grid-template-columns: auto auto; - @include bodySmallTypography; - height: $s-32; - display: flex; - align-items: center; - margin-bottom: $s-8; -} - -.file-name { - @include textEllipsis; +.grayed-text { color: var(--comment-subtitle-color); } -.page-name { - @include textEllipsis; +.location { color: var(--comment-subtitle-color); -} - -.icon { display: flex; align-items: center; - padding: 0 $s-6 0 $s-4; - width: $s-24; - height: $s-32; - margin-left: $s-6; - svg { - @extend .button-icon-small; - stroke: var(--icon-foreground); - } -} - -.threads { - display: flex; - flex-direction: column; - gap: $s-24; -} - -// Comment-thread -.comment { - @include bodySmallTypography; - display: flex; - flex-direction: column; - gap: $s-12; -} - -.author { - display: flex; gap: $s-8; } -.thread-bubble { - @extend .comment-bubbles; - &.resolved { - @extend .resolved-comment-bubble; - } - &.unread { - @extend .unread-comment-bubble; - } +.location-icon { + display: flex; +} + +.location-text { + @include textEllipsis; +} + +.author { + @include bodySmallTypography; + display: flex; + align-items: center; + gap: $s-8; +} + +.author-identity { + flex-grow: 1; +} + +.author-fullname { + @include textEllipsis; + color: var(--comment-title-color); +} + +.author-timeago { + @include textEllipsis; + color: var(--comment-subtitle-color); } .avatar { + position: relative; + height: $s-24; + width: $s-24; + border-radius: $br-circle; +} + +.avatar-lg { height: $s-32; width: $s-32; +} + +.avatar-read { + border: $s-2 solid var(--color-background-tertiary); +} + +.avatar-unread { + border: $s-2 solid var(--color-accent-primary); +} + +.avatar-solved { + border: $s-2 solid var(--color-background-tertiary); +} + +.avatar-image { border-radius: $br-circle; - img { - border-radius: $br-circle; - } } -.name { - flex-grow: 1; - .fullname { - @include textEllipsis; - color: var(--comment-title-color); - } - .timeago { - @include textEllipsis; - color: var(--comment-subtitle-color); - } +.avatar-mask { + border-radius: $br-circle; + position: absolute; + height: 100%; + width: 100%; + left: 0; + top: 0; } -.content { - position: relative; +.avatar-darken { + background: rgba(0, 0, 0, 0.5); +} + +.cover { + @include bodySmallTypography; + cursor: pointer; + display: flex; + flex-direction: column; + gap: $s-8; + padding: $s-20; + border-bottom: $s-1 solid var(--color-background-quaternary); +} + +.item { @include bodySmallTypography; color: var(--color-foreground-primary); word-wrap: break-word; @@ -112,119 +107,128 @@ } .replies { + @include bodySmallTypography; display: flex; gap: $s-8; } -.total-replies { +.replies-total { color: var(--color-foreground-secondary); } -.new-replies { +.replies-unread { color: var(--color-accent-primary); } -// Thread-bubble -.floating-thread-bubble { - @extend .comment-bubbles; +.floating-preview-wrapper { + z-index: $z-index-1; position: absolute; + user-select: none; cursor: pointer; pointer-events: auto; transform: translate(calc(-1 * $s-16), calc(-1 * $s-16)); - - &.resolved { - @extend .resolved-comment-bubble; - } - &.unread { - @extend .unread-comment-bubble; - } } -// thread-content -.thread-content { - position: absolute; - overflow-y: auto; - width: $s-284; - padding: $s-12; - padding-inline-end: $s-8; +.floating-preview-bubble { + z-index: initial; +} +.floating-preview-displacement { + margin-left: calc(-1 * ($s-12 + $s-2)); + margin-top: calc(-1 * ($s-8 + $s-2)); +} + +.grabbing { + cursor: grabbing; +} + +.floating-thread-wrapper { + position: absolute; + display: flex; + flex-direction: column; + gap: $s-12; + width: $s-284; + padding: $s-8 $s-12 $s-8 $s-12; pointer-events: auto; - user-select: text; border-radius: $br-8; border: $s-2 solid var(--modal-border-color); background-color: var(--comment-modal-background-color); --translate-x: 0%; --translate-y: 0%; transform: translate(var(--translate-x), var(--translate-y)); - .comments { - display: flex; - flex-direction: column; - gap: $s-24; + &.left { + --translate-x: -100%; + } + &.top { + --translate-y: -100%; } } -.thread-content-left { - --translate-x: -100%; -} -.thread-content-top { - --translate-y: -100%; -} - -// comment-item - -.comment-container { +.floating-thread-header { position: relative; - .comment { - @include bodySmallTypography; - .author { - display: flex; - gap: $s-8; - .avatar { - height: $s-32; - width: $s-32; - border-radius: $br-circle; - img { - border-radius: $br-circle; - } - } - .name { - flex-grow: 1; - .fullname { - @include textEllipsis; - color: var(--comment-title-color); - } - .timeago { - @include textEllipsis; - color: var(--comment-subtitle-color); - } - } - .options-resolve-wrapper { - @include flexCenter; - width: $s-16; - height: $s-32; - .options-resolve { - @extend .checkbox-icon; - cursor: pointer; - } - } - } - } - .comment-options-dropdown { - @extend .dropdown-wrapper; - position: absolute; - width: fit-content; - max-width: $s-200; - right: 0; - left: unset; - .context-menu-option { - @extend .dropdown-element-base; - } - } + display: flex; + justify-content: space-between; + align-items: center; + height: $s-32; } -// edit-form & reply-form +.floating-thread-header-left { + @include bodySmallTypography; + color: var(--color-foreground-primary); +} -.edit-form, -.reply-form { +.floating-thread-header-right { + display: flex; + align-items: center; +} + +.floating-thread-main { + display: flex; + flex-direction: column; + gap: $s-16; + overflow-y: auto; + padding-bottom: $s-16; +} + +.floating-thread-item-wrapper { + position: relative; +} + +.floating-thread-item { + display: flex; + flex-direction: column; + gap: $s-8; + @include bodySmallTypography; +} + +.checkbox-wrapper { + @include flexCenter; + width: $s-16; + height: $s-24; + margin-right: $s-8; +} + +.checkbox { + @extend .checkbox-icon; +} + +.dropdown-menu { + @extend .dropdown-wrapper; + position: absolute; + width: fit-content; + max-width: $s-200; + right: $s-32; + top: 0; + left: unset; +} + +.dropdown-menu-option { + @extend .dropdown-element-base; +} + +.form { + display: flex; + flex-direction: column; + gap: $s-8; textarea { @extend .input-element; @include bodySmallTypography; @@ -232,8 +236,8 @@ height: 100%; width: 100%; max-width: $s-260; - margin-bottom: $s-8; padding: $s-8; + margin-top: $s-4; color: var(--input-foreground-color-active); resize: vertical; &:focus { @@ -241,21 +245,119 @@ outline: none; } } - .buttons-wrapper { - display: flex; - justify-content: flex-end; - gap: $s-4; - .post-btn { - @extend .button-primary; - height: $s-32; - width: $s-92; - margin-bottom: 0; - } - .cancel-btn { - @extend .button-secondary; - height: $s-32; - width: $s-92; - margin-bottom: 0; - } +} + +.form-buttons-wrapper { + display: grid; + grid-template-columns: 1fr auto auto; + justify-content: flex-end; + gap: $s-8; +} + +.open-mentions-button { + cursor: pointer; + stroke: none; + fill: var(--color-foreground-secondary); + + &.is-toggled { + fill: var(--color-accent-primary); } } + +.comments-mentions-choice { + background: var(--color-background-tertiary); + border-radius: $s-8; + border: none; + display: flex; + flex-direction: column; + left: calc(-1 * $s-2); + margin-top: $s-8; + overflow: hidden; + padding: $s-2; + position: absolute; + top: 100%; + width: calc(100% + $s-4); +} + +.comments-mentions-entry { + cursor: pointer; + display: grid; + grid-template-areas: + "avatar name" + "avatar email"; + grid-template-columns: $s-32 1fr; + column-gap: $s-8; + margin: $s-4 $s-8; + padding: 0 $s-4; + border-radius: $br-8; + border: $s-1 solid transparent; + + &:hover { + background: var(--color-background-quaternary); + } + + .comments-mentions-avatar { + grid-area: avatar; + border-radius: 50%; + } + + .comments-mentions-name { + grid-area: name; + font-size: $fs-12; + color: var(--color-foreground-primary); + } + + .comments-mentions-email { + grid-area: email; + font-size: $fs-12; + color: var(--color-foreground-secondary); + } + + &.is-selected { + border: 1px solid var(--color-accent-primary-muted); + background: var(--color-background-quaternary); + } +} + +.comment-input { + @include bodySmallTypography; + white-space: pre; + background: var(--input-background-color); + border-radius: $br-8; + border: $s-1 solid var(--input-border-color); + color: var(--input-foreground-color); + height: $s-36; + margin-bottom: $s-8; + max-width: $s-260; + overflow-y: auto; + padding: $s-8; + resize: vertical; + width: 100%; + + &:focus { + border: $s-1 solid var(--input-border-color-active); + outline: none; + } + + [data-type="mention"] { + color: var(--color-accent-primary); + } + + [data-type="text"] { + color: var(--color-foreground-primary); + } + + &::before { + content: var(--placeholder); + } +} + +.comment-mention { + color: var(--color-accent-primary); +} + +.comments-mentions-empty { + font-size: $fs-12; + color: var(--color-foreground-secondary); + padding: $s-6 $s-8; +} diff --git a/frontend/src/app/main/ui/components/context_menu_a11y.cljs b/frontend/src/app/main/ui/components/context_menu_a11y.cljs index 04475e7c24..a3f199ebb4 100644 --- a/frontend/src/app/main/ui/components/context_menu_a11y.cljs +++ b/frontend/src/app/main/ui/components/context_menu_a11y.cljs @@ -11,7 +11,7 @@ [app.common.data.macros :as dm] [app.common.schema :as sm] [app.main.refs :as refs] - [app.main.ui.components.dropdown :refer [dropdown']] + [app.main.ui.components.dropdown :refer [dropdown-content*]] [app.main.ui.icons :as i] [app.util.dom :as dom] [app.util.i18n :as i18n :refer [tr]] @@ -52,8 +52,6 @@ (sm/lazy-validator schema:option)) (mf/defc context-menu* - {::mf/props :obj} - [{:keys [show on-close options selectable selected top left fixed min-width origin width] :as props}] @@ -90,7 +88,7 @@ (on-close))) props - (mf/spread props :on-close on-local-close) + (mf/spread-props props {:on-close on-local-close}) ids (mf/with-memo [levels] @@ -221,7 +219,7 @@ #(dom/focus! (dom/get-element (first ids))))) (when (and show (some? levels)) - [:> dropdown' props + [:> dropdown-content* props (let [level (peek levels) options (:options level) parent (:parent level)] diff --git a/frontend/src/app/main/ui/components/dropdown.cljs b/frontend/src/app/main/ui/components/dropdown.cljs index f27662421f..8da3f0b036 100644 --- a/frontend/src/app/main/ui/components/dropdown.cljs +++ b/frontend/src/app/main/ui/components/dropdown.cljs @@ -12,17 +12,13 @@ [app.util.keyboard :as kbd] [app.util.timers :as tm] [goog.events :as events] - [goog.object :as gobj] [rumext.v2 :as mf]) (:import goog.events.EventType)) -(mf/defc dropdown' - {::mf/wrap-props false} - [props] - (let [children (gobj/get props "children") - on-close (gobj/get props "on-close") - container-ref (gobj/get props "container") - listening-ref (mf/use-ref nil) +(mf/defc dropdown-content* + [{:keys [children on-close container]}] + (let [listening-ref (mf/use-ref nil) + container-ref container on-click (fn [event] @@ -57,10 +53,13 @@ children)) (mf/defc dropdown - {::mf/wrap-props false} - [props] - (assert (fn? (gobj/get props "on-close")) "missing `on-close` prop") - (assert (boolean? (gobj/get props "show")) "missing `show` prop") + {::mf/props :obj} + [{:keys [on-close show children container]}] + (assert (fn? on-close) "missing `on-close` prop") + (assert (boolean? show) "missing `show` prop") - (when (gobj/get props "show") - (mf/element dropdown' props))) + (when ^boolean show + [:> dropdown-content* + {:on-close on-close + :container container + :children children}])) diff --git a/frontend/src/app/main/ui/components/radio_buttons.cljs b/frontend/src/app/main/ui/components/radio_buttons.cljs index 17a3fe5942..c51aa6ab47 100644 --- a/frontend/src/app/main/ui/components/radio_buttons.cljs +++ b/frontend/src/app/main/ui/components/radio_buttons.cljs @@ -87,10 +87,16 @@ (dom/blur! input)))) context-value - (mf/spread props - :on-change on-change' - :encode-fn encode-fn - :decode-fn decode-fn)] + (mf/spread-object props + ;; We pass a special metadata for disable + ;; key casing transformation in this + ;; concrete case, because this component + ;; uses legacy mode and props are in + ;; kebab-case style + ^{::mf/transform false} + {:on-change on-change' + :encode-fn encode-fn + :decode-fn decode-fn})] [:& (mf/provider context) {:value context-value} [:div {:class (dm/str class " " (stl/css :radio-btn-wrapper)) diff --git a/frontend/src/app/main/ui/components/reorder_handler.cljs b/frontend/src/app/main/ui/components/reorder_handler.cljs index 8f4acfe320..a8df960209 100644 --- a/frontend/src/app/main/ui/components/reorder_handler.cljs +++ b/frontend/src/app/main/ui/components/reorder_handler.cljs @@ -16,7 +16,7 @@ [:* [:div {:ref ref :class (stl/css :reorder)} [:> icon* - {:id ic/reorder + {:icon-id ic/reorder :class (stl/css :reorder-icon) :aria-hidden true}]] [:hr {:class (stl/css :reorder-separator-top)}] diff --git a/frontend/src/app/main/ui/dashboard/comments.cljs b/frontend/src/app/main/ui/dashboard/comments.cljs index c2b77134ae..b0700e735d 100644 --- a/frontend/src/app/main/ui/dashboard/comments.cljs +++ b/frontend/src/app/main/ui/dashboard/comments.cljs @@ -14,25 +14,18 @@ [app.main.store :as st] [app.main.ui.comments :as cmt] [app.main.ui.components.dropdown :refer [dropdown]] + [app.main.ui.ds.buttons.icon-button :refer [icon-button*]] [app.main.ui.icons :as i] [app.util.i18n :as i18n :refer [tr]] - [app.util.keyboard :as kbd] [potok.v2.core :as ptk] [rumext.v2 :as mf])) - -(def ^:private close-icon - (i/icon-xref :close (stl/css :close-icon))) - (def ^:private comments-icon-svg (i/icon-xref :comments (stl/css :comments-icon))) - -(def ^:private comments-icon-small - (i/icon-xref :comments (stl/css :comments-icon-small))) - -(mf/defc comments-icon - [{:keys [profile show? on-show-comments]}] +(mf/defc comments-icon* + {::mf/props :obj} + [{:keys [profile on-show-comments]}] (let [threads-map (mf/deref refs/comment-threads) @@ -41,24 +34,18 @@ (sort-by :modified-at) (reverse) (dcm/apply-filters {} profile) - (dcm/group-threads-by-file-and-page)) - - handle-keydown - (mf/use-callback - (mf/deps on-show-comments) - (fn [event] - (when (kbd/enter? event) - (on-show-comments event))))] + (dcm/group-threads-by-file-and-page))] [:div {:class (stl/css :dashboard-comments-section)} - [:button {:tab-index "0" - :on-click on-show-comments - :on-key-down handle-keydown - :data-testid "open-comments" - :class (stl/css-case :comment-button true - :open show? - :unread (boolean (seq tgroups)))} - comments-icon-small]])) + [:> icon-button* {:variant "ghost" + :tab-index "0" + :class (stl/css :comment-button) + :data-testid "open-comments" + :aria-label (tr "dashboard.notifications.view") + :on-click on-show-comments + :icon "comments"} + (when (seq tgroups) + [:div {:class (stl/css :unread)}])]])) (mf/defc comments-section [{:keys [profile team show? on-hide-comments]}] @@ -72,13 +59,6 @@ (dcm/apply-filters {} profile) (dcm/group-threads-by-file-and-page)) - handle-keydown - (mf/use-callback - (mf/deps on-hide-comments) - (fn [event] - (when (kbd/enter? event) - (on-hide-comments event)))) - on-navigate (mf/use-callback (fn [thread] @@ -101,22 +81,22 @@ [:& dropdown {:show show? :on-close on-hide-comments} [:div {:class (stl/css :dropdown :comments-section :comment-threads-section)} [:div {:class (stl/css :header)} - [:h3 {:class (stl/css :header-title)} (tr "labels.comments")] - [:button {:class (stl/css :close-btn) - :tab-index (if show? "0" "-1") - :on-click on-hide-comments - :on-key-down handle-keydown} - close-icon]] + [:h3 {:class (stl/css :header-title)} (tr "dashboard.notifications")] + [:> icon-button* {:variant "ghost" + :tab-index (if show? "0" "-1") + :aria-label (tr "labels.close") + :on-click on-hide-comments + :icon "close"}]] (if (seq tgroups) [:div {:class (stl/css :thread-groups)} - [:& cmt/comment-thread-group + [:> cmt/comment-dashboard-thread-group* {:group (first tgroups) :on-thread-click on-navigate :show-file-name true :profiles profiles}] (for [tgroup (rest tgroups)] - [:& cmt/comment-thread-group + [:> cmt/comment-dashboard-thread-group* {:group tgroup :on-thread-click on-navigate :show-file-name true diff --git a/frontend/src/app/main/ui/dashboard/comments.scss b/frontend/src/app/main/ui/dashboard/comments.scss index af55f6dd17..93070c2f7c 100644 --- a/frontend/src/app/main/ui/dashboard/comments.scss +++ b/frontend/src/app/main/ui/dashboard/comments.scss @@ -44,21 +44,16 @@ } .comment-button { - @include buttonStyle; - @include flexCenter; - border-radius: $br-8; - height: $s-32; - width: $s-32; - --comment-icon-small-foreground-color: var(--icon-foreground); - - &.unread, - &.open { - --comment-icon-small-foreground-color: var(--icon-foreground-selected); - } - - &:hover { - background-color: var(--color-background-quaternary); - --comment-icon-small-foreground-color: var(--icon-foreground-active); + position: relative; + .unread { + position: absolute; + width: $s-8; + height: $s-8; + border: $s-2 solid var(--color-background-tertiary); + border-radius: 50%; + background: red; + top: $s-6; + right: $s-6; } } @@ -100,13 +95,3 @@ flex-grow: 1; text-transform: uppercase; } - -.close-btn { - @include buttonStyle; - @include flexCenter; -} - -.close-icon { - @extend .button-icon; - stroke: var(--icon-foreground); -} diff --git a/frontend/src/app/main/ui/dashboard/fonts.cljs b/frontend/src/app/main/ui/dashboard/fonts.cljs index 7ae210b5ff..c9cb383fd2 100644 --- a/frontend/src/app/main/ui/dashboard/fonts.cljs +++ b/frontend/src/app/main/ui/dashboard/fonts.cljs @@ -11,6 +11,7 @@ [app.common.media :as cm] [app.main.data.fonts :as df] [app.main.data.modal :as modal] + [app.main.data.notifications :as ntf] [app.main.repo :as rp] [app.main.store :as st] [app.main.ui.components.context-menu-a11y :refer [context-menu*]] @@ -109,6 +110,8 @@ (swap! uploading* disj id) (st/emit! (df/add-font font))) (fn [error] + (st/emit! (ntf/error (tr "errors.bad-font" (first (:names item))))) + (swap! fonts* dissoc id) (js/console.log "error" error)))))) on-upload diff --git a/frontend/src/app/main/ui/dashboard/grid.cljs b/frontend/src/app/main/ui/dashboard/grid.cljs index 830d7caad7..2fee696969 100644 --- a/frontend/src/app/main/ui/dashboard/grid.cljs +++ b/frontend/src/app/main/ui/dashboard/grid.cljs @@ -189,7 +189,7 @@ [:& bc/color-bullet {:color {:color (:color color) :id (:id color) :opacity (:opacity color)} - :mini? true}] + :mini true}] [:div {:class (stl/css :name-block)} [:span {:class (stl/css :color-name)} (:name color)] (when-not (= (:name color) default-name) @@ -331,6 +331,15 @@ client-position)] (st/emit! (dd/show-file-menu-with-position file-id position))))) + on-context-menu + (mf/use-fn + (mf/deps is-library-view) + (fn [event] + (dom/stop-propagation event) + (dom/prevent-default event) + (when-not is-library-view + (on-menu-click event)))) + edit (mf/use-fn (mf/deps file) @@ -373,7 +382,7 @@ :on-key-down handle-key-down :on-double-click on-navigate :on-drag-start on-drag-start - :on-context-menu on-menu-click} + :on-context-menu on-context-menu} [:div {:class (stl/css :overlay)}] @@ -392,31 +401,32 @@ [:h3 (:name file)]) [:& grid-item-metadata {:modified-at (:modified-at file)}]] - [:div {:class (stl/css-case :project-th-actions true :force-display (:menu-open dashboard-local))} - [:div - {:class (stl/css :project-th-icon :menu) - :tab-index "0" - :ref menu-ref - :id (str file-id "-action-menu") - :on-click on-menu-click - :on-key-down (fn [event] - (when (kbd/enter? event) - (dom/stop-propagation event) - (on-menu-click event)))} - menu-icon - (when (and selected? file-menu-open?) + (when-not is-library-view + [:div {:class (stl/css-case :project-th-actions true :force-display (:menu-open dashboard-local))} + [:div + {:class (stl/css :project-th-icon :menu) + :tab-index "0" + :ref menu-ref + :id (str file-id "-action-menu") + :on-click on-menu-click + :on-key-down (fn [event] + (when (kbd/enter? event) + (dom/stop-propagation event) + (on-menu-click event)))} + menu-icon + (when (and selected? file-menu-open?) ;; When the menu is open we disable events in the dashboard. We need to force pointer events ;; so the menu can be handled - [:div {:style {:pointer-events "all"}} - [:> file-menu* {:files (vals selected-files) - :left (+ 24 (:x (:menu-pos dashboard-local))) - :top (:y (:menu-pos dashboard-local)) - :can-edit can-edit - :navigate true - :on-edit on-edit - :on-menu-close on-menu-close - :origin origin - :parent-id (dm/str file-id "-action-menu")}]])]]]]])) + [:div {:style {:pointer-events "all"}} + [:> file-menu* {:files (vals selected-files) + :left (+ 24 (:x (:menu-pos dashboard-local))) + :top (:y (:menu-pos dashboard-local)) + :can-edit can-edit + :navigate true + :on-edit on-edit + :on-menu-close on-menu-close + :origin origin + :parent-id (dm/str file-id "-action-menu")}]])]])]]])) (mf/defc grid {::mf/props :obj} diff --git a/frontend/src/app/main/ui/dashboard/sidebar.cljs b/frontend/src/app/main/ui/dashboard/sidebar.cljs index dfb3691d78..a4f3270154 100644 --- a/frontend/src/app/main/ui/dashboard/sidebar.cljs +++ b/frontend/src/app/main/ui/dashboard/sidebar.cljs @@ -23,7 +23,7 @@ [app.main.store :as st] [app.main.ui.components.dropdown-menu :refer [dropdown-menu dropdown-menu-item*]] [app.main.ui.components.link :refer [link]] - [app.main.ui.dashboard.comments :refer [comments-icon comments-section]] + [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.team-form] @@ -1071,9 +1071,8 @@ (tr "labels.logout")]] (when (and team profile) - [:& comments-icon + [:> comments-icon* {:profile profile - :show? show-comments? :on-show-comments handle-show-comments}])]])) (mf/defc sidebar* diff --git a/frontend/src/app/main/ui/dashboard/sidebar.scss b/frontend/src/app/main/ui/dashboard/sidebar.scss index 65afa269d2..95ad98c32d 100644 --- a/frontend/src/app/main/ui/dashboard/sidebar.scss +++ b/frontend/src/app/main/ui/dashboard/sidebar.scss @@ -412,7 +412,7 @@ border: $b-1 solid var(--color-background-quaternary); border-radius: var(--sp-s); padding: var(--sp-m); - margin: var(--sp-m) var(--sp-s) var(--sp-m) var(--sp-m); + margin: var(--sp-m); color: var(--color-foreground-secondary); cursor: pointer; } diff --git a/frontend/src/app/main/ui/dashboard/team.cljs b/frontend/src/app/main/ui/dashboard/team.cljs index ce2b9b7911..3daefc5d74 100644 --- a/frontend/src/app/main/ui/dashboard/team.cljs +++ b/frontend/src/app/main/ui/dashboard/team.cljs @@ -31,7 +31,6 @@ [app.util.i18n :as i18n :refer [tr]] [beicon.v2.core :as rx] [cuerdas.core :as str] - [okulary.core :as l] [rumext.v2 :as mf])) (def ^:private arrow-icon @@ -743,15 +742,12 @@ [:> i18n/tr-html* {:content (tr "labels.no-invitations-hint") :tag-name "span"}])]) -(def ^:private ref:invitations - (l/derived :invitations st/state)) - (mf/defc invitation-section* {::mf/props :obj ::mf/private true} [{:keys [team]}] (let [permissions (get team :permissions) - invitations (mf/deref ref:invitations) + invitations (get team :invitations) team-id (get team :id) @@ -957,7 +953,7 @@ [:span {:title (tr "dashboard.webhooks.cant-edit") :class (stl/css :menu-disabled)} - [:> icon* {:id "menu"}]]))) + [:> icon* {:icon-id "menu"}]]))) (mf/defc webhook-item* {::mf/wrap [mf/memo] @@ -1037,13 +1033,10 @@ :key (dm/str (:id webhook)) :permissions permissions}])]) -(def ^:private ref:webhooks - (l/derived :webhooks st/state)) - (mf/defc webhooks-page* {::mf/props :obj} [{:keys [team]}] - (let [webhooks (mf/deref ref:webhooks)] + (let [webhooks (:webhooks team)] (mf/with-effect [team] (dom/set-html-title diff --git a/frontend/src/app/main/ui/ds/buttons/button.cljs b/frontend/src/app/main/ui/ds/buttons/button.cljs index cfb30409dd..73af4824ee 100644 --- a/frontend/src/app/main/ui/ds/buttons/button.cljs +++ b/frontend/src/app/main/ui/ds/buttons/button.cljs @@ -32,5 +32,5 @@ :button-destructive (= variant "destructive"))) props (mf/spread-props props {:class class})] [:> "button" props - (when icon [:> icon* {:id icon :size "m"}]) + (when icon [:> icon* {:icon-id icon :size "m"}]) [:span {:class (stl/css :label-wrapper)} children]])) \ No newline at end of file diff --git a/frontend/src/app/main/ui/ds/buttons/icon_button.cljs b/frontend/src/app/main/ui/ds/buttons/icon_button.cljs index 0b45ad2382..88bf48bd13 100644 --- a/frontend/src/app/main/ui/ds/buttons/icon_button.cljs +++ b/frontend/src/app/main/ui/ds/buttons/icon_button.cljs @@ -34,4 +34,4 @@ :icon-button-action (= variant "action") :icon-button-destructive (= variant "destructive"))) props (mf/spread-props props {:class class :title aria-label})] - [:> "button" props [:> icon* {:id icon :aria-label aria-label :class icon-class}] children])) + [:> "button" props [:> icon* {:icon-id icon :aria-label aria-label :class icon-class}] children])) diff --git a/frontend/src/app/main/ui/ds/controls/combobox.cljs b/frontend/src/app/main/ui/ds/controls/combobox.cljs index e39efedb1c..5ed27a05eb 100644 --- a/frontend/src/app/main/ui/ds/controls/combobox.cljs +++ b/frontend/src/app/main/ui/ds/controls/combobox.cljs @@ -215,7 +215,7 @@ [:span {:class (stl/css-case :combobox-header true :header-icon (some? icon))} (when icon - [:> icon* {:id icon + [:> icon* {:icon-id icon :size "s" :aria-hidden true}]) [:input {:type "text" @@ -236,7 +236,7 @@ :aria-controls listbox-id :class (stl/css :button-toggle-list) :on-click on-click} - [:> icon* {:id i/arrow + [:> icon* {:icon-id i/arrow :class (stl/css :arrow) :size "s" :aria-hidden true diff --git a/frontend/src/app/main/ui/ds/controls/input.cljs b/frontend/src/app/main/ui/ds/controls/input.cljs index 0df0c0c6da..5637b287fd 100644 --- a/frontend/src/app/main/ui/ds/controls/input.cljs +++ b/frontend/src/app/main/ui/ds/controls/input.cljs @@ -30,11 +30,11 @@ (let [ref (or ref (mf/use-ref)) type (d/nilv type "text") props (mf/spread-props props - :class (stl/css-case - :input true - :input-with-icon (some? icon)) - :ref ref - :type type) + {:class (stl/css-case + :input true + :input-with-icon (some? icon)) + :ref ref + :type type}) on-icon-click (mf/use-fn @@ -46,5 +46,5 @@ [:> :span {:class (dm/str class " " (stl/css :container))} (when (some? icon) - [:> icon* {:id icon :class (stl/css :icon) :on-click on-icon-click}]) + [:> icon* {:icon-id icon :class (stl/css :icon) :on-click on-icon-click}]) [:> :input props]])) diff --git a/frontend/src/app/main/ui/ds/controls/select.cljs b/frontend/src/app/main/ui/ds/controls/select.cljs index 0d2730ebb6..02e291cfa9 100644 --- a/frontend/src/app/main/ui/ds/controls/select.cljs +++ b/frontend/src/app/main/ui/ds/controls/select.cljs @@ -171,12 +171,12 @@ [:span {:class (stl/css-case :select-header true :header-icon (some? icon))} (when icon - [:> icon* {:id icon + [:> icon* {:icon-id icon :size "s" :aria-hidden true}]) [:span {:class (stl/css :header-label)} label]] - [:> icon* {:id i/arrow + [:> icon* {:icon-id i/arrow :class (stl/css :arrow) :size "s" :aria-hidden true}]] diff --git a/frontend/src/app/main/ui/ds/controls/shared/options_dropdown.cljs b/frontend/src/app/main/ui/ds/controls/shared/options_dropdown.cljs index 16ce0240ac..6173366de5 100644 --- a/frontend/src/app/main/ui/ds/controls/shared/options_dropdown.cljs +++ b/frontend/src/app/main/ui/ds/controls/shared/options_dropdown.cljs @@ -31,7 +31,7 @@ (when (some? icon) [:> icon* - {:id icon + {:icon-id icon :size "s" :class (stl/css :option-icon) :aria-hidden (when label true) @@ -40,7 +40,7 @@ [:span {:class (stl/css :option-text)} label] (when selected [:> icon* - {:id i/tick + {:icon-id i/tick :size "s" :class (stl/css :option-check) :aria-hidden (when label true)}])]) diff --git a/frontend/src/app/main/ui/ds/foundations/assets/icon.cljs b/frontend/src/app/main/ui/ds/foundations/assets/icon.cljs index 5609a37491..6bd108a5aa 100644 --- a/frontend/src/app/main/ui/ds/foundations/assets/icon.cljs +++ b/frontend/src/app/main/ui/ds/foundations/assets/icon.cljs @@ -55,6 +55,7 @@ (def ^:icon-id arrow-right "arrow-right") (def ^:icon-id arrow-up "arrow-up") (def ^:icon-id asc-sort "asc-sort") +(def ^:icon-id at "at") (def ^:icon-id board "board") (def ^:icon-id boards-thumbnail "boards-thumbnail") (def ^:icon-id boolean-difference "boolean-difference") @@ -287,17 +288,17 @@ (def ^:private schema:icon [:map [:class {:optional true} [:maybe :string]] - [:id [:and :string [:fn #(contains? icon-list %)]]] + [:icon-id [:and :string [:fn #(contains? icon-list %)]]] [:size {:optional true} [:maybe [:enum "s" "m"]]]]) (mf/defc icon* {::mf/props :obj ::mf/schema schema:icon} - [{:keys [id size class] :rest props}] + [{:keys [icon-id size class] :rest props}] (let [class (dm/str (or class "") " " (stl/css :icon)) props (mf/spread-props props {:class class :width icon-size-m :height icon-size-m}) size-px (cond (= size "s") icon-size-s :else icon-size-m) offset (/ (- icon-size-m size-px) 2)] [:> "svg" props - [:use {:href (dm/str "#icon-" id) :width size-px :height size-px :x offset :y offset}]])) + [:use {:href (dm/str "#icon-" icon-id) :width size-px :height size-px :x offset :y offset}]])) diff --git a/frontend/src/app/main/ui/ds/foundations/assets/icon.mdx b/frontend/src/app/main/ui/ds/foundations/assets/icon.mdx index 140b897a2d..c1184acd51 100644 --- a/frontend/src/app/main/ui/ds/foundations/assets/icon.mdx +++ b/frontend/src/app/main/ui/ds/foundations/assets/icon.mdx @@ -47,7 +47,7 @@ Assuming the namespace is required as `i`: You can now use the icon IDs defined in the namespace: ```clj -[:> i/icon* {:id i/pin}] +[:> i/icon* {:icon-id i/pin}] ``` ### Customizing colors @@ -59,7 +59,7 @@ If you need to override this behavior, you can use a `class` in the `` component and set `color` to whatever value you prefer: ```clj -[:> i/icon* {:id i/add :class (stl/css :toolbar-icon)}] +[:> i/icon* {:icon-id i/add :class (stl/css :toolbar-icon)}] ``` ```scss @@ -74,7 +74,7 @@ By default, icons do not have any accessible text attached to them. You should add an `aria-label` attribute to set a proper text: ```clj -[:> i/icon* {:id i/add :aria-label (tr "foo.bar")}] +[:> i/icon* {:icon-id i/add :aria-label (tr "foo.bar")}] ``` ## Usage guidelines for design diff --git a/frontend/src/app/main/ui/ds/layout/tab_switcher.cljs b/frontend/src/app/main/ui/ds/layout/tab_switcher.cljs index 1228c4c1f0..5871c61d3e 100644 --- a/frontend/src/app/main/ui/ds/layout/tab_switcher.cljs +++ b/frontend/src/app/main/ui/ds/layout/tab_switcher.cljs @@ -38,7 +38,7 @@ [:> :button props (when (some? icon) [:> icon* - {:id icon + {:icon-id icon :aria-hidden (when label true) :aria-label (when (not label) aria-label)}]) (when (string? label) diff --git a/frontend/src/app/main/ui/ds/storybook.cljs b/frontend/src/app/main/ui/ds/storybook.cljs index d503f3a8f1..bec97b7b02 100644 --- a/frontend/src/app/main/ui/ds/storybook.cljs +++ b/frontend/src/app/main/ui/ds/storybook.cljs @@ -1,4 +1,3 @@ - ;; 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/. @@ -16,9 +15,9 @@ {::mf/props :obj} [{:keys [children size style] :rest other}] (let [class (stl/css :story-grid) - size (or size 16) - style (or style {}) - style (mf/spread style :--component-grid-size (dm/str size "px")) + size (or size 16) + style (or style #js {}) + style (mf/spread-props style {"--component-grid-size" (dm/str size "px")}) props (mf/spread-props other {:class class :style style})] [:> "article" props children])) @@ -41,4 +40,4 @@ [{:keys [children] :rest other}] (let [class (stl/css :story-grid-row) props (mf/spread-props other {:class class})] - [:> "article" props children])) \ No newline at end of file + [:> "article" props children])) diff --git a/frontend/src/app/main/ui/routes.cljs b/frontend/src/app/main/ui/routes.cljs index a199056976..5a114cfc6d 100644 --- a/frontend/src/app/main/ui/routes.cljs +++ b/frontend/src/app/main/ui/routes.cljs @@ -33,7 +33,8 @@ ["/password" :settings-password] ["/feedback" :settings-feedback] ["/options" :settings-options] - ["/access-tokens" :settings-access-tokens]] + ["/access-tokens" :settings-access-tokens] + ["/notifications" :settings-notifications]] ["/frame-preview" :frame-preview] diff --git a/frontend/src/app/main/ui/settings.cljs b/frontend/src/app/main/ui/settings.cljs index d5192320d8..e66c3f5ad3 100644 --- a/frontend/src/app/main/ui/settings.cljs +++ b/frontend/src/app/main/ui/settings.cljs @@ -17,6 +17,7 @@ [app.main.ui.settings.change-email] [app.main.ui.settings.delete-account] [app.main.ui.settings.feedback :refer [feedback-page]] + [app.main.ui.settings.notifications :refer [notifications-page]] [app.main.ui.settings.options :refer [options-page]] [app.main.ui.settings.password :refer [password-page]] [app.main.ui.settings.profile :refer [profile-page]] @@ -67,4 +68,7 @@ [:& options-page] :settings-access-tokens - [:& access-tokens-page])]]]])) + [:& access-tokens-page] + + :settings-notifications + [:& notifications-page])]]]])) diff --git a/frontend/src/app/main/ui/settings/notifications.cljs b/frontend/src/app/main/ui/settings/notifications.cljs new file mode 100644 index 0000000000..b402b3af88 --- /dev/null +++ b/frontend/src/app/main/ui/settings/notifications.cljs @@ -0,0 +1,106 @@ +;; 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.settings.notifications + (:require-macros [app.main.style :as stl]) + (:require + [app.common.data :as d] + [app.common.schema :as sm] + [app.main.data.notifications :as ntf] + [app.main.data.profile :as dp] + [app.main.refs :as refs] + [app.main.store :as st] + [app.main.ui.components.forms :as fm] + [app.util.dom :as dom] + [app.util.i18n :as i18n :refer [tr]] + [okulary.core :as l] + [rumext.v2 :as mf])) + +(def default-notification-settings + {:dashboard-comments :all + :email-comments :partial + :email-invites :all}) + +(def notification-settings-ref + (l/derived + (fn [profile] + (-> (merge default-notification-settings + (-> profile :props :notifications)) + (d/update-vals d/name))) + refs/profile)) + +(defn- on-error + [form _] + (reset! form nil) + (st/emit! (ntf/error (tr "generic.error")))) + +(defn- on-success + [_] + (st/emit! (ntf/success (tr "dashboard.notifications.notifications-saved")))) + +(defn- on-submit + [form event] + (dom/prevent-default event) + (let [params (with-meta (:clean-data @form) + {:on-success (partial on-success form) + :on-error (partial on-error form)})] + (st/emit! (dp/update-notifications params)))) + +(def ^:private schema:notifications-form + [:map {:title "NotificationsForm"} + [:dashboard-comments [::sm/one-of #{:all :partial :none}]] + [:email-comments [::sm/one-of #{:all :partial :none}]] + [:email-invites [::sm/one-of #{:all :partial :none}]]]) + +(mf/defc notifications-page + [] + (let [settings (mf/deref notification-settings-ref) + form (fm/use-form :schema schema:notifications-form + :initial settings)] + (mf/with-effect [] + (dom/set-html-title (tr "title.settings.notifications"))) + + [:section {:class (stl/css :notifications-page)} + [:& fm/form {:class (stl/css :notifications-form) + :on-submit on-submit + :form form} + [:div {:class (stl/css :form-container)} + [:h2 (tr "dashboard.settings.notifications.title")] + [:h3 (tr "dashboard.settings.notifications.dashboard.title")] + [:h4 (tr "dashboard.settings.notifications.dashboard-comments.title")] + [:div {:class (stl/css :fields-row)} + [:& fm/radio-buttons + {:options [{:label (tr "dashboard.settings.notifications.dashboard-comments.all") :value "all"} + {:label (tr "dashboard.settings.notifications.dashboard-comments.partial") :value "partial"} + {:label (tr "dashboard.settings.notifications.dashboard-comments.none") :value "none"}] + :name :dashboard-comments + :class (stl/css :radio-btns)}]] + + [:h3 (tr "dashboard.settings.notifications.email.title")] + [:h4 (tr "dashboard.settings.notifications.email-comments.title")] + [:div {:class (stl/css :fields-row)} + [:& fm/radio-buttons + {:options [{:label (tr "dashboard.settings.notifications.email-comments.all") :value "all"} + {:label (tr "dashboard.settings.notifications.email-comments.partial") :value "partial"} + {:label (tr "dashboard.settings.notifications.email-comments.none") :value "none"}] + :name :email-comments + :class (stl/css :radio-btns)}]] + + [:h4 (tr "dashboard.settings.notifications.email-invites.title")] + [:div {:class (stl/css :fields-row)} + [:& fm/radio-buttons + {:options [{:label (tr "dashboard.settings.notifications.email-invites.all") :value "all"} + ;; This type of notifications doesnt't exist yet + ;; {:label "Only invites and requests that my response" :value "partial"} + {:label (tr "dashboard.settings.notifications.email-invites.none") :value "none"}] + :name :email-invites + :class (stl/css :radio-btns)}]] + + [:> fm/submit-button* + {:label (tr "dashboard.settings.notifications.submit") + :data-testid "submit-settings" + :class (stl/css :update-btn)}]]]])) + diff --git a/frontend/src/app/main/ui/settings/notifications.scss b/frontend/src/app/main/ui/settings/notifications.scss new file mode 100644 index 0000000000..7e2cd4ae08 --- /dev/null +++ b/frontend/src/app/main/ui/settings/notifications.scss @@ -0,0 +1,42 @@ +// 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-refactor.scss" as *; +@use "./profile" as *; + +.update-btn { + margin-top: $s-16; + @extend .button-primary; + height: $s-36; +} + +.notifications-form { + width: $s-400; +} + +.notifications-page { + display: flex; + justify-content: center; +} + +.radio-btns { + display: flex; + flex-direction: column; + gap: 0; +} + +.form-container { + h3 { + color: var(--color-foreground-secondary); + } + + h4 { + font-size: $fs-11; + color: var(--color-foreground-primary); + text-transform: uppercase; + margin: $s-12; + } +} diff --git a/frontend/src/app/main/ui/settings/sidebar.cljs b/frontend/src/app/main/ui/settings/sidebar.cljs index 8da8bb6a3c..5de595091c 100644 --- a/frontend/src/app/main/ui/settings/sidebar.cljs +++ b/frontend/src/app/main/ui/settings/sidebar.cljs @@ -43,6 +43,9 @@ (def ^:private go-settings-access-tokens #(st/emit! (rt/nav :settings-access-tokens))) +(def ^:private go-settings-notifications + #(st/emit! (rt/nav :settings-notifications))) + (defn- show-release-notes [event] (let [version (:main cf/version)] @@ -60,6 +63,7 @@ options? (= section :settings-options) feedback? (= section :settings-feedback) access-tokens? (= section :settings-access-tokens) + notifications? (= section :settings-notifications) team-id (or (dtm/get-last-team-id) (:default-team-id profile)) @@ -89,6 +93,11 @@ :on-click go-settings-password} [:span {:class (stl/css :element-title)} (tr "labels.password")]] + [:li {:class (stl/css-case :current notifications? + :settings-item true) + :on-click go-settings-notifications} + [:span {:class (stl/css :element-title)} (tr "labels.notifications")]] + [:li {:class (stl/css-case :current options? :settings-item true) :on-click go-settings-options diff --git a/frontend/src/app/main/ui/static.cljs b/frontend/src/app/main/ui/static.cljs index ccf8926222..5b77a7b240 100644 --- a/frontend/src/app/main/ui/static.cljs +++ b/frontend/src/app/main/ui/static.cljs @@ -47,7 +47,8 @@ :on-click on-nav-root} [:> raw-svg* {:id "penpot-logo-icon" :class (stl/css :penpot-logo)}] (when profile-id - [:div {:class (stl/css :go-back-wrapper)} [:> icon* {:id "arrow" :class (stl/css :back-arrow)}] [:span (tr "not-found.no-permission.go-dashboard")]])] + [:div {:class (stl/css :go-back-wrapper)} + [:> icon* {:icon-id "arrow" :class (stl/css :back-arrow)}] [:span (tr "not-found.no-permission.go-dashboard")]])] [:div {:class (stl/css :deco-before)} i/logo-error-screen] (when-not profile-id [:button {:class (stl/css :login-header) diff --git a/frontend/src/app/main/ui/viewer/comments.cljs b/frontend/src/app/main/ui/viewer/comments.cljs index 2ab261bb30..db9d66c059 100644 --- a/frontend/src/app/main/ui/viewer/comments.cljs +++ b/frontend/src/app/main/ui/viewer/comments.cljs @@ -206,26 +206,28 @@ [:div {:class (stl/css :viewer-comments-container)} [:div {:class (stl/css :threads)} (for [item threads] - [:& cmt/thread-bubble + [:> cmt/comment-floating-bubble* {:thread item + :profiles users :position-modifier modifier1 :zoom zoom :on-click on-bubble-click - :open? (= (:id item) (:open local)) + :is-open (= (:id item) (:open local)) :key (:seqn item) :origin :viewer}]) (when-let [thread (get threads-map open-thread-id)] - [:& cmt/thread-comments + [:> cmt/comment-floating-thread* {:thread thread + :profiles users :position-modifier modifier1 :viewport {:offset-x 0 :offset-y 0 :width (:width vsize) :height (:height vsize)} - :profiles users :zoom zoom}]) (when-let [draft (:draft local)] - [:& cmt/draft-thread + [:> cmt/comment-floating-thread-draft* {:draft draft + :profiles users :position-modifier modifier1 :on-cancel on-draft-cancel :on-submit on-draft-submit diff --git a/frontend/src/app/main/ui/viewer/inspect/attributes/common.cljs b/frontend/src/app/main/ui/viewer/inspect/attributes/common.cljs index fcc2eb2502..e7d48424a2 100644 --- a/frontend/src/app/main/ui/viewer/inspect/attributes/common.cljs +++ b/frontend/src/app/main/ui/viewer/inspect/attributes/common.cljs @@ -70,7 +70,7 @@ [:div {:class (stl/css :bullet-wrapper) :style #js {"--bullet-size" "16px"}} [:& cb/color-bullet {:color color - :mini? true}]] + :mini true}]] [:div {:class (stl/css :format-wrapper)} [:div {:class (stl/css :image-format)} @@ -102,7 +102,7 @@ [:div {:class (stl/css :bullet-wrapper) :style #js {"--bullet-size" "16px"}} [:& cb/color-bullet {:color color - :mini? true}]] + :mini true}]] [:div {:class (stl/css :format-wrapper)} (when-not (and on-change-format (or (:gradient color) image)) diff --git a/frontend/src/app/main/ui/workspace.cljs b/frontend/src/app/main/ui/workspace.cljs index 67a831f309..325834266b 100644 --- a/frontend/src/app/main/ui/workspace.cljs +++ b/frontend/src/app/main/ui/workspace.cljs @@ -29,7 +29,7 @@ [app.main.ui.workspace.plugins] [app.main.ui.workspace.sidebar :refer [left-sidebar right-sidebar]] [app.main.ui.workspace.sidebar.collapsable-button :refer [collapsed-button]] - [app.main.ui.workspace.sidebar.history :refer [history-toolbox]] + [app.main.ui.workspace.sidebar.history :refer [history-toolbox*]] [app.main.ui.workspace.tokens.modals] [app.main.ui.workspace.tokens.modals.themes] [app.main.ui.workspace.viewport :refer [viewport]] @@ -100,7 +100,7 @@ (when (dbg/enabled? :history-overlay) [:div {:class (stl/css :history-debug-overlay)} [:button {:on-click #(st/emit! dw/reinitialize-undo)} "CLEAR"] - [:& history-toolbox]]) + [:> history-toolbox*]]) [:& viewport {:file file :wlocal wlocal diff --git a/frontend/src/app/main/ui/workspace/color_palette_ctx_menu.cljs b/frontend/src/app/main/ui/workspace/color_palette_ctx_menu.cljs index 9d9097d04c..33f98effb7 100644 --- a/frontend/src/app/main/ui/workspace/color_palette_ctx_menu.cljs +++ b/frontend/src/app/main/ui/workspace/color_palette_ctx_menu.cljs @@ -44,7 +44,7 @@ :style #js {"--bullet-size" "20px"}} (for [[i {:keys [color id gradient]}] (map-indexed vector (take 7 colors))] [:& cb/color-bullet {:key (dm/str "color-" i) - :mini? true + :mini true :color {:color color :id id :gradient gradient}}])]]])) [:li {:class (stl/css-case :file-library true @@ -68,7 +68,7 @@ :style #js {"--bullet-size" "20px"}} (for [[i color] (map-indexed vector (take 7 (vals file-colors)))] [:& cb/color-bullet {:key (dm/str "color-" i) - :mini? true + :mini true :color color}])]]] [:li {:class (stl/css :recent-colors true @@ -90,5 +90,5 @@ :style #js {"--bullet-size" "20px"}} (for [[idx color] (map-indexed vector (take 7 (reverse recent-colors)))] [:& cb/color-bullet {:key (str "color-" idx) - :mini? true + :mini true :color color}])]]]]])) diff --git a/frontend/src/app/main/ui/workspace/comments.cljs b/frontend/src/app/main/ui/workspace/comments.cljs index 7fa35a9af1..290e3f2999 100644 --- a/frontend/src/app/main/ui/workspace/comments.cljs +++ b/frontend/src/app/main/ui/workspace/comments.cljs @@ -63,6 +63,12 @@ :on-click update-mode} [:span {:class (stl/css :label)} (tr "labels.show-your-comments")] [:span {:class (stl/css :icon)} i/tick]] + [:li {:class (stl/css-case :dropdown-item true + :selected (= :mentions cmode)) + :data-value "mentions" + :on-click update-mode} + [:span {:class (stl/css :label)} (tr "labels.show-mentions")] + [:span {:class (stl/css :icon)} i/tick]] [:li {:class (stl/css :separator)}] [:li {:class (stl/css-case :dropdown-item true :selected (= :pending cshow)) @@ -137,9 +143,11 @@ [:button {:class (stl/css :mode-dropdown-wrapper) :on-click toggle-mode-selector} - [:span {:class (stl/css :mode-label)} (case (:mode local) - (nil :all) (tr "labels.show-all-comments") - :yours (tr "labels.show-your-comments"))] + [:span {:class (stl/css :mode-label)} + (case (:mode local) + (nil :all) (tr "labels.show-all-comments") + :yours (tr "labels.show-your-comments") + :mentions (tr "labels.show-mentions"))] [:div {:class (stl/css :arrow-icon)} i/arrow]] [:& dropdown {:show options? @@ -150,12 +158,12 @@ (if (seq tgroups) [:div {:class (stl/css :thread-groups)} - [:& cmt/comment-thread-group + [:> cmt/comment-sidebar-thread-group* {:group (first tgroups) :on-thread-click on-thread-click :profiles profiles}] (for [tgroup (rest tgroups)] - [:& cmt/comment-thread-group + [:> cmt/comment-sidebar-thread-group* {:group tgroup :on-thread-click on-thread-click :profiles profiles diff --git a/frontend/src/app/main/ui/workspace/comments.scss b/frontend/src/app/main/ui/workspace/comments.scss index 0d9026a782..af3fa9d43c 100644 --- a/frontend/src/app/main/ui/workspace/comments.scss +++ b/frontend/src/app/main/ui/workspace/comments.scss @@ -125,7 +125,6 @@ .thread-groups { display: flex; flex-direction: column; - gap: $s-24; } .thread-group-placeholder { diff --git a/frontend/src/app/main/ui/workspace/context_menu.cljs b/frontend/src/app/main/ui/workspace/context_menu.cljs index 6352a3ea74..8e160a564d 100644 --- a/frontend/src/app/main/ui/workspace/context_menu.cljs +++ b/frontend/src/app/main/ui/workspace/context_menu.cljs @@ -138,6 +138,8 @@ ::mf/private true} [] (let [do-copy #(st/emit! (dw/copy-selected)) + do-copy-link #(st/emit! (dw/copy-link-to-clipboard)) + do-cut #(st/emit! (dw/copy-selected) (dw/delete-selected)) do-paste #(st/emit! (dw/paste-from-clipboard)) @@ -146,6 +148,9 @@ [:> menu-entry* {:title (tr "workspace.shape.menu.copy") :shortcut (sc/get-tooltip :copy) :on-click do-copy}] + [:> menu-entry* {:title (tr "workspace.shape.menu.copy_link") + :shortcut (sc/get-tooltip :copy-link) + :on-click do-copy-link}] [:> menu-entry* {:title (tr "workspace.shape.menu.cut") :shortcut (sc/get-tooltip :cut) :on-click do-cut}] @@ -531,7 +536,7 @@ [{:keys [mdata]}] (let [{:keys [disable-booleans disable-flatten]} mdata shapes (mf/deref refs/selected-objects) - props (mf/spread-props + props (mf/props {:shapes shapes :disable-booleans disable-booleans :disable-flatten disable-flatten})] diff --git a/frontend/src/app/main/ui/workspace/right_header.cljs b/frontend/src/app/main/ui/workspace/right_header.cljs index 32d679fea0..6cb9618e9a 100644 --- a/frontend/src/app/main/ui/workspace/right_header.cljs +++ b/frontend/src/app/main/ui/workspace/right_header.cljs @@ -141,8 +141,7 @@ ;; --- Header Component -(mf/defc right-header - {::mf/wrap-props false} +(mf/defc right-header* [{:keys [file layout page-id]}] (let [file-id (:id file) diff --git a/frontend/src/app/main/ui/workspace/sidebar.cljs b/frontend/src/app/main/ui/workspace/sidebar.cljs index 80f8a03794..2c86658ec9 100644 --- a/frontend/src/app/main/ui/workspace/sidebar.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar.cljs @@ -14,21 +14,22 @@ [app.main.refs :as refs] [app.main.store :as st] [app.main.ui.context :as muc] + [app.main.ui.ds.buttons.icon-button :refer [icon-button*]] [app.main.ui.ds.foundations.assets.icon :refer [icon*]] [app.main.ui.ds.layout.tab-switcher :refer [tab-switcher*]] [app.main.ui.hooks.resize :refer [use-resize-hook]] [app.main.ui.workspace.comments :refer [comments-sidebar*]] [app.main.ui.workspace.left-header :refer [left-header]] - [app.main.ui.workspace.right-header :refer [right-header]] + [app.main.ui.workspace.right-header :refer [right-header*]] [app.main.ui.workspace.sidebar.assets :refer [assets-toolbox]] [app.main.ui.workspace.sidebar.debug :refer [debug-panel]] [app.main.ui.workspace.sidebar.debug-shape-info :refer [debug-shape-info]] - [app.main.ui.workspace.sidebar.history :refer [history-toolbox]] + [app.main.ui.workspace.sidebar.history :refer [history-toolbox*]] [app.main.ui.workspace.sidebar.layers :refer [layers-toolbox]] - [app.main.ui.workspace.sidebar.options :refer [options-toolbox]] + [app.main.ui.workspace.sidebar.options :refer [options-toolbox*]] [app.main.ui.workspace.sidebar.shortcuts :refer [shortcuts-container]] [app.main.ui.workspace.sidebar.sitemap :refer [sitemap]] - [app.main.ui.workspace.sidebar.versions :refer [versions-toolbox]] + [app.main.ui.workspace.sidebar.versions :refer [versions-toolbox*]] [app.main.ui.workspace.tokens.sidebar :refer [tokens-sidebar-tab]] [app.util.debug :as dbg] [app.util.i18n :refer [tr]] @@ -43,7 +44,7 @@ ;; NOTE: This custom button may be replace by an action button when this variant is designed [:button {:class (stl/css :collapse-sidebar-button) :on-click on-click} - [:& icon* {:id "arrow" + [:> icon* {:icon-id "arrow" :size "s" :aria-label (tr "workspace.sidebar.collapse")}]]) @@ -188,74 +189,99 @@ is-history? (contains? layout :document-history) is-inspect? (= section :inspect) + dbg-shape-panel? (dbg/enabled? :shape-panel) + current-section* (mf/use-state :info) current-section (deref current-section*) - can-be-expanded? (or (dbg/enabled? :shape-panel) - (and (not is-comments?) - (not is-history?) - is-inspect? - (= current-section :code))) + can-be-expanded? + (or dbg-shape-panel? + (and (not is-comments?) + (not is-history?) + is-inspect? + (= current-section :code))) {:keys [on-pointer-down on-lost-pointer-capture on-pointer-move set-size size]} (use-resize-hook :code 276 276 768 :x true :right) - handle-change-section - (mf/use-callback + on-change-section + (mf/use-fn (fn [section] (reset! current-section* section))) - handle-expand - (mf/use-callback + on-close-history + (mf/use-fn #(st/emit! (dw/remove-layout-flag :document-history))) + + on-expand + (mf/use-fn (mf/deps size) (fn [] (set-size (if (> size 276) 276 768)))) props - (mf/spread props - :on-change-section handle-change-section - :on-expand handle-expand) + (mf/spread-props props + {:on-change-section on-change-section + :on-expand on-expand})] - history-tab - (mf/html - [:article {:class (stl/css :history-tab)} - [:& history-toolbox {}]]) + [:> (mf/provider muc/sidebar) {:value :right} + [:aside + {:class (stl/css-case :right-settings-bar true + :not-expand (not can-be-expanded?) + :expanded (> size 276)) - versions-tab - (mf/html - [:article {:class (stl/css :versions-tab)} - [:& versions-toolbox {}]])] + :id "right-sidebar-aside" + :data-testid "right-sidebar" + :data-size (str size) + :style {"--width" (if can-be-expanded? (dm/str size "px") "276px")}} - [:& (mf/provider muc/sidebar) {:value :right} - [:aside {:class (stl/css-case :right-settings-bar true - :not-expand (not can-be-expanded?) - :expanded (> size 276)) - - :id "right-sidebar-aside" - :data-testid "right-sidebar" - :data-size (str size) - :style #js {"--width" (if can-be-expanded? (dm/str size "px") "276px")}} (when can-be-expanded? [:div {:class (stl/css :resize-area) :on-pointer-down on-pointer-down :on-lost-pointer-capture on-lost-pointer-capture :on-pointer-move on-pointer-move}]) - [:& right-header {:file file :layout layout :page-id page-id}] + + [:> right-header* + {:file file + :layout layout + :page-id page-id}] [:div {:class (stl/css :settings-bar-inside)} (cond - (dbg/enabled? :shape-panel) + dbg-shape-panel? [:& debug-shape-info] - (true? is-comments?) + is-comments? [:> comments-sidebar* {}] - (true? is-history?) - [:> tab-switcher* - {:tabs #js [#js {:label (tr "workspace.versions.tab.history") :id "history" :content versions-tab} - #js {:label (tr "workspace.versions.tab.actions") :id "actions" :content history-tab}] - :default-selected "history" - :class (stl/css :left-sidebar-tabs)}] + is-history? + (let [history-tab + (mf/html + [:article {:class (stl/css :history-tab)} + [:> history-toolbox*]]) + + versions-tab + (mf/html + [:article {:class (stl/css :versions-tab)} + [:> versions-toolbox*]]) + + button + (mf/html + [:> icon-button* {:variant "ghost" + :aria-label (tr "labels.close") + :on-click on-close-history + :icon "close"}])] + + [:> tab-switcher* + {:tabs [{:label (tr "workspace.versions.tab.history") + :id "history" + :content versions-tab} + {:label (tr "workspace.versions.tab.actions") + :id "actions" + :content history-tab}] + :default-selected "history" + :class (stl/css :left-sidebar-tabs) + :action-button-position "end" + :action-button button}]) :else - [:> options-toolbox props])]]])) + [:> options-toolbox* props])]]])) diff --git a/frontend/src/app/main/ui/workspace/sidebar/assets.cljs b/frontend/src/app/main/ui/workspace/sidebar/assets.cljs index bd0fa05f61..3af7840fd7 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/assets.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/assets.cljs @@ -90,6 +90,9 @@ reverse-sort? (= :desc ordering) num-libs (count (mf/deref refs/libraries)) + show-templates-02-test? + (and (cf/external-feature-flag "templates-02" "test") (zero? num-libs)) + toggle-ordering (mf/use-fn (mf/deps ordering) @@ -158,8 +161,7 @@ [:article {:class (stl/css :assets-bar)} [:div {:class (stl/css :assets-header)} (when-not ^boolean read-only? - (if (and (cf/external-feature-flag "templates-02" "test") - (zero? num-libs)) + (if show-templates-02-test? [:button {:class (stl/css :add-library-button) :on-click show-libraries-dialog :data-testid "libraries"} @@ -171,31 +173,32 @@ i/library] (tr "workspace.assets.libraries")])) - [:div {:class (stl/css :search-wrapper)} - [:& search-bar {:on-change on-search-term-change - :value term - :placeholder (tr "workspace.assets.search")} - [:button - {:on-click on-open-menu - :title (tr "workspace.assets.filter") - :class (stl/css-case :section-button true - :opened menu-open?)} - i/filter-icon]] - [:> context-menu* - {:on-close on-menu-close - :selectable true - :selected section - :show menu-open? - :fixed true - :min-width true - :width size - :top 158 - :left 18 - :options options}] - [:> icon-button* {:variant "ghost" - :aria-label (tr "workspace.assets.sort") - :on-click toggle-ordering - :icon (if reverse-sort? "asc-sort" "desc-sort")}]]] + (when-not show-templates-02-test? + [:div {:class (stl/css :search-wrapper)} + [:& search-bar {:on-change on-search-term-change + :value term + :placeholder (tr "workspace.assets.search")} + [:button + {:on-click on-open-menu + :title (tr "workspace.assets.filter") + :class (stl/css-case :section-button true + :opened menu-open?)} + i/filter-icon]] + [:> context-menu* + {:on-close on-menu-close + :selectable true + :selected section + :show menu-open? + :fixed true + :min-width true + :width size + :top 158 + :left 18 + :options options}] + [:> icon-button* {:variant "ghost" + :aria-label (tr "workspace.assets.sort") + :on-click toggle-ordering + :icon (if reverse-sort? "asc-sort" "desc-sort")}]])] [:& (mf/provider cmm/assets-filters) {:value filters} [:& (mf/provider cmm/assets-toggle-ordering) {:value toggle-ordering} diff --git a/frontend/src/app/main/ui/workspace/sidebar/assets/colors.cljs b/frontend/src/app/main/ui/workspace/sidebar/assets/colors.cljs index f3dfccfd8d..0738bd6901 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/assets/colors.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/assets/colors.cljs @@ -216,7 +216,7 @@ [:div {:class (stl/css :bullet-block)} [:& cb/color-bullet {:color color - :mini? true}]] + :mini true}]] (if ^boolean editing? [:input diff --git a/frontend/src/app/main/ui/workspace/sidebar/history.cljs b/frontend/src/app/main/ui/workspace/sidebar/history.cljs index 753c99c3c4..d5eb76bc3d 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/history.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/history.cljs @@ -320,7 +320,7 @@ (when @show-detail? [:& history-entry-details {:entry entry}])])) -(mf/defc history-toolbox +(mf/defc history-toolbox* [] (let [objects (mf/deref refs/workspace-page-objects) {:keys [items index]} (mf/deref workspace-undo) diff --git a/frontend/src/app/main/ui/workspace/sidebar/layers.cljs b/frontend/src/app/main/ui/workspace/sidebar/layers.cljs index 9dd8d234a2..491b86707f 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/layers.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/layers.cljs @@ -43,7 +43,7 @@ [{:keys [selected] :as props}] (let [pending-selected (mf/use-var selected) current-selected (mf/use-state selected) - props (mf/spread props :selected @current-selected) + props (mf/spread-object props {:selected @current-selected}) set-selected (mf/use-memo diff --git a/frontend/src/app/main/ui/workspace/sidebar/options.cljs b/frontend/src/app/main/ui/workspace/sidebar/options.cljs index ebf93ffb88..f8fd19e1a2 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options.cljs @@ -129,9 +129,9 @@ :file-id file-id :shared-libs shared-libs}])])) -(mf/defc options-content +(mf/defc options-content* {::mf/memo true - ::mf/props :obj} + ::mf/private true} [{:keys [selected shapes shapes-with-children page-id file-id on-change-section on-expand]}] (let [objects (mf/deref refs/workspace-page-objects) permissions (mf/use-ctx ctx/permissions) @@ -202,20 +202,19 @@ ;; selected-objects-with-children are derefed always but they only ;; need on multiple selection in majority of cases -(mf/defc options-toolbox - {::mf/memo true - ::mf/props :obj} +(mf/defc options-toolbox* + {::mf/memo true} [{:keys [section selected on-change-section on-expand]}] (let [page-id (mf/use-ctx ctx/current-page-id) file-id (mf/use-ctx ctx/current-file-id) shapes (mf/deref refs/selected-objects) shapes-with-children (mf/deref refs/selected-shapes-with-children)] - [:& options-content {:shapes shapes - :selected selected - :shapes-with-children shapes-with-children - :file-id file-id - :page-id page-id - :section section - :on-change-section on-change-section - :on-expand on-expand}])) + [:> options-content* {:shapes shapes + :selected selected + :shapes-with-children shapes-with-children + :file-id file-id + :page-id page-id + :section section + :on-change-section on-change-section + :on-expand on-expand}])) diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/border_radius.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/menus/border_radius.cljs index 20404b3e6a..7809c85680 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/border_radius.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/border_radius.cljs @@ -64,7 +64,7 @@ (if (not radius-expanded) [:div {:class (stl/css :radius-1) :title (tr "workspace.options.radius")} - [:> icon* {:id "corner-radius" + [:> icon* {:icon-id "corner-radius" :size "s" :class (stl/css :icon)}] [:> numeric-input* @@ -116,8 +116,7 @@ [:> icon-button* {:class (stl/css-case :selected radius-expanded) :variant "ghost" :on-click toggle-radius-mode - :aria-label (tr "workspace.options.radius") - :title (if radius-expanded - (tr "workspace.options.radius.all-corners") - (tr "workspace.options.radius.single-corners")) + :aria-label (if radius-expanded + (tr "workspace.options.radius.all-corners") + (tr "workspace.options.radius.single-corners")) :icon "corner-radius"}]])) \ No newline at end of file diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/component.scss b/frontend/src/app/main/ui/workspace/sidebar/options/menus/component.scss index aa443fa33e..030d64cacd 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/component.scss +++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/component.scss @@ -402,6 +402,7 @@ .component-swap { padding-top: $s-12; + max-width: $s-248; } .component-swap-content { diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/layout_container.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/menus/layout_container.cljs index 57cf42d9d8..b1b1a1c7e0 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/layout_container.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/layout_container.cljs @@ -456,7 +456,7 @@ type (if (= type "multiple") :simple :multiple)] (on-type-change type)))) - props (mf/spread props {:on-change on-change})] + props (mf/spread-object props {:on-change on-change})] (mf/with-effect [] ;; on destroy component diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/layout_item.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/menus/layout_item.cljs index 681e879f3a..21a5c5fafe 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/layout_item.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/layout_item.cljs @@ -43,8 +43,7 @@ [prop] (select-margins (= prop :m1) (= prop :m2) (= prop :m3) (= prop :m4))) -(mf/defc margin-simple - {::mf/props :obj} +(mf/defc margin-simple* [{:keys [value on-change on-blur]}] (let [m1 (:m1 value) m2 (:m2 value) @@ -103,8 +102,7 @@ :nillable true :value m2}]]])) -(mf/defc margin-multiple - {::mf/props :obj} +(mf/defc margin-multiple* [{:keys [value on-change on-blur]}] (let [m1 (:m1 value) m2 (:m2 value) @@ -182,14 +180,13 @@ :value m4}]]])) -(mf/defc margin-section - {::mf/props :obj - ::mf/private true +(mf/defc margin-section* + {::mf/private true ::mf/expect-props #{:value :type :on-type-change :on-change}} [{:keys [type on-type-change] :as props}] (let [type (d/nilv type :simple) on-blur (mf/use-fn #(select-margins false false false false)) - props (mf/spread props :on-blur on-blur) + props (mf/spread-props props {:on-blur on-blur}) on-type-change' (mf/use-fn @@ -206,10 +203,10 @@ [:div {:class (stl/css :inputs-wrapper)} (cond (= type :simple) - [:> margin-simple props] + [:> margin-simple* props] (= type :multiple) - [:> margin-multiple props])] + [:> margin-multiple* props])] [:button {:class (stl/css-case :margin-mode true @@ -500,10 +497,10 @@ (when is-layout-child? [:div {:class (stl/css :row)} - [:& margin-section {:value (:layout-item-margin values) - :type (:layout-item-margin-type values) - :on-type-change on-margin-type-change - :on-change on-margin-change}]]) + [:> margin-section* {:value (:layout-item-margin values) + :type (:layout-item-margin-type values) + :on-type-change on-margin-type-change + :on-change on-margin-change}]]) (when (or (= h-sizing :fill) (= v-sizing :fill)) diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs index f53360fc30..04dfdb89ba 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs @@ -212,7 +212,7 @@ (nil? color-name) (assoc :id nil :file-id nil)) - :mini? true + :mini true :on-click handle-click-color}]] (cond ;; Rendering a color with ID diff --git a/frontend/src/app/main/ui/workspace/sidebar/shortcuts.cljs b/frontend/src/app/main/ui/workspace/sidebar/shortcuts.cljs index dad7ddcf29..70d1b1b68a 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/shortcuts.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/shortcuts.cljs @@ -91,6 +91,7 @@ (tr "shortcuts.bring-front") (tr "shortcuts.clear-undo") (tr "shortcuts.copy") + (tr "shortcuts.copy-link") (tr "shortcuts.create-component") (tr "shortcuts.create-new-project") (tr "shortcuts.cut") diff --git a/frontend/src/app/main/ui/workspace/sidebar/versions.cljs b/frontend/src/app/main/ui/workspace/sidebar/versions.cljs index c8d8a55a46..8d893e55ef 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/versions.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/versions.cljs @@ -226,14 +226,13 @@ :on-click handle-pin-snapshot} (tr "workspace.versions.button.pin")]]]])]]])) -(mf/defc versions-toolbox +(mf/defc versions-toolbox* [] (let [profiles (mf/deref refs/profiles) profile (mf/deref refs/profile) expanded (mf/use-state #{}) - {:keys [status data editing]} (mf/deref versions) diff --git a/frontend/src/app/main/ui/workspace/tokens/modals/themes.cljs b/frontend/src/app/main/ui/workspace/tokens/modals/themes.cljs index e6cb23f38b..b407624957 100644 --- a/frontend/src/app/main/ui/workspace/tokens/modals/themes.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/modals/themes.cljs @@ -90,7 +90,7 @@ :class (stl/css :theme-group-label) :typography "body-large"} [:span {:class (stl/css :group-title)} - [:> icon* {:id "group"}] + [:> icon* {:icon-id "group"}] group]]) [:ul {:class (stl/css :theme-group-rows-wrapper)} (for [[_ {:keys [group name] :as theme}] themes @@ -131,7 +131,7 @@ [:div {:class (stl/css :label-wrapper)} [:> text* {:as "span" :typography "body-medium"} (tr "workspace.token.num-sets" sets-count)] - [:> icon* {:id "arrow-right"}]]] + [:> icon* {:icon-id "arrow-right"}]]] [:> button* {:class (stl/css :sets-count-empty-button) :type "button" @@ -140,7 +140,7 @@ [:div {:class (stl/css :label-wrapper)} [:> text* {:as "span" :typography "body-medium"} (tr "workspace.token.no-sets")] - [:> icon* {:id "arrow-right"}]]]) + [:> icon* {:icon-id "arrow-right"}]]]) [:> icon-button* {:on-click delete-theme :variant "ghost" @@ -186,7 +186,7 @@ :on-click (fn [e] (dom/stop-propagation e) (on-toggle-dropdown))} - [:> icon* {:id "arrow-down"}]]))}]] + [:> icon* {:icon-id "arrow-down"}]]))}]] [:div {:class (stl/css :group-input-wrapper)} ;; TODO: This span should be remove when labeled-input is updated [:span {:class (stl/css :labeled-input-label)} "Theme"] @@ -306,7 +306,7 @@ [:button {:on-click on-back :class (stl/css :back-btn) :type "button"} - [:> icon* {:id ic/arrow-left :aria-hidden true}] + [:> icon* {:icon-id ic/arrow-left :aria-hidden true}] (tr "workspace.token.back-to-themes")] [:& theme-inputs {:dropdown-open? dropdown-open? diff --git a/frontend/src/app/main/ui/workspace/tokens/sets.cljs b/frontend/src/app/main/ui/workspace/tokens/sets.cljs index 127f13c3fa..0c3eb69281 100644 --- a/frontend/src/app/main/ui/workspace/tokens/sets.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/sets.cljs @@ -96,9 +96,8 @@ :aria-label (tr "labels.collapse") :icon (if @collapsed? "arrow-right" "arrow-down") :variant "action"}] - [:> icon* - {:id "group" - :class (stl/css :icon)}] + [:> icon* {:icon-id "group" + :class (stl/css :icon)}] (if editing?' [:& editing-label {:default-value label @@ -139,10 +138,9 @@ :on-click on-click :on-double-click #(on-edit tree-path) :on-context-menu on-context-menu} - [:> icon* - {:id "document" - :class (stl/css-case :icon true - :root-icon (not tree-depth))}] + [:> icon* {:icon-id "document" + :class (stl/css-case :icon true + :root-icon (not tree-depth))}] (if editing?' [:& editing-label {:default-value label @@ -160,7 +158,7 @@ [:> icon* {:aria-label (tr "workspace.token.select-set") :class (stl/css :check-icon) :size "s" - :id ic/tick}])]])])) + :icon-id ic/tick}])]])])) (mf/defc sets-tree [{:keys [set-path set-node tree-depth tree-path on-select selected? on-toggle active? editing? on-edit on-edit-reset on-edit-submit] diff --git a/frontend/src/app/main/ui/workspace/tokens/sidebar.cljs b/frontend/src/app/main/ui/workspace/tokens/sidebar.cljs index 1579002644..8fcbab4322 100644 --- a/frontend/src/app/main/ui/workspace/tokens/sidebar.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/sidebar.cljs @@ -73,7 +73,7 @@ (wtt/resolved-value-hex theme-token) (wtt/resolved-value-hex token))] [:& color-bullet {:color color - :mini? true}]) + :mini true}]) name])) (mf/defc token-section-icon diff --git a/frontend/src/app/main/ui/workspace/tokens/theme_select.cljs b/frontend/src/app/main/ui/workspace/tokens/theme_select.cljs index 484c806c5d..85a3e2eeb0 100644 --- a/frontend/src/app/main/ui/workspace/tokens/theme_select.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/theme_select.cljs @@ -42,7 +42,7 @@ :is-selected selected?) :on-click select-theme} [:> text* {:as "span" :typography "body-small" :class (stl/css :label)} name] - [:> icon* {:id i/tick + [:> icon* {:icon-id i/tick :aria-hidden true :class (stl/css-case :check-icon true :check-icon-visible selected?)}]])])) @@ -70,7 +70,7 @@ :role "option" :on-click on-edit-click} [:> text* {:as "span" :typography "body-small"} (tr "workspace.token.edit-themes")] - [:> icon* {:id i/arrow-right :aria-hidden true}]]]))) + [:> icon* {:icon-id i/arrow-right :aria-hidden true}]]]))) (mf/defc theme-select [{:keys []}] @@ -108,7 +108,7 @@ :class (stl/css :custom-select)} [:> text* {:as "span" :typography "body-small" :class (stl/css :current-label)} current-label] - [:> icon* {:id i/arrow-down :class (stl/css :dropdown-button) :aria-hidden true}] + [:> icon* {:icon-id i/arrow-down :class (stl/css :dropdown-button) :aria-hidden true}] [:& dropdown {:show is-open? :on-close on-close-dropdown :ref dropdown-element*} diff --git a/frontend/src/app/main/ui/workspace/viewport.cljs b/frontend/src/app/main/ui/workspace/viewport.cljs index 8aa9942b83..33f0cc9256 100644 --- a/frontend/src/app/main/ui/workspace/viewport.cljs +++ b/frontend/src/app/main/ui/workspace/viewport.cljs @@ -211,7 +211,7 @@ show-outlines? (and (nil? transform) (not edition) (not drawing-obj) - (not (#{:comments :path :curve} drawing-tool))) + (not (#{:path :curve} drawing-tool))) show-pixel-grid? (and (contains? layout :show-pixel-grid) (>= zoom 8)) diff --git a/frontend/src/app/main/ui/workspace/viewport/comments.cljs b/frontend/src/app/main/ui/workspace/viewport/comments.cljs index 1b226dcae0..5cc97b5746 100644 --- a/frontend/src/app/main/ui/workspace/viewport/comments.cljs +++ b/frontend/src/app/main/ui/workspace/viewport/comments.cljs @@ -75,22 +75,24 @@ [:div {:class (stl/css :threads) :style {:transform (dm/fmt "translate(%px, %px)" pos-x pos-y)}} (for [item threads] - [:& cmt/thread-bubble {:thread item - :zoom zoom - :open? (= (:id item) (:open local)) - :key (:seqn item)}]) + [:> cmt/comment-floating-bubble* {:thread item + :profiles profiles + :zoom zoom + :is-open (= (:id item) (:open local)) + :key (:seqn item)}]) (when-let [id (:open local)] (when-let [thread (get threads-map id)] (when (seq (dcm/apply-filters local profile [thread])) - [:& cmt/thread-comments {:thread (update-position positions thread) - :profiles profiles - :viewport {:offset-x pos-x :offset-y pos-y :width (:width vport) :height (:height vport)} - :zoom zoom}]))) + [:> cmt/comment-floating-thread* {:thread (update-position positions thread) + :profiles profiles + :viewport {:offset-x pos-x :offset-y pos-y :width (:width vport) :height (:height vport)} + :zoom zoom}]))) (when-let [draft (:comment drawing)] - [:& cmt/draft-thread {:draft draft - :on-cancel on-draft-cancel - :on-submit on-draft-submit - :zoom zoom}])]]])) + [:> cmt/comment-floating-thread-draft* {:draft draft + :profiles profiles + :on-cancel on-draft-cancel + :on-submit on-draft-submit + :zoom zoom}])]]])) diff --git a/frontend/src/app/main/ui/workspace/viewport_wasm.cljs b/frontend/src/app/main/ui/workspace/viewport_wasm.cljs index 00ac129443..30964d8697 100644 --- a/frontend/src/app/main/ui/workspace/viewport_wasm.cljs +++ b/frontend/src/app/main/ui/workspace/viewport_wasm.cljs @@ -284,8 +284,7 @@ (p/fmap (fn [ready?] (when ready? (reset! canvas-init? true) - (wasm.api/assign-canvas canvas) - (wasm.api/set-canvas-background background))))) + (wasm.api/assign-canvas canvas))))) (fn [] (wasm.api/clear-canvas)))) @@ -293,15 +292,15 @@ (when @canvas-init? (wasm.api/resize-viewbox (:width vport) (:height vport)))) - (mf/with-effect [base-objects canvas-init?] + (mf/with-effect [base-objects @canvas-init?] (when @canvas-init? (wasm.api/set-objects base-objects))) - (mf/with-effect [preview-blend canvas-init?] + (mf/with-effect [preview-blend @canvas-init?] (when (and @canvas-init? preview-blend) (wasm.api/request-render))) - (mf/with-effect [vbox canvas-init?] + (mf/with-effect [vbox @canvas-init?] (when @canvas-init? (wasm.api/set-view zoom vbox))) diff --git a/frontend/src/app/plugins/parser.cljs b/frontend/src/app/plugins/parser.cljs index c58e6f1ea9..4731528abe 100644 --- a/frontend/src/app/plugins/parser.cljs +++ b/frontend/src/app/plugins/parser.cljs @@ -340,76 +340,6 @@ (when (some? guides) (into [] (map parse-frame-guide) guides))) -;;interface PathCommand { -;; command: -;; | 'M' | 'move-to' -;; | 'Z' | 'close-path' -;; | 'L' | 'line-to' -;; | 'H' | 'line-to-horizontal' -;; | 'V' | 'line-to-vertical' -;; | 'C' | 'curve-to' -;; | 'S' | 'smooth-curve-to' -;; | 'Q' | 'quadratic-bezier-curve-to' -;; | 'T' | 'smooth-quadratic-bezier-curve-to' -;; | 'A' | 'elliptical-arc'; -;; -;; params?: { -;; x?: number; -;; y?: number; -;; c1x: number; -;; c1y: number; -;; c2x: number; -;; c2y: number; -;; rx?: number; -;; ry?: number; -;; xAxisRotation?: number; -;; largeArcFlag?: boolean; -;; sweepFlag?: boolean; -;; }; -;;} -(defn parse-command-type - [^string command-type] - (case command-type - "M" :move-to - "Z" :close-path - "L" :line-to - "H" :line-to-horizontal - "V" :line-to-vertical - "C" :curve-to - "S" :smooth-curve-to - "Q" :quadratic-bezier-curve-to - "T" :smooth-quadratic-bezier-curve-to - "A" :elliptical-arc - (parse-keyword command-type))) - -(defn parse-command-params - [^js params] - (when (some? params) - (d/without-nils - {:x (obj/get params "x") - :y (obj/get params "y") - :c1x (obj/get params "c1x") - :c1y (obj/get params "c1y") - :c2x (obj/get params "c2x") - :c2y (obj/get params "c2y") - :rx (obj/get params "rx") - :ry (obj/get params "ry") - :x-axis-rotation (obj/get params "xAxisRotation") - :large-arc-flag (obj/get params "largeArcFlag") - :sweep-flag (obj/get params "sweepFlag")}))) - -(defn parse-command - [^js command] - (when (some? command) - (d/without-nils - {:command (-> (obj/get command "command") parse-command-type) - :params (-> (obj/get command "params") parse-command-params)}))) - -(defn parse-path-content - [^js content] - (when (some? content) - (into [] (map parse-command) content))) - ;; export interface Dissolve { ;; type: 'dissolve'; ;; duration: number; diff --git a/frontend/src/app/plugins/shape.cljs b/frontend/src/app/plugins/shape.cljs index 82e07f1de8..a16deb8aaa 100644 --- a/frontend/src/app/plugins/shape.cljs +++ b/frontend/src/app/plugins/shape.cljs @@ -15,7 +15,7 @@ [app.common.record :as crc] [app.common.schema :as sm] [app.common.spec :as us] - [app.common.svg.path.legacy-parser2 :as spp] + [app.common.svg.path :as path] [app.common.text :as txt] [app.common.types.component :as ctk] [app.common.types.container :as ctn] @@ -1296,12 +1296,10 @@ (cond-> (or (cfh/path-shape? data) (cfh/bool-shape? data)) (crc/add-properties! {:name "content" - :get #(-> % u/proxy->shape :content format/format-path-content) + :get #(-> % u/proxy->shape :content upf/format-path) :set (fn [_ value] - (let [content - (->> (parser/parse-path-content value) - (spp/simplify-commands))] + (let [content (->> (path/parse value))] (cond (not (cfh/path-shape? data)) (u/display-not-valid :content-type type) diff --git a/frontend/src/app/plugins/user.cljs b/frontend/src/app/plugins/user.cljs index bf2022435b..b8087f6e96 100644 --- a/frontend/src/app/plugins/user.cljs +++ b/frontend/src/app/plugins/user.cljs @@ -18,26 +18,24 @@ (defn- add-session-properties [user-proxy session-id] - (let [plugin-id (obj/get user-proxy "$plugin")] - (crc/add-properties! - user-proxy - {:name "$plugin" :enumerable false :get (constantly plugin-id)} - {:name "$session" :enumerable false :get (constantly session-id)} + (crc/add-properties! + user-proxy + {:name "$session" :enumerable false :get (constantly session-id)} - {:name "id" - :get (fn [_] (-> (u/locate-profile session-id) :id str))} + {:name "id" + :get (fn [_] (-> (u/locate-profile session-id) :id str))} - {:name "name" - :get (fn [_] (-> (u/locate-profile session-id) :fullname))} + {:name "name" + :get (fn [_] (-> (u/locate-profile session-id) :fullname))} - {:name "avatarUrl" - :get (fn [_] (cfg/resolve-profile-photo-url (u/locate-profile session-id)))} + {:name "avatarUrl" + :get (fn [_] (cfg/resolve-profile-photo-url (u/locate-profile session-id)))} - {:name "color" - :get (fn [_] (-> (u/locate-presence session-id) :color))} + {:name "color" + :get (fn [_] (-> (u/locate-presence session-id) :color))} - {:name "sessionId" - :get (fn [_] (str session-id))}))) + {:name "sessionId" + :get (fn [_] (str session-id))})) (defn current-user-proxy? [p] @@ -46,7 +44,8 @@ (defn current-user-proxy [plugin-id session-id] (-> (obj/reify {:name "CurrentUserProxy"} - :$plugin {:enumerable false :get (fn [] plugin-id)}) + :$plugin + {:enumerable false :get (fn [] plugin-id)}) (add-session-properties session-id))) (defn active-user-proxy? [p] @@ -55,7 +54,8 @@ (defn active-user-proxy [plugin-id session-id] (-> (obj/reify {:name "ActiveUserProxy"} - :$plugin {:enumerable false :get (fn [] plugin-id)} + :$plugin + {:enumerable false :get (fn [] plugin-id)} :position {:get (fn [] (-> (u/locate-presence session-id) :point format/format-point))} @@ -66,19 +66,16 @@ (defn- add-user-properties [user-proxy data] - (let [plugin-id (obj/get user-proxy "$plugin")] - (crc/add-properties! - user-proxy - {:name "$plugin" :enumerable false :get (constantly plugin-id)} + (crc/add-properties! + user-proxy + {:name "id" + :get (fn [_] (-> data :id str))} - {:name "id" - :get (fn [_] (-> data :id str))} + {:name "name" + :get (fn [_] (-> data :fullname))} - {:name "name" - :get (fn [_] (-> data :fullname))} - - {:name "avatarUrl" - :get (fn [_] (cfg/resolve-profile-photo-url data))}))) + {:name "avatarUrl" + :get (fn [_] (cfg/resolve-profile-photo-url data))})) (defn user-proxy [plugin-id data] diff --git a/frontend/src/app/render_wasm/api.cljs b/frontend/src/app/render_wasm/api.cljs index 96e045d24d..eb3f38dd34 100644 --- a/frontend/src/app/render_wasm/api.cljs +++ b/frontend/src/app/render_wasm/api.cljs @@ -211,6 +211,93 @@ (store-image id)))))) fills)) +(defn- translate-stroke-style + [stroke-style] + (case stroke-style + :dotted 1 + :dashed 2 + :mixed 3 + 0)) + +(defn- translate-stroke-cap + [stroke-cap] + (case stroke-cap + :line-arrow 1 + :triangle-arrow 2 + :square-marker 3 + :circle-marker 4 + :diamond-marker 5 + :round 6 + :square 7 + 0)) + +(defn set-shape-strokes + [strokes] + (h/call internal-module "_clear_shape_strokes") + (keep (fn [stroke] + (let [opacity (or (:stroke-opacity stroke) 1.0) + color (:stroke-color stroke) + gradient (:stroke-color-gradient stroke) + image (:stroke-image stroke) + width (:stroke-width stroke) + align (:stroke-alignment stroke) + style (-> stroke :stroke-style translate-stroke-style) + cap-start (-> stroke :stroke-cap-start translate-stroke-cap) + cap-end (-> stroke :stroke-cap-end translate-stroke-cap)] + (case align + :inner (h/call internal-module "_add_shape_inner_stroke" width style cap-start cap-end) + :outer (h/call internal-module "_add_shape_outer_stroke" width style cap-start cap-end) + (h/call internal-module "_add_shape_center_stroke" width style cap-start cap-end)) + + (cond + (some? gradient) + (let [stops (:stops gradient) + n-stops (count stops) + mem-size (* 5 n-stops) + stops-ptr (h/call internal-module "_alloc_bytes" mem-size) + heap (gobj/get ^js internal-module "HEAPU8") + mem (js/Uint8Array. (.-buffer heap) stops-ptr mem-size)] + (if (= (:type gradient) :linear) + (h/call internal-module "_add_shape_stroke_linear_fill" + (:start-x gradient) + (:start-y gradient) + (:end-x gradient) + (:end-y gradient) + opacity) + (h/call internal-module "_add_shape_stroke_radial_fill" + (:start-x gradient) + (:start-y gradient) + (:end-x gradient) + (:end-y gradient) + opacity + (:width gradient))) + (.set mem (js/Uint8Array. (clj->js (flatten (map (fn [stop] + (let [[r g b a] (rgba-bytes-from-hex (:color stop) (:opacity stop)) + offset (:offset stop)] + [r g b a (* 100 offset)])) + stops))))) + (h/call internal-module "_add_shape_stroke_stops" stops-ptr n-stops)) + + (some? image) + (let [id (dm/get-prop image :id) + buffer (uuid/get-u32 id) + cached-image? (h/call internal-module "_is_image_cached" (aget buffer 0) (aget buffer 1) (aget buffer 2) (aget buffer 3))] + (h/call internal-module "_add_shape_image_stroke" + (aget buffer 0) + (aget buffer 1) + (aget buffer 2) + (aget buffer 3) + opacity + (dm/get-prop image :width) + (dm/get-prop image :height)) + (when (== cached-image? 0) + (store-image id))) + + (some? color) + (let [rgba (rgba-from-hex color opacity)] + (h/call internal-module "_add_shape_stroke_solid_fill" rgba))))) + strokes)) + (defn set-shape-path-content [content] (let [buffer (path/content->buffer content) @@ -280,6 +367,8 @@ transform (dm/get-prop shape :transform) fills (if (= type :group) [] (dm/get-prop shape :fills)) + strokes (if (= type :group) + [] (dm/get-prop shape :strokes)) children (dm/get-prop shape :shapes) blend-mode (dm/get-prop shape :blend-mode) opacity (dm/get-prop shape :opacity) @@ -297,8 +386,8 @@ (set-shape-opacity opacity) (set-shape-hidden hidden) (when (and (some? content) (= type :path)) (set-shape-path-content content)) - (let [pending-fills (doall (set-shape-fills fills))] - (recur (inc index) (into pending pending-fills)))) + (let [pending' (concat (set-shape-fills fills) (set-shape-strokes strokes))] + (recur (inc index) (into pending pending')))) pending))] (request-render) (when-let [pending (seq pending)] diff --git a/frontend/src/app/render_wasm/shape.cljs b/frontend/src/app/render_wasm/shape.cljs index 582c611039..9be274472e 100644 --- a/frontend/src/app/render_wasm/shape.cljs +++ b/frontend/src/app/render_wasm/shape.cljs @@ -117,6 +117,7 @@ :rotation (api/set-shape-rotation v) :transform (api/set-shape-transform v) :fills (api/set-shape-fills v) + :strokes (api/set-shape-strokes v) :blend-mode (api/set-shape-blend-mode v) :opacity (api/set-shape-opacity v) :hidden (api/set-shape-hidden v) diff --git a/frontend/src/app/util/dom.cljs b/frontend/src/app/util/dom.cljs index f13553a269..4257e8c36e 100644 --- a/frontend/src/app/util/dom.cljs +++ b/frontend/src/app/util/dom.cljs @@ -314,7 +314,8 @@ (defn set-html! [^js el html] (when (some? el) - (set! (.-innerHTML el) html))) + (set! (.-innerHTML el) html)) + el) (defn append-child! [^js el child] @@ -322,6 +323,16 @@ (.appendChild ^js el child)) el) +(defn insert-after! + [^js el ^js ref child] + (when (and (some? el) (some? ref)) + (let [nodes (.-childNodes el) + idx (d/index-of-pred nodes #(= ref %))] + (if-let [sibnode (unchecked-get nodes (inc idx))] + (.insertBefore el child sibnode) + (.appendChild ^js el child)))) + el) + (defn remove-child! [^js el child] (when (some? el) @@ -459,6 +470,11 @@ (when (some? node) (.focus node))) +(defn focus? + [^js node] + (and node + (= (.-activeElement js/document) node))) + (defn blur! [^js node] (when (some? node) @@ -525,7 +541,8 @@ (.setAttribute node property value)) node) -(defn get-text [^js node] +(defn get-text + [^js node] (when (some? node) (.-textContent node))) @@ -626,7 +643,8 @@ (defn set-data! [^js node ^string attr value] (when (some? node) - (.setAttribute node (dm/str "data-" attr) (dm/str value)))) + (.setAttribute node (dm/str "data-" attr) (dm/str value))) + node) (defn set-attribute! [^js node ^string attr value] (when (some? node) @@ -842,6 +860,11 @@ ([^js node deep?] (.cloneNode node deep?))) +(defn get-children + [node] + (when (some? node) + (.-children node))) + (defn has-children? [^js node] (> (-> node .-children .-length) 0)) @@ -861,3 +884,11 @@ ptk/EffectEvent (effect [_ _ _] (focus! (get-element name))))) + +(defn first-child + [^js node] + (.. node -firstChild)) + +(defn last-child + [^js node] + (.. node -lastChild)) diff --git a/frontend/src/app/util/keyboard.cljs b/frontend/src/app/util/keyboard.cljs index 5151b2f502..27ff1493a8 100644 --- a/frontend/src/app/util/keyboard.cljs +++ b/frontend/src/app/util/keyboard.cljs @@ -90,4 +90,5 @@ (def backspace? (is-key? "Backspace")) (def home? (is-key? "Home")) (def tab? (is-key? "Tab")) +(def delete? (is-key? "Delete")) diff --git a/frontend/src/app/util/queue.cljs b/frontend/src/app/util/queue.cljs index 564fd3cda8..4fbc72b302 100644 --- a/frontend/src/app/util/queue.cljs +++ b/frontend/src/app/util/queue.cljs @@ -9,6 +9,7 @@ (:require [app.common.logging :as l] [app.common.math :as mth] + [app.util.object :as obj] [app.util.time :as t] [beicon.v2.core :as rx])) @@ -47,13 +48,14 @@ ;; NOTE: Right now there are no cases where we need to cancel a process ;; but if we do, we can use this function -;; (defn- cancel-process -;; [queue] -;; (l/dbg :hint "queue::cancel-process") -;; (let [timeout (unchecked-get queue "timeout")] -;; (when (some? timeout) -;; (js/clearTimeout timeout)) -;; (unchecked-set queue "timeout" nil))) +(defn- cancel-process! + [queue] + (l/dbg :hint "queue::cancel-process") + (let [timeout (unchecked-get queue "timeout")] + (when (some? timeout) + (js/clearTimeout timeout)) + (unchecked-set queue "timeout" nil)) + queue) (defn- process [queue iterations] @@ -131,3 +133,10 @@ (enqueue-last queue request)))) (rx/to-observable result))) + +(defn clear! + [queue] + (-> queue + (cancel-process!) + (obj/set! "items" #js []) + (obj/set! "time" 0))) diff --git a/frontend/src/app/util/webapi.cljs b/frontend/src/app/util/webapi.cljs index 722067fe77..4a280f57ff 100644 --- a/frontend/src/app/util/webapi.cljs +++ b/frontend/src/app/util/webapi.cljs @@ -10,6 +10,7 @@ [app.common.data :as d] [app.common.exceptions :as ex] [app.common.logging :as log] + [app.util.globals :as globals] [app.util.object :as obj] [beicon.v2.core :as rx] [cuerdas.core :as str] @@ -264,3 +265,103 @@ (catch :default e (reject e)))))) (def empty-png-size (memoize empty-png-size*)) + +(defn create-range + [] + (let [document globals/document] + (.createRange document))) + +(defn select-contents! + [range node] + (when (and range node) + (.selectNodeContents range node)) + range) + +(defn select-all-children! + [^js selection ^js node] + (.selectAllChildren selection node)) + +(defn get-selection + [] + (when-let [document globals/document] + (.getSelection document))) + +(defn get-anchor-node + [^js selection] + (when selection + (.-anchorNode selection))) + +(defn get-anchor-offset + [^js selection] + (when selection + (.-anchorOffset selection))) + +(defn remove-all-ranges! + [^js sel] + (.removeAllRanges sel) + sel) + +(defn add-range! + [^js sel ^js range] + (.addRange sel range) + sel) + +(defn collapse-end! + [^js sel] + (.collapseToEnd sel) + sel) + +(defn set-cursor! + ([^js node] + (set-cursor! node 0)) + ([^js node offset] + (when node + (let [child-nodes (.-childNodes node) + sel (get-selection) + r (create-range)] + (if (= (.-length child-nodes) 0) + (do (.setStart r node offset) + (.setEnd r node offset) + (remove-all-ranges! sel) + (add-range! sel r)) + + (let [text-node (aget child-nodes 0)] + (.setStart r text-node offset) + (.setEnd r text-node offset) + (remove-all-ranges! sel) + (add-range! sel r))))))) + +(defn set-cursor-before! + [^js node] + (set-cursor! node 1)) + +(defn set-cursor-after! + [^js node] + (let [child-nodes (.-childNodes node) + first-child (aget child-nodes 0) + offset (if first-child (.-length first-child) 0)] + (set-cursor! node offset))) + +(defn get-range + [^js selection idx] + (.getRangeAt selection idx)) + +(defn range-start-container + [^js range] + (when range + (.-startContainer range))) + +(defn range-start-offset + [^js range] + (when range + (.-startOffset range))) + +(defn range-end-container + [^js range] + (when range + (.-endContainer range))) + +(defn range-end-offset + [^js range] + (when range + (.-endOffset range))) diff --git a/frontend/text-editor/src/editor/content/dom/Style.js b/frontend/text-editor/src/editor/content/dom/Style.js index a4a8837701..b7abe2f8b2 100644 --- a/frontend/text-editor/src/editor/content/dom/Style.js +++ b/frontend/text-editor/src/editor/content/dom/Style.js @@ -139,7 +139,7 @@ export function normalizeStyles(node, styleDefaults = getStyleDefaultsDeclaratio // a --fills CSS variable property. const fills = styleDeclaration.getPropertyValue("--fills"); const color = styleDeclaration.getPropertyValue("color"); - if (color) { + if (color && !fills) { styleDeclaration.removeProperty("color"); styleDeclaration.setProperty("--fills", getFills(color)); } else { diff --git a/frontend/translations/de.po b/frontend/translations/de.po index 106ddc76c2..2a8f833efe 100644 --- a/frontend/translations/de.po +++ b/frontend/translations/de.po @@ -1,7 +1,7 @@ msgid "" msgstr "" -"PO-Revision-Date: 2024-11-14 11:14+0000\n" -"Last-Translator: Anonymous \n" +"PO-Revision-Date: 2024-11-25 20:01+0000\n" +"Last-Translator: Stas Haas \n" "Language-Team: German \n" "Language: de\n" @@ -6079,3 +6079,88 @@ msgstr "Aktualisieren" #, unused msgid "workspace.viewport.click-to-close-path" msgstr "Klicken Sie, um den Pfad zu schließen" + +#: src/app/main/ui/workspace/sidebar/options/menus/fill.cljs:150 +msgid "workspace.options.fill.add-fill" +msgstr "Füllfarbe hinzufügen" + +#: src/app/main/ui/workspace/sidebar/options/menus/shadow.cljs:302 +msgid "workspace.options.shadow-options.add-shadow" +msgstr "Schatten hinzufügen" + +#: src/app/main/ui/workspace/sidebar/options/menus/shadow.cljs:177, src/app/main/ui/workspace/sidebar/options/menus/shadow.cljs:315 +msgid "workspace.options.shadow-options.remove-shadow" +msgstr "Schatten entfernen" + +#: src/app/main/ui/dashboard/fonts.cljs:444 +msgid "dashboard.fonts.empty-placeholder-viewer" +msgstr "Noch keine eigenen Schriftarten vorhanden." + +#: src/app/main/ui/dashboard/team.cljs:944 +msgid "dashboard.webhooks.cant-edit" +msgstr "Sie können nur von Ihnen erstellte Webhooks löschen oder ändern." + +#: src/app/main/data/common.cljs:233 +msgid "dashboard.removed-from-team" +msgstr "Sie sind nicht mehr Teil des Teams “%s“." + +#: src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs:271 +msgid "settings.remove-color" +msgstr "Farbe entfernen" + +#: src/app/main/ui/workspace/plugins.cljs:196 +msgid "workspace.plugins.error.manifest" +msgstr "Das Plugin-Manifest ist falsch." + +#: src/app/main/ui/dashboard/placeholder.cljs:32 +msgid "dashboard.empty-placeholder-libraries-title" +msgstr "Noch keine Bibliotheken vorhanden." + +#: src/app/main/data/common.cljs:204 +msgid "dashboard.permissions-change.editor" +msgstr "Sie sind jetzt ein Redakteur in diesem Team." + +#: src/app/main/data/common.cljs:203 +msgid "dashboard.permissions-change.viewer" +msgstr "Sie sind jetzt ein Zuschauer in diesem Team." + +#: src/app/main/ui/workspace/tokens/sets.cljs:153 +msgid "labels.collapse" +msgstr "Zusammenklappen" + +#: src/app/main/ui/workspace/sidebar/assets/colors.cljs:495 +msgid "workspace.assets.colors.add-color" +msgstr "Farbe hinzufügen" + +#: src/app/main/ui/workspace/sidebar/assets/components.cljs:532 +msgid "workspace.assets.components.add-component" +msgstr "Komponente hinzufügen" + +#: src/app/main/ui/workspace/right_header.cljs:255 +msgid "workspace.header.share" +msgstr "Teilen" + +#: src/app/main/ui/workspace/libraries.cljs:304 +msgid "workspace.libraries.more-templates-link" +msgstr "weitere Vorlagen sind hier" + +#: src/app/main/ui/comments.cljs:340, src/app/main/ui/workspace/sidebar/options/menus/text.cljs:295, src/app/main/ui/workspace/sidebar/options/menus/text.cljs:324 +msgid "labels.options" +msgstr "Optionen" + +#: src/app/main/ui/workspace/sidebar/options/menus/layout_container.cljs:1051 +#, unused +msgid "labels.add" +msgstr "Hinzufügen" + +#: src/app/main/ui/dashboard/files.cljs:186, src/app/main/ui/dashboard/projects.cljs:280 +msgid "dashboard.empty-placeholder-files-title" +msgstr "Noch keine Dateien vorhanden." + +#: src/app/main/data/common.cljs:205 +msgid "dashboard.permissions-change.admin" +msgstr "Sie sind jetzt ein Admin in diesem Team." + +#: src/app/main/ui/workspace/sidebar/versions.cljs:149, src/app/main/ui/workspace/sidebar/versions.cljs:288 +msgid "labels.restore" +msgstr "Wiederherstellen" diff --git a/frontend/translations/en.po b/frontend/translations/en.po index 2e3010559d..a69ddf28be 100644 --- a/frontend/translations/en.po +++ b/frontend/translations/en.po @@ -170,7 +170,7 @@ msgstr "The open-source solution for design and prototyping." msgid "auth.terms-and-privacy-agreement" msgstr "I agree to the [terms of service](%s) and [privacy policy](%s)." -#: src/app/main/ui/auth/register.cljs:290, src/app/main/ui/dashboard/sidebar.cljs:1022, src/app/main/ui/workspace/main_menu.cljs:154 +#: src/app/main/ui/auth/register.cljs:290, src/app/main/ui/dashboard/sidebar.cljs:1022, src/app/main/ui/workspace/main_menu.cljs:155 msgid "auth.terms-of-service" msgstr "Terms of service" @@ -392,22 +392,15 @@ msgstr "The token will expire on %s" msgid "dashboard.access-tokens.token-will-not-expire" msgstr "The token has no expiration date" -#: src/app/main/ui/dashboard/file_menu.cljs:311, src/app/main/ui/workspace/main_menu.cljs:585 +#: src/app/main/ui/dashboard/file_menu.cljs:311, src/app/main/ui/workspace/main_menu.cljs:614 msgid "dashboard.add-shared" msgstr "Add as Shared Library" -#: src/app/main/ui/workspace/main_menu.cljs:607 -msgid "dashboard.show-version-history" -msgstr "Version history" - -msgid "dashboard.create-version-menu" -msgstr "Pin this version" - #: src/app/main/ui/settings/profile.cljs:72 msgid "dashboard.change-email" msgstr "Change email" -#: src/app/main/data/dashboard.cljs:771, src/app/main/data/dashboard.cljs:991 +#: src/app/main/data/dashboard.cljs:773, src/app/main/data/dashboard.cljs:993 msgid "dashboard.copy-suffix" msgstr "(copy)" @@ -415,6 +408,10 @@ msgstr "(copy)" msgid "dashboard.create-new-team" msgstr "Create new team" +#: src/app/main/ui/workspace/main_menu.cljs:623 +msgid "dashboard.create-version-menu" +msgstr "Pin this version" + #: src/app/main/ui/components/context_menu_a11y.cljs:284, src/app/main/ui/dashboard/sidebar.cljs:646 msgid "dashboard.default-team-name" msgstr "Your Penpot" @@ -423,11 +420,11 @@ msgstr "Your Penpot" msgid "dashboard.delete-team" msgstr "Delete team" -#: src/app/main/ui/dashboard/file_menu.cljs:318, src/app/main/ui/dashboard/file_menu.cljs:323, src/app/main/ui/workspace/main_menu.cljs:603, src/app/main/ui/workspace/main_menu.cljs:612 +#: src/app/main/ui/dashboard/file_menu.cljs:318, src/app/main/ui/dashboard/file_menu.cljs:323, src/app/main/ui/workspace/main_menu.cljs:650, src/app/main/ui/workspace/main_menu.cljs:659 msgid "dashboard.download-binary-file" msgstr "Download Penpot file (.penpot)" -#: src/app/main/ui/dashboard/file_menu.cljs:328, src/app/main/ui/workspace/main_menu.cljs:621 +#: src/app/main/ui/dashboard/file_menu.cljs:328, src/app/main/ui/workspace/main_menu.cljs:668 msgid "dashboard.download-standard-file" msgstr "Download standard file (.svg + .json)" @@ -483,11 +480,11 @@ msgstr "No libraries yet." msgid "dashboard.export-binary-multi" msgstr "Download %s Penpot files (.penpot)" -#: src/app/main/ui/workspace/main_menu.cljs:629 +#: src/app/main/ui/workspace/main_menu.cljs:676 msgid "dashboard.export-frames" msgstr "Export boards as PDF" -#: src/app/main/ui/exports/assets.cljs:206 +#: src/app/main/ui/exports/assets.cljs:199 msgid "dashboard.export-frames.title" msgstr "Export as PDF" @@ -495,29 +492,29 @@ msgstr "Export as PDF" msgid "dashboard.export-multi" msgstr "Export Penpot %s files" -#: src/app/main/ui/exports/assets.cljs:113 +#: src/app/main/ui/exports/assets.cljs:106 msgid "dashboard.export-multiple.selected" msgstr "%s of %s elements selected" -#: src/app/main/ui/workspace/main_menu.cljs:591 +#: src/app/main/ui/workspace/main_menu.cljs:638 msgid "dashboard.export-shapes" msgstr "Export" -#: src/app/main/ui/exports/assets.cljs:184 +#: src/app/main/ui/exports/assets.cljs:177 msgid "dashboard.export-shapes.how-to" msgstr "" "You can add export settings to elements from the design properties (at the " "bottom of the right sidebar)." -#: src/app/main/ui/exports/assets.cljs:188 +#: src/app/main/ui/exports/assets.cljs:181 msgid "dashboard.export-shapes.how-to-link" msgstr "Info how to set exports at Penpot." -#: src/app/main/ui/exports/assets.cljs:183 +#: src/app/main/ui/exports/assets.cljs:176 msgid "dashboard.export-shapes.no-elements" msgstr "There are no elements with export settings." -#: src/app/main/ui/exports/assets.cljs:194 +#: src/app/main/ui/exports/assets.cljs:187 msgid "dashboard.export-shapes.title" msgstr "Export selection" @@ -633,7 +630,7 @@ msgstr "" msgid "dashboard.import" msgstr "Import Penpot files" -#: src/app/main/ui/dashboard/import.cljs:288, src/app/worker/import.cljs:843, src/app/worker/import.cljs:846 +#: src/app/main/ui/dashboard/import.cljs:288, src/app/worker/import.cljs:851, src/app/worker/import.cljs:854 msgid "dashboard.import.analyze-error" msgstr "Oops! We couldn't import this file" @@ -731,7 +728,7 @@ msgstr "Move to other team" msgid "dashboard.new-file" msgstr "+ New File" -#: src/app/main/data/dashboard.cljs:966, src/app/main/data/dashboard.cljs:1189 +#: src/app/main/data/dashboard.cljs:968, src/app/main/data/dashboard.cljs:1195 msgid "dashboard.new-file-prefix" msgstr "New File" @@ -739,7 +736,7 @@ msgstr "New File" msgid "dashboard.new-project" msgstr "+ New project" -#: src/app/main/data/dashboard.cljs:735, src/app/main/data/dashboard.cljs:1192 +#: src/app/main/data/dashboard.cljs:737, src/app/main/data/dashboard.cljs:1198 msgid "dashboard.new-project-prefix" msgstr "New Project" @@ -751,6 +748,14 @@ msgstr "No matches found for “%s“" msgid "dashboard.no-projects-placeholder" msgstr "Pinned projects will appear here" +#: src/app/main/ui/dashboard/comments.cljs +msgid "dashboard.notifications" +msgstr "Notifications" + +#: src/app/main/ui/dashboard/comments.cljs +msgid "dashboard.notifications.view" +msgstr "View notifications" + #: src/app/main/ui/auth/verify_token.cljs:32 msgid "dashboard.notifications.email-changed-successfully" msgstr "Your email address has been updated successfully" @@ -779,19 +784,19 @@ msgstr "Options" msgid "dashboard.password-change" msgstr "Change password" -#: src/app/main/data/common.cljs:205 +#: src/app/main/data/common.cljs:202 msgid "dashboard.permissions-change.admin" msgstr "You are now an admin on this team." -#: src/app/main/data/common.cljs:204 +#: src/app/main/data/common.cljs:201 msgid "dashboard.permissions-change.editor" msgstr "You are now an editor on this team." -#: src/app/main/data/common.cljs:206 +#: src/app/main/data/common.cljs:203 msgid "dashboard.permissions-change.owner" msgstr "You are now owner on this team." -#: src/app/main/data/common.cljs:203 +#: src/app/main/data/common.cljs:200 msgid "dashboard.permissions-change.viewer" msgstr "You are now a viewer on this team." @@ -812,7 +817,7 @@ msgstr "Want to remove your account?" msgid "dashboard.remove-shared" msgstr "Remove as Shared Library" -#: src/app/main/data/common.cljs:233 +#: src/app/main/data/common.cljs:235 msgid "dashboard.removed-from-team" msgstr "You are not part of the team “%s“ anymore." @@ -840,6 +845,10 @@ msgstr "Select theme" msgid "dashboard.show-all-files" msgstr "Show all files" +#: src/app/main/ui/workspace/main_menu.cljs:630 +msgid "dashboard.show-version-history" +msgstr "Version history" + #: src/app/main/ui/dashboard/file_menu.cljs:101 msgid "dashboard.success-delete-file" msgid_plural "dashboard.success-delete-file" @@ -896,7 +905,7 @@ msgstr "Search results" msgid "dashboard.type-something" msgstr "Type to search results" -#: src/app/main/ui/dashboard/file_menu.cljs:308, src/app/main/ui/workspace/main_menu.cljs:578 +#: src/app/main/ui/dashboard/file_menu.cljs:308, src/app/main/ui/workspace/main_menu.cljs:606 msgid "dashboard.unpublish-shared" msgstr "Unpublish Library" @@ -1024,7 +1033,7 @@ msgstr "The fonts %s could not be loaded" msgid "errors.cannot-upload" msgstr "Cannot upload the media file." -#: src/app/main/data/workspace.cljs:1672 +#: src/app/main/data/workspace.cljs:1698 msgid "errors.clipboard-not-implemented" msgstr "Your browser cannot do this operation" @@ -1480,71 +1489,71 @@ msgstr "Unset" msgid "inspect.attributes.typography.text-transform.uppercase" msgstr "Upper Case" -#: src/app/main/ui/viewer/inspect/right_sidebar.cljs:152 +#: src/app/main/ui/viewer/inspect/right_sidebar.cljs:157 msgid "inspect.empty.help" msgstr "If you want to know more about design inspect visit Penpot's help center" -#: src/app/main/ui/viewer/inspect/right_sidebar.cljs:155 +#: src/app/main/ui/viewer/inspect/right_sidebar.cljs:160 msgid "inspect.empty.more-info" msgstr "More info about inspect" -#: src/app/main/ui/viewer/inspect/right_sidebar.cljs:147 +#: src/app/main/ui/viewer/inspect/right_sidebar.cljs:152 msgid "inspect.empty.select" msgstr "Select a shape, board or group to inspect their properties and code" -#: src/app/main/ui/viewer/inspect/right_sidebar.cljs:100 +#: src/app/main/ui/viewer/inspect/right_sidebar.cljs:105 msgid "inspect.tabs.code" msgstr "Code" -#: src/app/main/ui/viewer/inspect/right_sidebar.cljs:124 +#: src/app/main/ui/viewer/inspect/right_sidebar.cljs:129 msgid "inspect.tabs.code.selected.circle" msgstr "Circle" -#: src/app/main/ui/viewer/inspect/right_sidebar.cljs:125 +#: src/app/main/ui/viewer/inspect/right_sidebar.cljs:130 msgid "inspect.tabs.code.selected.component" msgstr "Component" -#: src/app/main/ui/viewer/inspect/right_sidebar.cljs:126 +#: src/app/main/ui/viewer/inspect/right_sidebar.cljs:131 msgid "inspect.tabs.code.selected.curve" msgstr "Curve" -#: src/app/main/ui/viewer/inspect/right_sidebar.cljs:127 +#: src/app/main/ui/viewer/inspect/right_sidebar.cljs:132 msgid "inspect.tabs.code.selected.frame" msgstr "Board" -#: src/app/main/ui/viewer/inspect/right_sidebar.cljs:128 +#: src/app/main/ui/viewer/inspect/right_sidebar.cljs:133 msgid "inspect.tabs.code.selected.group" msgstr "Group" -#: src/app/main/ui/viewer/inspect/right_sidebar.cljs:129 +#: src/app/main/ui/viewer/inspect/right_sidebar.cljs:134 msgid "inspect.tabs.code.selected.image" msgstr "Image" -#: src/app/main/ui/viewer/inspect/right_sidebar.cljs:130 +#: src/app/main/ui/viewer/inspect/right_sidebar.cljs:135 msgid "inspect.tabs.code.selected.mask" msgstr "Mask" -#: src/app/main/ui/viewer/inspect/right_sidebar.cljs:119 +#: src/app/main/ui/viewer/inspect/right_sidebar.cljs:124 msgid "inspect.tabs.code.selected.multiple" msgstr "%s Selected" -#: src/app/main/ui/viewer/inspect/right_sidebar.cljs:131 +#: src/app/main/ui/viewer/inspect/right_sidebar.cljs:136 msgid "inspect.tabs.code.selected.path" msgstr "Path" -#: src/app/main/ui/viewer/inspect/right_sidebar.cljs:132 +#: src/app/main/ui/viewer/inspect/right_sidebar.cljs:137 msgid "inspect.tabs.code.selected.rect" msgstr "Rectangle" -#: src/app/main/ui/viewer/inspect/right_sidebar.cljs:133 +#: src/app/main/ui/viewer/inspect/right_sidebar.cljs:138 msgid "inspect.tabs.code.selected.svg-raw" msgstr "SVG" -#: src/app/main/ui/viewer/inspect/right_sidebar.cljs:134 +#: src/app/main/ui/viewer/inspect/right_sidebar.cljs:139 msgid "inspect.tabs.code.selected.text" msgstr "Text" -#: src/app/main/ui/viewer/inspect/right_sidebar.cljs:96 +#: src/app/main/ui/viewer/inspect/right_sidebar.cljs:101 msgid "inspect.tabs.info" msgstr "Info" @@ -1553,11 +1562,11 @@ msgstr "Info" msgid "intersection" msgstr "" -#: src/app/main/ui/workspace/main_menu.cljs:162 +#: src/app/main/ui/workspace/main_menu.cljs:163 msgid "label.shortcuts" msgstr "Shortcuts" -#: src/app/main/data/common.cljs:93, src/app/main/ui/dashboard/import.cljs:503 +#: src/app/main/data/common.cljs:90, src/app/main/ui/dashboard/import.cljs:503 msgid "labels.accept" msgstr "Accept" @@ -1612,7 +1621,7 @@ msgstr "" msgid "labels.bad-gateway.main-message" msgstr "Bad Gateway" -#: src/app/main/data/common.cljs:131, src/app/main/ui/dashboard/change_owner.cljs:68, src/app/main/ui/dashboard/import.cljs:489, src/app/main/ui/dashboard/team.cljs:906, src/app/main/ui/delete_shared.cljs:35, src/app/main/ui/exports/assets.cljs:168, src/app/main/ui/exports/files.cljs:192, src/app/main/ui/settings/access_tokens.cljs:177, src/app/main/ui/viewer/share_link.cljs:205, src/app/main/ui/workspace/sidebar/assets/groups.cljs:145, src/app/main/ui/workspace/tokens/form.cljs:429, src/app/main/ui/workspace/tokens/modals/themes.cljs:203 +#: src/app/main/data/common.cljs:128, src/app/main/ui/dashboard/change_owner.cljs:68, src/app/main/ui/dashboard/import.cljs:489, src/app/main/ui/dashboard/team.cljs:906, src/app/main/ui/delete_shared.cljs:35, src/app/main/ui/exports/assets.cljs:161, src/app/main/ui/exports/files.cljs:192, src/app/main/ui/settings/access_tokens.cljs:177, src/app/main/ui/viewer/share_link.cljs:205, src/app/main/ui/workspace/sidebar/assets/groups.cljs:145, src/app/main/ui/workspace/tokens/form.cljs:431, src/app/main/ui/workspace/tokens/modals/themes.cljs:203 msgid "labels.cancel" msgstr "Cancel" @@ -1620,19 +1629,26 @@ msgstr "Cancel" msgid "labels.canva" msgstr "Canva" -#: src/app/main/ui/dashboard/projects.cljs:96, src/app/main/ui/exports/files.cljs:210, src/app/main/ui/settings/access_tokens.cljs:172, src/app/main/ui/viewer/login.cljs:71, src/app/main/ui/viewer/share_link.cljs:176, src/app/main/ui/workspace/comments.cljs:129, src/app/main/ui/workspace/libraries.cljs:538, src/app/main/ui/workspace/sidebar/debug.cljs:40, src/app/main/ui/workspace/sidebar/layers.cljs:299, src/app/main/ui/workspace/tokens/modals/themes.cljs:366, src/app/main/ui/workspace/tokens/modals.cljs:56 +#: src/app/main/ui/dashboard/projects.cljs:96, src/app/main/ui/exports/files.cljs:210, src/app/main/ui/settings/access_tokens.cljs:172, src/app/main/ui/viewer/login.cljs:71, src/app/main/ui/viewer/share_link.cljs:176, src/app/main/ui/workspace/comments.cljs:129, src/app/main/ui/workspace/libraries.cljs:538, src/app/main/ui/workspace/sidebar/debug.cljs:40, src/app/main/ui/workspace/sidebar/layers.cljs:300, src/app/main/ui/workspace/tokens/modals/themes.cljs:366, src/app/main/ui/workspace/tokens/modals.cljs:56 msgid "labels.close" msgstr "Close" -#: src/app/main/ui/workspace/tokens/sets.cljs:153 +#: src/app/main/ui/workspace/tokens/sets.cljs:96 msgid "labels.collapse" msgstr "Collapse" +msgid "labels.comment" +msgstr "Comment" + +#: src/app/main/ui/comments.cljs:446 +msgid "labels.comment.mark-as-solved" +msgstr "Mark as solved" + #: src/app/main/ui/dashboard/comments.cljs:104, src/app/main/ui/viewer/comments.cljs:70, src/app/main/ui/workspace/comments.cljs:127 msgid "labels.comments" msgstr "Comments" -#: src/app/main/ui/dashboard/sidebar.cljs:985, src/app/main/ui/workspace/main_menu.cljs:114 +#: src/app/main/ui/dashboard/sidebar.cljs:985, src/app/main/ui/workspace/main_menu.cljs:115 msgid "labels.community" msgstr "Community" @@ -1664,11 +1680,11 @@ msgstr "Kaleidos @2024" msgid "labels.create" msgstr "Create" -#: src/app/main/ui/dashboard/team_form.cljs:101, src/app/main/ui/dashboard/team_form.cljs:121 +#: src/app/main/ui/dashboard/team_form.cljs:103, src/app/main/ui/dashboard/team_form.cljs:123 msgid "labels.create-team" msgstr "Create new team" -#: src/app/main/ui/dashboard/team_form.cljs:113 +#: src/app/main/ui/dashboard/team_form.cljs:115 msgid "labels.create-team.placeholder" msgstr "Enter new team name" @@ -1680,7 +1696,7 @@ msgstr "Custom fonts" msgid "labels.dashboard" msgstr "Dashboard" -#: src/app/main/ui/dashboard/file_menu.cljs:336, src/app/main/ui/dashboard/fonts.cljs:256, src/app/main/ui/dashboard/fonts.cljs:332, src/app/main/ui/dashboard/fonts.cljs:346, src/app/main/ui/dashboard/project_menu.cljs:114, src/app/main/ui/dashboard/team.cljs:942, src/app/main/ui/settings/access_tokens.cljs:198, src/app/main/ui/workspace/sidebar/options/menus/component.cljs:209, src/app/main/ui/workspace/sidebar/versions.cljs:152, src/app/main/ui/workspace/tokens/form.cljs:425, src/app/main/ui/workspace/tokens/modals/themes.cljs:335, src/app/main/ui/workspace/tokens/sets_context_menu.cljs:44 +#: src/app/main/ui/dashboard/file_menu.cljs:336, src/app/main/ui/dashboard/fonts.cljs:256, src/app/main/ui/dashboard/fonts.cljs:332, src/app/main/ui/dashboard/fonts.cljs:346, src/app/main/ui/dashboard/project_menu.cljs:114, src/app/main/ui/dashboard/team.cljs:942, src/app/main/ui/settings/access_tokens.cljs:198, src/app/main/ui/workspace/sidebar/options/menus/component.cljs:209, src/app/main/ui/workspace/sidebar/versions.cljs:153, src/app/main/ui/workspace/tokens/form.cljs:427, src/app/main/ui/workspace/tokens/modals/themes.cljs:335, src/app/main/ui/workspace/tokens/sets_context_menu.cljs:44 msgid "labels.delete" msgstr "Delete" @@ -1716,7 +1732,7 @@ msgstr "Discard" msgid "labels.drafts" msgstr "Drafts" -#: src/app/main/ui/comments.cljs:356, src/app/main/ui/dashboard/fonts.cljs:253, src/app/main/ui/dashboard/team.cljs:940, src/app/main/ui/workspace/sidebar/options/menus/component.cljs:205, src/app/main/ui/workspace/tokens/sidebar.cljs:199 +#: src/app/main/ui/comments.cljs:356, src/app/main/ui/dashboard/fonts.cljs:253, src/app/main/ui/dashboard/team.cljs:940, src/app/main/ui/workspace/sidebar/options/menus/component.cljs:205, src/app/main/ui/workspace/tokens/sidebar.cljs:200 msgid "labels.edit" msgstr "Edit" @@ -1736,7 +1752,7 @@ msgstr "Event" msgid "labels.expired-invitation" msgstr "Expired" -#: src/app/main/ui/exports/assets.cljs:177 +#: src/app/main/ui/exports/assets.cljs:170 msgid "labels.export" msgstr "Export" @@ -1776,11 +1792,11 @@ msgstr "CEO or Founder" msgid "labels.freelancer" msgstr "Freelancer" -#: src/app/main/ui/dashboard/sidebar.cljs:1015, src/app/main/ui/workspace/main_menu.cljs:146 +#: src/app/main/ui/dashboard/sidebar.cljs:1015, src/app/main/ui/workspace/main_menu.cljs:147 msgid "labels.github-repo" msgstr "Github repository" -#: src/app/main/ui/dashboard/sidebar.cljs:1032, src/app/main/ui/settings/sidebar.cljs:113, src/app/main/ui/workspace/main_menu.cljs:175 +#: src/app/main/ui/dashboard/sidebar.cljs:1032, src/app/main/ui/settings/sidebar.cljs:113, src/app/main/ui/workspace/main_menu.cljs:176 msgid "labels.give-feedback" msgstr "Give feedback" @@ -1792,7 +1808,7 @@ msgstr "Go back" msgid "labels.graphic-design" msgstr "Graphic design" -#: src/app/main/ui/dashboard/sidebar.cljs:978, src/app/main/ui/workspace/main_menu.cljs:106, src/app/main/ui/workspace/sidebar/options/menus/layout_container.cljs:1079, src/app/main/ui/workspace/sidebar/options/menus/layout_container.cljs:1104, src/app/main/ui/workspace/sidebar/options/menus/layout_container.cljs:1290 +#: src/app/main/ui/dashboard/sidebar.cljs:978, src/app/main/ui/workspace/main_menu.cljs:107, src/app/main/ui/workspace/sidebar/options/menus/layout_container.cljs:1079, src/app/main/ui/workspace/sidebar/options/menus/layout_container.cljs:1104, src/app/main/ui/workspace/sidebar/options/menus/layout_container.cljs:1290 msgid "labels.help-center" msgstr "Help Center" @@ -1830,11 +1846,11 @@ msgstr "Invitations" msgid "labels.language" msgstr "Language" -#: src/app/main/ui/dashboard/sidebar.cljs:1008, src/app/main/ui/workspace/main_menu.cljs:138 +#: src/app/main/ui/dashboard/sidebar.cljs:1008, src/app/main/ui/workspace/main_menu.cljs:139 msgid "labels.libraries-and-templates" msgstr "Libraries & Templates" -#: src/app/main/ui/auth/verify_token.cljs:97, src/app/main/ui/dashboard/grid.cljs:104, src/app/main/ui/dashboard/grid.cljs:124, src/app/main/ui/dashboard/import.cljs:253, src/app/main/ui/dashboard/placeholder.cljs:52, src/app/main/ui/ds/product/loader.cljs:52, src/app/main/ui/exports/files.cljs:62, src/app/main/ui/viewer.cljs:637, src/app/main/ui/workspace.cljs:129 +#: src/app/main/ui/auth/verify_token.cljs:97, src/app/main/ui/dashboard/grid.cljs:104, src/app/main/ui/dashboard/grid.cljs:124, src/app/main/ui/dashboard/import.cljs:253, src/app/main/ui/dashboard/placeholder.cljs:52, src/app/main/ui/ds/product/loader.cljs:52, src/app/main/ui/exports/files.cljs:62, src/app/main/ui/viewer.cljs:637, src/app/main/ui/workspace.cljs:130 msgid "labels.loading" msgstr "Loading…" @@ -1951,6 +1967,10 @@ msgstr "Password" msgid "labels.pending-invitation" msgstr "Pending" +#: src/app/main/ui/comments.cljs:147 +msgid "labels.post" +msgstr "Post" + #: src/app/main/ui/onboarding/questions.cljs:51 msgid "labels.previous" msgstr "Previous" @@ -1971,7 +1991,7 @@ msgstr "Profile" msgid "labels.projects" msgstr "Projects" -#: src/app/main/ui/dashboard/sidebar.cljs:998, src/app/main/ui/settings/sidebar.cljs:106, src/app/main/ui/workspace/main_menu.cljs:130 +#: src/app/main/ui/dashboard/sidebar.cljs:998, src/app/main/ui/settings/sidebar.cljs:106, src/app/main/ui/workspace/main_menu.cljs:131 msgid "labels.release-notes" msgstr "Release notes" @@ -1989,19 +2009,39 @@ msgstr "Remove" msgid "labels.remove-member" msgstr "Remove member" -#: src/app/main/ui/dashboard/file_menu.cljs:288, src/app/main/ui/dashboard/project_menu.cljs:87, src/app/main/ui/dashboard/sidebar.cljs:539, src/app/main/ui/workspace/sidebar/assets/groups.cljs:153, src/app/main/ui/workspace/sidebar/versions.cljs:146, src/app/main/ui/workspace/tokens/sets_context_menu.cljs:43 +#: src/app/main/ui/dashboard/file_menu.cljs:288, src/app/main/ui/dashboard/project_menu.cljs:87, src/app/main/ui/dashboard/sidebar.cljs:539, src/app/main/ui/workspace/sidebar/assets/groups.cljs:153, src/app/main/ui/workspace/sidebar/versions.cljs:147, src/app/main/ui/workspace/tokens/sets_context_menu.cljs:43 msgid "labels.rename" msgstr "Rename" -#: src/app/main/ui/dashboard/team_form.cljs:99 +#: src/app/main/ui/dashboard/team_form.cljs:101 msgid "labels.rename-team" msgstr "Rename team" +#: src/app/main/ui/comments.cljs:145 +msgid "labels.reply" +msgstr "reply" + +#: src/app/main/ui/comments.cljs:150 +msgid "labels.reply.new" +msgstr "new reply" + +#: src/app/main/ui/comments.cljs:188 +msgid "labels.reply.thread" +msgstr "Reply" + +#: src/app/main/ui/comments.cljs:146 +msgid "labels.replies" +msgstr "replies" + +#: src/app/main/ui/comments.cljs:151 +msgid "labels.replies.new" +msgstr "new replies" + #: src/app/main/ui/dashboard/team.cljs:681 msgid "labels.resend-invitation" msgstr "Resend invitation" -#: src/app/main/ui/workspace/sidebar/versions.cljs:149, src/app/main/ui/workspace/sidebar/versions.cljs:288 +#: src/app/main/ui/workspace/sidebar/versions.cljs:150, src/app/main/ui/workspace/sidebar/versions.cljs:290 msgid "labels.restore" msgstr "Restore" @@ -2013,7 +2053,7 @@ msgstr "Retry" msgid "labels.role" msgstr "Role" -#: src/app/main/ui/dashboard/fonts.cljs:382, src/app/main/ui/workspace/sidebar/options/menus/component.cljs:191, src/app/main/ui/workspace/tokens/form.cljs:433 +#: src/app/main/ui/dashboard/fonts.cljs:382, src/app/main/ui/workspace/sidebar/options/menus/component.cljs:191, src/app/main/ui/workspace/tokens/form.cljs:435 msgid "labels.save" msgstr "Save" @@ -2045,7 +2085,7 @@ msgstr "We are in programmed maintenance of our systems." msgid "labels.service-unavailable.main-message" msgstr "Service Unavailable" -#: src/app/main/ui/workspace/tokens/sidebar.cljs:229 +#: src/app/main/ui/workspace/tokens/sidebar.cljs:246 msgid "labels.sets" msgstr "Sets" @@ -2077,6 +2117,9 @@ msgstr "Show comments list" msgid "labels.show-your-comments" msgstr "Show only your comments" +msgid "labels.show-mentions" +msgstr "Show only your mentions" + #: src/app/main/ui/onboarding/questions.cljs:167 msgid "labels.sketch" msgstr "Sketch" @@ -2105,7 +2148,7 @@ msgstr "Team member" msgid "labels.themes" msgstr "Themes" -#: src/app/main/ui/dashboard/sidebar.cljs:992, src/app/main/ui/workspace/main_menu.cljs:122 +#: src/app/main/ui/dashboard/sidebar.cljs:992, src/app/main/ui/workspace/main_menu.cljs:123 msgid "labels.tutorials" msgstr "Tutorials" @@ -2117,7 +2160,7 @@ msgstr "Unpublish %s files" msgid "labels.update" msgstr "Update" -#: src/app/main/ui/dashboard/team_form.cljs:120 +#: src/app/main/ui/dashboard/team_form.cljs:122 msgid "labels.update-team" msgstr "Update team" @@ -2161,14 +2204,15 @@ msgstr "Your account" msgid "labels.youtube" msgstr "YouTube" -#: src/app/main/ui/workspace/colorpicker.cljs:344, src/app/main/ui/workspace/colorpicker.cljs:345, src/app/main/ui/workspace/colorpicker.cljs:347 +#: src/app/main/ui/workspace/colorpicker.cljs:475, src/app/main/ui/workspace/colorpicker.cljs:476, src/app/main/ui/workspace/colorpicker.cljs:478 msgid "media.choose-image" msgstr "Choose image" +#: src/app/main/ui/workspace/colorpicker.cljs:243 msgid "media.gradient" msgstr "Gradient" -#: src/app/main/data/workspace/media.cljs:272, src/app/main/ui/components/color_bullet.cljs:32, src/app/main/ui/components/color_bullet.cljs:45, src/app/main/ui/viewer/inspect/attributes/common.cljs:66, src/app/main/ui/workspace/colorpicker.cljs:231, src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs:240 +#: src/app/main/data/workspace/media.cljs:272, src/app/main/ui/components/color_bullet.cljs:34, src/app/main/ui/components/color_bullet.cljs:47, src/app/main/ui/viewer/inspect/attributes/common.cljs:66, src/app/main/ui/workspace/colorpicker.cljs:245, src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs:240 msgid "media.image" msgstr "Image" @@ -2176,11 +2220,12 @@ msgstr "Image" msgid "media.image.short" msgstr "img" -#: src/app/main/ui/workspace/colorpicker.cljs:337 +#: src/app/main/ui/workspace/colorpicker.cljs:468 msgid "media.keep-aspect-ratio" msgstr "Keep aspect ratio" #: src/app/main/ui/workspace/colorpicker.cljs:228 +#, unused msgid "media.linear" msgstr "Linear" @@ -2189,31 +2234,32 @@ msgid "media.loading" msgstr "Loading image…" #: src/app/main/ui/workspace/colorpicker.cljs:229 +#, unused msgid "media.radial" msgstr "Radial" -#: src/app/main/ui/workspace/colorpicker.cljs:226 +#: src/app/main/ui/workspace/colorpicker.cljs:241 msgid "media.solid" msgstr "Solid" -#: src/app/main/data/common.cljs:130 +#: src/app/main/data/common.cljs:127 msgid "modals.add-shared-confirm-empty.hint" msgstr "" "Your library is empty. Once added as Shared Library, the assets you create " "will be available to be used among the rest of your files. Are you sure you " "want to publish it?" -#: src/app/main/data/common.cljs:132 +#: src/app/main/data/common.cljs:129 msgid "modals.add-shared-confirm.accept" msgstr "Add as Shared Library" -#: src/app/main/data/common.cljs:130 +#: src/app/main/data/common.cljs:127 msgid "modals.add-shared-confirm.hint" msgstr "" "Once added as Shared Library, the assets of this file library will be " "available to be used among the rest of your files." -#: src/app/main/data/common.cljs:129 +#: src/app/main/data/common.cljs:126 msgid "modals.add-shared-confirm.message" msgstr "Add “%s” as Shared Library" @@ -2380,11 +2426,11 @@ msgstr "" msgid "modals.delete-font.title" msgstr "Deleting font" -#: src/app/main/ui/workspace/context_menu.cljs:533, src/app/main/ui/workspace/sidebar/sitemap.cljs:46 +#: src/app/main/ui/workspace/context_menu.cljs:539, src/app/main/ui/workspace/sidebar/sitemap.cljs:46 msgid "modals.delete-page.body" msgstr "Are you sure you want to delete this page?" -#: src/app/main/ui/workspace/context_menu.cljs:532, src/app/main/ui/workspace/sidebar/sitemap.cljs:45 +#: src/app/main/ui/workspace/context_menu.cljs:538, src/app/main/ui/workspace/sidebar/sitemap.cljs:45 msgid "modals.delete-page.title" msgstr "Delete page" @@ -2574,7 +2620,7 @@ msgid_plural "modals.move-shared-confirm.title" msgstr[0] "Move library" msgstr[1] "Move libraries" -#: src/app/main/ui/workspace/main_menu.cljs:271, src/app/main/ui/workspace/nudge.cljs:47 +#: src/app/main/ui/workspace/main_menu.cljs:272, src/app/main/ui/workspace/nudge.cljs:47 msgid "modals.nudge-title" msgstr "Nudge amount" @@ -2661,21 +2707,21 @@ msgstr "" msgid "modals.update-remote-component-in-bulk.message" msgstr "Update components in a shared library" -#: src/app/main/ui/workspace/sidebar/assets/common.cljs:380 +#: src/app/main/ui/workspace/sidebar/assets/common.cljs:384 msgid "modals.update-remote-component.accept" msgstr "Update" -#: src/app/main/ui/workspace/sidebar/assets/common.cljs:379 +#: src/app/main/ui/workspace/sidebar/assets/common.cljs:383 msgid "modals.update-remote-component.cancel" msgstr "Cancel" -#: src/app/main/ui/workspace/sidebar/assets/common.cljs:378 +#: src/app/main/ui/workspace/sidebar/assets/common.cljs:382 msgid "modals.update-remote-component.hint" msgstr "" "You are about to update a component in a shared library. This may affect " "other files that use it." -#: src/app/main/ui/workspace/sidebar/assets/common.cljs:377 +#: src/app/main/ui/workspace/sidebar/assets/common.cljs:381 msgid "modals.update-remote-component.message" msgstr "Update a component in a shared library" @@ -2779,11 +2825,11 @@ msgstr "To access this file, you can ask the team owner." msgid "not-found.no-permission.you-can-ask.project" msgstr "To access this project, you can ask the team owner." -#: src/app/main/data/common.cljs:90 +#: src/app/main/data/common.cljs:87 msgid "notifications.by-code.maintenance" msgstr "Maintenance break: we will be down for a short maintenance within 5 minutes." -#: src/app/main/data/common.cljs:81 +#: src/app/main/data/common.cljs:78 msgid "notifications.by-code.upgrade-version" msgstr "A new version is available, please refresh the page" @@ -3155,7 +3201,7 @@ msgstr "Go to login" msgid "settings.detach" msgstr "Detach" -#: src/app/main/ui/viewer/inspect/exports.cljs:155, src/app/main/ui/workspace/sidebar/options/menus/component.cljs:632, src/app/main/ui/workspace/sidebar/options/menus/constraints.cljs:137, src/app/main/ui/workspace/sidebar/options/menus/constraints.cljs:148, src/app/main/ui/workspace/sidebar/options/menus/exports.cljs:204, src/app/main/ui/workspace/sidebar/options/menus/fill.cljs:161, src/app/main/ui/workspace/sidebar/options/menus/measures.cljs:470, src/app/main/ui/workspace/sidebar/options/menus/measures.cljs:476, src/app/main/ui/workspace/sidebar/options/menus/measures.cljs:494, src/app/main/ui/workspace/sidebar/options/menus/measures.cljs:500, src/app/main/ui/workspace/sidebar/options/menus/measures.cljs:526, src/app/main/ui/workspace/sidebar/options/menus/measures.cljs:537, src/app/main/ui/workspace/sidebar/options/menus/measures.cljs:554, src/app/main/ui/workspace/sidebar/options/menus/measures.cljs:569, src/app/main/ui/workspace/sidebar/options/menus/measures.cljs:576, src/app/main/ui/workspace/sidebar/options/menus/shadow.cljs:312, src/app/main/ui/workspace/sidebar/options/menus/stroke.cljs:182, src/app/main/ui/workspace/sidebar/options/menus/typography.cljs:378, src/app/main/ui/workspace/sidebar/options/menus/typography.cljs:395, src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs:248, src/app/main/ui/workspace/sidebar/options/rows/stroke_row.cljs:172 +#: src/app/main/ui/viewer/inspect/exports.cljs:147, src/app/main/ui/workspace/sidebar/options/menus/component.cljs:632, src/app/main/ui/workspace/sidebar/options/menus/constraints.cljs:137, src/app/main/ui/workspace/sidebar/options/menus/constraints.cljs:148, src/app/main/ui/workspace/sidebar/options/menus/exports.cljs:196, src/app/main/ui/workspace/sidebar/options/menus/fill.cljs:161, src/app/main/ui/workspace/sidebar/options/menus/measures.cljs:470, src/app/main/ui/workspace/sidebar/options/menus/measures.cljs:476, src/app/main/ui/workspace/sidebar/options/menus/measures.cljs:494, src/app/main/ui/workspace/sidebar/options/menus/measures.cljs:500, src/app/main/ui/workspace/sidebar/options/menus/measures.cljs:526, src/app/main/ui/workspace/sidebar/options/menus/measures.cljs:537, src/app/main/ui/workspace/sidebar/options/menus/measures.cljs:554, src/app/main/ui/workspace/sidebar/options/menus/measures.cljs:569, src/app/main/ui/workspace/sidebar/options/menus/measures.cljs:576, src/app/main/ui/workspace/sidebar/options/menus/shadow.cljs:312, src/app/main/ui/workspace/sidebar/options/menus/stroke.cljs:182, src/app/main/ui/workspace/sidebar/options/menus/typography.cljs:378, src/app/main/ui/workspace/sidebar/options/menus/typography.cljs:395, src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs:248, src/app/main/ui/workspace/sidebar/options/rows/stroke_row.cljs:172 msgid "settings.multiple" msgstr "Mixed" @@ -3168,19 +3214,19 @@ msgid "settings.select-this-color" msgstr "Select items using this style" # SECTIONS -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:414 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:416 msgid "shortcut-section.basics" msgstr "Basics" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:420 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:422 msgid "shortcut-section.dashboard" msgstr "Dashboard" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:423 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:425 msgid "shortcut-section.viewer" msgstr "Viewer" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:417 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:419 msgid "shortcut-section.workspace" msgstr "Workspace" @@ -3201,7 +3247,7 @@ msgstr "Generic" msgid "shortcut-subsection.general-viewer" msgstr "Generic" -#: src/app/main/ui/workspace/main_menu.cljs:777, src/app/main/ui/workspace/sidebar/shortcuts.cljs:60 +#: src/app/main/ui/workspace/main_menu.cljs:824, src/app/main/ui/workspace/sidebar/shortcuts.cljs:60 msgid "shortcut-subsection.main-menu" msgstr "Main menu" @@ -3338,498 +3384,503 @@ msgid "shortcuts.copy" msgstr "Copy" #: src/app/main/ui/workspace/sidebar/shortcuts.cljs:94 +msgid "shortcuts.copy-link" +msgstr "Copy link to clipboard" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:95 msgid "shortcuts.create-component" msgstr "Create component" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:95 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:96 msgid "shortcuts.create-new-project" msgstr "Create new" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:96 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:97 msgid "shortcuts.cut" msgstr "Cut" -#: src/app/main/ui/workspace/right_header.cljs:115, src/app/main/ui/workspace/sidebar/shortcuts.cljs:97 +#: src/app/main/ui/workspace/right_header.cljs:115, src/app/main/ui/workspace/sidebar/shortcuts.cljs:98 msgid "shortcuts.decrease-zoom" msgstr "Zoom out" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:98 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:99 msgid "shortcuts.delete" msgstr "Delete" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:99 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:100 msgid "shortcuts.delete-node" msgstr "Delete node" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:100 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:101 msgid "shortcuts.detach-component" msgstr "Detach component" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:101 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:102 msgid "shortcuts.draw-curve" msgstr "Curve" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:102 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:103 msgid "shortcuts.draw-ellipse" msgstr "Ellipse" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:103 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:104 msgid "shortcuts.draw-frame" msgstr "Board" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:104 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:105 msgid "shortcuts.draw-nodes" msgstr "Draw path" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:105 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:106 msgid "shortcuts.draw-path" msgstr "Path" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:106 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:107 msgid "shortcuts.draw-rect" msgstr "Rectangle" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:107 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:108 msgid "shortcuts.draw-text" msgstr "Text" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:108 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:109 msgid "shortcuts.duplicate" msgstr "Duplicate" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:109 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:110 msgid "shortcuts.escape" msgstr "Cancel" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:110 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:111 msgid "shortcuts.export-shapes" msgstr "Export shapes" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:111 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:112 msgid "shortcuts.fit-all" msgstr "Zoom to fit all" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:112 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:113 msgid "shortcuts.flip-horizontal" msgstr "Flip horizontally" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:113 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:114 msgid "shortcuts.flip-vertical" msgstr "Flip vertically" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:114 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:115 msgid "shortcuts.font-size-dec" msgstr "Decrement font size" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:115 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:116 msgid "shortcuts.font-size-inc" msgstr "Increment font size" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:116 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:117 msgid "shortcuts.go-to-drafts" msgstr "Go to drafts" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:117 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:118 msgid "shortcuts.go-to-libs" msgstr "Go to shared libraries" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:118 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:119 msgid "shortcuts.go-to-search" msgstr "Search" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:119 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:120 msgid "shortcuts.group" msgstr "Group" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:120 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:121 msgid "shortcuts.h-distribute" msgstr "Distribute horizontally" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:121 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:122 msgid "shortcuts.hide-ui" msgstr "Show / Hide UI" -#: src/app/main/ui/workspace/right_header.cljs:120, src/app/main/ui/workspace/sidebar/shortcuts.cljs:122 +#: src/app/main/ui/workspace/right_header.cljs:120, src/app/main/ui/workspace/sidebar/shortcuts.cljs:123 msgid "shortcuts.increase-zoom" msgstr "Zoom in" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:123 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:124 msgid "shortcuts.insert-image" msgstr "Insert image" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:124 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:125 msgid "shortcuts.italic" msgstr "Toggle italic" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:125 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:126 msgid "shortcuts.join-nodes" msgstr "Join nodes" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:126 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:127 msgid "shortcuts.letter-spacing-dec" msgstr "Decrement letter spacing" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:127 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:128 msgid "shortcuts.letter-spacing-inc" msgstr "Increment letter spacing" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:128 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:129 msgid "shortcuts.line-height-dec" msgstr "Decrement line height" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:129 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:130 msgid "shortcuts.line-height-inc" msgstr "Increment line height" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:130 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:131 msgid "shortcuts.line-through" msgstr "Toggle line through" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:131 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:132 msgid "shortcuts.make-corner" msgstr "Make corner" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:132 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:133 msgid "shortcuts.make-curve" msgstr "Make curve" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:133 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:134 msgid "shortcuts.mask" msgstr "Mask" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:134 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:135 msgid "shortcuts.merge-nodes" msgstr "Merge nodes" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:135 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:136 msgid "shortcuts.move" msgstr "Move" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:136 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:137 msgid "shortcuts.move-fast-down" msgstr "Move down fast" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:137 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:138 msgid "shortcuts.move-fast-left" msgstr "Move left fast" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:138 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:139 msgid "shortcuts.move-fast-right" msgstr "Move right fast" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:139 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:140 msgid "shortcuts.move-fast-up" msgstr "Move up fast" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:140 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:141 msgid "shortcuts.move-nodes" msgstr "Move node" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:141 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:142 msgid "shortcuts.move-unit-down" msgstr "Move down" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:142 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:143 msgid "shortcuts.move-unit-left" msgstr "Move left" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:143 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:144 msgid "shortcuts.move-unit-right" msgstr "Move right" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:144 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:145 msgid "shortcuts.move-unit-up" msgstr "Move up" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:145 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:146 msgid "shortcuts.next-frame" msgstr "Next board" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:516 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:518 msgid "shortcuts.not-found" msgstr "No shortcuts found" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:146 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:147 msgid "shortcuts.opacity-0" msgstr "Set opacity to 100%" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:147 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:148 msgid "shortcuts.opacity-1" msgstr "Set opacity to 10%" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:148 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:149 msgid "shortcuts.opacity-2" msgstr "Set opacity to 20%" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:149 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:150 msgid "shortcuts.opacity-3" msgstr "Set opacity to 30%" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:150 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:151 msgid "shortcuts.opacity-4" msgstr "Set opacity to 40%" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:151 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:152 msgid "shortcuts.opacity-5" msgstr "Set opacity to 50%" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:152 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:153 msgid "shortcuts.opacity-6" msgstr "Set opacity to 60%" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:153 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:154 msgid "shortcuts.opacity-7" msgstr "Set opacity to 70%" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:154 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:155 msgid "shortcuts.opacity-8" msgstr "Set opacity to 80%" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:155 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:156 msgid "shortcuts.opacity-9" msgstr "Set opacity to 90%" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:156 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:157 msgid "shortcuts.open-color-picker" msgstr "Color picker" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:157 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:158 msgid "shortcuts.open-comments" msgstr "Go to viewer comment section" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:158 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:159 msgid "shortcuts.open-dashboard" msgstr "Go to dashboard" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:159 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:160 msgid "shortcuts.open-inspect" msgstr "Go to viewer inspect section" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:160 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:161 msgid "shortcuts.open-interactions" msgstr "Go to viewer interactions section" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:161 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:162 msgid "shortcuts.open-viewer" msgstr "Go to viewer interactions section" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:162 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:163 msgid "shortcuts.open-workspace" msgstr "Go to workspace" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:260 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:262 msgid "shortcuts.or" msgstr " or " -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:163 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:164 msgid "shortcuts.paste" msgstr "Paste" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:164 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:165 msgid "shortcuts.prev-frame" msgstr "Previous board" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:165 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:166 msgid "shortcuts.redo" msgstr "Redo" +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:167 msgid "shortcuts.rename" msgstr "Rename" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:166 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:168 msgid "shortcuts.reset-zoom" msgstr "Reset zoom" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:167 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:169 msgid "shortcuts.scale" msgstr "Scale" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:168 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:170 msgid "shortcuts.search-placeholder" msgstr "Search shortcuts" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:169 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:171 msgid "shortcuts.select-all" msgstr "Select all" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:170 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:172 msgid "shortcuts.select-next" msgstr "Select next layer" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:171 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:173 msgid "shortcuts.select-parent-layer" msgstr "Select parent layer" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:172 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:174 msgid "shortcuts.select-prev" msgstr "Select previous layer" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:173 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:175 msgid "shortcuts.separate-nodes" msgstr "Separate nodes" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:174 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:176 msgid "shortcuts.show-pixel-grid" msgstr "Show / Hide pixel grid" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:175 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:177 msgid "shortcuts.show-shortcuts" msgstr "Show / Hide shortcuts" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:176 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:178 msgid "shortcuts.snap-nodes" msgstr "Snap to nodes" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:177 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:179 msgid "shortcuts.snap-pixel-grid" msgstr "Snap to pixel grid" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:178 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:180 msgid "shortcuts.start-editing" msgstr "Start editing" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:179 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:181 msgid "shortcuts.start-measure" msgstr "Start measurement" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:180 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:182 msgid "shortcuts.stop-measure" msgstr "Stop measurement" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:181 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:183 msgid "shortcuts.text-align-center" msgstr "Align center" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:182 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:184 msgid "shortcuts.text-align-justify" msgstr "Align justify" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:183 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:185 msgid "shortcuts.text-align-left" msgstr "Align left" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:184 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:186 msgid "shortcuts.text-align-right" msgstr "Align right" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:185 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:187 msgid "shortcuts.thumbnail-set" msgstr "Set thumbnails" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:496, src/app/main/ui/workspace/sidebar/shortcuts.cljs:505 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:498, src/app/main/ui/workspace/sidebar/shortcuts.cljs:507 msgid "shortcuts.title" msgstr "Keyboard shortcuts" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:186 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:188 msgid "shortcuts.toggle-alignment" msgstr "Toggle dynamic alignment" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:187 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:189 msgid "shortcuts.toggle-assets" msgstr "Toggle assets" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:188 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:190 msgid "shortcuts.toggle-colorpalette" msgstr "Toggle color palette" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:189 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:191 msgid "shortcuts.toggle-focus-mode" msgstr "Toggle focus mode" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:190 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:192 msgid "shortcuts.toggle-fullscreen" msgstr "Toggle fullscreen" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:191 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:193 msgid "shortcuts.toggle-guides" msgstr "Show / Hide guides" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:192 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:194 msgid "shortcuts.toggle-history" msgstr "Toggle history" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:193 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:195 msgid "shortcuts.toggle-layers" msgstr "Toggle layers" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:194 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:196 msgid "shortcuts.toggle-layout-flex" msgstr "Add / Remove flex layout" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:195 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:197 msgid "shortcuts.toggle-layout-grid" msgstr "Add/remove grid layout" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:196 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:198 msgid "shortcuts.toggle-lock" msgstr "Lock / Unlock" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:197 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:199 msgid "shortcuts.toggle-lock-size" msgstr "Lock proportions" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:198 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:200 msgid "shortcuts.toggle-rulers" msgstr "Show / Hide rulers" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:199 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:201 #, fuzzy msgid "shortcuts.toggle-rules" msgstr "" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:200 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:202 msgid "shortcuts.toggle-snap-guides" msgstr "Snap to guides" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:201 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:203 msgid "shortcuts.toggle-snap-ruler-guide" msgstr "Snap to ruler guides" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:202 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:204 msgid "shortcuts.toggle-textpalette" msgstr "Toggle text palette" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:203 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:205 msgid "shortcuts.toggle-theme" msgstr "Change theme" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:204 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:206 msgid "shortcuts.toggle-visibility" msgstr "Show / Hide" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:205 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:207 msgid "shortcuts.toggle-zoom-style" msgstr "Toggle zoom style" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:206 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:208 msgid "shortcuts.underline" msgstr "Toggle underline" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:207 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:209 msgid "shortcuts.undo" msgstr "Undo" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:208 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:210 msgid "shortcuts.ungroup" msgstr "Ungroup" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:209 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:211 msgid "shortcuts.unmask" msgstr "Unmask" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:210 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:212 msgid "shortcuts.v-distribute" msgstr "Distribute vertically" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:211 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:213 msgid "shortcuts.zoom-lense-decrease" msgstr "Zoom lense decrease" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:212 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:214 msgid "shortcuts.zoom-lense-increase" msgstr "Zoom lense increase" -#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:213 +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:215 msgid "shortcuts.zoom-selected" msgstr "Zoom to selected" @@ -3901,7 +3952,7 @@ msgstr "Webhooks - %s - Penpot" msgid "title.viewer" msgstr "%s - View mode - Penpot" -#: src/app/main/ui/workspace.cljs:198 +#: src/app/main/ui/workspace.cljs:199 msgid "title.workspace" msgstr "%s - Penpot" @@ -4008,19 +4059,19 @@ msgstr "Assets" msgid "workspace.assets.box-filter-all" msgstr "All assets" -#: src/app/main/ui/dashboard/grid.cljs:138, src/app/main/ui/dashboard/grid.cljs:170, src/app/main/ui/workspace/sidebar/assets/colors.cljs:487, src/app/main/ui/workspace/sidebar/assets.cljs:147 +#: src/app/main/ui/dashboard/grid.cljs:138, src/app/main/ui/dashboard/grid.cljs:170, src/app/main/ui/workspace/sidebar/assets/colors.cljs:492, src/app/main/ui/workspace/sidebar/assets.cljs:147 msgid "workspace.assets.colors" msgstr "Colors" -#: src/app/main/ui/workspace/sidebar/assets/colors.cljs:495 +#: src/app/main/ui/workspace/sidebar/assets/colors.cljs:500 msgid "workspace.assets.colors.add-color" msgstr "Add color" -#: src/app/main/ui/dashboard/grid.cljs:134, src/app/main/ui/dashboard/grid.cljs:149, src/app/main/ui/workspace/sidebar/assets/components.cljs:511, src/app/main/ui/workspace/sidebar/assets.cljs:138 +#: src/app/main/ui/dashboard/grid.cljs:134, src/app/main/ui/dashboard/grid.cljs:149, src/app/main/ui/workspace/sidebar/assets/components.cljs:502, src/app/main/ui/workspace/sidebar/assets.cljs:138 msgid "workspace.assets.components" msgstr "Components" -#: src/app/main/ui/workspace/sidebar/assets/components.cljs:532 +#: src/app/main/ui/workspace/sidebar/assets/components.cljs:523 msgid "workspace.assets.components.add-component" msgstr "Add component" @@ -4032,19 +4083,19 @@ msgstr "Create a group" msgid "workspace.assets.create-group-hint" msgstr "Your items are going to be named automatically as \"group name / item name\"" -#: src/app/main/ui/workspace/context_menu.cljs:540, src/app/main/ui/workspace/sidebar/assets/colors.cljs:251, src/app/main/ui/workspace/sidebar/assets/components.cljs:576, src/app/main/ui/workspace/sidebar/assets/graphics.cljs:424, src/app/main/ui/workspace/sidebar/assets/typographies.cljs:447 +#: src/app/main/ui/workspace/context_menu.cljs:548, src/app/main/ui/workspace/sidebar/assets/colors.cljs:256, src/app/main/ui/workspace/sidebar/assets/components.cljs:567, src/app/main/ui/workspace/sidebar/assets/graphics.cljs:424, src/app/main/ui/workspace/sidebar/assets/typographies.cljs:460 msgid "workspace.assets.delete" msgstr "Delete" -#: src/app/main/ui/workspace/context_menu.cljs:545, src/app/main/ui/workspace/sidebar/assets/components.cljs:571 +#: src/app/main/ui/workspace/context_menu.cljs:553, src/app/main/ui/workspace/sidebar/assets/components.cljs:562 msgid "workspace.assets.duplicate" msgstr "Duplicate" -#: src/app/main/ui/workspace/sidebar/assets/components.cljs:570 +#: src/app/main/ui/workspace/sidebar/assets/components.cljs:561 msgid "workspace.assets.duplicate-main" msgstr "Duplicate main" -#: src/app/main/ui/workspace/sidebar/assets/colors.cljs:247, src/app/main/ui/workspace/sidebar/assets/typographies.cljs:443 +#: src/app/main/ui/workspace/sidebar/assets/colors.cljs:252, src/app/main/ui/workspace/sidebar/assets/typographies.cljs:456 msgid "workspace.assets.edit" msgstr "Edit" @@ -4056,11 +4107,11 @@ msgstr "Filter" msgid "workspace.assets.graphics" msgstr "Graphics" -#: src/app/main/ui/workspace/sidebar/assets/components.cljs:527 +#: src/app/main/ui/workspace/sidebar/assets/components.cljs:518 msgid "workspace.assets.grid-view" msgstr "Grid view" -#: src/app/main/ui/workspace/sidebar/assets/colors.cljs:255, src/app/main/ui/workspace/sidebar/assets/components.cljs:580, src/app/main/ui/workspace/sidebar/assets/graphics.cljs:428, src/app/main/ui/workspace/sidebar/assets/typographies.cljs:452 +#: src/app/main/ui/workspace/sidebar/assets/colors.cljs:260, src/app/main/ui/workspace/sidebar/assets/components.cljs:571, src/app/main/ui/workspace/sidebar/assets/graphics.cljs:428, src/app/main/ui/workspace/sidebar/assets/typographies.cljs:465 msgid "workspace.assets.group" msgstr "Group" @@ -4079,19 +4130,19 @@ msgstr "Add library" msgid "workspace.assets.list-view" msgstr "List view" -#: src/app/main/ui/workspace/sidebar/assets/file_library.cljs:62, src/app/main/ui/workspace/sidebar/options/menus/component.cljs:347 +#: src/app/main/ui/workspace/sidebar/assets/file_library.cljs:72, src/app/main/ui/workspace/sidebar/options/menus/component.cljs:347 msgid "workspace.assets.local-library" msgstr "local library" -#: src/app/main/ui/workspace/sidebar/assets/file_library.cljs:295 +#: src/app/main/ui/workspace/sidebar/assets/file_library.cljs:304 msgid "workspace.assets.not-found" msgstr "No assets found" -#: src/app/main/ui/workspace/sidebar/assets/file_library.cljs:68 +#: src/app/main/ui/workspace/sidebar/assets/file_library.cljs:78 msgid "workspace.assets.open-library" msgstr "Open library file" -#: src/app/main/ui/workspace/context_menu.cljs:543, src/app/main/ui/workspace/sidebar/assets/colors.cljs:243, src/app/main/ui/workspace/sidebar/assets/components.cljs:565, src/app/main/ui/workspace/sidebar/assets/graphics.cljs:421, src/app/main/ui/workspace/sidebar/assets/groups.cljs:62, src/app/main/ui/workspace/sidebar/assets/typographies.cljs:438 +#: src/app/main/ui/workspace/context_menu.cljs:551, src/app/main/ui/workspace/sidebar/assets/colors.cljs:248, src/app/main/ui/workspace/sidebar/assets/components.cljs:556, src/app/main/ui/workspace/sidebar/assets/graphics.cljs:421, src/app/main/ui/workspace/sidebar/assets/groups.cljs:62, src/app/main/ui/workspace/sidebar/assets/typographies.cljs:451 msgid "workspace.assets.rename" msgstr "Rename" @@ -4125,11 +4176,11 @@ msgstr[1] "%s components" msgid "workspace.assets.sort" msgstr "Sort" -#: src/app/main/ui/dashboard/grid.cljs:142, src/app/main/ui/dashboard/grid.cljs:197, src/app/main/ui/workspace/sidebar/assets/typographies.cljs:400, src/app/main/ui/workspace/sidebar/assets.cljs:151 +#: src/app/main/ui/dashboard/grid.cljs:142, src/app/main/ui/dashboard/grid.cljs:197, src/app/main/ui/workspace/sidebar/assets/typographies.cljs:413, src/app/main/ui/workspace/sidebar/assets.cljs:151 msgid "workspace.assets.typography" msgstr "Typographies" -#: src/app/main/ui/workspace/sidebar/assets/typographies.cljs:408 +#: src/app/main/ui/workspace/sidebar/assets/typographies.cljs:421 msgid "workspace.assets.typography.add-typography" msgstr "Add typography" @@ -4174,67 +4225,67 @@ msgstr "Text Transform" msgid "workspace.assets.ungroup" msgstr "Ungroup" -#: src/app/main/ui/workspace/context_menu.cljs:648 +#: src/app/main/ui/workspace/context_menu.cljs:656 msgid "workspace.context-menu.grid-cells.area" msgstr "Create area" -#: src/app/main/ui/workspace/context_menu.cljs:651 +#: src/app/main/ui/workspace/context_menu.cljs:659 msgid "workspace.context-menu.grid-cells.create-board" msgstr "Create board" -#: src/app/main/ui/workspace/context_menu.cljs:643 +#: src/app/main/ui/workspace/context_menu.cljs:651 msgid "workspace.context-menu.grid-cells.merge" msgstr "Merge cells" -#: src/app/main/ui/workspace/context_menu.cljs:608 +#: src/app/main/ui/workspace/context_menu.cljs:616 msgid "workspace.context-menu.grid-track.column.add-after" msgstr "Add 1 column to the right" -#: src/app/main/ui/workspace/context_menu.cljs:607 +#: src/app/main/ui/workspace/context_menu.cljs:615 msgid "workspace.context-menu.grid-track.column.add-before" msgstr "Add 1 column to the left" -#: src/app/main/ui/workspace/context_menu.cljs:609 +#: src/app/main/ui/workspace/context_menu.cljs:617 msgid "workspace.context-menu.grid-track.column.delete" msgstr "Delete column" -#: src/app/main/ui/workspace/context_menu.cljs:610 +#: src/app/main/ui/workspace/context_menu.cljs:618 msgid "workspace.context-menu.grid-track.column.delete-shapes" msgstr "Delete column and shapes" -#: src/app/main/ui/workspace/context_menu.cljs:606 +#: src/app/main/ui/workspace/context_menu.cljs:614 msgid "workspace.context-menu.grid-track.column.duplicate" msgstr "Duplicate column" -#: src/app/main/ui/workspace/context_menu.cljs:615 +#: src/app/main/ui/workspace/context_menu.cljs:623 msgid "workspace.context-menu.grid-track.row.add-after" msgstr "Add 1 row below" -#: src/app/main/ui/workspace/context_menu.cljs:614 +#: src/app/main/ui/workspace/context_menu.cljs:622 msgid "workspace.context-menu.grid-track.row.add-before" msgstr "Add 1 row above" -#: src/app/main/ui/workspace/context_menu.cljs:616 +#: src/app/main/ui/workspace/context_menu.cljs:624 msgid "workspace.context-menu.grid-track.row.delete" msgstr "Delete row" -#: src/app/main/ui/workspace/context_menu.cljs:617 +#: src/app/main/ui/workspace/context_menu.cljs:625 msgid "workspace.context-menu.grid-track.row.delete-shapes" msgstr "Delete row and shapes" -#: src/app/main/ui/workspace/context_menu.cljs:613 +#: src/app/main/ui/workspace/context_menu.cljs:621 msgid "workspace.context-menu.grid-track.row.duplicate" msgstr "Duplicate row" -#: src/app/main/ui/workspace/sidebar/layers.cljs:527 +#: src/app/main/ui/workspace/sidebar/layers.cljs:528 msgid "workspace.focus.focus-mode" msgstr "Focus mode" -#: src/app/main/ui/workspace/context_menu.cljs:298, src/app/main/ui/workspace/context_menu.cljs:567 +#: src/app/main/ui/workspace/context_menu.cljs:304, src/app/main/ui/workspace/context_menu.cljs:575 msgid "workspace.focus.focus-off" msgstr "Focus off" -#: src/app/main/ui/workspace/context_menu.cljs:297 +#: src/app/main/ui/workspace/context_menu.cljs:303 msgid "workspace.focus.focus-on" msgstr "Focus on" @@ -4250,11 +4301,11 @@ msgstr "Linear gradient" msgid "workspace.gradients.radial" msgstr "Radial gradient" -#: src/app/main/ui/workspace/main_menu.cljs:243 +#: src/app/main/ui/workspace/main_menu.cljs:244 msgid "workspace.header.menu.disable-dynamic-alignment" msgstr "Disable dynamic alignment" -#: src/app/main/ui/workspace/main_menu.cljs:197 +#: src/app/main/ui/workspace/main_menu.cljs:198 msgid "workspace.header.menu.disable-scale-content" msgstr "Disable proportional scale" @@ -4263,23 +4314,23 @@ msgstr "Disable proportional scale" msgid "workspace.header.menu.disable-scale-text" msgstr "Disable scale text" -#: src/app/main/ui/workspace/main_menu.cljs:228 +#: src/app/main/ui/workspace/main_menu.cljs:229 msgid "workspace.header.menu.disable-snap-guides" msgstr "Disable snap to guides" -#: src/app/main/ui/workspace/main_menu.cljs:258 +#: src/app/main/ui/workspace/main_menu.cljs:259 msgid "workspace.header.menu.disable-snap-pixel-grid" msgstr "Disable snap to pixel" -#: src/app/main/ui/workspace/main_menu.cljs:212 +#: src/app/main/ui/workspace/main_menu.cljs:213 msgid "workspace.header.menu.disable-snap-ruler-guides" msgstr "Disable snap to ruler guides" -#: src/app/main/ui/workspace/main_menu.cljs:244 +#: src/app/main/ui/workspace/main_menu.cljs:245 msgid "workspace.header.menu.enable-dynamic-alignment" msgstr "Enable dynamic alignment" -#: src/app/main/ui/workspace/main_menu.cljs:198 +#: src/app/main/ui/workspace/main_menu.cljs:199 msgid "workspace.header.menu.enable-scale-content" msgstr "Enable proportional scale" @@ -4288,59 +4339,59 @@ msgstr "Enable proportional scale" msgid "workspace.header.menu.enable-scale-text" msgstr "Enable scale text" -#: src/app/main/ui/workspace/main_menu.cljs:229 +#: src/app/main/ui/workspace/main_menu.cljs:230 msgid "workspace.header.menu.enable-snap-guides" msgstr "Snap to guides" -#: src/app/main/ui/workspace/main_menu.cljs:259 +#: src/app/main/ui/workspace/main_menu.cljs:260 msgid "workspace.header.menu.enable-snap-pixel-grid" msgstr "Enable snap to pixel" -#: src/app/main/ui/workspace/main_menu.cljs:213 +#: src/app/main/ui/workspace/main_menu.cljs:214 msgid "workspace.header.menu.enable-snap-ruler-guides" msgstr "Snap to ruler guides" -#: src/app/main/ui/workspace/main_menu.cljs:388 +#: src/app/main/ui/workspace/main_menu.cljs:389 msgid "workspace.header.menu.hide-artboard-names" msgstr "Hide board names" -#: src/app/main/ui/workspace/main_menu.cljs:342 +#: src/app/main/ui/workspace/main_menu.cljs:343 msgid "workspace.header.menu.hide-guides" msgstr "Hide guides" -#: src/app/main/ui/workspace/main_menu.cljs:359 +#: src/app/main/ui/workspace/main_menu.cljs:360 msgid "workspace.header.menu.hide-palette" msgstr "Hide color palette" -#: src/app/main/ui/workspace/main_menu.cljs:400 +#: src/app/main/ui/workspace/main_menu.cljs:401 msgid "workspace.header.menu.hide-pixel-grid" msgstr "Hide pixel grid" -#: src/app/main/ui/workspace/main_menu.cljs:326 +#: src/app/main/ui/workspace/main_menu.cljs:327 msgid "workspace.header.menu.hide-rules" msgstr "Hide rulers" -#: src/app/main/ui/workspace/main_menu.cljs:373 +#: src/app/main/ui/workspace/main_menu.cljs:374 msgid "workspace.header.menu.hide-textpalette" msgstr "Hide fonts palette" -#: src/app/main/ui/workspace/main_menu.cljs:803 +#: src/app/main/ui/workspace/main_menu.cljs:850 msgid "workspace.header.menu.option.edit" msgstr "Edit" -#: src/app/main/ui/workspace/main_menu.cljs:792 +#: src/app/main/ui/workspace/main_menu.cljs:839 msgid "workspace.header.menu.option.file" msgstr "File" -#: src/app/main/ui/workspace/main_menu.cljs:849 +#: src/app/main/ui/workspace/main_menu.cljs:896 msgid "workspace.header.menu.option.help-info" msgstr "Help & info" -#: src/app/main/ui/workspace/main_menu.cljs:825 +#: src/app/main/ui/workspace/main_menu.cljs:872 msgid "workspace.header.menu.option.preferences" msgstr "Preferences" -#: src/app/main/ui/workspace/main_menu.cljs:814 +#: src/app/main/ui/workspace/main_menu.cljs:861 msgid "workspace.header.menu.option.view" msgstr "View" @@ -4352,43 +4403,43 @@ msgstr "Power up your plan" msgid "workspace.header.menu.redo" msgstr "Redo" -#: src/app/main/ui/workspace/main_menu.cljs:442 +#: src/app/main/ui/workspace/main_menu.cljs:443 msgid "workspace.header.menu.select-all" msgstr "Select all" -#: src/app/main/ui/workspace/main_menu.cljs:389 +#: src/app/main/ui/workspace/main_menu.cljs:390 msgid "workspace.header.menu.show-artboard-names" msgstr "Show boards names" -#: src/app/main/ui/workspace/main_menu.cljs:343 +#: src/app/main/ui/workspace/main_menu.cljs:344 msgid "workspace.header.menu.show-guides" msgstr "Show guides" -#: src/app/main/ui/workspace/main_menu.cljs:360 +#: src/app/main/ui/workspace/main_menu.cljs:361 msgid "workspace.header.menu.show-palette" msgstr "Show color palette" -#: src/app/main/ui/workspace/main_menu.cljs:401 +#: src/app/main/ui/workspace/main_menu.cljs:402 msgid "workspace.header.menu.show-pixel-grid" msgstr "Show pixel grid" -#: src/app/main/ui/workspace/main_menu.cljs:327 +#: src/app/main/ui/workspace/main_menu.cljs:328 msgid "workspace.header.menu.show-rules" msgstr "Show rulers" -#: src/app/main/ui/workspace/main_menu.cljs:374 +#: src/app/main/ui/workspace/main_menu.cljs:375 msgid "workspace.header.menu.show-textpalette" msgstr "Show fonts palette" -#: src/app/main/ui/workspace/main_menu.cljs:284 +#: src/app/main/ui/workspace/main_menu.cljs:285 msgid "workspace.header.menu.toggle-dark-theme" msgstr "Switch to dark theme" -#: src/app/main/ui/workspace/main_menu.cljs:283 +#: src/app/main/ui/workspace/main_menu.cljs:284 msgid "workspace.header.menu.toggle-light-theme" msgstr "Switch to light theme" -#: src/app/main/ui/workspace/main_menu.cljs:457 +#: src/app/main/ui/workspace/main_menu.cljs:458 msgid "workspace.header.menu.undo" msgstr "Undo" @@ -4483,15 +4534,15 @@ msgstr "Add" msgid "workspace.libraries.colors" msgstr "%s colors" -#: src/app/main/ui/workspace/color_palette.cljs:129 +#: src/app/main/ui/workspace/color_palette.cljs:137 msgid "workspace.libraries.colors.empty-palette" msgstr "There are no color styles in your library yet" -#: src/app/main/ui/workspace/text_palette.cljs:153 +#: src/app/main/ui/workspace/text_palette.cljs:161 msgid "workspace.libraries.colors.empty-typography-palette" msgstr "There are no typography styles in your library yet" -#: src/app/main/ui/workspace/color_palette_ctx_menu.cljs:60, src/app/main/ui/workspace/colorpicker/libraries.cljs:73, src/app/main/ui/workspace/text_palette_ctx_menu.cljs:50 +#: src/app/main/ui/workspace/color_palette_ctx_menu.cljs:60, src/app/main/ui/workspace/colorpicker/libraries.cljs:74, src/app/main/ui/workspace/text_palette_ctx_menu.cljs:50 msgid "workspace.libraries.colors.file-library" msgstr "File library" @@ -4500,7 +4551,7 @@ msgstr "File library" msgid "workspace.libraries.colors.hsv" msgstr "HSV" -#: src/app/main/ui/workspace/color_palette_ctx_menu.cljs:82, src/app/main/ui/workspace/colorpicker/libraries.cljs:72 +#: src/app/main/ui/workspace/color_palette_ctx_menu.cljs:82, src/app/main/ui/workspace/colorpicker/libraries.cljs:73 msgid "workspace.libraries.colors.recent-colors" msgstr "Recent colors" @@ -4509,11 +4560,11 @@ msgstr "Recent colors" msgid "workspace.libraries.colors.rgb-complementary" msgstr "RGB Complementary" -#: src/app/main/ui/workspace/colorpicker.cljs:234 +#: src/app/main/ui/workspace/colorpicker.cljs:342 msgid "workspace.libraries.colors.rgba" msgstr "RGBA" -#: src/app/main/ui/workspace/colorpicker.cljs:382 +#: src/app/main/ui/workspace/colorpicker.cljs:513 msgid "workspace.libraries.colors.save-color" msgstr "Save color style" @@ -4731,7 +4782,7 @@ msgstr "Top & Bottom" msgid "workspace.options.design" msgstr "Design" -#: src/app/main/ui/viewer/inspect/exports.cljs:147 +#: src/app/main/ui/viewer/inspect/exports.cljs:139 msgid "workspace.options.export" msgstr "Export" @@ -4740,37 +4791,37 @@ msgstr "Export" msgid "workspace.options.export-multiple" msgstr "Export selection" -#: src/app/main/ui/viewer/inspect/exports.cljs:203, src/app/main/ui/workspace/sidebar/options/menus/exports.cljs:256 +#: src/app/main/ui/viewer/inspect/exports.cljs:195, src/app/main/ui/workspace/sidebar/options/menus/exports.cljs:248 msgid "workspace.options.export-object" msgid_plural "workspace.options.export-object" msgstr[0] "Export 1 element" msgstr[1] "Export %s elements" -#: src/app/main/ui/workspace/sidebar/options/menus/exports.cljs:195 +#: src/app/main/ui/workspace/sidebar/options/menus/exports.cljs:187 msgid "workspace.options.export.add-export" msgstr "Add export" -#: src/app/main/ui/workspace/sidebar/options/menus/exports.cljs:207, src/app/main/ui/workspace/sidebar/options/menus/exports.cljs:242 +#: src/app/main/ui/workspace/sidebar/options/menus/exports.cljs:199, src/app/main/ui/workspace/sidebar/options/menus/exports.cljs:234 msgid "workspace.options.export.remove-export" msgstr "Remove export" -#: src/app/main/ui/viewer/inspect/exports.cljs:186, src/app/main/ui/workspace/sidebar/options/menus/exports.cljs:236 +#: src/app/main/ui/viewer/inspect/exports.cljs:178, src/app/main/ui/workspace/sidebar/options/menus/exports.cljs:228 msgid "workspace.options.export.suffix" msgstr "Suffix" -#: src/app/main/ui/exports/assets.cljs:246 +#: src/app/main/ui/exports/assets.cljs:239 msgid "workspace.options.exporting-complete" msgstr "Export complete" -#: src/app/main/ui/exports/assets.cljs:176, src/app/main/ui/exports/assets.cljs:247, src/app/main/ui/viewer/inspect/exports.cljs:202, src/app/main/ui/workspace/sidebar/options/menus/exports.cljs:255 +#: src/app/main/ui/exports/assets.cljs:169, src/app/main/ui/exports/assets.cljs:240, src/app/main/ui/viewer/inspect/exports.cljs:194, src/app/main/ui/workspace/sidebar/options/menus/exports.cljs:247 msgid "workspace.options.exporting-object" msgstr "Exporting…" -#: src/app/main/ui/exports/assets.cljs:245 +#: src/app/main/ui/exports/assets.cljs:238 msgid "workspace.options.exporting-object-error" msgstr "Export failed" -#: src/app/main/ui/exports/assets.cljs:248 +#: src/app/main/ui/exports/assets.cljs:241 msgid "workspace.options.exporting-object-slow" msgstr "Export unexpectedly slow" @@ -5159,67 +5210,67 @@ msgstr "Add interaction" msgid "workspace.options.interactions.remove-interaction" msgstr "Remove interaction" -#: src/app/main/ui/workspace/sidebar/options/menus/layer.cljs:137 +#: src/app/main/ui/workspace/sidebar/options/menus/layer.cljs:152 msgid "workspace.options.layer-options.blend-mode.color" msgstr "Color" -#: src/app/main/ui/workspace/sidebar/options/menus/layer.cljs:126 +#: src/app/main/ui/workspace/sidebar/options/menus/layer.cljs:141 msgid "workspace.options.layer-options.blend-mode.color-burn" msgstr "Color burn" -#: src/app/main/ui/workspace/sidebar/options/menus/layer.cljs:129 +#: src/app/main/ui/workspace/sidebar/options/menus/layer.cljs:144 msgid "workspace.options.layer-options.blend-mode.color-dodge" msgstr "Color dodge" -#: src/app/main/ui/workspace/sidebar/options/menus/layer.cljs:124 +#: src/app/main/ui/workspace/sidebar/options/menus/layer.cljs:139 msgid "workspace.options.layer-options.blend-mode.darken" msgstr "Darken" -#: src/app/main/ui/workspace/sidebar/options/menus/layer.cljs:133 +#: src/app/main/ui/workspace/sidebar/options/menus/layer.cljs:148 msgid "workspace.options.layer-options.blend-mode.difference" msgstr "Difference" -#: src/app/main/ui/workspace/sidebar/options/menus/layer.cljs:134 +#: src/app/main/ui/workspace/sidebar/options/menus/layer.cljs:149 msgid "workspace.options.layer-options.blend-mode.exclusion" msgstr "Exclusion" -#: src/app/main/ui/workspace/sidebar/options/menus/layer.cljs:132 +#: src/app/main/ui/workspace/sidebar/options/menus/layer.cljs:147 msgid "workspace.options.layer-options.blend-mode.hard-light" msgstr "Hard light" -#: src/app/main/ui/workspace/sidebar/options/menus/layer.cljs:135 +#: src/app/main/ui/workspace/sidebar/options/menus/layer.cljs:150 msgid "workspace.options.layer-options.blend-mode.hue" msgstr "Hue" -#: src/app/main/ui/workspace/sidebar/options/menus/layer.cljs:127 +#: src/app/main/ui/workspace/sidebar/options/menus/layer.cljs:142 msgid "workspace.options.layer-options.blend-mode.lighten" msgstr "Lighten" -#: src/app/main/ui/workspace/sidebar/options/menus/layer.cljs:138 +#: src/app/main/ui/workspace/sidebar/options/menus/layer.cljs:153 msgid "workspace.options.layer-options.blend-mode.luminosity" msgstr "Luminosity" -#: src/app/main/ui/workspace/sidebar/options/menus/layer.cljs:125 +#: src/app/main/ui/workspace/sidebar/options/menus/layer.cljs:140 msgid "workspace.options.layer-options.blend-mode.multiply" msgstr "Multiply" -#: src/app/main/ui/workspace/sidebar/options/menus/layer.cljs:123 +#: src/app/main/ui/workspace/sidebar/options/menus/layer.cljs:138 msgid "workspace.options.layer-options.blend-mode.normal" msgstr "Normal" -#: src/app/main/ui/workspace/sidebar/options/menus/layer.cljs:130 +#: src/app/main/ui/workspace/sidebar/options/menus/layer.cljs:145 msgid "workspace.options.layer-options.blend-mode.overlay" msgstr "Overlay" -#: src/app/main/ui/workspace/sidebar/options/menus/layer.cljs:136 +#: src/app/main/ui/workspace/sidebar/options/menus/layer.cljs:151 msgid "workspace.options.layer-options.blend-mode.saturation" msgstr "Saturation" -#: src/app/main/ui/workspace/sidebar/options/menus/layer.cljs:128 +#: src/app/main/ui/workspace/sidebar/options/menus/layer.cljs:143 msgid "workspace.options.layer-options.blend-mode.screen" msgstr "Screen" -#: src/app/main/ui/workspace/sidebar/options/menus/layer.cljs:131 +#: src/app/main/ui/workspace/sidebar/options/menus/layer.cljs:146 msgid "workspace.options.layer-options.blend-mode.soft-light" msgstr "Soft light" @@ -5238,7 +5289,7 @@ msgstr "Group layers" msgid "workspace.options.layer-options.title.multiple" msgstr "Selected layers" -#: src/app/main/ui/workspace/sidebar/options/menus/layer.cljs:176, src/app/main/ui/workspace/sidebar/options/menus/layer.cljs:182 +#: src/app/main/ui/workspace/sidebar/options/menus/layer.cljs:191, src/app/main/ui/workspace/sidebar/options/menus/layer.cljs:197 msgid "workspace.options.layer-options.toggle-layer" msgstr "Toggle layer visibility" @@ -5381,7 +5432,7 @@ msgstr "More colors" msgid "workspace.options.more-lib-colors" msgstr "More library colors" -#: src/app/main/ui/workspace/sidebar/options/menus/layer.cljs:161 +#: src/app/main/ui/workspace/sidebar/options/menus/layer.cljs:176 msgid "workspace.options.opacity" msgstr "Opacity" @@ -5426,7 +5477,7 @@ msgstr "Independent corners" msgid "workspace.options.recent-fonts" msgstr "Recent" -#: src/app/main/ui/exports/assets.cljs:290 +#: src/app/main/ui/exports/assets.cljs:283 msgid "workspace.options.retry" msgstr "Retry" @@ -5796,7 +5847,7 @@ msgstr "No plugins installed yet" msgid "workspace.plugins.error.manifest" msgstr "The plugin manifest is incorrect." -#: src/app/main/data/plugins.cljs:86, src/app/main/ui/workspace/main_menu.cljs:696, src/app/main/ui/workspace/plugins.cljs:82 +#: src/app/main/data/plugins.cljs:86, src/app/main/ui/workspace/main_menu.cljs:743, src/app/main/ui/workspace/plugins.cljs:82 msgid "workspace.plugins.error.need-editor" msgstr "You need to be an editor to use this plugin" @@ -5812,11 +5863,11 @@ msgstr "Install" msgid "workspace.plugins.installed-plugins" msgstr "Installed plugins" -#: src/app/main/ui/workspace/main_menu.cljs:651 +#: src/app/main/ui/workspace/main_menu.cljs:698 msgid "workspace.plugins.menu.plugins-manager" msgstr "Plugins manager" -#: src/app/main/ui/workspace/main_menu.cljs:837 +#: src/app/main/ui/workspace/main_menu.cljs:884 msgid "workspace.plugins.menu.title" msgstr "Plugins" @@ -5911,11 +5962,11 @@ msgstr "'%s' PLUGIN IS INSTALLED FOR YOUR USER!" msgid "workspace.plugins.try-out.try" msgstr "TRY PLUGIN" -#: src/app/main/ui/workspace/context_menu.cljs:451 +#: src/app/main/ui/workspace/context_menu.cljs:457 msgid "workspace.shape.menu.add-flex" msgstr "Add flex layout" -#: src/app/main/ui/workspace/context_menu.cljs:455 +#: src/app/main/ui/workspace/context_menu.cljs:461 msgid "workspace.shape.menu.add-grid" msgstr "Add grid layout" @@ -5923,91 +5974,95 @@ msgstr "Add grid layout" msgid "workspace.shape.menu.add-layout" msgstr "Add layout" -#: src/app/main/ui/workspace/context_menu.cljs:194 +#: src/app/main/ui/workspace/context_menu.cljs:200 msgid "workspace.shape.menu.back" msgstr "Send to back" -#: src/app/main/ui/workspace/context_menu.cljs:191 +#: src/app/main/ui/workspace/context_menu.cljs:197 msgid "workspace.shape.menu.backward" msgstr "Send backward" -#: src/app/main/ui/workspace/context_menu.cljs:140 +#: src/app/main/ui/workspace/context_menu.cljs:143 msgid "workspace.shape.menu.copy" msgstr "Copy" -#: src/app/main/ui/workspace/sidebar/assets/common.cljs:427 +#: src/app/main/ui/workspace/context_menu.cljs:146 +msgid "workspace.shape.menu.copy_link" +msgstr "Copy link to clipboard" + +#: src/app/main/ui/workspace/sidebar/assets/common.cljs:431 msgid "workspace.shape.menu.create-annotation" msgstr "Create annotation" -#: src/app/main/ui/workspace/context_menu.cljs:286 +#: src/app/main/ui/workspace/context_menu.cljs:292 msgid "workspace.shape.menu.create-artboard-from-selection" msgstr "Selection to board" -#: src/app/main/ui/workspace/context_menu.cljs:475 +#: src/app/main/ui/workspace/context_menu.cljs:481 msgid "workspace.shape.menu.create-component" msgstr "Create component" -#: src/app/main/ui/workspace/context_menu.cljs:479 +#: src/app/main/ui/workspace/context_menu.cljs:485 msgid "workspace.shape.menu.create-multiple-components" msgstr "Create multiple components" -#: src/app/main/ui/workspace/context_menu.cljs:143 +#: src/app/main/ui/workspace/context_menu.cljs:149 msgid "workspace.shape.menu.cut" msgstr "Cut" -#: src/app/main/ui/workspace/context_menu.cljs:496, src/app/main/ui/workspace/sidebar/options/menus/layout_container.cljs:764, src/app/main/ui/workspace/sidebar/options/menus/layout_container.cljs:1052 +#: src/app/main/ui/workspace/context_menu.cljs:502, src/app/main/ui/workspace/sidebar/options/menus/layout_container.cljs:764, src/app/main/ui/workspace/sidebar/options/menus/layout_container.cljs:1052 msgid "workspace.shape.menu.delete" msgstr "Delete" -#: src/app/main/ui/workspace/context_menu.cljs:402 +#: src/app/main/ui/workspace/context_menu.cljs:408 msgid "workspace.shape.menu.delete-flow-start" msgstr "Delete flow start" -#: src/app/main/ui/workspace/sidebar/assets/common.cljs:432 +#: src/app/main/ui/workspace/sidebar/assets/common.cljs:436 msgid "workspace.shape.menu.detach-instance" msgstr "Detach instance" -#: src/app/main/ui/workspace/sidebar/assets/common.cljs:431 +#: src/app/main/ui/workspace/sidebar/assets/common.cljs:435 msgid "workspace.shape.menu.detach-instances-in-bulk" msgstr "Detach instances" -#: src/app/main/ui/workspace/context_menu.cljs:346, src/app/main/ui/workspace/sidebar/options/menus/bool.cljs:75 +#: src/app/main/ui/workspace/context_menu.cljs:352, src/app/main/ui/workspace/sidebar/options/menus/bool.cljs:75 msgid "workspace.shape.menu.difference" msgstr "Difference" -#: src/app/main/ui/workspace/context_menu.cljs:149 +#: src/app/main/ui/workspace/context_menu.cljs:155 msgid "workspace.shape.menu.duplicate" msgstr "Duplicate" -#: src/app/main/ui/workspace/context_menu.cljs:332 +#: src/app/main/ui/workspace/context_menu.cljs:338 msgid "workspace.shape.menu.edit" msgstr "Edit" -#: src/app/main/ui/workspace/context_menu.cljs:352 +#: src/app/main/ui/workspace/context_menu.cljs:358 msgid "workspace.shape.menu.exclude" msgstr "Exclude" -#: src/app/main/ui/workspace/context_menu.cljs:359, src/app/main/ui/workspace/sidebar/options/menus/bool.cljs:89 +#: src/app/main/ui/workspace/context_menu.cljs:365, src/app/main/ui/workspace/sidebar/options/menus/bool.cljs:89 msgid "workspace.shape.menu.flatten" msgstr "Flatten" -#: src/app/main/ui/workspace/context_menu.cljs:209 +#: src/app/main/ui/workspace/context_menu.cljs:215 msgid "workspace.shape.menu.flip-horizontal" msgstr "Flip horizontal" -#: src/app/main/ui/workspace/context_menu.cljs:205 +#: src/app/main/ui/workspace/context_menu.cljs:211 msgid "workspace.shape.menu.flip-vertical" msgstr "Flip vertical" -#: src/app/main/ui/workspace/context_menu.cljs:404 +#: src/app/main/ui/workspace/context_menu.cljs:410 msgid "workspace.shape.menu.flow-start" msgstr "Flow start" -#: src/app/main/ui/workspace/context_menu.cljs:185 +#: src/app/main/ui/workspace/context_menu.cljs:191 msgid "workspace.shape.menu.forward" msgstr "Bring forward" -#: src/app/main/ui/workspace/context_menu.cljs:188 +#: src/app/main/ui/workspace/context_menu.cljs:194 msgid "workspace.shape.menu.front" msgstr "Bring to front" @@ -6016,43 +6071,43 @@ msgstr "Bring to front" msgid "workspace.shape.menu.go-main" msgstr "Go to main component file" -#: src/app/main/ui/workspace/context_menu.cljs:272 +#: src/app/main/ui/workspace/context_menu.cljs:278 msgid "workspace.shape.menu.group" msgstr "Group" -#: src/app/main/ui/workspace/context_menu.cljs:374, src/app/main/ui/workspace/sidebar/layer_item.cljs:145 +#: src/app/main/ui/workspace/context_menu.cljs:380, src/app/main/ui/workspace/sidebar/layer_item.cljs:145 msgid "workspace.shape.menu.hide" msgstr "Hide" -#: src/app/main/ui/workspace/context_menu.cljs:562, src/app/main/ui/workspace/main_menu.cljs:414 +#: src/app/main/ui/workspace/context_menu.cljs:570, src/app/main/ui/workspace/main_menu.cljs:415 msgid "workspace.shape.menu.hide-ui" msgstr "Show / Hide UI" -#: src/app/main/ui/workspace/context_menu.cljs:349 +#: src/app/main/ui/workspace/context_menu.cljs:355 msgid "workspace.shape.menu.intersection" msgstr "Intersection" -#: src/app/main/ui/workspace/context_menu.cljs:382, src/app/main/ui/workspace/sidebar/layer_item.cljs:153, src/app/main/ui/workspace/sidebar/options/menus/layer.cljs:189 +#: src/app/main/ui/workspace/context_menu.cljs:388, src/app/main/ui/workspace/sidebar/layer_item.cljs:153, src/app/main/ui/workspace/sidebar/options/menus/layer.cljs:204 msgid "workspace.shape.menu.lock" msgstr "Lock" -#: src/app/main/ui/workspace/context_menu.cljs:277 +#: src/app/main/ui/workspace/context_menu.cljs:283 msgid "workspace.shape.menu.mask" msgstr "Mask" -#: src/app/main/ui/workspace/context_menu.cljs:146, src/app/main/ui/workspace/context_menu.cljs:559 +#: src/app/main/ui/workspace/context_menu.cljs:152, src/app/main/ui/workspace/context_menu.cljs:567 msgid "workspace.shape.menu.paste" msgstr "Paste" -#: src/app/main/ui/workspace/context_menu.cljs:342 +#: src/app/main/ui/workspace/context_menu.cljs:348 msgid "workspace.shape.menu.path" msgstr "Path" -#: src/app/main/ui/workspace/context_menu.cljs:442 +#: src/app/main/ui/workspace/context_menu.cljs:448 msgid "workspace.shape.menu.remove-flex" msgstr "Remove flex layout" -#: src/app/main/ui/workspace/context_menu.cljs:445 +#: src/app/main/ui/workspace/context_menu.cljs:451 msgid "workspace.shape.menu.remove-grid" msgstr "Remove grid layout" @@ -6060,59 +6115,59 @@ msgstr "Remove grid layout" msgid "workspace.shape.menu.remove-layout" msgstr "Remove layout" -#: src/app/main/ui/workspace/context_menu.cljs:235 +#: src/app/main/ui/workspace/context_menu.cljs:241 msgid "workspace.shape.menu.rename" msgstr "Rename" -#: src/app/main/ui/workspace/sidebar/assets/common.cljs:436 +#: src/app/main/ui/workspace/sidebar/assets/common.cljs:440 msgid "workspace.shape.menu.reset-overrides" msgstr "Reset overrides" -#: src/app/main/ui/workspace/sidebar/assets/common.cljs:439 +#: src/app/main/ui/workspace/sidebar/assets/common.cljs:443 msgid "workspace.shape.menu.restore-main" msgstr "Restore main component" -#: src/app/main/ui/workspace/context_menu.cljs:175 +#: src/app/main/ui/workspace/context_menu.cljs:181 msgid "workspace.shape.menu.select-layer" msgstr "Select layer" -#: src/app/main/ui/workspace/context_menu.cljs:371, src/app/main/ui/workspace/sidebar/layer_item.cljs:144 +#: src/app/main/ui/workspace/context_menu.cljs:377, src/app/main/ui/workspace/sidebar/layer_item.cljs:144 msgid "workspace.shape.menu.show" msgstr "Show" -#: src/app/main/ui/workspace/sidebar/assets/common.cljs:424 +#: src/app/main/ui/workspace/sidebar/assets/common.cljs:428 msgid "workspace.shape.menu.show-in-assets" msgstr "Show in assets panel" -#: src/app/main/ui/workspace/sidebar/assets/common.cljs:442, src/app/main/ui/workspace/sidebar/assets/components.cljs:585 +#: src/app/main/ui/workspace/sidebar/assets/common.cljs:446, src/app/main/ui/workspace/sidebar/assets/components.cljs:576 msgid "workspace.shape.menu.show-main" msgstr "Show main component" -#: src/app/main/ui/workspace/context_menu.cljs:222 +#: src/app/main/ui/workspace/context_menu.cljs:228 msgid "workspace.shape.menu.thumbnail-remove" msgstr "Remove thumbnail" -#: src/app/main/ui/workspace/context_menu.cljs:224 +#: src/app/main/ui/workspace/context_menu.cljs:230 msgid "workspace.shape.menu.thumbnail-set" msgstr "Set as thumbnail" -#: src/app/main/ui/workspace/context_menu.cljs:337 +#: src/app/main/ui/workspace/context_menu.cljs:343 msgid "workspace.shape.menu.transform-to-path" msgstr "Transform to path" -#: src/app/main/ui/workspace/context_menu.cljs:268 +#: src/app/main/ui/workspace/context_menu.cljs:274 msgid "workspace.shape.menu.ungroup" msgstr "Ungroup" -#: src/app/main/ui/workspace/context_menu.cljs:343, src/app/main/ui/workspace/sidebar/options/menus/bool.cljs:70 +#: src/app/main/ui/workspace/context_menu.cljs:349, src/app/main/ui/workspace/sidebar/options/menus/bool.cljs:70 msgid "workspace.shape.menu.union" msgstr "Union" -#: src/app/main/ui/workspace/context_menu.cljs:379, src/app/main/ui/workspace/sidebar/layer_item.cljs:152, src/app/main/ui/workspace/sidebar/options/menus/layer.cljs:195 +#: src/app/main/ui/workspace/context_menu.cljs:385, src/app/main/ui/workspace/sidebar/layer_item.cljs:152, src/app/main/ui/workspace/sidebar/options/menus/layer.cljs:210 msgid "workspace.shape.menu.unlock" msgstr "Unlock" -#: src/app/main/ui/workspace/context_menu.cljs:282 +#: src/app/main/ui/workspace/context_menu.cljs:288 msgid "workspace.shape.menu.unmask" msgstr "Unmask" @@ -6121,7 +6176,7 @@ msgstr "Unmask" msgid "workspace.shape.menu.update-components-in-bulk" msgstr "Update main components" -#: src/app/main/ui/workspace/sidebar/assets/common.cljs:445 +#: src/app/main/ui/workspace/sidebar/assets/common.cljs:449 msgid "workspace.shape.menu.update-main" msgstr "Update main component" @@ -6137,39 +6192,39 @@ msgstr "Expand sidebar" msgid "workspace.sidebar.history" msgstr "History" -#: src/app/main/ui/workspace/sidebar/layers.cljs:524, src/app/main/ui/workspace/sidebar.cljs:110, src/app/main/ui/workspace/sidebar.cljs:114, src/app/main/ui/workspace/sidebar.cljs:123 +#: src/app/main/ui/workspace/sidebar/layers.cljs:525, src/app/main/ui/workspace/sidebar.cljs:110, src/app/main/ui/workspace/sidebar.cljs:114, src/app/main/ui/workspace/sidebar.cljs:123 msgid "workspace.sidebar.layers" msgstr "Layers" -#: src/app/main/ui/workspace/sidebar/layers.cljs:310, src/app/main/ui/workspace/sidebar/layers.cljs:382 +#: src/app/main/ui/workspace/sidebar/layers.cljs:311, src/app/main/ui/workspace/sidebar/layers.cljs:383 msgid "workspace.sidebar.layers.components" msgstr "Components" -#: src/app/main/ui/workspace/sidebar/layers.cljs:307, src/app/main/ui/workspace/sidebar/layers.cljs:340 +#: src/app/main/ui/workspace/sidebar/layers.cljs:308, src/app/main/ui/workspace/sidebar/layers.cljs:341 msgid "workspace.sidebar.layers.frames" msgstr "Boards" -#: src/app/main/ui/workspace/sidebar/layers.cljs:308, src/app/main/ui/workspace/sidebar/layers.cljs:354 +#: src/app/main/ui/workspace/sidebar/layers.cljs:309, src/app/main/ui/workspace/sidebar/layers.cljs:355 msgid "workspace.sidebar.layers.groups" msgstr "Groups" -#: src/app/main/ui/workspace/sidebar/layers.cljs:312, src/app/main/ui/workspace/sidebar/layers.cljs:410 +#: src/app/main/ui/workspace/sidebar/layers.cljs:313, src/app/main/ui/workspace/sidebar/layers.cljs:411 msgid "workspace.sidebar.layers.images" msgstr "Images" -#: src/app/main/ui/workspace/sidebar/layers.cljs:309, src/app/main/ui/workspace/sidebar/layers.cljs:368 +#: src/app/main/ui/workspace/sidebar/layers.cljs:310, src/app/main/ui/workspace/sidebar/layers.cljs:369 msgid "workspace.sidebar.layers.masks" msgstr "Masks" -#: src/app/main/ui/workspace/sidebar/layers.cljs:290 +#: src/app/main/ui/workspace/sidebar/layers.cljs:291 msgid "workspace.sidebar.layers.search" msgstr "Search layers" -#: src/app/main/ui/workspace/sidebar/layers.cljs:313, src/app/main/ui/workspace/sidebar/layers.cljs:424 +#: src/app/main/ui/workspace/sidebar/layers.cljs:314, src/app/main/ui/workspace/sidebar/layers.cljs:425 msgid "workspace.sidebar.layers.shapes" msgstr "Shapes" -#: src/app/main/ui/workspace/sidebar/layers.cljs:311, src/app/main/ui/workspace/sidebar/layers.cljs:396 +#: src/app/main/ui/workspace/sidebar/layers.cljs:312, src/app/main/ui/workspace/sidebar/layers.cljs:397 msgid "workspace.sidebar.layers.texts" msgstr "Texts" @@ -6206,7 +6261,7 @@ msgstr "Back to theme list" msgid "workspace.token.create-new-theme" msgstr "Create your first theme now." -#: src/app/main/ui/workspace/tokens/sidebar.cljs:194, src/app/main/ui/workspace/tokens/sidebar.cljs:210 +#: src/app/main/ui/workspace/tokens/sidebar.cljs:194, src/app/main/ui/workspace/tokens/sidebar.cljs:215 msgid "workspace.token.create-one" msgstr "Create one." @@ -6214,7 +6269,7 @@ msgstr "Create one." msgid "workspace.token.create-theme-title" msgstr "Create theme" -#: src/app/main/ui/workspace/tokens/form.cljs:362 +#: src/app/main/ui/workspace/tokens/form.cljs:364 msgid "workspace.token.create-token" msgstr "Create new %s token" @@ -6230,11 +6285,27 @@ msgstr "Edit theme" msgid "workspace.token.edit-themes" msgstr "Edit themes" -#: src/app/main/ui/workspace/tokens/form.cljs:361 +#: src/app/main/ui/workspace/tokens/form.cljs:363 msgid "workspace.token.edit-token" msgstr "Edit token" +#: src/app/main/ui/workspace/tokens/form.cljs:408 +#, fuzzy +msgid "workspace.token.enter-token-description" +msgstr "" + +#: src/app/main/ui/workspace/tokens/form.cljs:370 +#, fuzzy +msgid "workspace.token.enter-token-name" +msgstr "" + +#: src/app/main/ui/workspace/tokens/form.cljs:390 +#, fuzzy +msgid "workspace.token.enter-token-value" +msgstr "" + #: src/app/main/ui/workspace/tokens/sets.cljs:186 +#, unused msgid "workspace.token.grouping-set-alert" msgstr "Token Set grouping is not supported yet." @@ -6250,11 +6321,11 @@ msgstr "No theme active" msgid "workspace.token.no-sets" msgstr "No sets" -#: src/app/main/ui/workspace/tokens/sets.cljs:216 +#: src/app/main/ui/workspace/tokens/sets.cljs:241, src/app/main/ui/workspace/tokens/sets.cljs:245 msgid "workspace.token.no-sets-create" msgstr "There are no sets defined yet. Create one first." -#: src/app/main/ui/workspace/tokens/sidebar.cljs:239 +#: src/app/main/ui/workspace/tokens/sidebar.cljs:212 msgid "workspace.token.no-sets-yet" msgstr "There are no sets yet." @@ -6274,7 +6345,7 @@ msgstr "%s sets" msgid "workspace.token.original-value" msgstr "Original value: " -#: src/app/main/ui/workspace/tokens/form.cljs:193, src/app/main/ui/workspace/tokens/form.cljs:196, src/app/main/ui/workspace/tokens/sidebar.cljs:67 +#: src/app/main/ui/workspace/tokens/form.cljs:194, src/app/main/ui/workspace/tokens/form.cljs:197, src/app/main/ui/workspace/tokens/sidebar.cljs:67 msgid "workspace.token.resolved-value" msgstr "Resolved value: " @@ -6282,7 +6353,7 @@ msgstr "Resolved value: " msgid "workspace.token.save-theme" msgstr "Save theme" -#: src/app/main/ui/workspace/tokens/sets.cljs:172 +#: src/app/main/ui/workspace/tokens/sets.cljs:160 msgid "workspace.token.select-set" msgstr "Select set." @@ -6304,6 +6375,21 @@ msgstr "Theme %s" msgid "workspace.token.themes" msgstr "Themes" +#: src/app/main/ui/workspace/tokens/form.cljs:409 +#, fuzzy +msgid "workspace.token.token-description" +msgstr "" + +#: src/app/main/ui/workspace/tokens/form.cljs:373 +#, fuzzy +msgid "workspace.token.token-name" +msgstr "" + +#: src/app/main/ui/workspace/tokens/form.cljs:391 +#, fuzzy +msgid "workspace.token.token-value" +msgstr "" + #: src/app/main/ui/workspace/sidebar.cljs:117, src/app/main/ui/workspace/sidebar.cljs:126 msgid "workspace.toolbar.assets" msgstr "Assets" @@ -6316,35 +6402,35 @@ msgstr "Color Palette (%s)" msgid "workspace.toolbar.comments" msgstr "Comments (%s)" -#: src/app/main/ui/workspace/top_toolbar.cljs:181, src/app/main/ui/workspace/top_toolbar.cljs:182 +#: src/app/main/ui/workspace/top_toolbar.cljs:182, src/app/main/ui/workspace/top_toolbar.cljs:183 msgid "workspace.toolbar.curve" msgstr "Curve (%s)" -#: src/app/main/ui/workspace/top_toolbar.cljs:161, src/app/main/ui/workspace/top_toolbar.cljs:162 +#: src/app/main/ui/workspace/top_toolbar.cljs:162, src/app/main/ui/workspace/top_toolbar.cljs:163 msgid "workspace.toolbar.ellipse" msgstr "Ellipse (%s)" -#: src/app/main/ui/workspace/top_toolbar.cljs:143, src/app/main/ui/workspace/top_toolbar.cljs:144 +#: src/app/main/ui/workspace/top_toolbar.cljs:144, src/app/main/ui/workspace/top_toolbar.cljs:145 msgid "workspace.toolbar.frame" msgstr "Board (%s)" -#: src/app/main/ui/workspace/top_toolbar.cljs:60, src/app/main/ui/workspace/top_toolbar.cljs:61 +#: src/app/main/ui/workspace/top_toolbar.cljs:61, src/app/main/ui/workspace/top_toolbar.cljs:62 msgid "workspace.toolbar.image" msgstr "Image (%s)" -#: src/app/main/ui/workspace/top_toolbar.cljs:133, src/app/main/ui/workspace/top_toolbar.cljs:134 +#: src/app/main/ui/workspace/top_toolbar.cljs:134, src/app/main/ui/workspace/top_toolbar.cljs:135 msgid "workspace.toolbar.move" msgstr "Move (%s)" -#: src/app/main/ui/workspace/top_toolbar.cljs:190, src/app/main/ui/workspace/top_toolbar.cljs:191 +#: src/app/main/ui/workspace/top_toolbar.cljs:191, src/app/main/ui/workspace/top_toolbar.cljs:192 msgid "workspace.toolbar.path" msgstr "Path (%s)" -#: src/app/main/ui/workspace/top_toolbar.cljs:201, src/app/main/ui/workspace/top_toolbar.cljs:202 +#: src/app/main/ui/workspace/top_toolbar.cljs:202, src/app/main/ui/workspace/top_toolbar.cljs:203 msgid "workspace.toolbar.plugins" msgstr "Plugins (%s)" -#: src/app/main/ui/workspace/top_toolbar.cljs:152, src/app/main/ui/workspace/top_toolbar.cljs:153 +#: src/app/main/ui/workspace/top_toolbar.cljs:153, src/app/main/ui/workspace/top_toolbar.cljs:154 msgid "workspace.toolbar.rect" msgstr "Rectangle (%s)" @@ -6353,7 +6439,7 @@ msgstr "Rectangle (%s)" msgid "workspace.toolbar.shortcuts" msgstr "Shortcuts (%s)" -#: src/app/main/ui/workspace/top_toolbar.cljs:170, src/app/main/ui/workspace/top_toolbar.cljs:171 +#: src/app/main/ui/workspace/top_toolbar.cljs:171, src/app/main/ui/workspace/top_toolbar.cljs:172 msgid "workspace.toolbar.text" msgstr "Text (%s)" @@ -6361,7 +6447,7 @@ msgstr "Text (%s)" msgid "workspace.toolbar.text-palette" msgstr "Typographies (%s)" -#: src/app/main/ui/workspace/top_toolbar.cljs:219, src/app/main/ui/workspace/top_toolbar.cljs:220 +#: src/app/main/ui/workspace/top_toolbar.cljs:220, src/app/main/ui/workspace/top_toolbar.cljs:221 msgid "workspace.toolbar.toggle-toolbar" msgstr "Toggle toolbar" @@ -6374,143 +6460,143 @@ msgstr "Done" msgid "workspace.top-bar.view-only" msgstr "**Inspecting code** (View Only)" -#: src/app/main/ui/workspace/sidebar/history.cljs:331 +#: src/app/main/ui/workspace/sidebar/history.cljs:332 msgid "workspace.undo.empty" msgstr "There are no history changes so far" -#: src/app/main/ui/workspace/sidebar/history.cljs:145 +#: src/app/main/ui/workspace/sidebar/history.cljs:146 msgid "workspace.undo.entry.delete" msgstr "Deleted %s" -#: src/app/main/ui/workspace/sidebar/history.cljs:144 +#: src/app/main/ui/workspace/sidebar/history.cljs:145 msgid "workspace.undo.entry.modify" msgstr "Modified %s" -#: src/app/main/ui/workspace/sidebar/history.cljs:146 +#: src/app/main/ui/workspace/sidebar/history.cljs:147 msgid "workspace.undo.entry.move" msgstr "Moved objects" -#: src/app/main/ui/workspace/sidebar/history.cljs:109 +#: src/app/main/ui/workspace/sidebar/history.cljs:110 msgid "workspace.undo.entry.multiple.circle" msgstr "circles" -#: src/app/main/ui/workspace/sidebar/history.cljs:110 +#: src/app/main/ui/workspace/sidebar/history.cljs:111 msgid "workspace.undo.entry.multiple.color" msgstr "color assets" -#: src/app/main/ui/workspace/sidebar/history.cljs:111 +#: src/app/main/ui/workspace/sidebar/history.cljs:112 msgid "workspace.undo.entry.multiple.component" msgstr "components" -#: src/app/main/ui/workspace/sidebar/history.cljs:112 +#: src/app/main/ui/workspace/sidebar/history.cljs:113 msgid "workspace.undo.entry.multiple.curve" msgstr "curves" -#: src/app/main/ui/workspace/sidebar/history.cljs:113 +#: src/app/main/ui/workspace/sidebar/history.cljs:114 msgid "workspace.undo.entry.multiple.frame" msgstr "board" -#: src/app/main/ui/workspace/sidebar/history.cljs:114 +#: src/app/main/ui/workspace/sidebar/history.cljs:115 msgid "workspace.undo.entry.multiple.group" msgstr "groups" -#: src/app/main/ui/workspace/sidebar/history.cljs:115 +#: src/app/main/ui/workspace/sidebar/history.cljs:116 msgid "workspace.undo.entry.multiple.media" msgstr "graphic assets" -#: src/app/main/ui/workspace/sidebar/history.cljs:116 +#: src/app/main/ui/workspace/sidebar/history.cljs:117 msgid "workspace.undo.entry.multiple.multiple" msgstr "objects" -#: src/app/main/ui/workspace/sidebar/history.cljs:117 +#: src/app/main/ui/workspace/sidebar/history.cljs:118 msgid "workspace.undo.entry.multiple.page" msgstr "pages" -#: src/app/main/ui/workspace/sidebar/history.cljs:118 +#: src/app/main/ui/workspace/sidebar/history.cljs:119 msgid "workspace.undo.entry.multiple.path" msgstr "paths" -#: src/app/main/ui/workspace/sidebar/history.cljs:119 +#: src/app/main/ui/workspace/sidebar/history.cljs:120 msgid "workspace.undo.entry.multiple.rect" msgstr "rectangles" -#: src/app/main/ui/workspace/sidebar/history.cljs:120 +#: src/app/main/ui/workspace/sidebar/history.cljs:121 msgid "workspace.undo.entry.multiple.shape" msgstr "shapes" -#: src/app/main/ui/workspace/sidebar/history.cljs:121 +#: src/app/main/ui/workspace/sidebar/history.cljs:122 msgid "workspace.undo.entry.multiple.text" msgstr "texts" -#: src/app/main/ui/workspace/sidebar/history.cljs:122 +#: src/app/main/ui/workspace/sidebar/history.cljs:123 msgid "workspace.undo.entry.multiple.typography" msgstr "typography assets" -#: src/app/main/ui/workspace/sidebar/history.cljs:143 +#: src/app/main/ui/workspace/sidebar/history.cljs:144 msgid "workspace.undo.entry.new" msgstr "New %s" -#: src/app/main/ui/workspace/sidebar/history.cljs:123 +#: src/app/main/ui/workspace/sidebar/history.cljs:124 msgid "workspace.undo.entry.single.circle" msgstr "circle" -#: src/app/main/ui/workspace/sidebar/history.cljs:124 +#: src/app/main/ui/workspace/sidebar/history.cljs:125 msgid "workspace.undo.entry.single.color" msgstr "color asset" -#: src/app/main/ui/workspace/sidebar/history.cljs:125 +#: src/app/main/ui/workspace/sidebar/history.cljs:126 msgid "workspace.undo.entry.single.component" msgstr "component" -#: src/app/main/ui/workspace/sidebar/history.cljs:126 +#: src/app/main/ui/workspace/sidebar/history.cljs:127 msgid "workspace.undo.entry.single.curve" msgstr "curve" -#: src/app/main/ui/workspace/sidebar/history.cljs:127 +#: src/app/main/ui/workspace/sidebar/history.cljs:128 msgid "workspace.undo.entry.single.frame" msgstr "board" -#: src/app/main/ui/workspace/sidebar/history.cljs:128 +#: src/app/main/ui/workspace/sidebar/history.cljs:129 msgid "workspace.undo.entry.single.group" msgstr "group" -#: src/app/main/ui/workspace/sidebar/history.cljs:129 +#: src/app/main/ui/workspace/sidebar/history.cljs:130 msgid "workspace.undo.entry.single.image" msgstr "image" -#: src/app/main/ui/workspace/sidebar/history.cljs:130 +#: src/app/main/ui/workspace/sidebar/history.cljs:131 msgid "workspace.undo.entry.single.media" msgstr "graphic asset" -#: src/app/main/ui/workspace/sidebar/history.cljs:131 +#: src/app/main/ui/workspace/sidebar/history.cljs:132 msgid "workspace.undo.entry.single.multiple" msgstr "object" -#: src/app/main/ui/workspace/sidebar/history.cljs:132 +#: src/app/main/ui/workspace/sidebar/history.cljs:133 msgid "workspace.undo.entry.single.page" msgstr "page" -#: src/app/main/ui/workspace/sidebar/history.cljs:133 +#: src/app/main/ui/workspace/sidebar/history.cljs:134 msgid "workspace.undo.entry.single.path" msgstr "path" -#: src/app/main/ui/workspace/sidebar/history.cljs:134 +#: src/app/main/ui/workspace/sidebar/history.cljs:135 msgid "workspace.undo.entry.single.rect" msgstr "rectangle" -#: src/app/main/ui/workspace/sidebar/history.cljs:135 +#: src/app/main/ui/workspace/sidebar/history.cljs:136 msgid "workspace.undo.entry.single.shape" msgstr "shape" -#: src/app/main/ui/workspace/sidebar/history.cljs:136 +#: src/app/main/ui/workspace/sidebar/history.cljs:137 msgid "workspace.undo.entry.single.text" msgstr "text" -#: src/app/main/ui/workspace/sidebar/history.cljs:137 +#: src/app/main/ui/workspace/sidebar/history.cljs:138 msgid "workspace.undo.entry.single.typography" msgstr "typography asset" -#: src/app/main/ui/workspace/sidebar/history.cljs:147 +#: src/app/main/ui/workspace/sidebar/history.cljs:148 msgid "workspace.undo.entry.unknown" msgstr "Operation over %s" @@ -6519,71 +6605,71 @@ msgstr "Operation over %s" msgid "workspace.undo.title" msgstr "History" -#: src/app/main/data/workspace/libraries.cljs:1147, src/app/main/ui/workspace/sidebar/versions.cljs:285 +#: src/app/main/data/workspace/libraries.cljs:1159, src/app/main/ui/workspace/sidebar/versions.cljs:287 msgid "workspace.updates.dismiss" msgstr "Dismiss" -#: src/app/main/data/workspace/libraries.cljs:1145 +#: src/app/main/data/workspace/libraries.cljs:1157 msgid "workspace.updates.more-info" msgstr "More info" -#: src/app/main/data/workspace/libraries.cljs:1143 +#: src/app/main/data/workspace/libraries.cljs:1155 msgid "workspace.updates.there-are-updates" msgstr "There are updates in shared libraries" -#: src/app/main/data/workspace/libraries.cljs:1150 +#: src/app/main/data/workspace/libraries.cljs:1162 msgid "workspace.updates.update" msgstr "Update" -#: src/app/main/ui/workspace/sidebar/versions.cljs:193 +#: src/app/main/ui/workspace/sidebar/versions.cljs:194 msgid "workspace.versions.autosaved.entry" msgstr "%s autosave versions" -#: src/app/main/ui/workspace/sidebar/versions.cljs:187 +#: src/app/main/ui/workspace/sidebar/versions.cljs:188 msgid "workspace.versions.autosaved.version" msgstr "Autosaved %s" -#: src/app/main/ui/workspace/sidebar/versions.cljs:224 +#: src/app/main/ui/workspace/sidebar/versions.cljs:225 msgid "workspace.versions.button.pin" msgstr "Pin version" -#: src/app/main/ui/workspace/sidebar/versions.cljs:219 +#: src/app/main/ui/workspace/sidebar/versions.cljs:220 msgid "workspace.versions.button.restore" msgstr "Restore version" -#: src/app/main/ui/workspace/sidebar/versions.cljs:345, src/app/main/ui/workspace/sidebar/versions.cljs:347 +#: src/app/main/ui/workspace/sidebar/versions.cljs:359, src/app/main/ui/workspace/sidebar/versions.cljs:361 msgid "workspace.versions.button.save" msgstr "Save version" -#: src/app/main/ui/workspace/sidebar/versions.cljs:354 +#: src/app/main/ui/workspace/sidebar/versions.cljs:368 msgid "workspace.versions.empty" msgstr "There are no versions yet" -#: src/app/main/ui/workspace/sidebar/versions.cljs:190 +#: src/app/main/ui/workspace/sidebar/versions.cljs:191 msgid "workspace.versions.expand-snapshot" msgstr "Expand snapshots" -#: src/app/main/ui/workspace/sidebar/versions.cljs:327 +#: src/app/main/ui/workspace/sidebar/versions.cljs:341 msgid "workspace.versions.filter.all" msgstr "All versions" -#: src/app/main/ui/workspace/sidebar/versions.cljs:326 +#: src/app/main/ui/workspace/sidebar/versions.cljs:340 msgid "workspace.versions.filter.label" msgstr "Versions filter" -#: src/app/main/ui/workspace/sidebar/versions.cljs:328 +#: src/app/main/ui/workspace/sidebar/versions.cljs:342 msgid "workspace.versions.filter.mine" msgstr "My versions" -#: src/app/main/ui/workspace/sidebar/versions.cljs:334 +#: src/app/main/ui/workspace/sidebar/versions.cljs:348 msgid "workspace.versions.filter.user" msgstr "%s's versions" -#: src/app/main/ui/workspace/sidebar/versions.cljs:340 +#: src/app/main/ui/workspace/sidebar/versions.cljs:354 msgid "workspace.versions.loading" msgstr "Loading..." -#: src/app/main/ui/workspace/sidebar/versions.cljs:283 +#: src/app/main/ui/workspace/sidebar/versions.cljs:285 msgid "workspace.versions.restore-warning" msgstr "Do you want to restore this version?" @@ -6598,7 +6684,15 @@ msgstr "If you'd like to increase this limit, write to us at [support@penpot.app msgid "workspace.versions.snapshot-menu" msgstr "Open snapshot menu" -#: src/app/main/ui/workspace/sidebar/versions.cljs:138 +#: src/app/main/ui/workspace/sidebar.cljs:242 +msgid "workspace.versions.tab.actions" +msgstr "Actions" + +#: src/app/main/ui/workspace/sidebar.cljs:241 +msgid "workspace.versions.tab.history" +msgstr "History" + +#: src/app/main/ui/workspace/sidebar/versions.cljs:139 msgid "workspace.versions.version-menu" msgstr "Open version menu" @@ -6606,8 +6700,59 @@ msgstr "Open version menu" msgid "workspace.viewport.click-to-close-path" msgstr "Click to close the path" -msgid "workspace.versions.tab.history" -msgstr "History" +msgid "dashboard.notifications.notifications-saved" +msgstr "Notification settings updated" -msgid "workspace.versions.tab.actions" -msgstr "Actions" +msgid "title.settings.notifications" +msgstr "Notifications - Penpot" + +msgid "dashboard.settings.notifications.title" +msgstr "Notifications" + +msgid "dashboard.settings.notifications.dashboard.title" +msgstr "Dashboard Notifications" + +msgid "dashboard.settings.notifications.dashboard-comments.title" +msgstr "File comments" + +msgid "dashboard.settings.notifications.dashboard-comments.all" +msgstr "All comments, mentions and replies" + +msgid "dashboard.settings.notifications.dashboard-comments.partial" +msgstr "Only mentions and replies" + +msgid "dashboard.settings.notifications.dashboard-comments.none" +msgstr "None" + +msgid "dashboard.settings.notifications.email.title" +msgstr "Email Notifications" + +msgid "dashboard.settings.notifications.email-comments.title" +msgstr "File comments" + +msgid "dashboard.settings.notifications.email-comments.all" +msgstr "All comments, mentions and replies" + +msgid "dashboard.settings.notifications.email-comments.partial" +msgstr "Only mentions and replies" + +msgid "dashboard.settings.notifications.email-comments.none" +msgstr "None" + +msgid "dashboard.settings.notifications.email-invites.title" +msgstr "Invites and requests" + +msgid "dashboard.settings.notifications.email-invites.all" +msgstr "All types of invites and requests" + +msgid "dashboard.settings.notifications.email-invites.none" +msgstr "None" + +msgid "dashboard.settings.notifications.submit" +msgstr "Update settings" + +msgid "labels.notifications" +msgstr "Notifications" + +msgid "comments.mentions.not-found" +msgstr "No people found for @%s" diff --git a/frontend/translations/es.po b/frontend/translations/es.po index d8cb5e6ef7..df0f5dc8ed 100644 --- a/frontend/translations/es.po +++ b/frontend/translations/es.po @@ -759,6 +759,14 @@ msgstr "No se encuentra “%s“" msgid "dashboard.no-projects-placeholder" msgstr "Los proyectos fijados aparecerán aquí" +#: src/app/main/ui/dashboard/comments.cljs +msgid "dashboard.notifications" +msgstr "Notificaciones" + +#: src/app/main/ui/dashboard/comments.cljs +msgid "dashboard.notifications.view" +msgstr "Ver notificaciones" + #: src/app/main/ui/auth/verify_token.cljs:32 msgid "dashboard.notifications.email-changed-successfully" msgstr "Tu dirección de correo ha sido actualizada" @@ -1634,6 +1642,13 @@ msgstr "Cerrar" msgid "labels.collapse" msgstr "Colapsar" +msgid "labels.comment" +msgstr "Comentario" + +#: src/app/main/ui/comments.cljs:446 +msgid "labels.comment.mark-as-solved" +msgstr "Marcar como resuelto" + #: src/app/main/ui/dashboard/comments.cljs:104, src/app/main/ui/viewer/comments.cljs:70, src/app/main/ui/workspace/comments.cljs:127 msgid "labels.comments" msgstr "Comentarios" @@ -1957,6 +1972,10 @@ msgstr "Contraseña" msgid "labels.pending-invitation" msgstr "Pendiente" +#: src/app/main/ui/comments.cljs:147 +msgid "labels.post" +msgstr "Publicar" + #: src/app/main/ui/onboarding/questions.cljs:51 msgid "labels.previous" msgstr "Anterior" @@ -2003,6 +2022,26 @@ msgstr "Renombrar" msgid "labels.rename-team" msgstr "Renombra el equipo" +#: src/app/main/ui/comments.cljs:145 +msgid "labels.reply" +msgstr "respuesta" + +#: src/app/main/ui/comments.cljs:150 +msgid "labels.reply.new" +msgstr "nueva respuesta" + +#: src/app/main/ui/comments.cljs:188 +msgid "labels.reply.thread" +msgstr "Responder" + +#: src/app/main/ui/comments.cljs:146 +msgid "labels.replies" +msgstr "respuestas" + +#: src/app/main/ui/comments.cljs:151 +msgid "labels.replies.new" +msgstr "nuevas respuestas" + #: src/app/main/ui/dashboard/team.cljs:681 msgid "labels.resend-invitation" msgstr "Reenviar invitacion" @@ -2083,6 +2122,9 @@ msgstr "Mostrar lista de comentarios" msgid "labels.show-your-comments" msgstr "Mostrar sólo tus comentarios" +msgid "labels.show-mentions" +msgstr "Mostrar sólo tus menciones" + #: src/app/main/ui/onboarding/questions.cljs:167 msgid "labels.sketch" msgstr "Sketch" @@ -3341,6 +3383,9 @@ msgstr "Limpiar historial" msgid "shortcuts.copy" msgstr "Copiar" +msgid "shortcuts.copy-link" +msgstr "Copiar enlace al portapapeles" + #: src/app/main/ui/workspace/sidebar/shortcuts.cljs:94 msgid "shortcuts.create-component" msgstr "Crear componente" @@ -5940,6 +5985,9 @@ msgstr "Enviar atrás" msgid "workspace.shape.menu.copy" msgstr "Copiar" +msgid "workspace.shape.menu.copy_link" +msgstr "Copiar enlace al portapapeles" + #: src/app/main/ui/workspace/sidebar/assets/common.cljs:427 msgid "workspace.shape.menu.create-annotation" msgstr "Crear una nota" @@ -6607,3 +6655,60 @@ msgstr "Histórico" msgid "workspace.versions.tab.actions" msgstr "Acciones" + +msgid "dashboard.notifications.notifications-saved" +msgstr "Configuración de notificaciones actualizada" + +msgid "title.settings.notifications" +msgstr "Notificaciones - Penpot" + +msgid "dashboard.settings.notifications.title" +msgstr "Notificaciones" + +msgid "dashboard.settings.notifications.dashboard.title" +msgstr "Notificaciones en el panel" + +msgid "dashboard.settings.notifications.dashboard-comments.title" +msgstr "Comentarios de ficheros" + +msgid "dashboard.settings.notifications.dashboard-comments.all" +msgstr "Todos los comentarios, menciones y respuestas" + +msgid "dashboard.settings.notifications.dashboard-comments.partial" +msgstr "Sólo menciones y respuestas" + +msgid "dashboard.settings.notifications.dashboard-comments.none" +msgstr "Ninguna" + +msgid "dashboard.settings.notifications.email.title" +msgstr "Notificaciones de correo electrónico" + +msgid "dashboard.settings.notifications.email-comments.title" +msgstr "Comentarios de ficheros" + +msgid "dashboard.settings.notifications.email-comments.all" +msgstr "Todos los comentarios, menciones y respuestas" + +msgid "dashboard.settings.notifications.email-comments.partial" +msgstr "Sólo menciones y respuestas" + +msgid "dashboard.settings.notifications.email-comments.none" +msgstr "Ninguna" + +msgid "dashboard.settings.notifications.email-invites.title" +msgstr "Invitaciones y solicitudes" + +msgid "dashboard.settings.notifications.email-invites.all" +msgstr "Todas las invitaciones y solicitudes" + +msgid "dashboard.settings.notifications.email-invites.none" +msgstr "Ninguna" + +msgid "dashboard.settings.notifications.submit" +msgstr "Actualizar configuración" + +msgid "labels.notifications" +msgstr "Notificaciones" + +msgid "comments.mentions.not-found" +msgstr "No se encuentra miembros con @%s" diff --git a/frontend/translations/he.po b/frontend/translations/he.po index a275e7962d..bc626150da 100644 --- a/frontend/translations/he.po +++ b/frontend/translations/he.po @@ -1,7 +1,7 @@ msgid "" msgstr "" -"PO-Revision-Date: 2024-11-14 11:14+0000\n" -"Last-Translator: Anonymous \n" +"PO-Revision-Date: 2024-11-17 14:00+0000\n" +"Last-Translator: Yaron Shahrabani \n" "Language-Team: Hebrew \n" "Language: he\n" @@ -5527,9 +5527,11 @@ msgid "workspace.plugins.permissions.content-write" msgstr "קריאה ושינוי התוכן של קבצים שלמשתמשים יש גישה אליהם." #: src/app/main/ui/workspace/plugins.cljs:323 -#, fuzzy msgid "workspace.plugins.permissions.disclaimer" -msgstr "נא לשים לב שהתוסף הזה נוצר על ידי גוף חיצוני." +msgstr "" +"נא לשים לב שהתוסף הזה נוצר על ידי גוף חיצוני, לכן כדאי לוודא שהוא אמין לפי " +"שמעניקים לו גישה. פרטיות ואבטחת המידע שלך חשובים לנו. במקרה של ספק נא ליצור " +"קשר עם התמיכה." #: src/app/main/ui/workspace/plugins.cljs:263 msgid "workspace.plugins.permissions.library-read" @@ -5540,9 +5542,8 @@ msgid "workspace.plugins.permissions.library-write" msgstr "קריאה ושינוי הספריות והמשאבים שלך." #: src/app/main/ui/workspace/plugins.cljs:316 -#, fuzzy msgid "workspace.plugins.permissions.title" -msgstr "התוסף הזה רוצה לגשת אל:" +msgstr "התוסף ‚%s’ רוצה לגשת אל:" #: src/app/main/ui/workspace/plugins.cljs:250 msgid "workspace.plugins.permissions.user-read" @@ -6060,3 +6061,449 @@ msgstr "עדכון" #, unused msgid "workspace.viewport.click-to-close-path" msgstr "לחיצה תסגור את הנתיב" + +#: src/app/main/ui/dashboard/files.cljs:190, src/app/main/ui/dashboard/projects.cljs:284 +msgid "dashboard.empty-placeholder-drafts-subtitle" +msgstr "כשאחד או אחת מחברי הצוות יוצרים טיוטה, היא תוצג כאן." + +#: src/app/main/ui/dashboard/files.cljs:186, src/app/main/ui/dashboard/projects.cljs:280 +msgid "dashboard.empty-placeholder-files-title" +msgstr "אין קבצים עדיין." + +#: src/app/main/ui/dashboard/files.cljs:185, src/app/main/ui/dashboard/projects.cljs:279 +msgid "dashboard.empty-placeholder-drafts-title" +msgstr "אין טיוטות עדיין." + +#: src/app/main/ui/dashboard/files.cljs:191, src/app/main/ui/dashboard/projects.cljs:285 +msgid "dashboard.empty-placeholder-files-subtitle" +msgstr "כשחבר או חברה במיזם יוצרים קובץ, הוא יופיע כאן." + +#: src/app/main/ui/dashboard/placeholder.cljs:35 +msgid "dashboard.empty-placeholder-libraries-subtitle-viewer-role" +msgstr "ספריות שנוספו למיזם תופענה כאן." + +#: src/app/main/ui/dashboard/placeholder.cljs:39 +#, markdown +msgid "dashboard.empty-placeholder-libraries" +msgstr "" +"ספריות שנוספו למיזם תופענה כאן. כדאי לנסות לשתף את הקבצים שלך או להוסיף מ[" +"הספריות והתבניות](https://penpot.app/libraries-templates) שלנו." + +#: src/app/main/data/common.cljs:205 +msgid "dashboard.permissions-change.admin" +msgstr "מונית לנהל את הצוות הזה." + +#: src/app/main/data/common.cljs:204 +msgid "dashboard.permissions-change.editor" +msgstr "מונית לערוך בצוות הזה." + +#: src/app/main/data/common.cljs:206 +msgid "dashboard.permissions-change.owner" +msgstr "מונית לבעלי הצוות הזה." + +#: src/app/main/ui/workspace/libraries.cljs:304 +msgid "workspace.libraries.more-templates-link" +msgstr "תבניות נוספות כאן" + +#: src/app/main/ui/workspace/sidebar/options/menus/exports.cljs:195 +msgid "workspace.options.export.add-export" +msgstr "הוספת ייצוא" + +#: src/app/main/ui/workspace/sidebar/options/menus/fill.cljs:150 +msgid "workspace.options.fill.add-fill" +msgstr "הוספת צבע מילוי" + +#: src/app/main/ui/workspace/sidebar/options/menus/layer.cljs:176, src/app/main/ui/workspace/sidebar/options/menus/layer.cljs:182 +msgid "workspace.options.layer-options.toggle-layer" +msgstr "הצגת/הסתרת שכבה" + +#: src/app/main/ui/workspace/sidebar/options/menus/stroke.cljs:184 +msgid "workspace.options.stroke.remove-stroke" +msgstr "הסרת מתאר" + +#: src/app/main/ui/workspace/plugins.cljs:196 +msgid "workspace.plugins.error.manifest" +msgstr "המצהר/מניפסט של התוסף שגוי." + +#: src/app/main/ui/workspace/plugins.cljs:376 +msgid "workspace.plugins.permissions-update.warning" +msgstr "התוסף הזה השתנה מאז שפתחת אותו. עכשיו הוא רוצה גם לגשת אל:" + +#: src/app/main/ui/workspace/plugins.cljs:283 +msgid "workspace.plugins.permissions.allow-download" +msgstr "התחלת הורדות קבצים." + +#: src/app/main/ui/workspace/plugins.cljs:372 +msgid "workspace.plugins.permissions-update.title" +msgstr "לעדכן את התוסף הזה" + +#: src/app/main/ui/workspace/plugins.cljs:270 +msgid "workspace.plugins.permissions.comment-write" +msgstr "לקרוא ולשנות את ההערות שלך ולהגיב בשמך." + +#: src/app/main/ui/workspace/plugins.cljs:86 +msgid "workspace.plugins.remove-plugin" +msgstr "הסרת תוסף" + +#: src/app/main/ui/workspace/plugins.cljs:442 +msgid "workspace.plugins.try-out.try" +msgstr "התנסות בתוסף" + +#: src/app/main/ui/workspace/sidebar/options/menus/layout_container.cljs:1004, src/app/main/ui/workspace/sidebar/options/menus/layout_container.cljs:1030 +msgid "workspace.shape.menu.add-layout" +msgstr "הוספת פריסה" + +#: src/app/main/ui/workspace/sidebar/sitemap.cljs:229 +msgid "workspace.sidebar.sitemap.add-page" +msgstr "הוספת עמוד" + +#: src/app/main/ui/workspace/tokens/form.cljs:361 +msgid "workspace.token.edit-token" +msgstr "עריכת אסימון" + +#: src/app/main/ui/workspace/tokens/sets.cljs:186 +msgid "workspace.token.grouping-set-alert" +msgstr "אין עדיין תמיכה בקיבוץ סדרות אסימונים." + +#: src/app/main/ui/workspace/tokens/modals/themes.cljs:52 +msgid "workspace.token.new-theme" +msgstr "ערכת עיצוב חדשה" + +#: src/app/main/ui/workspace/tokens/theme_select.cljs:88 +msgid "workspace.token.no-active-theme" +msgstr "אין ערכת עיצוב פעילה" + +#: src/app/main/ui/workspace/tokens/modals/themes.cljs:133 +msgid "workspace.token.num-sets" +msgstr "%s סדרות" + +#: src/app/main/ui/workspace/tokens/sidebar.cljs:66 +msgid "workspace.token.original-value" +msgstr "ערך מקורי: " + +#: src/app/main/ui/workspace/tokens/modals/themes.cljs:43 +msgid "workspace.token.no-themes-currently" +msgstr "אין לך ערכות עיצוב עדיין." + +#: src/app/main/ui/workspace/tokens/form.cljs:193, src/app/main/ui/workspace/tokens/form.cljs:196, src/app/main/ui/workspace/tokens/sidebar.cljs:67 +msgid "workspace.token.resolved-value" +msgstr "ערך פתור: " + +#: src/app/main/ui/workspace/tokens/modals/themes.cljs:208 +msgid "workspace.token.save-theme" +msgstr "שמירת ערכת עיצוב" + +#: src/app/main/ui/workspace/tokens/sets.cljs:172 +msgid "workspace.token.select-set" +msgstr "בחירה ערכה." + +#: src/app/main/ui/workspace/tokens/modals/themes.cljs:39, src/app/main/ui/workspace/tokens/modals/themes.cljs:84 +msgid "workspace.token.themes" +msgstr "ערכות עיצוב" + +#: src/app/main/ui/workspace/tokens/modals/themes.cljs +#, unused +msgid "workspace.token.theme-name" +msgstr "ערכת עיצוב %s" + +#: src/app/main/ui/workspace/sidebar/versions.cljs:334 +msgid "workspace.versions.filter.user" +msgstr "הגרסה של %s" + +#: src/app/main/ui/workspace/sidebar/versions.cljs:328 +msgid "workspace.versions.filter.mine" +msgstr "הגרסאות שלי" + +#: src/app/main/ui/workspace/sidebar/versions.cljs:326 +msgid "workspace.versions.filter.label" +msgstr "מסנן גרסאות" + +#: src/app/main/ui/workspace/sidebar/versions.cljs:327 +msgid "workspace.versions.filter.all" +msgstr "כל הגרסאות" + +#: src/app/main/ui/dashboard/placeholder.cljs:32 +msgid "dashboard.empty-placeholder-libraries-title" +msgstr "אין ספריות עדיין." + +#: src/app/main/ui/dashboard/fonts.cljs:444 +msgid "dashboard.fonts.empty-placeholder-viewer" +msgstr "אין גופנים מותאמים אישית עדיין." + +#: src/app/main/ui/dashboard/team.cljs:944 +msgid "dashboard.webhooks.cant-edit" +msgstr "אפשר למחוק או לשנות את ההתליות שיצרת." + +#: src/app/main/ui/comments.cljs:340, src/app/main/ui/workspace/sidebar/options/menus/text.cljs:295, src/app/main/ui/workspace/sidebar/options/menus/text.cljs:324 +msgid "labels.options" +msgstr "אפשרויות" + +#: src/app/main/ui/workspace/sidebar/assets/colors.cljs:495 +msgid "workspace.assets.colors.add-color" +msgstr "הוספת צבע" + +#: src/app/main/ui/workspace/sidebar/assets/typographies.cljs:408 +msgid "workspace.assets.typography.add-typography" +msgstr "הוספת טיפוגרפיה" + +#: src/app/main/ui/workspace/right_header.cljs:255 +msgid "workspace.header.share" +msgstr "שיתוף" + +#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs:735 +msgid "workspace.options.interactions.add-interaction" +msgstr "הוספת אינטראקציה" + +#: src/app/main/ui/workspace/sidebar/options/menus/shadow.cljs:173 +msgid "workspace.options.shadow-options.toggle-shadow" +msgstr "הצגת/הסתרת הצללה" + +#: src/app/main/ui/workspace/plugins.cljs:436 +msgid "workspace.plugins.try-out.cancel" +msgstr "לא עכשיו" + +#: src/app/main/ui/workspace/plugins.cljs:425 +msgid "workspace.plugins.try-out.title" +msgstr "תוסף ‚%s’ מותקן למשתמש שלך!" + +#: src/app/main/ui/workspace/sidebar/options/menus/layout_container.cljs:1022 +msgid "workspace.shape.menu.remove-layout" +msgstr "הסרת פריסה" + +#: src/app/main/ui/workspace/tokens/sets.cljs:216 +msgid "workspace.token.no-sets-create" +msgstr "עדיין לא מוגדרות סדרות. נא ליצור אחת קודם." + +#: src/app/main/ui/workspace/tokens/modals/themes.cljs:142 +msgid "workspace.token.no-sets" +msgstr "אין סדרות" + +#: src/app/main/ui/workspace/tokens/form.cljs:362 +msgid "workspace.token.create-token" +msgstr "יצירת אסימון %s חדש" + +#: src/app/main/ui/workspace/tokens/modals/themes.cljs:155, src/app/main/ui/workspace/tokens/modals/themes.cljs:239 +msgid "workspace.token.create-theme-title" +msgstr "יצירת ערכת עיצוב" + +#: src/app/main/ui/workspace/tokens/sidebar.cljs:194, src/app/main/ui/workspace/tokens/sidebar.cljs:210 +msgid "workspace.token.create-one" +msgstr "ליצור אחד." + +#: src/app/main/ui/workspace/tokens/modals/themes.cljs:47 +msgid "workspace.token.create-new-theme" +msgstr "אפשר ליצור את ערכת העיצוב הראשונה שלך עכשיו." + +#: src/app/main/ui/workspace/sidebar/versions.cljs:187 +msgid "workspace.versions.autosaved.version" +msgstr "%s נשמר אוטומטית" + +#: src/app/main/ui/workspace/sidebar/versions.cljs:193 +msgid "workspace.versions.autosaved.entry" +msgstr "%s גרסאות שנשמרות אוטומטית" + +#: src/app/main/ui/workspace/sidebar/versions.cljs:138 +msgid "workspace.versions.version-menu" +msgstr "פתיחת תפריט גרסאות" + +#: src/app/main/ui/workspace/sidebar/versions.cljs:190 +msgid "workspace.versions.expand-snapshot" +msgstr "הרחבת תמונות מצב" + +#: src/app/main/ui/workspace/sidebar/versions.cljs:207 +msgid "workspace.versions.snapshot-menu" +msgstr "פתיחת תפריט תמונת מצב" + +#: src/app/main/ui/workspace/sidebar/versions.cljs:283 +msgid "workspace.versions.restore-warning" +msgstr "לשחזר את הגרסה הזאת?" + +#: src/app/main/ui/workspace/sidebar/versions.cljs:340 +msgid "workspace.versions.loading" +msgstr "בטעינה…" + +#: src/app/main/ui/workspace/sidebar/versions.cljs:219 +msgid "workspace.versions.button.restore" +msgstr "שחזור גרסה" + +#: src/app/main/ui/workspace/sidebar/assets/components.cljs:532 +msgid "workspace.assets.components.add-component" +msgstr "הוספת רכיב" + +#: src/app/main/ui/workspace/sidebar/versions.cljs:345, src/app/main/ui/workspace/sidebar/versions.cljs:347 +msgid "workspace.versions.button.save" +msgstr "שמירת גרסה" + +#: src/app/main/ui/workspace/sidebar/versions.cljs:354 +msgid "workspace.versions.empty" +msgstr "אין גרסאות עדיין" + +#: src/app/main/ui/workspace/sidebar/versions.cljs:224 +msgid "workspace.versions.button.pin" +msgstr "נעיצת גרסה" + +#: src/app/main/ui/workspace/tokens/sidebar.cljs:191 +msgid "workspace.token.no-themes" +msgstr "אין ערכות עיצוב." + +#: src/app/main/ui/workspace/tokens/sidebar.cljs:239 +msgid "workspace.token.no-sets-yet" +msgstr "אין סדרות עדיין." + +#: src/app/main/ui/workspace/sidebar/options/menus/layout_container.cljs:1051 +#, unused +msgid "labels.add" +msgstr "הוספה" + +#: src/app/main/ui/workspace/sidebar/versions.cljs:149, src/app/main/ui/workspace/sidebar/versions.cljs:288 +msgid "labels.restore" +msgstr "שחזור" + +#: src/app/main/ui/workspace/tokens/sets.cljs:153 +msgid "labels.collapse" +msgstr "צמצום" + +#: src/app/main/ui/workspace/tokens/sidebar.cljs:229 +msgid "labels.sets" +msgstr "סדרות" + +#: src/app/main/ui/workspace/tokens/sidebar.cljs:187 +msgid "labels.themes" +msgstr "ערכות עיצוב" + +#: src/app/main/ui/dashboard/team.cljs:216 +msgid "modals.invite-team-member.text" +msgstr "" +"אפשר להזמין חברים לצוות כדי שיוכלו לגשת לקובץ הזה ולהיחשף לכל שאר קובצי " +"הצוות." + +#: src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs:271 +msgid "settings.remove-color" +msgstr "הסרת צבע" + +#: src/app/main/ui/workspace/libraries.cljs:300 +msgid "workspace.libraries.more-templates" +msgstr "אפשר לחפש " + +#: src/app/main/data/common.cljs:203 +msgid "dashboard.permissions-change.viewer" +msgstr "מונית לצפות בצוות הזה." + +#: src/app/main/ui/workspace/sidebar/options/menus/blur.cljs:108 +msgid "workspace.options.blur-options.toggle-blur" +msgstr "החלת/הסרת טשטוש" + +#: src/app/main/data/common.cljs:233 +msgid "dashboard.removed-from-team" +msgstr "נגרעת מהצוות „%s”." + +#: src/app/main/ui/workspace/tokens/modals/themes.cljs:318 +msgid "workspace.token.set-selection-theme" +msgstr "נא להגדיר באילו סדרות אסימונים להשתמש כחלק מאפשרות ערכת העיצוב הזאת:" + +#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs:154 +msgid "workspace.options.flows.remove-flow" +msgstr "הסרת זרימה" + +#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs +#, unused +msgid "workspace.options.interactions.remove-interaction" +msgstr "הסרת אינטראקציה" + +#: src/app/main/ui/workspace/sidebar/options/menus/blur.cljs:91 +msgid "workspace.options.blur-options.add-blur" +msgstr "הוספת טשטוש" + +#: src/app/main/ui/workspace/sidebar/options/menus/frame_grid.cljs:323 +msgid "workspace.options.guides.add-guide" +msgstr "הוספת קו מנחה" + +#: src/app/main/ui/workspace/sidebar/options/menus/shadow.cljs:302 +msgid "workspace.options.shadow-options.add-shadow" +msgstr "הוספת הצללה" + +#: src/app/main/ui/workspace/tokens/modals/themes.cljs:310 +msgid "workspace.token.back-to-themes" +msgstr "חזרה לרשימת ערכות העיצוב" + +#: src/app/main/ui/workspace/sidebar/options/menus/blur.cljs:112 +msgid "workspace.options.blur-options.remove-blur" +msgstr "הסרת טשטוש" + +#: src/app/main/ui/workspace/sidebar/options/menus/exports.cljs:207, src/app/main/ui/workspace/sidebar/options/menus/exports.cljs:242 +msgid "workspace.options.export.remove-export" +msgstr "הסרת ייצוא" + +#: src/app/main/ui/workspace/sidebar/options/menus/fill.cljs:163 +msgid "workspace.options.fill.remove-fill" +msgstr "הסרת מילוי" + +#: src/app/main/ui/workspace/sidebar/options/menus/frame_grid.cljs:187 +msgid "workspace.options.guides.remove-guide" +msgstr "הסרת קו מנחה" + +#: src/app/main/ui/workspace/plugins.cljs:276 +msgid "workspace.plugins.permissions.comment-read" +msgstr "קריאת התגובות שלך ומתן מענה עליהן." + +#: src/app/main/ui/workspace/sidebar/options/menus/frame_grid.cljs:183 +msgid "workspace.options.guides.toggle-guide" +msgstr "הצגת/הסתרת קו מנחה" + +#: src/app/main/ui/workspace/sidebar/options/menus/stroke.cljs:171 +msgid "workspace.options.stroke.add-stroke" +msgstr "הוספת צבע מתאר" + +#: src/app/main/ui/workspace/sidebar/options/menus/shadow.cljs:177, src/app/main/ui/workspace/sidebar/options/menus/shadow.cljs:315 +msgid "workspace.options.shadow-options.remove-shadow" +msgstr "הסרת הצללה" + +#: src/app/main/ui/workspace/plugins.cljs:429 +msgid "workspace.plugins.try-out.message" +msgstr "" +"מעניין אותך להציץ? בחירה בזה תיפתח בטיוטה חדשה לצוות הנוכחי שלך. (אם לא, " +"תמיד אפשר למצוא אותו בתוספים המותקנים של כל קובץ שהוא.)" + +#: src/app/main/data/plugins.cljs:86, src/app/main/ui/workspace/main_menu.cljs:696, src/app/main/ui/workspace/plugins.cljs:82 +msgid "workspace.plugins.error.need-editor" +msgstr "צריך הרשאות עריכה כדי להשתמש בתוסף הזה" + +#: src/app/main/ui/workspace/tokens/theme_select.cljs:84 +msgid "workspace.token.active-themes" +msgstr "%s ערכות עיצוב פעילות" + +#: src/app/main/ui/workspace/tokens/sidebar.cljs +#, unused +msgid "workspace.token.add set" +msgstr "הוספת סדרה" + +#: src/app/main/ui/workspace/context_menu.cljs:235 +msgid "workspace.shape.menu.rename" +msgstr "שינוי שם" + +#: src/app/main/ui/workspace/tokens/modals/themes.cljs:302 +msgid "workspace.token.edit-theme-title" +msgstr "עריכת ערכת עיצוב" + +#: src/app/main/ui/workspace/tokens/modals/themes.cljs:147 +msgid "workspace.token.delete-theme-title" +msgstr "מחיקת ערכת עיצוב" + +#: src/app/main/ui/workspace/tokens/theme_select.cljs:72 +msgid "workspace.token.edit-themes" +msgstr "עריכת ערכות עיצוב" + +#: src/app/main/ui/dashboard/fonts.cljs:445 +msgid "dashboard.fonts.empty-placeholder-viewer-sub" +msgstr "לאחר העלאת גופן בהתאמה אישית על ידי חברים, הוא יוצג כאן." + +#: src/app/main/ui/dashboard/placeholder.cljs +#, markdown, unused +msgid "dashboard.empty-placeholder-libraries-subtitle" +msgstr "" +"ספריות שנוספו למיזם תופענה כאן. כדאי לנסות לשתף את הקבצים שלך או להוסיף מ[" +"הספריות והתבניות](https://penpot.app/libraries-templates) שלנו." + +#: src/app/main/ui/dashboard/team.cljs:181, src/app/main/ui/onboarding/team_choice.cljs:100 +msgid "errors.maximum-invitations-by-request-reached" +msgstr "הגעת למספר הכתובות המרבי (%s) שאפשר להזמין בבקשה אחת" diff --git a/frontend/translations/id.po b/frontend/translations/id.po index d1a6b3ca04..c2db2c50df 100644 --- a/frontend/translations/id.po +++ b/frontend/translations/id.po @@ -1,7 +1,7 @@ msgid "" msgstr "" -"PO-Revision-Date: 2024-11-14 11:14+0000\n" -"Last-Translator: Anonymous \n" +"PO-Revision-Date: 2024-11-27 13:02+0000\n" +"Last-Translator: Linerly \n" "Language-Team: Indonesian \n" "Language: id\n" @@ -335,7 +335,6 @@ msgid "dashboard.access-tokens.create-success" msgstr "Token akses berhasil dibuat." #: src/app/main/ui/settings/access_tokens.cljs:65 -#, fuzzy msgid "dashboard.access-tokens.create.success" msgstr " " @@ -1053,7 +1052,6 @@ msgstr "" "tinggi)." #: src/app/main/errors.cljs:228 -#, fuzzy msgid "errors.migration-in-progress" msgstr " " @@ -1157,7 +1155,6 @@ msgid "errors.wrong-old-password" msgstr "Kata sandi lama tidak benar" #: src/app/main/ui/workspace/sidebar/options/menus/bool.cljs:85 -#, fuzzy msgid "exclude" msgstr " " @@ -1465,7 +1462,6 @@ msgid "inspect.tabs.info" msgstr "Info" #: src/app/main/ui/workspace/sidebar/options/menus/bool.cljs:80 -#, fuzzy msgid "intersection" msgstr " " @@ -2156,7 +2152,6 @@ msgid "modals.create-access-token.title" msgstr "Buat token baru" #: src/app/main/ui/settings/access_tokens.cljs:152 -#, fuzzy msgid "modals.create-access-token.token" msgstr " " @@ -3646,7 +3641,6 @@ msgid "shortcuts.toggle-rulers" msgstr "Tampilkan / Sembunyikan penggaris" #: src/app/main/ui/workspace/sidebar/shortcuts.cljs:199 -#, fuzzy msgid "shortcuts.toggle-rules" msgstr " " @@ -5574,9 +5568,11 @@ msgid "workspace.plugins.permissions.content-write" msgstr "Membaca dan mengubah konten berkas yang dapat diakses pengguna." #: src/app/main/ui/workspace/plugins.cljs:323 -#, fuzzy msgid "workspace.plugins.permissions.disclaimer" -msgstr "Dicatat bahwa plugin ini telah dibuat oleh pihak eksternal." +msgstr "" +"Harap diingat bahwa plugin ini dibuat oleh pihak eksternal, jadi pastikan " +"Anda mempercayainya sebelum memberikan akses. Privasi dan keamanan data Anda " +"penting bagi kami. Jika Anda memiliki masalah, silakan hubungi dukungan." #: src/app/main/ui/workspace/plugins.cljs:263 msgid "workspace.plugins.permissions.library-read" @@ -5587,9 +5583,8 @@ msgid "workspace.plugins.permissions.library-write" msgstr "Membaca dan mengubah pustaka dan aset Anda." #: src/app/main/ui/workspace/plugins.cljs:316 -#, fuzzy msgid "workspace.plugins.permissions.title" -msgstr "PLUGIN INI MEMINTA AKSES KE:" +msgstr "PLUGIN '%s' MEMINTA AKSES:" #: src/app/main/ui/workspace/plugins.cljs:250 msgid "workspace.plugins.permissions.user-read" @@ -6107,3 +6102,461 @@ msgstr "Perbarui" #, unused msgid "workspace.viewport.click-to-close-path" msgstr "Klik untuk menutup jalur" + +#: src/app/main/ui/dashboard/files.cljs:185, src/app/main/ui/dashboard/projects.cljs:279 +msgid "dashboard.empty-placeholder-drafts-title" +msgstr "Belum ada draf." + +#: src/app/main/ui/workspace/tokens/modals/themes.cljs:119 +msgid "workspace.token.theme" +msgstr " " + +#: src/app/main/ui/dashboard/fonts.cljs:445 +msgid "dashboard.fonts.empty-placeholder-viewer-sub" +msgstr "" +"Ketika anggota proyek mengunggah fon kustom, itu akan ditampilkan di sini." + +#: src/app/main/data/common.cljs:205 +msgid "dashboard.permissions-change.admin" +msgstr "Anda sekarang seorang admin di tim ini." + +#: src/app/main/ui/workspace/sidebar/options/menus/layout_container.cljs:1051 +#, unused +msgid "labels.add" +msgstr "Tambahkan" + +#: src/app/main/ui/workspace/tokens/sets.cljs:153 +msgid "labels.collapse" +msgstr "Tutup" + +#: src/app/main/ui/dashboard/placeholder.cljs:39 +#, markdown +msgid "dashboard.empty-placeholder-libraries" +msgstr "" +"Pustaka yang ditambahkan ke proyek akan muncul di sini. Coba membagikan " +"berkas Anda atau tambahkan dari [Pustaka dan tempat] (https://penpot.app/" +"libraries-templates) kami." + +#: src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs:271 +msgid "settings.remove-color" +msgstr "Hapus warna" + +#: src/app/main/ui/dashboard/placeholder.cljs +#, markdown, unused +msgid "dashboard.empty-placeholder-libraries-subtitle" +msgstr "" +"Pustaka yang ditambahkan ke proyek akan muncul di sini. Coba membagikan " +"berkas Anda atau tambahkan dari [Pustaka dan tempat] (https://penpot.app/" +"libraries-templates) kami." + +#: src/app/main/ui/workspace/sidebar/versions.cljs:149, src/app/main/ui/workspace/sidebar/versions.cljs:288 +msgid "labels.restore" +msgstr "Pulihkan" + +#: src/app/main/ui/workspace/sidebar/assets/colors.cljs:495 +msgid "workspace.assets.colors.add-color" +msgstr "Tambahkan warna" + +#: src/app/main/ui/workspace/sidebar/assets/components.cljs:532 +msgid "workspace.assets.components.add-component" +msgstr "Tambahkan komponen" + +#: src/app/main/ui/workspace/libraries.cljs:304 +msgid "workspace.libraries.more-templates-link" +msgstr "lebih banyak tempat di sini" + +#: src/app/main/ui/workspace/sidebar/options/menus/blur.cljs:108 +msgid "workspace.options.blur-options.toggle-blur" +msgstr "Sakelar buram" + +#: src/app/main/ui/workspace/sidebar/assets/typographies.cljs:408 +msgid "workspace.assets.typography.add-typography" +msgstr "Tambahkan tipografi" + +#: src/app/main/ui/workspace/right_header.cljs:255 +msgid "workspace.header.share" +msgstr "Bagikan" + +#: src/app/main/ui/workspace/plugins.cljs:372 +msgid "workspace.plugins.permissions-update.title" +msgstr "PERBARUI PLUGIN INI" + +#: src/app/main/data/plugins.cljs:86, src/app/main/ui/workspace/main_menu.cljs:696, src/app/main/ui/workspace/plugins.cljs:82 +msgid "workspace.plugins.error.need-editor" +msgstr "Anda perlu menjadi penyunting untuk menggunakan plugin ini" + +#: src/app/main/ui/workspace/plugins.cljs:270 +msgid "workspace.plugins.permissions.comment-write" +msgstr "Membaca dan mengubah komentar Anda dan membalas dengan nama Anda." + +#: src/app/main/ui/workspace/plugins.cljs:442 +msgid "workspace.plugins.try-out.try" +msgstr "COBA PLUGIN" + +#: src/app/main/ui/workspace/plugins.cljs:429 +msgid "workspace.plugins.try-out.message" +msgstr "" +"Ingin melihat? Ini akan membuka dalam draf baru untuk tim Anda saat ini. (" +"Jika tidak, Anda selalu dapat mencarinya dalam plugin terpasang dalam berkas " +"apa pun.)" + +#: src/app/main/ui/workspace/plugins.cljs:425 +msgid "workspace.plugins.try-out.title" +msgstr "PLUGIN '%s' TERPASANG UNTUK PENGGUNA ANDA!" + +#: src/app/main/ui/workspace/sidebar/options/menus/layout_container.cljs:1004, src/app/main/ui/workspace/sidebar/options/menus/layout_container.cljs:1030 +msgid "workspace.shape.menu.add-layout" +msgstr "Tambahkan tata letak" + +#: src/app/main/ui/workspace/tokens/sidebar.cljs:66 +msgid "workspace.token.original-value" +msgstr "Nilai asli: " + +#: src/app/main/ui/workspace/tokens/form.cljs:193, src/app/main/ui/workspace/tokens/form.cljs:196, src/app/main/ui/workspace/tokens/sidebar.cljs:67 +msgid "workspace.token.resolved-value" +msgstr "Nilai terselesaikan: " + +#: src/app/main/ui/workspace/tokens/form.cljs:362 +msgid "workspace.token.create-token" +msgstr "Buat token %s baru" + +#: src/app/main/ui/workspace/tokens/modals/themes.cljs:302 +msgid "workspace.token.edit-theme-title" +msgstr "Sunting tema" + +#: src/app/main/ui/workspace/tokens/modals/themes.cljs:147 +msgid "workspace.token.delete-theme-title" +msgstr "Hapus tema" + +#: src/app/main/ui/workspace/tokens/theme_select.cljs:72 +msgid "workspace.token.edit-themes" +msgstr "Sunting tema" + +#: src/app/main/ui/workspace/sidebar/versions.cljs:219 +msgid "workspace.versions.button.restore" +msgstr "Pulihkan versi" + +#: src/app/main/ui/workspace/sidebar/versions.cljs:354 +msgid "workspace.versions.empty" +msgstr "Belum ada versi" + +#: src/app/main/ui/workspace/sidebar/versions.cljs:187 +msgid "workspace.versions.autosaved.version" +msgstr "%s disimpan otomatis" + +#: src/app/main/ui/workspace/sidebar/versions.cljs:224 +msgid "workspace.versions.button.pin" +msgstr "Sematkan versi" + +#: src/app/main/ui/workspace/sidebar/versions.cljs:345, src/app/main/ui/workspace/sidebar/versions.cljs:347 +msgid "workspace.versions.button.save" +msgstr "Simpan versi" + +#: src/app/main/ui/workspace/sidebar/versions.cljs:190 +msgid "workspace.versions.expand-snapshot" +msgstr "Buka snapshot" + +#: src/app/main/ui/workspace/sidebar/versions.cljs:340 +msgid "workspace.versions.loading" +msgstr "Memuat..." + +#: src/app/main/ui/workspace/sidebar/versions.cljs:283 +msgid "workspace.versions.restore-warning" +msgstr "Apakah Anda ingin memulihkan versi ini?" + +#: src/app/main/ui/workspace/sidebar/versions.cljs:138 +msgid "workspace.versions.version-menu" +msgstr "Buka menu versi" + +#: src/app/main/ui/workspace/sidebar/versions.cljs:207 +msgid "workspace.versions.snapshot-menu" +msgstr "Buka menu snapshot" + +#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs:154 +msgid "workspace.options.flows.remove-flow" +msgstr "Hapus alur" + +#: src/app/main/ui/workspace/sidebar/options/menus/fill.cljs:163 +msgid "workspace.options.fill.remove-fill" +msgstr "Hapus isian" + +#: src/app/main/ui/workspace/sidebar/options/menus/frame_grid.cljs:323 +msgid "workspace.options.guides.add-guide" +msgstr "Tambahkan alur" + +#: src/app/main/ui/workspace/sidebar/options/menus/layer.cljs:176, src/app/main/ui/workspace/sidebar/options/menus/layer.cljs:182 +msgid "workspace.options.layer-options.toggle-layer" +msgstr "Sakelar keterlihatan lapisan" + +#: src/app/main/ui/workspace/sidebar/options/menus/frame_grid.cljs:187 +msgid "workspace.options.guides.remove-guide" +msgstr "Hapus alur" + +#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs +#, unused +msgid "workspace.options.interactions.remove-interaction" +msgstr "Hapus interaksi" + +#: src/app/main/ui/workspace/sidebar/options/menus/shadow.cljs:173 +msgid "workspace.options.shadow-options.toggle-shadow" +msgstr "Sakelar bayangan" + +#: src/app/main/ui/dashboard/files.cljs:191, src/app/main/ui/dashboard/projects.cljs:285 +msgid "dashboard.empty-placeholder-files-subtitle" +msgstr "Ketika anggota proyek membuat berkas, itu akan ditampilkan di sini." + +#: src/app/main/ui/dashboard/files.cljs:190, src/app/main/ui/dashboard/projects.cljs:284 +msgid "dashboard.empty-placeholder-drafts-subtitle" +msgstr "Ketika anggota proyek membuat draf, itu akan ditampilkan di sini." + +#: src/app/main/ui/dashboard/files.cljs:186, src/app/main/ui/dashboard/projects.cljs:280 +msgid "dashboard.empty-placeholder-files-title" +msgstr "Belum ada berkas." + +#: src/app/main/ui/dashboard/placeholder.cljs:35 +msgid "dashboard.empty-placeholder-libraries-subtitle-viewer-role" +msgstr "Pustaka yang ditambahkan ke proyek akan muncul di sini." + +#: src/app/main/ui/dashboard/fonts.cljs:444 +msgid "dashboard.fonts.empty-placeholder-viewer" +msgstr "Belum ada fon kustom." + +#: src/app/main/ui/dashboard/team.cljs:944 +msgid "dashboard.webhooks.cant-edit" +msgstr "Anda hanya dapat menghapus atau mengubah webhook yang dibuat oleh Anda." + +#: src/app/main/ui/comments.cljs:340, src/app/main/ui/workspace/sidebar/options/menus/text.cljs:295, src/app/main/ui/workspace/sidebar/options/menus/text.cljs:324 +msgid "labels.options" +msgstr "Opsi" + +#: src/app/main/ui/workspace/tokens/sidebar.cljs:229 +msgid "labels.sets" +msgstr "Set" + +#: src/app/main/ui/workspace/tokens/sidebar.cljs:187 +msgid "labels.themes" +msgstr "Tema" + +#: src/app/main/ui/workspace/sidebar/options/menus/blur.cljs:91 +msgid "workspace.options.blur-options.add-blur" +msgstr "Tambahkan buram" + +#: src/app/main/ui/workspace/sidebar/options/menus/blur.cljs:112 +msgid "workspace.options.blur-options.remove-blur" +msgstr "Hapus buram" + +#: src/app/main/ui/workspace/sidebar/options/menus/shadow.cljs:177, src/app/main/ui/workspace/sidebar/options/menus/shadow.cljs:315 +msgid "workspace.options.shadow-options.remove-shadow" +msgstr "Hapus bayangan" + +#: src/app/main/ui/workspace/plugins.cljs:196 +msgid "workspace.plugins.error.manifest" +msgstr "Manifes plugin tidak benar." + +#: src/app/main/ui/workspace/plugins.cljs:283 +msgid "workspace.plugins.permissions.allow-download" +msgstr "Memulai pengunduhan berkas." + +#: src/app/main/ui/workspace/plugins.cljs:276 +msgid "workspace.plugins.permissions.comment-read" +msgstr "Membaca komentar dan balasan Anda." + +#: src/app/main/ui/workspace/plugins.cljs:376 +msgid "workspace.plugins.permissions-update.warning" +msgstr "" +"Plugin ini telah diubah sejak terakhir kali Anda membukanya. Ini sekarang " +"memerlukan akses:" + +#: src/app/main/ui/workspace/sidebar/options/menus/layout_container.cljs:1022 +msgid "workspace.shape.menu.remove-layout" +msgstr "Hapus tata letak" + +#: src/app/main/ui/workspace/context_menu.cljs:235 +msgid "workspace.shape.menu.rename" +msgstr "Ubah nama" + +#: src/app/main/ui/workspace/tokens/modals/themes.cljs:318 +msgid "workspace.token.set-selection-theme" +msgstr "Tentukan set token apa yang digunakan sebagai bagian opsi tema ini:" + +#: src/app/main/ui/workspace/tokens/modals/themes.cljs +#, unused +msgid "workspace.token.theme-name" +msgstr "Tema %s" + +#: src/app/main/ui/workspace/tokens/modals/themes.cljs:39, src/app/main/ui/workspace/tokens/modals/themes.cljs:84 +msgid "workspace.token.themes" +msgstr "Tema" + +#: src/app/main/ui/workspace/sidebar/versions.cljs:327 +msgid "workspace.versions.filter.all" +msgstr "Semua versi" + +#: src/app/main/ui/dashboard/placeholder.cljs:32 +msgid "dashboard.empty-placeholder-libraries-title" +msgstr "Belum ada pustaka." + +#: src/app/main/data/common.cljs:204 +msgid "dashboard.permissions-change.editor" +msgstr "Anda sekarang seorang penyunting di tim ini." + +#: src/app/main/data/common.cljs:206 +msgid "dashboard.permissions-change.owner" +msgstr "Anda sekarang seorang pemilik di tim ini." + +#: src/app/main/data/common.cljs:203 +msgid "dashboard.permissions-change.viewer" +msgstr "Anda sekarang seorang peninjau di tim ini." + +#: src/app/main/data/common.cljs:233 +msgid "dashboard.removed-from-team" +msgstr "Anda bukan merupakan bagian dari tim “%s” lagi." + +#: src/app/main/ui/dashboard/team.cljs:181, src/app/main/ui/onboarding/team_choice.cljs:100 +msgid "errors.maximum-invitations-by-request-reached" +msgstr "" +"Jumlah email maksimum (%s) yang dapat diundang dalam satu permintaan telah " +"tercapai" + +#: src/app/main/ui/dashboard/team.cljs:216 +msgid "modals.invite-team-member.text" +msgstr "" +"Anda dapat mengundang anggota ke tim supaya mereka dapat mengakses berkas " +"ini dan semua berkas tim." + +#: src/app/main/ui/workspace/libraries.cljs:300 +msgid "workspace.libraries.more-templates" +msgstr "Anda dapat mencari " + +#: src/app/main/ui/workspace/sidebar/options/menus/exports.cljs:195 +msgid "workspace.options.export.add-export" +msgstr "Tambahkan ekspor" + +#: src/app/main/ui/workspace/sidebar/options/menus/exports.cljs:207, src/app/main/ui/workspace/sidebar/options/menus/exports.cljs:242 +msgid "workspace.options.export.remove-export" +msgstr "Hapus ekspor" + +#: src/app/main/ui/workspace/sidebar/options/menus/fill.cljs:150 +msgid "workspace.options.fill.add-fill" +msgstr "Tambahkan warna isian" + +#: src/app/main/ui/workspace/sidebar/options/menus/frame_grid.cljs:183 +msgid "workspace.options.guides.toggle-guide" +msgstr "Sakelar pemandu" + +#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs:735 +msgid "workspace.options.interactions.add-interaction" +msgstr "Tambahkan interaksi" + +#: src/app/main/ui/workspace/sidebar/options/menus/shadow.cljs:302 +msgid "workspace.options.shadow-options.add-shadow" +msgstr "Tambahkan bayangan" + +#: src/app/main/ui/workspace/sidebar/options/menus/stroke.cljs:171 +msgid "workspace.options.stroke.add-stroke" +msgstr "Tambahkan warna garis" + +#: src/app/main/ui/workspace/sidebar/options/menus/stroke.cljs:184 +msgid "workspace.options.stroke.remove-stroke" +msgstr "Hapus garis" + +#: src/app/main/ui/workspace/plugins.cljs:86 +msgid "workspace.plugins.remove-plugin" +msgstr "Hapus plugin" + +#: src/app/main/ui/workspace/plugins.cljs:436 +msgid "workspace.plugins.try-out.cancel" +msgstr "NANTI" + +#: src/app/main/ui/workspace/tokens/modals/themes.cljs:310 +msgid "workspace.token.back-to-themes" +msgstr "Kembali ke daftar tema" + +#: src/app/main/ui/workspace/tokens/sidebar.cljs +#, unused +msgid "workspace.token.add set" +msgstr "Tambahkan set" + +#: src/app/main/ui/workspace/tokens/modals/themes.cljs:47 +msgid "workspace.token.create-new-theme" +msgstr "Buat tema pertama Anda sekarang." + +#: src/app/main/ui/workspace/tokens/sidebar.cljs:194, src/app/main/ui/workspace/tokens/sidebar.cljs:210 +msgid "workspace.token.create-one" +msgstr "Buat baru." + +#: src/app/main/ui/workspace/tokens/modals/themes.cljs:155, src/app/main/ui/workspace/tokens/modals/themes.cljs:239 +msgid "workspace.token.create-theme-title" +msgstr "Buat tema" + +#: src/app/main/ui/workspace/tokens/form.cljs:361 +msgid "workspace.token.edit-token" +msgstr "Sunting token" + +#: src/app/main/ui/workspace/tokens/sets.cljs:186 +msgid "workspace.token.grouping-set-alert" +msgstr "Pengelompokan Set Token belum didukung." + +#: src/app/main/ui/workspace/tokens/modals/themes.cljs:52 +msgid "workspace.token.new-theme" +msgstr "Tema baru" + +#: src/app/main/ui/workspace/tokens/theme_select.cljs:88 +msgid "workspace.token.no-active-theme" +msgstr "Tidak ada tema aktif" + +#: src/app/main/ui/workspace/tokens/modals/themes.cljs:142 +msgid "workspace.token.no-sets" +msgstr "Tidak ada set" + +#: src/app/main/ui/workspace/tokens/sets.cljs:216 +msgid "workspace.token.no-sets-create" +msgstr "Belum ada set yang ditetapkan. Buatlah terlebih dahulu." + +#: src/app/main/ui/workspace/tokens/sidebar.cljs:239 +msgid "workspace.token.no-sets-yet" +msgstr "Belum ada set." + +#: src/app/main/ui/workspace/tokens/sidebar.cljs:191 +msgid "workspace.token.no-themes" +msgstr "Belum ada tema." + +#: src/app/main/ui/workspace/tokens/modals/themes.cljs:43 +msgid "workspace.token.no-themes-currently" +msgstr "Anda saat ini belum memiliki tema." + +#: src/app/main/ui/workspace/tokens/modals/themes.cljs:133 +msgid "workspace.token.num-sets" +msgstr "%s set" + +#: src/app/main/ui/workspace/tokens/modals/themes.cljs:208 +msgid "workspace.token.save-theme" +msgstr "Simpan tema" + +#: src/app/main/ui/workspace/tokens/sets.cljs:172 +msgid "workspace.token.select-set" +msgstr "Pilih set." + +#: src/app/main/ui/workspace/sidebar/versions.cljs:193 +msgid "workspace.versions.autosaved.entry" +msgstr "%s versi tersimpan otomatis" + +#: src/app/main/ui/workspace/sidebar/versions.cljs:326 +msgid "workspace.versions.filter.label" +msgstr "Saringan versi" + +#: src/app/main/ui/workspace/sidebar/versions.cljs:328 +msgid "workspace.versions.filter.mine" +msgstr "Versi saya" + +#: src/app/main/ui/workspace/sidebar/versions.cljs:334 +msgid "workspace.versions.filter.user" +msgstr "Versi %s" + +#: src/app/main/ui/workspace/sidebar/sitemap.cljs:229 +msgid "workspace.sidebar.sitemap.add-page" +msgstr "Tambahkan halaman" + +#: src/app/main/ui/workspace/tokens/theme_select.cljs:84 +msgid "workspace.token.active-themes" +msgstr "%s tema aktif" diff --git a/frontend/translations/it.po b/frontend/translations/it.po index d20c96dfa4..4d6664918a 100644 --- a/frontend/translations/it.po +++ b/frontend/translations/it.po @@ -1,15 +1,15 @@ msgid "" msgstr "" -"PO-Revision-Date: 2024-06-17 08:07+0000\n" +"PO-Revision-Date: 2025-01-07 11:20+0000\n" "Last-Translator: Anonymous \n" -"Language-Team: Italian " -"\n" +"Language-Team: Italian \n" "Language: it\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.10-dev\n" #: src/app/main/ui/auth/register.cljs:133, src/app/main/ui/static.cljs:154, src/app/main/ui/viewer/login.cljs:98 msgid "auth.already-have-account" @@ -183,7 +183,7 @@ msgstr "Gestisci permessi" msgid "common.share-link.page-shared" msgid_plural "common.share-link.page-shared" msgstr[0] "1 pagina condivisa" -msgstr[1] "% di pagine condivise" +msgstr[1] "%s pagine condivise" #: src/app/main/ui/viewer/share_link.cljs:300 msgid "common.share-link.permissions-can-comment" @@ -303,7 +303,7 @@ msgstr "Duplica" #: src/app/main/ui/dashboard/file_menu.cljs:249 msgid "dashboard.duplicate-multi" -msgstr "Duplicare %s file" +msgstr "Duplica %s file" #: src/app/main/ui/dashboard/file_menu.cljs:259, src/app/main/ui/dashboard/file_menu.cljs:264 msgid "dashboard.export-binary-multi" @@ -311,7 +311,7 @@ msgstr "Scarica %s file Penpot (.penpot)" #: src/app/main/ui/workspace/main_menu.cljs:629 msgid "dashboard.export-frames" -msgstr "Esportare le tavole da disegno in PDF" +msgstr "Esporta le tavole da disegno in PDF" #: src/app/main/ui/exports/assets.cljs:206 msgid "dashboard.export-frames.title" @@ -319,7 +319,7 @@ msgstr "Esporta in PDF" #, unused msgid "dashboard.export-multi" -msgstr "Esportare %s file Penpot" +msgstr "Esporta %s file Penpot" #: src/app/main/ui/exports/assets.cljs:113 msgid "dashboard.export-multiple.selected" @@ -395,11 +395,11 @@ msgstr "Esporta i file" #: src/app/main/ui/workspace/sidebar/options/menus/typography.cljs:311 msgid "dashboard.fonts.deleted-placeholder" -msgstr "Font eliminato" +msgstr "Font mancante" #: src/app/main/ui/dashboard/fonts.cljs:207 msgid "dashboard.fonts.dismiss-all" -msgstr "Chiudere tutto" +msgstr "Chiudi tutto" #: src/app/main/ui/dashboard/fonts.cljs:441 msgid "dashboard.fonts.empty-placeholder" @@ -437,7 +437,7 @@ msgstr "Carica tutto" #: src/app/main/ui/dashboard/import.cljs:452, src/app/main/ui/dashboard/project_menu.cljs:108 msgid "dashboard.import" -msgstr "Importare file Penpot" +msgstr "Importa file Penpot" #: src/app/main/ui/dashboard/import.cljs:288, src/app/worker/import.cljs:843, src/app/worker/import.cljs:846 msgid "dashboard.import.analyze-error" @@ -449,10 +449,6 @@ msgstr "" "C'è stato un problema con l'importazione del file. Il file non è stato " "importato." -#: src/app/main/ui/dashboard/import.cljs:466 -msgid "dashboard.import.import-message" -msgstr "%s file sono stati importati con successo." - #: src/app/main/ui/dashboard/import.cljs:461 msgid "dashboard.import.import-warning" msgstr "Alcuni file contenenti oggetti non validi sono stati rimossi." @@ -521,15 +517,15 @@ msgstr "caricamento dei font …" #: src/app/main/ui/dashboard/file_menu.cljs:301, src/app/main/ui/dashboard/project_menu.cljs:100 msgid "dashboard.move-to" -msgstr "Sposta verso" +msgstr "Sposta in" #: src/app/main/ui/dashboard/file_menu.cljs:254 msgid "dashboard.move-to-multi" -msgstr "Sposta %s file verso" +msgstr "Sposta %s file in" #: src/app/main/ui/dashboard/file_menu.cljs:233 msgid "dashboard.move-to-other-team" -msgstr "Sposta verso un altro team" +msgstr "Sposta in un altro team" #: src/app/main/ui/dashboard/files.cljs:101, src/app/main/ui/dashboard/projects.cljs:251, src/app/main/ui/dashboard/projects.cljs:252 msgid "dashboard.new-file" @@ -598,7 +594,7 @@ msgstr "Desideri eliminare il tuo account?" #: src/app/main/ui/workspace/header.cljs, src/app/main/ui/dashboard/file_menu.cljs #, unused msgid "dashboard.remove-shared" -msgstr "Elimina come Libreria Condivisa" +msgstr "Elimina come libreria condivisa" #: src/app/main/ui/settings/profile.cljs:75 msgid "dashboard.save-settings" @@ -606,7 +602,7 @@ msgstr "Salva impostazioni" #: src/app/main/ui/dashboard/sidebar.cljs:246, src/app/main/ui/dashboard/sidebar.cljs:247 msgid "dashboard.search-placeholder" -msgstr "Cerca …" +msgstr "Cerca…" #: src/app/main/ui/dashboard/search.cljs:56 msgid "dashboard.searching-for" @@ -624,18 +620,10 @@ msgstr "Seleziona un tema" msgid "dashboard.show-all-files" msgstr "Mostra tutti i file" -#: src/app/main/ui/dashboard/file_menu.cljs:101 -msgid "dashboard.success-delete-file" -msgstr "Il tuo file è stato eliminato con successo" - #: src/app/main/ui/dashboard/project_menu.cljs:60 msgid "dashboard.success-delete-project" msgstr "Il tuo progetto è stato eliminato con successo" -#: src/app/main/ui/dashboard/file_menu.cljs:96 -msgid "dashboard.success-duplicate-file" -msgstr "Il tuo file è stato duplicato con successo" - #: src/app/main/ui/dashboard/project_menu.cljs:34 msgid "dashboard.success-duplicate-project" msgstr "Il tuo progetto è stato duplicato con successo" @@ -678,7 +666,7 @@ msgstr "Scrivi per cercare" #: src/app/main/ui/dashboard/file_menu.cljs:308, src/app/main/ui/workspace/main_menu.cljs:578 msgid "dashboard.unpublish-shared" -msgstr "Spubblicare la libreria" +msgstr "Annulla pubblicazione libreria" #: src/app/main/ui/settings/options.cljs:68 msgid "dashboard.update-settings" @@ -779,11 +767,11 @@ msgstr "Questo è invito può essere stato revocato o può essere scaduto." #: src/app/main/ui/auth/login.cljs:106 msgid "errors.ldap-disabled" -msgstr "Autenticazione LDAP disattivata." +msgstr "Autenticazione LDAP disabilitata." #: src/app/main/data/workspace/media.cljs:184 msgid "errors.media-too-large" -msgstr "L'immagine è troppo grande (deve essere inferiore a 5MB)." +msgstr "L'immagine è troppo grande per essere inserita." #: src/app/main/data/media.cljs:68, src/app/main/data/workspace/media.cljs:187 msgid "errors.media-type-mismatch" @@ -807,13 +795,13 @@ msgstr "La password deve contenere almeno 8 caratteri" #: src/app/main/data/users.cljs:729, src/app/main/ui/auth/register.cljs:51 msgid "errors.registration-disabled" -msgstr "La registrazione è al momento disattivata." +msgstr "La registrazione è al momento disabilitata." #: src/app/main/ui/dashboard/sidebar.cljs:365, src/app/main/ui/dashboard/team.cljs:389 msgid "errors.team-leave.insufficient-members" msgstr "" -"Il numero di membri non è sufficiente per abbandonare il team. Vuoi " -"probabilmente eliminare il team." +"Il numero di membri non è sufficiente per abbandonare il team. Probabilmente " +"lo vuoi eliminare." #: src/app/main/ui/dashboard/sidebar.cljs:368, src/app/main/ui/dashboard/team.cljs:392 msgid "errors.team-leave.member-does-not-exists" @@ -893,7 +881,7 @@ msgstr "Si è verificato un errore" #: src/app/main/ui/viewer/inspect/attributes/blur.cljs:26 msgid "inspect.attributes.blur" -msgstr "Sfumatura" +msgstr "Sfocatura" #: src/app/main/ui/workspace/sidebar/options/menus/blur.cljs:119 msgid "inspect.attributes.blur.value" @@ -913,11 +901,11 @@ msgstr "RGBA" #: src/app/main/ui/viewer/inspect/attributes/fill.cljs:57 msgid "inspect.attributes.fill" -msgstr "Riempire" +msgstr "Riempimento" #: src/app/main/ui/viewer/inspect/attributes/common.cljs:99, src/app/main/ui/viewer/inspect/attributes/image.cljs:51 msgid "inspect.attributes.image.download" -msgstr "Scaricare l'immagine sorgente" +msgstr "Scarica l'immagine sorgente" #: src/app/main/ui/viewer/inspect/attributes/image.cljs:39 msgid "inspect.attributes.image.height" @@ -1025,7 +1013,7 @@ msgstr "Spaziatura delle lettere" #: src/app/main/ui/viewer/inspect/attributes/text.cljs:125, src/app/main/ui/workspace/sidebar/options/menus/typography.cljs:367 msgid "inspect.attributes.typography.line-height" -msgstr "Altezza Linea" +msgstr "Interlinea" #: src/app/main/ui/viewer/inspect/attributes/text.cljs:143 msgid "inspect.attributes.typography.text-decoration" @@ -1077,11 +1065,11 @@ msgstr "Componente" #: src/app/main/ui/viewer/inspect/right_sidebar.cljs:126 msgid "inspect.tabs.code.selected.curve" -msgstr "Curvo" +msgstr "Curva" #: src/app/main/ui/viewer/inspect/right_sidebar.cljs:128 msgid "inspect.tabs.code.selected.group" -msgstr "Raggruppa" +msgstr "Gruppo" #: src/app/main/ui/viewer/inspect/right_sidebar.cljs:129 msgid "inspect.tabs.code.selected.image" @@ -1121,11 +1109,11 @@ msgstr "Scorciatoie" #: src/app/main/data/common.cljs:93, src/app/main/ui/dashboard/import.cljs:503 msgid "labels.accept" -msgstr "Accettare" +msgstr "Accetto" #: src/app/main/ui/dashboard/fonts.cljs:176 msgid "labels.add-custom-font" -msgstr "Aggiungere un carattere personalizzato" +msgstr "Aggiungi un carattere personalizzato" #: src/app/main/ui/dashboard/team.cljs:128, src/app/main/ui/dashboard/team.cljs:310, src/app/main/ui/dashboard/team.cljs:550, src/app/main/ui/dashboard/team.cljs:580, src/app/main/ui/onboarding/team_choice.cljs:66 msgid "labels.admin" @@ -1160,7 +1148,7 @@ msgstr "Annulla" #: src/app/main/ui/dashboard/projects.cljs:96, src/app/main/ui/exports/files.cljs:210, src/app/main/ui/settings/access_tokens.cljs:172, src/app/main/ui/viewer/login.cljs:71, src/app/main/ui/viewer/share_link.cljs:176, src/app/main/ui/workspace/comments.cljs:129, src/app/main/ui/workspace/libraries.cljs:538, src/app/main/ui/workspace/sidebar/debug.cljs:40, src/app/main/ui/workspace/sidebar/layers.cljs:299, src/app/main/ui/workspace/tokens/modals/themes.cljs:366, src/app/main/ui/workspace/tokens/modals.cljs:56 msgid "labels.close" -msgstr "Chiudere" +msgstr "Chiudi" #: src/app/main/ui/dashboard/comments.cljs:104, src/app/main/ui/viewer/comments.cljs:70, src/app/main/ui/workspace/comments.cljs:127 msgid "labels.comments" @@ -1204,27 +1192,27 @@ msgstr "Font personalizzati" #: src/app/main/ui/settings/sidebar.cljs:73 msgid "labels.dashboard" -msgstr "Dashboard" +msgstr "Pannello di controllo" #: src/app/main/ui/dashboard/file_menu.cljs:336, src/app/main/ui/dashboard/fonts.cljs:256, src/app/main/ui/dashboard/fonts.cljs:332, src/app/main/ui/dashboard/fonts.cljs:346, src/app/main/ui/dashboard/project_menu.cljs:114, src/app/main/ui/dashboard/team.cljs:942, src/app/main/ui/settings/access_tokens.cljs:198, src/app/main/ui/workspace/sidebar/options/menus/component.cljs:209, src/app/main/ui/workspace/sidebar/versions.cljs:152, src/app/main/ui/workspace/tokens/form.cljs:425, src/app/main/ui/workspace/tokens/modals/themes.cljs:335, src/app/main/ui/workspace/tokens/sets_context_menu.cljs:44 msgid "labels.delete" -msgstr "Eliminare" +msgstr "Elimina" #: src/app/main/ui/comments.cljs:363 msgid "labels.delete-comment" -msgstr "Eliminare il commento" +msgstr "Elimina il commento" #: src/app/main/ui/comments.cljs:360 msgid "labels.delete-comment-thread" -msgstr "Eliminare il thread" +msgstr "Elimina il thread" #: src/app/main/ui/dashboard/team.cljs:684 msgid "labels.delete-invitation" -msgstr "Eliminare l'invito" +msgstr "Elimina l'invito" #: src/app/main/ui/dashboard/file_menu.cljs:280 msgid "labels.delete-multi-files" -msgstr "Eliminare %s file" +msgstr "Elimina %s file" #: src/app/main/ui/dashboard/file_menu.cljs:30, src/app/main/ui/dashboard/files.cljs:75, src/app/main/ui/dashboard/files.cljs:168, src/app/main/ui/dashboard/projects.cljs:225, src/app/main/ui/dashboard/projects.cljs:229, src/app/main/ui/dashboard/sidebar.cljs:791 msgid "labels.drafts" @@ -1232,11 +1220,11 @@ msgstr "Bozze" #: src/app/main/ui/comments.cljs:356, src/app/main/ui/dashboard/fonts.cljs:253, src/app/main/ui/dashboard/team.cljs:940, src/app/main/ui/workspace/sidebar/options/menus/component.cljs:205, src/app/main/ui/workspace/tokens/sidebar.cljs:199 msgid "labels.edit" -msgstr "Modificare" +msgstr "Modifica" #, unused msgid "labels.edit-file" -msgstr "Modificare il file" +msgstr "Modifica il file" #: src/app/main/ui/dashboard/team.cljs:126, src/app/main/ui/dashboard/team.cljs:307, src/app/main/ui/dashboard/team.cljs:551, src/app/main/ui/dashboard/team.cljs:584, src/app/main/ui/onboarding/team_choice.cljs:65 msgid "labels.editor" @@ -1248,7 +1236,7 @@ msgstr "Scaduto" #: src/app/main/ui/exports/assets.cljs:177 msgid "labels.export" -msgstr "Esportare" +msgstr "Esporta" #: src/app/main/ui/settings/feedback.cljs:48 msgid "labels.feedback-disabled" @@ -1416,7 +1404,7 @@ msgstr "Note di versione" #: src/app/main/ui/workspace/libraries.cljs, src/app/main/ui/dashboard/team.cljs #, unused msgid "labels.remove" -msgstr "Rimuovere" +msgstr "Rimuovi" #: src/app/main/ui/dashboard/team.cljs:345 msgid "labels.remove-member" @@ -1424,11 +1412,11 @@ msgstr "Rimuovi membro" #: src/app/main/ui/dashboard/file_menu.cljs:288, src/app/main/ui/dashboard/project_menu.cljs:87, src/app/main/ui/dashboard/sidebar.cljs:539, src/app/main/ui/workspace/sidebar/assets/groups.cljs:153, src/app/main/ui/workspace/sidebar/versions.cljs:146, src/app/main/ui/workspace/tokens/sets_context_menu.cljs:43 msgid "labels.rename" -msgstr "Rinominare" +msgstr "Rinomina" #: src/app/main/ui/dashboard/team_form.cljs:99 msgid "labels.rename-team" -msgstr "Rinominare il team" +msgstr "Rinomina il team" #: src/app/main/ui/dashboard/team.cljs:681 msgid "labels.resend-invitation" @@ -1444,7 +1432,7 @@ msgstr "Ruolo" #: src/app/main/ui/dashboard/fonts.cljs:382, src/app/main/ui/workspace/sidebar/options/menus/component.cljs:191, src/app/main/ui/workspace/tokens/form.cljs:433 msgid "labels.save" -msgstr "Salvare" +msgstr "Salva" #: src/app/main/ui/dashboard/fonts.cljs:421 msgid "labels.search-font" @@ -1452,7 +1440,7 @@ msgstr "Cerca un font" #: src/app/main/ui/settings/feedback.cljs:79 msgid "labels.send" -msgstr "Inviare" +msgstr "Invia" #: src/app/main/ui/settings/feedback.cljs:79 msgid "labels.sending" @@ -1508,11 +1496,11 @@ msgstr "Aggiorna team" #: src/app/main/ui/dashboard/fonts.cljs:242 msgid "labels.upload" -msgstr "Caricare" +msgstr "Carica" #: src/app/main/ui/dashboard/fonts.cljs:170 msgid "labels.upload-custom-fonts" -msgstr "Caricare font personalizzati" +msgstr "Carica font personalizzati" #: src/app/main/ui/dashboard/fonts.cljs:241 msgid "labels.uploading" @@ -1520,11 +1508,11 @@ msgstr "Caricamento…" #: src/app/main/ui/dashboard/team.cljs:125, src/app/main/ui/dashboard/team.cljs:304, src/app/main/ui/dashboard/team.cljs:552, src/app/main/ui/dashboard/team.cljs:588, src/app/main/ui/onboarding/team_choice.cljs:64 msgid "labels.viewer" -msgstr "" +msgstr "Visualizzatore" #: src/app/main/ui/comments.cljs:197 msgid "labels.write-new-comment" -msgstr "Scrivere un nuovo commento" +msgstr "Scrivi un nuovo commento" #: src/app/main/ui/dashboard/team.cljs:262 msgid "labels.you" @@ -1550,7 +1538,7 @@ msgstr "" #: src/app/main/data/common.cljs:129 msgid "modals.add-shared-confirm.message" -msgstr "Aggiungere \"%s\" come libreria condivisa" +msgstr "Aggiungi \"%s\" come libreria condivisa" #: src/app/main/ui/workspace/nudge.cljs:60 msgid "modals.big-nudge" @@ -1584,7 +1572,7 @@ msgstr "Annulla e mantieni il mio account" #: src/app/main/ui/settings/delete_account.cljs:64 msgid "modals.delete-account.confirm" -msgstr "Sì, cancellare il mio account" +msgstr "Sì, cancella il mio account" #: src/app/main/ui/settings/delete_account.cljs:53 msgid "modals.delete-account.info" @@ -1791,29 +1779,25 @@ msgstr "Nuovo proprietario del team" #: src/app/main/ui/workspace/header.cljs, src/app/main/ui/dashboard/file_menu.cljs #, unused msgid "modals.remove-shared-confirm.accept" -msgstr "Elimina come Libreria Condivisa" +msgstr "Elimina come libreria condivisa" #: src/app/main/ui/workspace/header.cljs, src/app/main/ui/dashboard/file_menu.cljs #, unused msgid "modals.remove-shared-confirm.hint" msgstr "" -"Una volta eliminata come Libreria Condivisa, la Libreria dei File di questo " +"Una volta eliminata come libreria condivisa, la libreria dei file di questo " "file smetterà di essere a disposizione per essere usata con il resto dei " "tuoi file." #: src/app/main/ui/workspace/header.cljs, src/app/main/ui/dashboard/file_menu.cljs #, unused msgid "modals.remove-shared-confirm.message" -msgstr "Elimina \"%s\" come Libreria Condivisa" +msgstr "Elimina \"%s\" come libreria condivisa" #: src/app/main/ui/workspace/nudge.cljs:53 msgid "modals.small-nudge" msgstr "Piccolo scatto" -#: src/app/main/ui/delete_shared.cljs:52 -msgid "modals.unpublish-shared-confirm.accept" -msgstr "Annulla pubblicazione" - #: src/app/main/ui/delete_shared.cljs:47 msgid "modals.unpublish-shared-confirm.message" msgid_plural "modals.unpublish-shared-confirm.message" @@ -1969,7 +1953,7 @@ msgstr "Condizioni sulla Privacy." #: src/app/main/ui/onboarding/newsletter.cljs:60 msgid "onboarding.newsletter.title" -msgstr "Vuoi ricevere le news di Pentot?" +msgstr "Vuoi ricevere le news di Penpot?" #: src/app/main/ui/dashboard/team.cljs:764 msgid "title.team-invitations" @@ -2003,3 +1987,4591 @@ msgstr "Inviti - %s - Penpot" #~ msgid "onboarding.slide.1.desc1" #~ msgstr "Crea interazioni complete per imitare al meglio il prodotto finale." + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:207 +msgid "shortcuts.undo" +msgstr "Annulla" + +#: src/app/main/ui/auth/recovery_request.cljs:113, src/app/main/ui/auth/register.cljs:274 +msgid "auth.check-mail" +msgstr "Controlla la tua email" + +#: src/app/main/ui/auth/register.cljs:254 +msgid "auth.register-account-tagline" +msgstr "" +"Facci sapere come dovremmo chiamarti nel pannello di controllo e nelle email." + +#: src/app/main/ui/auth/register.cljs:253 +msgid "auth.register-account-title" +msgstr "Il tuo nome" + +#: src/app/main/ui/auth/register.cljs:157 +#, markdown +msgid "auth.terms-and-privacy-agreement" +msgstr "Accetto i [termini di servizio](%s) e la [politica sulla privacy](%s)." + +#: src/app/main/ui/settings/access_tokens.cljs:288 +msgid "dashboard.access-tokens.empty.no-access-tokens" +msgstr "Al momento non hai token." + +#: src/app/main/ui/settings/access_tokens.cljs:135 +msgid "dashboard.access-tokens.expiration-90-days" +msgstr "90 giorni" + +#: src/app/main/ui/settings/access_tokens.cljs:271 +msgid "dashboard.access-tokens.expired-on" +msgstr "Scaduto il %s" + +#: src/app/main/ui/settings/access_tokens.cljs:132 +msgid "dashboard.access-tokens.expiration-never" +msgstr "Mai" + +#: src/app/main/ui/settings/access_tokens.cljs:272 +msgid "dashboard.access-tokens.expires-on" +msgstr "Scade il %s" + +#: src/app/main/ui/settings/access_tokens.cljs:270 +msgid "dashboard.access-tokens.no-expiration" +msgstr "Nessuna data di scadenza" + +#: src/app/main/ui/settings/access_tokens.cljs:186 +msgid "dashboard.access-tokens.personal" +msgstr "Token di accesso personale" + +#: src/app/main/ui/dashboard/team.cljs:900 +msgid "dashboard.webhooks.active.explain" +msgstr "" +"Quando questo webhook viene attivato verranno inviati i dati dell'evento" + +#: src/app/main/ui/settings/access_tokens.cljs:258 +msgid "modals.delete-acces-token.title" +msgstr "Elimina token" + +#: src/app/main/ui/dashboard/team.cljs:223 +msgid "modals.invite-member.repeated-invitation" +msgstr "" +"Alcune email appartengono a membri attuali del team. I loro inviti non " +"saranno inviati." + +#: src/app/main/ui/onboarding/questions.cljs:169 +msgid "labels.adobe-xd" +msgstr "Adobe XD" + +#: src/app/main/ui/onboarding/questions.cljs:246 +msgid "labels.developer" +msgstr "Sviluppo" + +#: src/app/main/ui/onboarding/questions.cljs:404 +msgid "labels.event" +msgstr "Evento" + +#: src/app/main/ui/onboarding/questions.cljs:403 +msgid "labels.youtube" +msgstr "YouTube" + +#: src/app/main/ui/dashboard/templates.cljs:275, src/app/main/ui/onboarding/questions.cljs:55 +msgid "labels.next" +msgstr "Successivo" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:58 +msgid "shortcut-subsection.general-dashboard" +msgstr "Generico" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:68 +msgid "shortcut-subsection.text-editor" +msgstr "Testi" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:130 +msgid "shortcuts.line-through" +msgstr "Attiva/disattiva testo barrato" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:146 +msgid "shortcuts.opacity-0" +msgstr "Imposta opacità al 100%" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:188 +msgid "shortcuts.toggle-colorpalette" +msgstr "Attiva/Disattiva palette colori" + +#: src/app/main/ui/workspace/sidebar/assets.cljs:135 +msgid "workspace.assets.box-filter-all" +msgstr "Tutti gli asset" + +#: src/app/main/ui/workspace/sidebar/assets/groups.cljs:127 +msgid "workspace.assets.create-group" +msgstr "Crea un gruppo" + +#: src/app/main/ui/workspace/sidebar/assets/common.cljs:220 +msgid "workspace.assets.sidebar.components" +msgid_plural "workspace.assets.sidebar.components" +msgstr[0] "1 componente" +msgstr[1] "%s componenti" + +#: src/app/main/ui/workspace/context_menu.cljs:609 +msgid "workspace.context-menu.grid-track.column.delete" +msgstr "Elimina colonna" + +#: src/app/main/ui/workspace/context_menu.cljs:613 +msgid "workspace.context-menu.grid-track.row.duplicate" +msgstr "Duplica riga" + +#: src/app/main/ui/workspace/main_menu.cljs:400 +msgid "workspace.header.menu.hide-pixel-grid" +msgstr "Nascondi griglia pixel" + +#: src/app/main/ui/workspace/libraries.cljs:75, src/app/main/ui/workspace/libraries.cljs:92 +msgid "workspace.libraries.components" +msgstr "%s componenti" + +#: src/app/main/ui/workspace/sidebar/options/menus/measures.cljs:655 +msgid "workspace.options.clip-content" +msgstr "Ritaglia contenuto" + +#: src/app/main/ui/viewer/inspect/exports.cljs:203, src/app/main/ui/workspace/sidebar/options/menus/exports.cljs:256 +msgid "workspace.options.export-object" +msgid_plural "workspace.options.export-object" +msgstr[0] "Esporta 1 elemento" +msgstr[1] "Esporta %s elementi" + +#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs:57 +msgid "workspace.options.interaction-close-overlay-dest" +msgstr "Chiudi sovrapposizione: %s" + +#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs:462 +msgid "workspace.options.interaction-delay" +msgstr "Ritardo" + +#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs:697 +msgid "workspace.options.interaction-offset-effect" +msgstr "Effetti di offset" + +#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs:731 +msgid "workspace.options.interactions" +msgstr "Interazioni" + +#: src/app/main/ui/workspace/sidebar/options/menus/layer.cljs +#, unused +msgid "workspace.options.layer-options.title" +msgstr "Livello" + +#: src/app/main/ui/workspace/sidebar/options/menus/color_selection.cljs:136 +msgid "workspace.options.more-lib-colors" +msgstr "Più librerie colori" + +#: src/app/main/ui/workspace/sidebar/options/menus/shadow.cljs:146 +msgid "workspace.options.shadow-options.inner-shadow" +msgstr "Ombra interna" + +#: src/app/main/ui/workspace/sidebar/options/menus/shadow.cljs:296 +msgid "workspace.options.shadow-options.title.group" +msgstr "Ombra di gruppo" + +#: src/app/main/ui/workspace/sidebar/options/rows/stroke_row.cljs:128 +msgid "workspace.options.stroke-cap.square-marker-short" +msgstr "Rettangolo" + +#: src/app/main/ui/workspace/sidebar/options/menus/text.cljs:143 +msgid "workspace.options.text-options.grow-fixed" +msgstr "Fisso" + +#: src/app/main/ui/workspace/sidebar/options/menus/text.cljs:57 +msgid "workspace.options.text-options.text-align-right" +msgstr "Allinea a destra (%s)" + +#: src/app/main/ui/workspace/sidebar/options/menus/typography.cljs +#, unused +msgid "workspace.options.text-options.titlecase" +msgstr "Iniziale maiuscola" + +#: src/app/main/ui/workspace/sidebar/options/menus/text.cljs:173 +msgid "workspace.options.text-options.underline" +msgstr "Sottolineato (%s)" + +#: src/app/main/ui/workspace/sidebar/options/menus/typography.cljs +#, unused +msgid "workspace.options.text-options.uppercase" +msgstr "Maiuscolo" + +#: src/app/main/ui/workspace/context_menu.cljs:402 +msgid "workspace.shape.menu.delete-flow-start" +msgstr "Elimina inizio del flusso" + +#: src/app/main/ui/workspace/sidebar/assets/common.cljs:432 +msgid "workspace.shape.menu.detach-instance" +msgstr "Scollega istanza" + +#: src/app/main/ui/workspace/sidebar/layers.cljs:310, src/app/main/ui/workspace/sidebar/layers.cljs:382 +msgid "workspace.sidebar.layers.components" +msgstr "Componenti" + +#: src/app/main/ui/workspace/sidebar/sitemap.cljs:219 +msgid "workspace.sidebar.sitemap" +msgstr "Pagine" + +#: src/app/main/ui/workspace/sidebar/history.cljs:144 +msgid "workspace.undo.entry.modify" +msgstr "Modificato %s" + +#: src/app/main/ui/workspace/sidebar/history.cljs:145 +msgid "workspace.undo.entry.delete" +msgstr "Eliminato %s" + +#: src/app/main/ui/workspace/plugins.cljs:192 +msgid "workspace.plugins.error.url" +msgstr "Il plugin non esiste o l'URL non è corretto." + +#: src/app/main/ui/auth/verify_token.cljs:46 +msgid "auth.notifications.team-invitation-accepted" +msgstr "Unito al team con successo" + +#: src/app/main/ui/workspace/sidebar/history.cljs:135 +msgid "workspace.undo.entry.single.shape" +msgstr "forma" + +#: src/app/main/ui/settings/access_tokens.cljs:289 +msgid "dashboard.access-tokens.empty.add-one" +msgstr "Premi il bottone \"Genera un nuovo token\" per generarne uno." + +#: src/app/main/ui/dashboard/team.cljs:678 +msgid "labels.copy-invitation-link" +msgstr "Copia link" + +#: src/app/main/ui/workspace/sidebar/options/menus/component.cljs:436 +msgid "labels.search" +msgstr "Cerca" + +#: src/app/main/ui/settings/access_tokens.cljs:180 +msgid "modals.create-access-token.submit-label" +msgstr "Crea token" + +#: src/app/main/ui/onboarding/team_choice.cljs:55 +msgid "onboarding.team-modal.create-team-feature-5" +msgstr "100% gratuito!" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:66 +msgid "shortcut-subsection.path-editor" +msgstr "Tracciati" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:70 +msgid "shortcut-subsection.zoom-viewer" +msgstr "Zoom" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:88 +msgid "shortcuts.bring-back" +msgstr "Porta sotto" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:93 +msgid "shortcuts.copy" +msgstr "Copia" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:135 +msgid "shortcuts.move" +msgstr "Sposta" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:136 +msgid "shortcuts.move-fast-down" +msgstr "Sposta rapidamente in basso" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:139 +msgid "shortcuts.move-fast-up" +msgstr "Sposta rapidamente in alto" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:137 +msgid "shortcuts.move-fast-left" +msgstr "Sposta rapidamente a sinistra" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:124 +msgid "shortcuts.italic" +msgstr "Attiva/Disattiva corsivo" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:205 +msgid "shortcuts.toggle-zoom-style" +msgstr "Attiva/Disattiva stile zoom" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:209 +msgid "shortcuts.unmask" +msgstr "Rimuovi maschera" + +#: src/app/main/ui/workspace/context_menu.cljs:297 +msgid "workspace.focus.focus-on" +msgstr "Modalità focus attivata" + +#: src/app/util/color.cljs:34 +msgid "workspace.gradients.linear" +msgstr "Gradiente lineare" + +#: src/app/util/color.cljs:35 +msgid "workspace.gradients.radial" +msgstr "Gradiente radiale" + +#: src/app/main/ui/workspace/libraries.cljs:210 +msgid "workspace.libraries.in-this-file" +msgstr "LIBRERIE IN QUESTO FILE" + +#: src/app/main/ui/workspace/sidebar/options/menus/text.cljs:314 +msgid "workspace.libraries.text.multiple-typography-tooltip" +msgstr "Scollega tutti gli elementi tipografici" + +#: src/app/main/ui/workspace/libraries.cljs:84, src/app/main/ui/workspace/libraries.cljs:104 +msgid "workspace.libraries.typography" +msgstr "%s elementi tipografici" + +#: src/app/main/ui/workspace/sidebar/options/menus/blur.cljs:87, src/app/main/ui/workspace/sidebar/options/menus/blur.cljs:105 +msgid "workspace.options.blur-options.title" +msgstr "Sfocatura" + +#: src/app/main/ui/workspace/sidebar/options/menus/layer.cljs:123 +msgid "workspace.options.layer-options.blend-mode.normal" +msgstr "Normale" + +#: src/app/main/ui/workspace/sidebar/options/menus/measures.cljs:629 +msgid "workspace.options.radius-bottom-right" +msgstr "Inferiore destro" + +#: src/app/main/ui/workspace/context_menu.cljs:349 +msgid "workspace.shape.menu.intersection" +msgstr "Interesezione" + +#: src/app/main/ui/workspace/sidebar/layers.cljs:312, src/app/main/ui/workspace/sidebar/layers.cljs:410 +msgid "workspace.sidebar.layers.images" +msgstr "Immagini" + +#: src/app/main/ui/workspace/sidebar/layers.cljs:309, src/app/main/ui/workspace/sidebar/layers.cljs:368 +msgid "workspace.sidebar.layers.masks" +msgstr "Maschere" + +#: src/app/main/data/workspace/libraries.cljs:1143 +msgid "workspace.updates.there-are-updates" +msgstr "Sono presenti degli aggiornamenti nelle librerie condivise" + +#: src/app/main/data/workspace/libraries.cljs:1150 +msgid "workspace.updates.update" +msgstr "Aggiorna" + +#: src/app/main/ui/workspace/colorpicker.cljs:229 +msgid "media.radial" +msgstr "Radiale" + +#: src/app/main/ui/workspace/colorpicker.cljs:344, src/app/main/ui/workspace/colorpicker.cljs:345, src/app/main/ui/workspace/colorpicker.cljs:347 +msgid "media.choose-image" +msgstr "Scegli un'immagine" + +#: src/app/main/ui/delete_shared.cljs:59 +msgid "modals.delete-unpublish-shared-confirm.activated.hint" +msgid_plural "modals.delete-unpublish-shared-confirm.activated.hint" +msgstr[0] "" +"Le risorse già utilizzate in questo file rimarranno lì (nessun design verrà " +"compromesso)." +msgstr[1] "" +"Le risorse già utilizzare in questi file rimarranno lì (nessun design verrà " +"compromesso)." + +#: src/app/main/ui/workspace/plugins.cljs:188 +msgid "workspace.plugins.install" +msgstr "Installa" + +#: src/app/main/ui/workspace/plugins.cljs:183 +msgid "workspace.plugins.search-placeholder" +msgstr "Scrivi URL di un plugin" + +#: src/app/main/ui/workspace/plugins.cljs:209 +msgid "workspace.plugins.empty-plugins" +msgstr "Nessun plugin ancora installata" + +#: src/app/main/ui/workspace/plugins.cljs:214 +msgid "workspace.plugins.plugin-list-link" +msgstr "Lista plugin" + +#: src/app/main/ui/exports/files.cljs:170 +msgid "dashboard.export.options.merge.title" +msgstr "Includi gli asset delle librerie condivise nelle librerie del file" + +#: src/app/main/ui/workspace/main_menu.cljs:777, src/app/main/ui/workspace/sidebar/shortcuts.cljs:60 +msgid "shortcut-subsection.main-menu" +msgstr "Menu principale" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:157 +msgid "shortcuts.open-comments" +msgstr "Vai alla sezione commenti" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:158 +msgid "shortcuts.open-dashboard" +msgstr "Vai al pannello di controllo" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:260 +msgid "shortcuts.or" +msgstr " o " + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:165 +msgid "shortcuts.redo" +msgstr "Ripeti" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:176 +msgid "shortcuts.snap-nodes" +msgstr "Aggancia ai nodi" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:180 +msgid "shortcuts.stop-measure" +msgstr "Interrompi misurazione" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:185 +msgid "shortcuts.thumbnail-set" +msgstr "Imposta miniature" + +#: src/app/main/ui/dashboard/search.cljs:33 +msgid "title.dashboard.search" +msgstr "Cerca - %s - Penpot" + +#: src/app/main/ui/workspace/sidebar/options/menus/typography.cljs:519 +msgid "workspace.assets.typography.line-height" +msgstr "Interlinea" + +#: src/app/main/ui/workspace/sidebar/options/menus/typography.cljs:527 +msgid "workspace.assets.typography.text-transform" +msgstr "Trasforma testo" + +#: src/app/main/ui/workspace/main_menu.cljs:401 +msgid "workspace.header.menu.show-pixel-grid" +msgstr "Mostra griglia pixel" + +#: src/app/main/ui/workspace/sidebar/options/menus/constraints.cljs:142, src/app/main/ui/workspace/sidebar/options/menus/constraints.cljs:153 +msgid "workspace.options.constraints.scale" +msgstr "Ridimensionamento" + +#: src/app/main/ui/exports/assets.cljs:246 +msgid "workspace.options.exporting-complete" +msgstr "Esportazione completata" + +#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs:620 +msgid "workspace.options.interaction-animation" +msgstr "Animazione" + +#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs:411 +msgid "workspace.options.interaction-animation-none" +msgstr "Nessuna" + +#: src/app/main/ui/workspace/sidebar/options/menus/layout.cljs +#, unused +msgid "workspace.options.layout.packed" +msgstr "compatto" + +#: src/app/main/ui/workspace/sidebar/options/menus/layer.cljs:161 +msgid "workspace.options.opacity" +msgstr "Opacità" + +#: src/app/main/ui/workspace/viewport/path_actions.cljs:174 +msgid "workspace.path.actions.delete-node" +msgstr "Elimina nodo (%s)" + +#: src/app/main/ui/workspace/sidebar/history.cljs:117 +msgid "workspace.undo.entry.multiple.page" +msgstr "pagine" + +#: src/app/main/ui/workspace/sidebar/options/menus/constraints.cljs:150 +msgid "workspace.options.constraints.bottom" +msgstr "Inferiore" + +#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs:182 +msgid "workspace.options.flows.add-flow-start" +msgstr "Aggiungi inizio flusso" + +#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs:425 +msgid "workspace.options.interaction-easing-ease-in-out" +msgstr "Ease in out" + +#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs:53 +msgid "workspace.options.interaction-open-overlay-dest" +msgstr "Apri la sovrapposizione: %s" + +#: src/app/main/ui/workspace/sidebar/options/menus/layer.cljs:134 +msgid "workspace.options.layer-options.blend-mode.exclusion" +msgstr "Esclusione" + +#: src/app/main/ui/workspace/sidebar/options/rows/stroke_row.cljs:89 +msgid "workspace.options.stroke.outer" +msgstr "Esterno" + +#: src/app/main/ui/workspace/sidebar/options/menus/text.cljs:178 +msgid "workspace.options.text-options.strikethrough" +msgstr "Barrato (%s)" + +#: src/app/main/ui/workspace/context_menu.cljs:337 +msgid "workspace.shape.menu.transform-to-path" +msgstr "Trasforma in tracciato" + +#: src/app/main/ui/workspace/sidebar/layers.cljs:527 +msgid "workspace.focus.focus-mode" +msgstr "Modalità focus" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:196 +msgid "shortcuts.toggle-lock" +msgstr "Blocca/Sblocca" + +#: src/app/main/ui/workspace/main_menu.cljs:471 +msgid "workspace.header.menu.redo" +msgstr "Ripeti" + +#: src/app/main/ui/workspace/libraries.cljs +#, unused +msgid "workspace.libraries.library" +msgstr "LIBRERIA" + +#: src/app/main/data/workspace/libraries.cljs:1147, src/app/main/ui/workspace/sidebar/versions.cljs:285 +msgid "workspace.updates.dismiss" +msgstr "Ignora" + +#: src/app/main/errors.cljs:242 +msgid "errors.feature-mismatch" +msgstr "" +"Sembra che tu stia aprendo un file con la funzione '%s' abilitata, ma la " +"versione attuale di Penpot non la supporta o l'ha disabilitata." + +#: src/app/main/ui/dashboard/team.cljs:832 +msgid "errors.webhooks.timeout" +msgstr "Timeout" + +#: src/app/main/ui/viewer/inspect/right_sidebar.cljs:155 +msgid "inspect.empty.more-info" +msgstr "Maggiori informazioni sull'ispezione" + +#: src/app/main/ui/viewer/inspect/right_sidebar.cljs:147 +msgid "inspect.empty.select" +msgstr "" +"Seleziona una forma, una tavola da disegno o un gruppo per ispezionare le " +"loro proprietà e il loro codice" + +#: src/app/main/ui/dashboard/team.cljs:1005 +msgid "labels.active" +msgstr "Attivo" + +#: src/app/main/ui/workspace/sidebar/sitemap.cljs:226 +msgid "labels.view-only" +msgstr "Solo visualizzazione" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:61 +msgid "shortcut-subsection.modify-layers" +msgstr "Modifica livelli" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:166 +msgid "shortcuts.reset-zoom" +msgstr "Reimposta zoom" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:163 +msgid "shortcuts.paste" +msgstr "Incolla" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:168 +msgid "shortcuts.search-placeholder" +msgstr "Scorciatoie di ricerca" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:190 +msgid "shortcuts.toggle-fullscreen" +msgstr "Attiva/Disattiva schermo intero" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:210 +msgid "shortcuts.v-distribute" +msgstr "Distribuisci verticalmente" + +#: src/app/main/ui/viewer.cljs:575 +msgid "viewer.frame-not-found" +msgstr "Tavola da disegno non trovata." + +#: src/app/main/ui/workspace/sidebar/assets.cljs +#, unused +msgid "workspace.assets.selected-count" +msgid_plural "workspace.assets.selected-count" +msgstr[0] "%s elemento selezionato" +msgstr[1] "%s elementi selezionati" + +#: src/app/main/ui/workspace/sidebar/options/menus/measures.cljs:489 +msgid "workspace.options.height" +msgstr "Altezza" + +#: src/app/main/ui/workspace/sidebar/options/rows/stroke_row.cljs:165 +msgid "workspace.options.stroke-width" +msgstr "Spessore traccia" + +#: src/app/main/ui/workspace/sidebar/options/menus/text.cljs:84 +msgid "workspace.options.text-options.direction-ltr" +msgstr "LTR" + +#: src/app/main/ui/workspace/context_menu.cljs:352 +msgid "workspace.shape.menu.exclude" +msgstr "Escludi" + +#: src/app/main/ui/workspace/context_menu.cljs:382, src/app/main/ui/workspace/sidebar/layer_item.cljs:153, src/app/main/ui/workspace/sidebar/options/menus/layer.cljs:189 +msgid "workspace.shape.menu.lock" +msgstr "Blocca" + +#: src/app/main/ui/workspace/context_menu.cljs:268 +msgid "workspace.shape.menu.ungroup" +msgstr "Separa" + +#: src/app/main/ui/workspace/context_menu.cljs:282 +msgid "workspace.shape.menu.unmask" +msgstr "Rimuovi maschera" + +#: src/app/main/ui/workspace/sidebar/collapsable_button.cljs:25, src/app/main/ui/workspace/sidebar/collapsable_button.cljs:29 +msgid "workspace.sidebar.expand" +msgstr "Espandi barra laterale" + +#: src/app/main/ui/workspace/top_toolbar.cljs:170, src/app/main/ui/workspace/top_toolbar.cljs:171 +msgid "workspace.toolbar.text" +msgstr "Testo (%s)" + +#: src/app/main/ui/workspace/sidebar/history.cljs:112 +msgid "workspace.undo.entry.multiple.curve" +msgstr "curve" + +#: src/app/main/ui/onboarding/team_choice.cljs:238 +msgid "onboarding.team-modal.create-team" +msgstr "Crea un team" + +#: src/app/main/ui/settings/profile.cljs:121 +msgid "title.settings.profile" +msgstr "Profilo - Penpot" + +#: src/app/main/ui/viewer/header.cljs:237 +msgid "viewer.header.sitemap" +msgstr "Sitemap" + +#: src/app/main/ui/workspace/context_menu.cljs:540, src/app/main/ui/workspace/sidebar/assets/colors.cljs:251, src/app/main/ui/workspace/sidebar/assets/components.cljs:576, src/app/main/ui/workspace/sidebar/assets/graphics.cljs:424, src/app/main/ui/workspace/sidebar/assets/typographies.cljs:447 +msgid "workspace.assets.delete" +msgstr "Elimina" + +#: src/app/main/ui/workspace/sidebar/options/menus/frame_grid.cljs:263 +msgid "workspace.options.grid.params.gutter" +msgstr "Interspazio" + +#: src/app/main/ui/workspace/sidebar/options/menus/layer.cljs +#, unused +msgid "workspace.options.layer-options.title.multiple" +msgstr "Livelli selezionati" + +#: src/app/main/ui/workspace/sidebar/history.cljs:118 +msgid "workspace.undo.entry.multiple.path" +msgstr "tracciati" + +#: src/app/main/ui/settings/access_tokens.cljs:104 +msgid "dashboard.access-tokens.copied-success" +msgstr "Token copiato" + +#: src/app/main/ui/settings/access_tokens.cljs:191 +msgid "dashboard.access-tokens.create" +msgstr "Genera un nuovo token" + +#: src/app/main/ui/settings/access_tokens.cljs:136 +msgid "dashboard.access-tokens.expiration-180-days" +msgstr "180 giorni" + +#: src/app/main/ui/settings/access_tokens.cljs:133 +msgid "dashboard.access-tokens.expiration-30-days" +msgstr "30 giorni" + +#: src/app/main/ui/settings/access_tokens.cljs:144 +msgid "dashboard.access-tokens.token-will-not-expire" +msgstr "Il token non ha una data di scadenza" + +#: src/app/main/data/fonts.cljs:189 +msgid "errors.bad-font" +msgstr "Il font %s non può essere caricato" + +#: src/app/main/data/fonts.cljs:188 +msgid "errors.bad-font-plural" +msgstr "I font %s non posso essere caricati" + +#: src/app/main/ui/viewer/thumbnails.cljs:82 +msgid "labels.num-of-frames" +msgid_plural "labels.num-of-frames" +msgstr[0] "1 tavola da disegno" +msgstr[1] "%s tavole da disegno" + +#: src/app/main/ui/dashboard/file_menu.cljs:274 +msgid "labels.unpublish-multi-files" +msgstr "Rimuovi pubblicazione a %s file" + +#: src/app/main/ui/settings/access_tokens.cljs:154, src/app/main/ui/settings/access_tokens.cljs:160 +msgid "modals.create-access-token.copy-token" +msgstr "Copia token" + +#: src/app/main/ui/settings/access_tokens.cljs:112 +msgid "modals.create-access-token.title" +msgstr "Genera token di accesso" + +#: src/app/main/ui/dashboard/team.cljs:911 +msgid "modals.create-webhook.submit-label" +msgstr "Crea webhook" + +#: src/app/main/ui/dashboard/team.cljs:876 +msgid "modals.create-webhook.title" +msgstr "Crea webhook" + +#: src/app/main/ui/dashboard/team.cljs:887 +msgid "modals.create-webhook.url.label" +msgstr "URL del payload" + +#: src/app/main/ui/onboarding/newsletter.cljs:97 +msgid "onboarding-v2.newsletter.privacy2" +msgstr "" +"Ti invieremo solo email rilevanti. Puoi annullare l'iscrizione in qualsiasi " +"momento tramite il link di cancellazione presente in ogni nostra newsletter." + +#: src/app/main/ui/onboarding/newsletter.cljs:91 +msgid "onboarding-v2.newsletter.privacy1" +msgstr "Ci teniamo alla privacy, qui puoi leggere la nostra " + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:71 +msgid "shortcut-subsection.zoom-workspace" +msgstr "Zoom" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:76 +msgid "shortcuts.align-hcenter" +msgstr "Allinea al centro orizzontalmente" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:77 +msgid "shortcuts.align-justify" +msgstr "Allinea giustificato" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:126 +msgid "shortcuts.letter-spacing-dec" +msgstr "Diminuisci spaziatura tra le lettere" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:125 +msgid "shortcuts.join-nodes" +msgstr "Unisci nodi" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:127 +msgid "shortcuts.letter-spacing-inc" +msgstr "Aumenta spaziatura tra le lettere" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:147 +msgid "shortcuts.opacity-1" +msgstr "Imposta opacità al 10%" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:149 +msgid "shortcuts.opacity-3" +msgstr "Imposta opacità al 30%" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:183 +msgid "shortcuts.text-align-left" +msgstr "Allinea a sinistra" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:194 +msgid "shortcuts.toggle-layout-flex" +msgstr "Aggiungi/Rimuovi flex layout" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:202 +msgid "shortcuts.toggle-textpalette" +msgstr "Attiva/Disattiva palette testi" + +#: src/app/main/ui/workspace/sidebar/assets/components.cljs:570 +msgid "workspace.assets.duplicate-main" +msgstr "Duplica principale" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:211 +msgid "shortcuts.zoom-lense-decrease" +msgstr "Diminuire lo zoom" + +#: src/app/main/ui/workspace/sidebar/options/menus/typography.cljs:515 +msgid "workspace.assets.typography.font-size" +msgstr "Dimensione" + +#: src/app/main/ui/workspace/sidebar/options/menus/typography.cljs:511 +msgid "workspace.assets.typography.font-variant-id" +msgstr "Variante" + +#: src/app/main/ui/dashboard/grid.cljs:207, src/app/main/ui/workspace/libraries.cljs:469, src/app/main/ui/workspace/sidebar/options/menus/typography.cljs:474, src/app/main/ui/workspace/sidebar/options/menus/typography.cljs:499, src/app/main/ui/workspace/sidebar/options/menus/typography.cljs:606, src/app/main/ui/workspace/sidebar/options/menus/typography.cljs:625 +msgid "workspace.assets.typography.sample" +msgstr "Ag" + +#: src/app/main/ui/workspace/main_menu.cljs:228 +msgid "workspace.header.menu.disable-snap-guides" +msgstr "Disattiva allineamento a guide" + +#: src/app/main/ui/workspace/main_menu.cljs:258 +msgid "workspace.header.menu.disable-snap-pixel-grid" +msgstr "Disattiva allineamento al pixel" + +#: src/app/main/ui/workspace/main_menu.cljs:244 +msgid "workspace.header.menu.enable-dynamic-alignment" +msgstr "Attiva allineamento dinamico" + +#: src/app/main/ui/workspace/header.cljs +#, unused +msgid "workspace.header.menu.enable-scale-text" +msgstr "Attiva ridimensionamento testo" + +#: src/app/main/ui/workspace/main_menu.cljs:229 +msgid "workspace.header.menu.enable-snap-guides" +msgstr "Allinea alle guide" + +#: src/app/main/ui/workspace/main_menu.cljs:359 +msgid "workspace.header.menu.hide-palette" +msgstr "Nascondi palette colori" + +#: src/app/main/ui/workspace/main_menu.cljs:326 +msgid "workspace.header.menu.hide-rules" +msgstr "Nascondi righelli" + +#: src/app/main/ui/workspace/main_menu.cljs:825 +msgid "workspace.header.menu.option.preferences" +msgstr "Preferenze" + +#: src/app/main/ui/workspace/main_menu.cljs:814 +msgid "workspace.header.menu.option.view" +msgstr "Visualizza" + +#: src/app/main/ui/workspace/main_menu.cljs:442 +msgid "workspace.header.menu.select-all" +msgstr "Seleziona tutto" + +#: src/app/main/ui/workspace/main_menu.cljs:327 +msgid "workspace.header.menu.show-rules" +msgstr "Mostra righelli" + +#: src/app/main/ui/workspace/main_menu.cljs:374 +msgid "workspace.header.menu.show-textpalette" +msgstr "Mostra palette caratteri" + +#: src/app/main/ui/workspace/header.cljs +#, unused +msgid "workspace.header.saving" +msgstr "In salvataggio" + +#: src/app/main/ui/workspace/right_header.cljs:47, src/app/main/ui/workspace/right_header.cljs:52 +msgid "workspace.header.unsaved" +msgstr "Cambiamenti non salvati" + +#: src/app/main/ui/workspace/libraries.cljs:297 +msgid "workspace.libraries.no-shared-libraries-available" +msgstr "Non ci sono librerie condivise disponibili" + +#: src/app/main/ui/workspace/libraries.cljs:388 +msgid "workspace.libraries.no-libraries-need-sync" +msgstr "Non ci sono librerie condivise che necessitano un aggiornamento" + +#: src/app/main/ui/workspace/sidebar/options/menus/blur.cljs:85 +msgid "workspace.options.blur-options.title.multiple" +msgstr "Sfocatura della selezione" + +#: src/app/main/ui/workspace/sidebar/options/menus/component.cljs:600, src/app/main/ui/workspace/sidebar/options/menus/component.cljs:605 +msgid "workspace.options.component" +msgstr "Componente" + +#: src/app/main/ui/exports/assets.cljs:176, src/app/main/ui/exports/assets.cljs:247, src/app/main/ui/viewer/inspect/exports.cljs:202, src/app/main/ui/workspace/sidebar/options/menus/exports.cljs:255 +msgid "workspace.options.exporting-object" +msgstr "In esportazione…" + +#: src/app/main/ui/workspace/sidebar/options/menus/fill.cljs:50, src/app/main/ui/workspace/sidebar/options/menus/fill.cljs:178 +msgid "workspace.options.fill" +msgstr "Riempimento" + +#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs +#, unused +msgid "workspace.options.flows.flow-start" +msgstr "Inizio flusso" + +#: src/app/main/ui/workspace/sidebar/options/menus/frame_grid.cljs:200, src/app/main/ui/workspace/sidebar/options/menus/frame_grid.cljs:241 +msgid "workspace.options.grid.params.color" +msgstr "Colore" + +#: src/app/main/ui/workspace/sidebar/options/menus/frame_grid.cljs:274 +msgid "workspace.options.grid.params.margin" +msgstr "Margine" + +#: src/app/main/ui/workspace/sidebar/options/menus/frame_grid.cljs:235 +msgid "workspace.options.grid.params.type.bottom" +msgstr "Basso" + +#: src/app/main/ui/workspace/sidebar/options/menus/frame_grid.cljs:233 +msgid "workspace.options.grid.params.type.center" +msgstr "Centro" + +#: src/app/main/ui/workspace/sidebar/options/menus/frame_grid.cljs:215, src/app/main/ui/workspace/sidebar/options/menus/frame_grid.cljs:292 +msgid "workspace.options.grid.params.use-default" +msgstr "Usa predefinito" + +#: src/app/main/ui/workspace/sidebar/options/menus/frame_grid.cljs:251 +msgid "workspace.options.grid.params.width" +msgstr "Larghezza" + +#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs:42, src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs:373 +msgid "workspace.options.interaction-after-delay" +msgstr "Dopo un ritardo" + +#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs:474 +msgid "workspace.options.interaction-action" +msgstr "Azione" + +#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs:484 +msgid "workspace.options.interaction-destination" +msgstr "Destinazione" + +#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs:667 +msgid "workspace.options.interaction-duration" +msgstr "Durata" + +#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs:421 +msgid "workspace.options.interaction-easing-linear" +msgstr "Linear" + +#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs:51 +msgid "workspace.options.interaction-navigate-to-dest" +msgstr "Naviga verso: %s" + +#: src/app/main/ui/workspace/sidebar/options/menus/layer.cljs:133 +msgid "workspace.options.layer-options.blend-mode.difference" +msgstr "Differenza" + +#: src/app/main/ui/workspace/sidebar/options/menus/layout_item.cljs:531 +msgid "workspace.options.layout-item.layout-item-max-w" +msgstr "Larghezza.Max" + +#: src/app/main/ui/workspace/sidebar/options/menus/layout_item.cljs:548 +msgid "workspace.options.layout-item.layout-item-min-h" +msgstr "Altezza.Min" + +#: src/app/main/ui/workspace/sidebar/options/menus/layout_item.cljs +#, unused +msgid "workspace.options.layout-item.title.layout-item-max-h" +msgstr "Altezza massima" + +#: src/app/main/ui/workspace/sidebar/options/menus/measures.cljs:640 +msgid "workspace.options.radius.single-corners" +msgstr "Angoli indipendenti" + +#: src/app/main/ui/workspace/sidebar/options/menus/measures.cljs:639 +msgid "workspace.options.radius.all-corners" +msgstr "Tutti gli angoli" + +#: src/app/main/ui/workspace/sidebar/options/menus/stroke.cljs:41 +msgid "workspace.options.selection-stroke" +msgstr "Traccia di selezione" + +#: src/app/main/ui/workspace/sidebar/options/menus/color_selection.cljs:118 +msgid "workspace.options.selection-color" +msgstr "Colori selezionati" + +#: src/app/main/ui/viewer/inspect/attributes/shadow.cljs:39, src/app/main/ui/workspace/sidebar/options/menus/shadow.cljs:225 +msgid "workspace.options.shadow-options.offsety" +msgstr "Y" + +#: src/app/main/ui/workspace/sidebar/options/menus/stroke.cljs:43 +msgid "workspace.options.stroke" +msgstr "Traccia" + +#: src/app/main/ui/workspace/sidebar/options/menus/stroke.cljs +#, unused +msgid "workspace.options.stroke-cap.circle-marker" +msgstr "Marcatore circolare" + +#: src/app/main/ui/workspace/sidebar/options/rows/stroke_row.cljs:130 +msgid "workspace.options.stroke-cap.diamond-marker-short" +msgstr "Diamante" + +#: src/app/main/ui/workspace/sidebar/options/menus/stroke.cljs +#, unused +msgid "workspace.options.stroke-cap.line-arrow" +msgstr "Freccia di linea" + +#: src/app/main/ui/workspace/sidebar/options/rows/stroke_row.cljs:126 +msgid "workspace.options.stroke-cap.line-arrow-short" +msgstr "Freccia" + +#: src/app/main/ui/workspace/sidebar/options/menus/text.cljs:109 +msgid "workspace.options.text-options.align-top" +msgstr "Allinea in alto" + +#: src/app/main/ui/workspace/sidebar/options/menus/text.cljs:53 +msgid "workspace.options.text-options.text-align-center" +msgstr "Allinea al centro (%s)" + +#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs:753 +msgid "workspace.options.use-play-button" +msgstr "" +"Utilizza il pulsante di riproduzione nell'header per avviare la " +"visualizzazione del prototipo." + +#: src/app/main/ui/workspace/viewport/path_actions.cljs:189 +msgid "workspace.path.actions.join-nodes" +msgstr "Unisci nodi (%s)" + +#: src/app/main/ui/workspace/context_menu.cljs:451 +msgid "workspace.shape.menu.add-flex" +msgstr "Aggiungi flex layout" + +#: src/app/main/ui/workspace/sidebar/options/menus/component.cljs, src/app/main/ui/workspace/sidebar/options/menus/component.cljs, src/app/main/ui/workspace/context_menu.cljs, src/app/main/ui/workspace/context_menu.cljs +#, unused +msgid "workspace.shape.menu.update-components-in-bulk" +msgstr "Aggiorna componente principale" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:420 +msgid "shortcut-section.dashboard" +msgstr "Pannello di controllo" + +#: src/app/main/ui/viewer/header.cljs:351 +msgid "viewer.header.inspect-section" +msgstr "Ispeziona (%s)" + +#: src/app/main/ui/workspace/main_menu.cljs:389 +msgid "workspace.header.menu.show-artboard-names" +msgstr "Mostra nomi delle tavole da disegno" + +#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs:38, src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs:368 +msgid "workspace.options.interaction-while-hovering" +msgstr "Durante il passaggio del mouse" + +#: src/app/main/ui/workspace/sidebar/options/menus/measures.cljs:534 +msgid "workspace.options.y" +msgstr "Asse Y" + +#: src/app/main/ui/workspace/sidebar/assets/common.cljs:439 +msgid "workspace.shape.menu.restore-main" +msgstr "Ripristina componente principale" + +#: src/app/main/ui/onboarding/questions.cljs +#, unused +msgid "branding-illustrations-marketing-pieces" +msgstr "…branding, illustrazione, materiali di marketing, etc." + +#: src/app/main/data/common.cljs:81 +msgid "notifications.by-code.upgrade-version" +msgstr "Una nuova versione è disponibile, si prega di ricaricare la pagina" + +#: src/app/main/ui/dashboard/files.cljs:191, src/app/main/ui/dashboard/projects.cljs:285 +msgid "dashboard.empty-placeholder-files-subtitle" +msgstr "Quando un membro del progetto crea un file, verrà mostrato qui." + +#: src/app/main/ui/dashboard/files.cljs:186, src/app/main/ui/dashboard/projects.cljs:280 +msgid "dashboard.empty-placeholder-files-title" +msgstr "Nessun file presente." + +#: src/app/main/ui/dashboard/placeholder.cljs:39 +#, markdown +msgid "dashboard.empty-placeholder-libraries" +msgstr "" +"Le librerie aggiunte al progetto appariranno qui. Prova a condividere i tuoi " +"file o ad aggiungerle dal nostro [Librerie e modelli](https://penpot.app/" +"libraries-templates)." + +#: src/app/main/ui/dashboard/placeholder.cljs:35 +msgid "dashboard.empty-placeholder-libraries-subtitle-viewer-role" +msgstr "Le librerie aggiunte al progetto verrano mostrate qui." + +#: src/app/main/ui/dashboard/placeholder.cljs:32 +msgid "dashboard.empty-placeholder-libraries-title" +msgstr "Nessuna libreria presente." + +#: src/app/main/ui/dashboard/placeholder.cljs +#, markdown, unused +msgid "dashboard.empty-placeholder-libraries-subtitle" +msgstr "" +"Le librerie aggiunte al progetto appariranno qui. Prova a condividere i tuoi " +"file o ad aggiungerle dal nostro [Librerie e modelli](https://penpot.app/" +"libraries-templates)." + +#: src/app/main/ui/auth/register.cljs:124 +msgid "auth.register-tagline" +msgstr "" +"Con un account PenPot gratuito, puoi creare team illimitati e collaborare " +"con altri designer e sviluppatori su quanti progetti desideri. " + +#: src/app/main/ui/auth/login.cljs:180, src/app/main/ui/auth/recovery_request.cljs:77, src/app/main/ui/auth/register.cljs:88 +msgid "auth.work-email" +msgstr "Email di lavoro" + +#: src/app/main/ui/dashboard/files.cljs:185, src/app/main/ui/dashboard/projects.cljs:279 +msgid "dashboard.empty-placeholder-drafts-title" +msgstr "Nessuna bozza presente." + +#: src/app/main/ui/dashboard/files.cljs:190, src/app/main/ui/dashboard/projects.cljs:284 +msgid "dashboard.empty-placeholder-drafts-subtitle" +msgstr "Quando un membro del progetto crea una bozza, verrà mostrata qui." + +#: src/app/main/data/common.cljs:203 +msgid "dashboard.permissions-change.viewer" +msgstr "Ora sei un visualizzatore di questo team." + +#: src/app/main/data/common.cljs:204 +msgid "dashboard.permissions-change.editor" +msgstr "Ora sei un editor di questo team." + +#: src/app/main/data/common.cljs:206 +msgid "dashboard.permissions-change.owner" +msgstr "Ora sei il proprietario di questo team." + +#: src/app/main/data/common.cljs:233 +msgid "dashboard.removed-from-team" +msgstr "Non fai più parte del team \"%s\"." + +#: src/app/main/ui/dashboard/team.cljs:944 +msgid "dashboard.webhooks.cant-edit" +msgstr "Puoi solo eliminare o modificare i webhook creati da te." + +#: src/app/main/ui/dashboard/team.cljs:890 +msgid "dashboard.webhooks.content-type" +msgstr "Tipo di contenuto" + +#: src/app/main/ui/auth/recovery_request.cljs:57, src/app/main/ui/auth/register.cljs:57, src/app/main/ui/auth/register.cljs:60, src/app/main/ui/dashboard/team.cljs:615, src/app/main/ui/settings/change_email.cljs:37 +msgid "errors.email-has-permanent-bounces" +msgstr "L'email «%s» ha molti report di rimbalzi permanenti." + +#, unused +msgid "errors.field-min-length" +msgstr "Deve contenere almeno 1 carattere." + +#: src/app/main/errors.cljs:254, src/app/main/ui/dashboard/team.cljs:185, src/app/main/ui/onboarding/team_choice.cljs:104 +msgid "errors.max-quote-reached" +msgstr "Hai raggiunto la quota '%s'. Contatta il supporto." + +#: src/app/main/ui/dashboard/team.cljs:610 +msgid "errors.member-is-muted" +msgstr "" +"Il profilo che stai invitando ha le email disattivate (rapporti di spam o " +"alti tassi di rimbalzo)." + +#: src/app/main/ui/dashboard/team.cljs:181, src/app/main/ui/onboarding/team_choice.cljs:100 +msgid "errors.maximum-invitations-by-request-reached" +msgstr "" +"È stato raggiunto il massimo numero di email (%s) che possono essere inviate " +"con una singola richiesta" + +#: src/app/main/ui/workspace/colorpicker.cljs:228 +msgid "media.linear" +msgstr "Lineare" + +#: src/app/main/ui/dashboard/team.cljs:888 +msgid "modals.create-webhook.url.placeholder" +msgstr "https://example.com/postreceive" + +#: src/app/main/ui/settings/access_tokens.cljs:260 +msgid "modals.delete-acces-token.accept" +msgstr "Elimina token" + +#: src/app/main/ui/settings/access_tokens.cljs:259 +msgid "modals.delete-acces-token.message" +msgstr "Sei sicuro di voler eliminare questo token?" + +#: src/app/main/ui/delete_shared.cljs:55 +msgid "modals.delete-shared-confirm.activated.no-files-message" +msgid_plural "modals.delete-shared-confirm.activated.no-files-message" +msgstr[0] "Non è attivato in alcun file." +msgstr[1] "Non sono attivati in alcun file." + +#: src/app/main/ui/dashboard/team.cljs:978 +msgid "modals.delete-webhook.message" +msgstr "Sei sicuro di voler eliminare questo webhook?" + +#: src/app/main/ui/dashboard/team.cljs:977 +msgid "modals.delete-webhook.title" +msgstr "Eliminazione del webhook in corso" + +#: src/app/main/ui/dashboard/team.cljs:910 +msgid "modals.edit-webhook.submit-label" +msgstr "Modifica webhook" + +#: src/app/main/ui/static.cljs:328 +msgid "not-found.desc-message.error" +msgstr "Errore 404" + +#: src/app/main/ui/auth/recovery_request.cljs:114 +msgid "not-found.login.sent-recovery" +msgstr "Abbiamo inviato un email di recupero a" + +#: src/app/main/ui/static.cljs:63 +msgid "not-found.made-with-love" +msgstr "Fatto con AMORE e Open Source" + +#: src/app/main/ui/static.cljs:310, src/app/main/ui/static.cljs:319 +msgid "not-found.no-permission.ask" +msgstr "RICHIEDI ACCESSO" + +#: src/app/main/ui/onboarding/questions.cljs:268 +msgid "onboarding.questions.team-size.11-30" +msgstr "11-30" + +#: src/app/main/ui/onboarding/questions.cljs:269 +msgid "onboarding.questions.team-size.2-10" +msgstr "2-10" + +#: src/app/main/ui/onboarding/questions.cljs:80 +msgid "onboarding.questions.use.education" +msgstr "Educazione" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:89 +msgid "shortcuts.bring-backward" +msgstr "Porta dietro" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:91 +msgid "shortcuts.bring-front" +msgstr "Porta in primo piano" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:92 +msgid "shortcuts.clear-undo" +msgstr "Pulisci cronologia" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:85 +msgid "shortcuts.bool-exclude" +msgstr "Escludi" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:86 +msgid "shortcuts.bool-intersection" +msgstr "Interseca" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:87 +msgid "shortcuts.bool-union" +msgstr "Unisci" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:101 +msgid "shortcuts.draw-curve" +msgstr "Curva" + +#: src/app/main/ui/workspace/right_header.cljs:115, src/app/main/ui/workspace/sidebar/shortcuts.cljs:97 +msgid "shortcuts.decrease-zoom" +msgstr "Zoom indietro" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:100 +msgid "shortcuts.detach-component" +msgstr "Scollega componente" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:128 +msgid "shortcuts.line-height-dec" +msgstr "Diminuisci interlinea" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:116 +msgid "shortcuts.go-to-drafts" +msgstr "Vai alle bozze" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:119 +msgid "shortcuts.group" +msgstr "Raggruppa" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:123 +msgid "shortcuts.insert-image" +msgstr "Inserisci immagine" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:138 +msgid "shortcuts.move-fast-right" +msgstr "Sposta rapidamente a destra" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:131 +msgid "shortcuts.make-corner" +msgstr "Crea angolo" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:132 +msgid "shortcuts.make-curve" +msgstr "Crea curva" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:134 +msgid "shortcuts.merge-nodes" +msgstr "Fondi nodi" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:129 +msgid "shortcuts.line-height-inc" +msgstr "Aumenta interlinea" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:133 +msgid "shortcuts.mask" +msgstr "Maschera" + +#: src/app/main/ui/workspace/sidebar/assets/file_library.cljs:295 +msgid "workspace.assets.not-found" +msgstr "Nessun asset trovato" + +#: src/app/main/ui/workspace/sidebar/assets/colors.cljs:495 +msgid "workspace.assets.colors.add-color" +msgstr "Aggiungi colore" + +#: src/app/main/ui/workspace/sidebar/assets/components.cljs:532 +msgid "workspace.assets.components.add-component" +msgstr "Aggiungi componente" + +#: src/app/main/ui/workspace/sidebar/assets.cljs:163 +msgid "workspace.assets.libraries" +msgstr "Librerie" + +#: src/app/main/ui/workspace/sidebar/assets/file_library.cljs:62, src/app/main/ui/workspace/sidebar/options/menus/component.cljs:347 +msgid "workspace.assets.local-library" +msgstr "libreria locale" + +#: src/app/main/ui/workspace/sidebar/assets/typographies.cljs:408 +msgid "workspace.assets.typography.add-typography" +msgstr "Aggiungi elemento tipografico" + +#: src/app/main/ui/workspace/sidebar/options/menus/typography.cljs +#, unused +msgid "workspace.assets.typography.font-id" +msgstr "Carattere" + +#, unused +msgid "workspace.assets.typography.text-styles" +msgstr "Stili di testo" + +#: src/app/main/ui/workspace/context_menu.cljs:298, src/app/main/ui/workspace/context_menu.cljs:567 +msgid "workspace.focus.focus-off" +msgstr "Modalità focus disattivata" + +#: src/app/main/ui/workspace/libraries.cljs:517, src/app/main/ui/workspace/libraries.cljs:542 +msgid "workspace.libraries.libraries" +msgstr "LIBRERIE" + +#: src/app/main/ui/workspace/libraries.cljs:390 +msgid "workspace.libraries.library-updates" +msgstr "AGGIORNAMENTI DELLA LIBRERIA" + +#: src/app/main/ui/workspace/libraries.cljs:300 +msgid "workspace.libraries.more-templates" +msgstr "Puoi cercare altri " + +#: src/app/main/ui/workspace/sidebar/options/menus/component.cljs:173 +msgid "workspace.options.component.create-annotation" +msgstr "Crea un'annotazione" + +#: src/app/main/ui/workspace/sidebar/options/page.cljs:38, src/app/main/ui/workspace/sidebar/options/page.cljs:45 +msgid "workspace.options.canvas-background" +msgstr "Colore di sfondo" + +#: src/app/main/ui/workspace/sidebar/options/menus/component.cljs:610 +msgid "workspace.options.component.copy" +msgstr "Copia" + +#: src/app/main/ui/workspace/sidebar/options/menus/constraints.cljs:163 +msgid "workspace.options.constraints" +msgstr "Vincoli" + +#: src/app/main/ui/workspace/sidebar/options/menus/frame_grid.cljs:158 +msgid "workspace.options.grid.square" +msgstr "Quadrato" + +#: src/app/main/ui/workspace/sidebar/options/menus/fill.cljs:49 +msgid "workspace.options.group-fill" +msgstr "Riempimento di gruppo" + +#: src/app/main/ui/workspace/sidebar/options/menus/stroke.cljs:42 +msgid "workspace.options.group-stroke" +msgstr "Traccia di gruppo" + +#: src/app/main/ui/workspace/sidebar/options/menus/frame_grid.cljs:159 +msgid "workspace.options.grid.column" +msgstr "Colonne" + +#: src/app/main/ui/workspace/sidebar/options/menus/frame_grid.cljs +#, unused +msgid "workspace.options.grid.grid-title" +msgstr "Griglia" + +#: src/app/main/ui/workspace/sidebar/options/menus/frame_grid.cljs:229 +msgid "workspace.options.grid.params.type.stretch" +msgstr "Estendi" + +#: src/app/main/ui/workspace/sidebar/options/menus/frame_grid.cljs:160 +msgid "workspace.options.grid.row" +msgstr "Righe" + +#: src/app/main/ui/workspace/sidebar/options/menus/frame_grid.cljs:183 +msgid "workspace.options.guides.toggle-guide" +msgstr "Attiva/Disattiva guida" + +#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs:412 +msgid "workspace.options.interaction-animation-dissolve" +msgstr "Dissolvenza" + +#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs:418 +msgid "workspace.options.interaction-animation-push" +msgstr "Spinta" + +#: src/app/main/ui/workspace/sidebar/options/menus/frame_grid.cljs:323 +msgid "workspace.options.guides.add-guide" +msgstr "Aggiungi guida" + +#: src/app/main/ui/workspace/sidebar/options/menus/frame_grid.cljs:187 +msgid "workspace.options.guides.remove-guide" +msgstr "Rimuovi guida" + +#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs:610 +msgid "workspace.options.interaction-background" +msgstr "Aggiungi sovrapposizione di sfondo" + +#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs:397 +msgid "workspace.options.interaction-auto" +msgstr "automatico" + +#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs:596 +msgid "workspace.options.interaction-close-outside" +msgstr "Chiudi al click esterno" + +#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs:378 +msgid "workspace.options.interaction-close-overlay" +msgstr "Chiudi sovrapposizione" + +#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs:52, src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs:54, src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs:56, src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs:386 +msgid "workspace.options.interaction-none" +msgstr "(non impostato)" + +#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs:36, src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs:366 +msgid "workspace.options.interaction-on-click" +msgstr "Al click" + +#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs:500 +msgid "workspace.options.interaction-preserve-scroll" +msgstr "Preserva posizione di scorrimento" + +#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs:59, src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs:379 +msgid "workspace.options.interaction-prev-screen" +msgstr "Schermata precedente" + +#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs:521 +msgid "workspace.options.interaction-relative-to" +msgstr "Relativo a" + +#: src/app/main/ui/workspace/sidebar/options/menus/measures.cljs:620 +msgid "workspace.options.radius-bottom-left" +msgstr "Inferiore sinistro" + +#: src/app/main/ui/workspace/sidebar/options/menus/shadow.cljs:302 +msgid "workspace.options.shadow-options.add-shadow" +msgstr "Aggiungi ombra" + +#: src/app/main/ui/workspace/sidebar/options/menus/shadow.cljs:239 +msgid "workspace.options.shadow-options.color" +msgstr "Colore ombra" + +#: src/app/main/ui/workspace/sidebar/options/rows/stroke_row.cljs:133 +msgid "workspace.options.stroke-cap.square" +msgstr "Quadrato" + +#: src/app/main/ui/workspace/sidebar/options/menus/stroke.cljs +#, unused +msgid "workspace.options.stroke-cap.diamond-marker" +msgstr "Marcatore diamante" + +#: src/app/main/ui/workspace/sidebar/options/rows/stroke_row.cljs:124 +msgid "workspace.options.stroke-cap.none" +msgstr "Nessuno" + +#: src/app/main/ui/workspace/sidebar/options/rows/stroke_row.cljs:132 +msgid "workspace.options.stroke-cap.round" +msgstr "Rotondo" + +#: src/app/main/ui/workspace/sidebar/options/rows/stroke_row.cljs:127 +msgid "workspace.options.stroke-cap.triangle-arrow-short" +msgstr "Triangolo" + +#: src/app/main/ui/workspace/plugins.cljs:270 +msgid "workspace.plugins.permissions.comment-write" +msgstr "Leggi e modifica i tuoi commenti e rispondi a tuo nome." + +#: src/app/main/ui/workspace/plugins.cljs:86 +msgid "workspace.plugins.remove-plugin" +msgstr "Rimuovi plugin" + +#: src/app/main/ui/workspace/plugins.cljs:436 +msgid "workspace.plugins.try-out.cancel" +msgstr "NON ORA" + +#: src/app/main/ui/workspace/plugins.cljs:429 +msgid "workspace.plugins.try-out.message" +msgstr "" +"Vuoi dare un'occhiata? Si aprirà in una nuova bozza per il tuo team attuale. " +"(In caso contrario, puoi sempre trovarlo nei plugin installati di qualsiasi " +"file.)" + +#: src/app/main/ui/workspace/plugins.cljs:425 +msgid "workspace.plugins.try-out.title" +msgstr "IL PLUGIN '%s' È INSTALLATO PER IL TUO UTENTE!" + +#: src/app/main/ui/workspace/context_menu.cljs:404 +msgid "workspace.shape.menu.flow-start" +msgstr "Inizio del flusso" + +#: src/app/main/ui/workspace/context_menu.cljs:188 +msgid "workspace.shape.menu.front" +msgstr "Porta in primo piano" + +#: src/app/main/ui/workspace/tokens/theme_select.cljs:84 +msgid "workspace.token.active-themes" +msgstr "%s temi attivi" + +#: src/app/main/ui/workspace/tokens/sidebar.cljs +#, unused +msgid "workspace.token.add set" +msgstr "Aggiungi set" + +#: src/app/main/ui/workspace/tokens/modals/themes.cljs:310 +msgid "workspace.token.back-to-themes" +msgstr "Torna alla lista temi" + +#: src/app/main/ui/workspace/tokens/modals/themes.cljs:155, src/app/main/ui/workspace/tokens/modals/themes.cljs:239 +msgid "workspace.token.create-theme-title" +msgstr "Crea tema" + +#: src/app/main/ui/workspace/tokens/form.cljs:362 +msgid "workspace.token.create-token" +msgstr "Crea un nuovo token %s" + +#: src/app/main/ui/workspace/tokens/modals/themes.cljs:142 +msgid "workspace.token.no-sets" +msgstr "Nessun set" + +#: src/app/main/ui/workspace/tokens/sets.cljs:216 +msgid "workspace.token.no-sets-create" +msgstr "Non sono ancora stati definiti dei set. Creane prima uno." + +#: src/app/main/ui/workspace/tokens/sidebar.cljs:239 +msgid "workspace.token.no-sets-yet" +msgstr "Non ci sono ancora dei set." + +#: src/app/main/ui/workspace/tokens/sidebar.cljs:191 +msgid "workspace.token.no-themes" +msgstr "Non ci sono temi." + +#: src/app/main/ui/workspace/tokens/sets.cljs:186 +msgid "workspace.token.grouping-set-alert" +msgstr "Il raggruppamento di set di token non è ancora supportato." + +#: src/app/main/ui/workspace/tokens/modals/themes.cljs:52 +msgid "workspace.token.new-theme" +msgstr "Nuovo tema" + +#: src/app/main/ui/workspace/tokens/theme_select.cljs:88 +msgid "workspace.token.no-active-theme" +msgstr "Nessun tema attivo" + +#: src/app/main/ui/workspace/tokens/modals/themes.cljs:43 +msgid "workspace.token.no-themes-currently" +msgstr "Al momento non hai temi." + +#: src/app/main/ui/workspace/tokens/form.cljs:193, src/app/main/ui/workspace/tokens/form.cljs:196, src/app/main/ui/workspace/tokens/sidebar.cljs:67 +msgid "workspace.token.resolved-value" +msgstr "Valore risultato: " + +#: src/app/main/ui/workspace/top_toolbar.cljs:133, src/app/main/ui/workspace/top_toolbar.cljs:134 +msgid "workspace.toolbar.move" +msgstr "Sposta (%s)" + +#: src/app/main/ui/workspace/left_toolbar.cljs +#, unused +msgid "workspace.toolbar.shortcuts" +msgstr "Scorciatoie (%s)" + +#: src/app/main/ui/workspace/palette.cljs:173, src/app/main/ui/workspace/palette.cljs:174 +msgid "workspace.toolbar.text-palette" +msgstr "Tipografie (%s)" + +#: src/app/main/ui/workspace/sidebar/versions.cljs:207 +msgid "workspace.versions.snapshot-menu" +msgstr "Apri menu delle istantanee" + +#: src/app/main/ui/workspace/sidebar/versions.cljs:138 +msgid "workspace.versions.version-menu" +msgstr "Apri menu delle versioni" + +#: src/app/main/ui/dashboard/fonts.cljs:444 +msgid "dashboard.fonts.empty-placeholder-viewer" +msgstr "Nessun font personalizzato presente." + +#: src/app/main/data/common.cljs:205 +msgid "dashboard.permissions-change.admin" +msgstr "Ora sei un amministratore di questo team." + +#: src/app/main/data/workspace/media.cljs:198 +msgid "errors.cannot-upload" +msgstr "Impossible caricare il file multimediale." + +#: src/app/main/errors.cljs:246, src/app/main/errors.cljs:260 +msgid "errors.feature-not-supported" +msgstr "La funzione '%s' non è supportata." + +#: src/app/main/ui/settings/team-form.cljs, src/app/main/ui/auth/register.cljs, src/app/main/ui/dashboard/team_form.cljs, src/app/main/ui/onboarding/team_choice.cljs, src/app/main/ui/settings/access_tokens.cljs, src/app/main/ui/settings/feedback.cljs, src/app/main/ui/settings/profile.cljs, src/app/main/ui/workspace/sidebar/assets.cljs +#, unused +msgid "errors.field-not-all-whitespace" +msgstr "Il nome deve contenere alcuni caratteri oltre allo spazio." + +#: src/app/main/errors.cljs:238 +msgid "errors.file-feature-mismatch" +msgstr "" +"Sembra che ci sia una discrepanza tra le funzioni abilitate e quelle del " +"file che stai cercando di aprire. È necessario applicare le migrazioni per " +"'%s' prima di poter aprire il file." + +#: src/app/main/errors.cljs:136 +msgid "errors.paste-data-validation" +msgstr "Dati non validi negli appunti" + +#: src/app/main/ui/auth/recovery_request.cljs:53, src/app/main/ui/dashboard/team.cljs:176, src/app/main/ui/dashboard/team.cljs:606, src/app/main/ui/onboarding/team_choice.cljs:96, src/app/main/ui/settings/change_email.cljs:33 +msgid "errors.profile-is-muted" +msgstr "" +"Il tuo profilo ha le email disattivate (rapporti di spam o alti tassi di " +"rimbalzo)." + +#: src/app/main/errors.cljs:250 +msgid "errors.version-not-supported" +msgstr "Il file ha un numero di versione incompatibile" + +#: src/app/main/ui/dashboard/team.cljs:834 +msgid "errors.webhooks.connection" +msgstr "Errore di connessione, l'URL è irraggiungibile" + +#: src/app/main/ui/dashboard/team.cljs:828 +msgid "errors.webhooks.invalid-uri" +msgstr "L'URL non ha superato la validazione." + +#: src/app/main/ui/dashboard/team.cljs:836, src/app/main/ui/dashboard/team.cljs:992 +msgid "errors.webhooks.unexpected-status" +msgstr "Stato inaspettato %s" + +#: src/app/main/ui/viewer/inspect/attributes/geometry.cljs:40 +msgid "inspect.attributes.size" +msgstr "Dimensione e posizione" + +#: src/app/main/ui/viewer/inspect/attributes/text.cljs:116 +msgid "inspect.attributes.typography.font-weight" +msgstr "Peso del carattere" + +#: src/app/main/ui/settings/sidebar.cljs:100 +msgid "labels.access-tokens" +msgstr "Token di accesso" + +#: src/app/main/ui/viewer/inspect/attributes/text.cljs:162 +msgid "inspect.attributes.typography.text-transform.unset" +msgstr "Annulla impostazione" + +#: src/app/main/ui/workspace/sidebar/options/menus/layout_container.cljs:1051 +#, unused +msgid "labels.add" +msgstr "Aggiungi" + +#: src/app/main/ui/onboarding/questions.cljs:171 +msgid "labels.canva" +msgstr "Canva" + +#: src/app/main/ui/workspace/tokens/sets.cljs:153 +msgid "labels.collapse" +msgstr "Comprimi" + +#: src/app/main/ui/onboarding/questions.cljs:260 +msgid "labels.director" +msgstr "Direttore" + +#: src/app/main/ui/workspace/sidebar/options/menus/component.cljs:199 +msgid "labels.discard" +msgstr "Scarta" + +#: src/app/main/ui/onboarding/questions.cljs:165 +msgid "labels.figma" +msgstr "Figma" + +#: src/app/main/ui/onboarding/questions.cljs:259 +msgid "labels.founder" +msgstr "Amministratore delegato e Fondatore" + +#: src/app/main/ui/onboarding/questions.cljs:258 +msgid "labels.freelancer" +msgstr "Libero professionista" + +#: src/app/main/ui/onboarding/questions.cljs:248 +msgid "labels.graphic-design" +msgstr "Graphic design" + +#: src/app/main/ui/dashboard/team.cljs:1006 +msgid "labels.inactive" +msgstr "Inattivo" + +#: src/app/main/ui/onboarding/questions.cljs:173 +msgid "labels.invision" +msgstr "InVision" + +#: src/app/main/ui/onboarding/questions.cljs:249 +msgid "labels.marketing" +msgstr "Marketing" + +#: src/app/main/ui/comments.cljs:340, src/app/main/ui/workspace/sidebar/options/menus/text.cljs:295, src/app/main/ui/workspace/sidebar/options/menus/text.cljs:324 +msgid "labels.options" +msgstr "Opzioni" + +#: src/app/main/ui/workspace/sidebar/versions.cljs:149, src/app/main/ui/workspace/sidebar/versions.cljs:288 +msgid "labels.restore" +msgstr "Ricarica file" + +#: src/app/main/ui/workspace/tokens/sidebar.cljs:229 +msgid "labels.sets" +msgstr "Set" + +#: src/app/main/ui/workspace/tokens/sidebar.cljs:187 +msgid "labels.themes" +msgstr "Temi" + +#: src/app/main/ui/dashboard/sidebar.cljs:523, src/app/main/ui/dashboard/team.cljs:97, src/app/main/ui/dashboard/team.cljs:107, src/app/main/ui/dashboard/team.cljs:918 +msgid "labels.webhooks" +msgstr "Webhook" + +#: src/app/main/ui/workspace/sidebar/options/menus/component.cljs:140 +msgid "modals.delete-component-annotation.message" +msgstr "Sei sicuro di voler eliminare questa annotazione?" + +#: src/app/main/ui/workspace/sidebar/options/menus/component.cljs:139 +msgid "modals.delete-component-annotation.title" +msgstr "Elimina annotazione" + +#: src/app/main/ui/delete_shared.cljs:57 +msgid "modals.delete-shared-confirm.activated.scd-message" +msgid_plural "modals.delete-shared-confirm.activated.scd-message" +msgstr[0] "Questa libreria è attivata qui: " +msgstr[1] "Queste librerie sono attivate qui: " + +#: src/app/main/ui/dashboard/team.cljs:216 +msgid "modals.invite-team-member.text" +msgstr "" +"Puoi invitare membri nel team affinché possano accedere a questo file e a " +"tutti i file del team." + +#: src/app/main/ui/dashboard/sidebar.cljs:400, src/app/main/ui/dashboard/sidebar.cljs:421, src/app/main/ui/dashboard/team.cljs:421, src/app/main/ui/dashboard/team.cljs:444 +msgid "modals.leave-confirm.title" +msgstr "Lasciando il team" + +#: src/app/main/ui/delete_shared.cljs:48 +msgid "modals.move-shared-confirm.message" +msgid_plural "modals.move-shared-confirm.message" +msgstr[0] "Sei sicuro di voler spostare questa libreria?" +msgstr[1] "Sei sicuro di voler spostare queste librerie?" + +#: src/app/main/ui/delete_shared.cljs:53 +msgid "modals.move-shared-confirm.accept" +msgid_plural "modals.move-shared-confirm.accept" +msgstr[0] "Sposta" +msgstr[1] "Sposta" + +#: src/app/main/ui/static.cljs:134 +msgid "not-found.login.free" +msgstr "" +"Penpot è lo strumento di design gratuito e open-source per la collaborazione " +"tra design e codice" + +#: src/app/main/ui/auth/recovery_request.cljs:116 +msgid "not-found.login.sent-recovery-check" +msgstr "Controlla la tua email e clicca nel link per creare una nuova password." + +#: src/app/main/ui/static.cljs:148 +msgid "not-found.login.signup-free" +msgstr "Iscriviti gratuitamente" + +#: src/app/main/ui/static.cljs:149 +msgid "not-found.login.start-using" +msgstr "E inizia ad utilizzare Penpot in pochi secondi!" + +#: src/app/main/ui/static.cljs:290 +msgid "not-found.no-permission.already-requested.or-others.file" +msgstr "" +"Hai già richiesto l'accesso a questo file o ad altri file o progetti di " +"questo team." + +#: src/app/main/ui/static.cljs:296 +msgid "not-found.no-permission.already-requested.or-others.project" +msgstr "" +"Hai già richiesto l'accesso a questo progetto o ad altri progetti o file di " +"questo team." + +#: src/app/main/ui/static.cljs:295 +msgid "not-found.no-permission.already-requested.project" +msgstr "Hai già richiesto l'accesso a questo progetto." + +#: src/app/main/ui/static.cljs:302 +msgid "not-found.no-permission.done.remember" +msgstr "Ricorda che, se il proprietario lo consente, verrai invitato nel team." + +#: src/app/main/ui/static.cljs:301 +msgid "not-found.no-permission.done.success" +msgstr "La tua richiesta è stata inviata correttamente!" + +#: src/app/main/ui/static.cljs:246, src/app/main/ui/static.cljs:257 +msgid "not-found.no-permission.project-name" +msgstr "PROGETTO" + +#: src/app/main/ui/static.cljs:308 +msgid "not-found.no-permission.you-can-ask.file" +msgstr "Per accedere a questo file, puoi chiedere al proprietario del team." + +#: src/app/main/data/common.cljs:90 +msgid "notifications.by-code.maintenance" +msgstr "" +"Pausa di manutenzione: saremo offline per una breve manutenzione tra 5 " +"minuti." + +#: src/app/main/ui/dashboard/team.cljs:652 +msgid "notifications.invitation-link-copied" +msgstr "Link d'invito copiato" + +#: src/app/main/ui/onboarding/newsletter.cljs:63 +msgid "onboarding-v2.newsletter.desc" +msgstr "" +"Iscriviti alla newsletter di Penpot per rimanere aggiornato sui progressi e " +"le novità dello sviluppo del prodotto." + +#: src/app/main/ui/onboarding/newsletter.cljs:83 +msgid "onboarding-v2.newsletter.news" +msgstr "" +"Inviami notizie su Penpot (contenuti del blog, tutorial video, dirette…)." + +#: src/app/main/ui/onboarding/newsletter.cljs:71 +msgid "onboarding-v2.newsletter.updates" +msgstr "" +"Inviami aggiornamenti sul prodotto (nuove funzionalità, versioni, " +"correzioni…)." + +#: src/app/main/ui/onboarding/team_choice.cljs:254 +msgid "onboarding.choice.team-up.continue-creating-team" +msgstr "Continua creando un team" + +#: src/app/main/ui/onboarding/team_choice.cljs:194 +msgid "onboarding.choice.team-up.create-team-without-invite" +msgstr "Crea team" + +#: src/app/main/ui/onboarding/team_choice.cljs:259 +msgid "onboarding.choice.team-up.start-without-a-team-description" +msgstr "Potrai creare un team più tardi." + +#: src/app/main/ui/onboarding/questions.cljs:113 +msgid "onboarding.questions.lets-get-started" +msgstr "Iniziamo!" + +#: src/app/main/ui/onboarding/questions.cljs:88 +msgid "onboarding.questions.reasons.exploring" +msgstr "Sto solo esplorando" + +#: src/app/main/ui/onboarding/questions.cljs:91 +msgid "onboarding.questions.reasons.fit" +msgstr "Sto valutando se Penpot è adatto al mio team" + +#: src/app/main/ui/onboarding/questions.cljs:97 +msgid "onboarding.questions.reasons.testing" +msgstr "Sto testando prima del self-hosting" + +#: src/app/main/ui/onboarding/questions.cljs:407 +msgid "onboarding.questions.referer.article" +msgstr "Articolo (Blog, Post, Newsletter)" + +#: src/app/main/ui/onboarding/questions.cljs:405 +msgid "onboarding.questions.referer.search" +msgstr "Motore di ricerca (Google, Yahoo, Bing)" + +#: src/app/main/ui/onboarding/questions.cljs:349 +msgid "onboarding.questions.start-with.code" +msgstr "Generare codice partendo dal design" + +#: src/app/main/ui/onboarding/questions.cljs:406 +msgid "onboarding.questions.referer.social" +msgstr "Social Media (X, LinkedIn, Facebook, etc)" + +#: src/app/main/ui/onboarding/questions.cljs:347 +msgid "onboarding.questions.start-with.ds" +msgstr "Creare Design System" + +#: src/app/main/ui/onboarding/questions.cljs:341 +msgid "onboarding.questions.start-with.ui" +msgstr "Progettare la UI/UX di un'applicazione" + +#: src/app/main/ui/onboarding/questions.cljs:343 +msgid "onboarding.questions.start-with.wireframing" +msgstr "Wireframing" + +#: src/app/main/ui/onboarding/questions.cljs:121 +msgid "onboarding.questions.step1.question1" +msgstr "Per cosa utilizzerai Penpot?" + +#: src/app/main/ui/onboarding/questions.cljs:128 +msgid "onboarding.questions.step1.question2" +msgstr "Cosa ti ha portato su Penpot oggi?" + +#: src/app/main/ui/onboarding/questions.cljs:117 +msgid "onboarding.questions.step1.subtitle" +msgstr "" +"Facci sapere qualcosa su di te per aiutarci ad ottimizzare Penpot rispetto " +"alle tue esigenze. Le tue risposte ci aiuteranno a dare priorità a nuove " +"funzionalità e a guidarti nella giusta direzione per iniziare." + +#: src/app/main/ui/onboarding/questions.cljs:115 +msgid "onboarding.questions.step1.title" +msgstr "Aiutaci a conoscerti meglio" + +#: src/app/main/ui/onboarding/questions.cljs:196 +msgid "onboarding.questions.step2.title" +msgstr "Quale di questi strumenti utilizzi maggiormente?" + +#: src/app/main/ui/onboarding/questions.cljs:289 +msgid "onboarding.questions.step3.question1" +msgstr "Che genere di lavori fai?" + +#: src/app/main/ui/onboarding/questions.cljs:317 +msgid "onboarding.questions.step3.question3" +msgstr "Qual è la dimensione della tua azienda?" + +#: src/app/main/ui/onboarding/questions.cljs:287 +msgid "onboarding.questions.step3.title" +msgstr "Parlaci del tuo lavoro" + +#: src/app/main/ui/onboarding/questions.cljs:303 +msgid "onboarding.questions.step3.question2" +msgstr "Qual è il tuo ruolo?" + +#: src/app/main/ui/onboarding/questions.cljs:370 +msgid "onboarding.questions.step4.title" +msgstr "Da dove ti piacerebbe iniziare?" + +#: src/app/main/ui/onboarding/questions.cljs:428 +msgid "onboarding.questions.step5.title" +msgstr "Come sei venuto a conoscenza di Penpot?" + +#: src/app/main/ui/onboarding/questions.cljs:81 +msgid "onboarding.questions.use.personal" +msgstr "Personale" + +#: src/app/main/ui/onboarding/questions.cljs:79 +msgid "onboarding.questions.use.work" +msgstr "Lavoro" + +#: src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs:271 +msgid "settings.remove-color" +msgstr "Rimuovi colore" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:414 +msgid "shortcut-section.basics" +msgstr "Nozioni di base" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:423 +msgid "shortcut-section.viewer" +msgstr "Visualizzatore" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:417 +msgid "shortcut-section.workspace" +msgstr "Area di lavoro" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:59 +msgid "shortcut-subsection.general-viewer" +msgstr "Generico" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:83 +msgid "shortcuts.bold" +msgstr "Attiva/Disattiva grassetto" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:67 +msgid "shortcut-subsection.shape" +msgstr "Forme" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:69 +msgid "shortcut-subsection.tools" +msgstr "Strumenti" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:80 +msgid "shortcuts.align-top" +msgstr "Allinea in alto" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:81 +msgid "shortcuts.align-vcenter" +msgstr "Allinea al centro verticalmente" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:82 +msgid "shortcuts.artboard-selection" +msgstr "Crea una tavola da disegno a partire dalla selezione" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:84 +msgid "shortcuts.bool-difference" +msgstr "Differenza" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:102 +msgid "shortcuts.draw-ellipse" +msgstr "Ellisse" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:105 +msgid "shortcuts.draw-path" +msgstr "Tracciato" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:140 +msgid "shortcuts.move-nodes" +msgstr "Sposta nodo" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:142 +msgid "shortcuts.move-unit-left" +msgstr "Sposta a sinistra" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:148 +msgid "shortcuts.opacity-2" +msgstr "Imposta opacità al 20%" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:156 +msgid "shortcuts.open-color-picker" +msgstr "Selettore colore" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:159 +msgid "shortcuts.open-inspect" +msgstr "Vai alla sezione di ispezione" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:161 +msgid "shortcuts.open-viewer" +msgstr "Vai alla sezione interazioni del visualizzatore" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:169 +msgid "shortcuts.select-all" +msgstr "Seleziona tutto" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:178 +msgid "shortcuts.start-editing" +msgstr "Inizia a modificare" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:189 +msgid "shortcuts.toggle-focus-mode" +msgstr "Attiva/Disattiva modalità focus" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:208 +msgid "shortcuts.ungroup" +msgstr "Separa" + +#: src/app/main/ui/dashboard/libraries.cljs:46 +msgid "title.dashboard.shared-libraries" +msgstr "Librerie condivise - %s - Penpot" + +#: src/app/main/ui/dashboard/team.cljs:1074 +msgid "title.team-settings" +msgstr "Impostazioni - %s - Penpot" + +#: src/app/main/ui/viewer.cljs:570 +msgid "viewer.empty-state" +msgstr "Nessuna tavola da disegno trovata nella pagina." + +#: src/app/main/ui/viewer/header.cljs:333 +msgid "viewer.header.interactions-section" +msgstr "Interazioni (%s)" + +#: src/app/main/ui/workspace/sidebar/options/menus/align.cljs:66 +msgid "workspace.align.hright" +msgstr "Allinea a destra (%s)" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:212 +msgid "shortcuts.zoom-lense-increase" +msgstr "Aumentare lo zoom" + +#: src/app/main/ui.cljs:137 +msgid "viewer.breaking-change.message" +msgstr "Spiacenti!" + +#: src/app/main/ui/workspace/sidebar/options/menus/align.cljs:83 +msgid "workspace.align.vtop" +msgstr "Allinea in alto (%s)" + +#: src/app/main/ui/workspace/sidebar/assets.cljs +#, unused +msgid "workspace.assets.assets" +msgstr "Asset" + +#: src/app/main/ui/workspace/context_menu.cljs:606 +msgid "workspace.context-menu.grid-track.column.duplicate" +msgstr "Duplica colonna" + +#: src/app/main/ui/workspace/main_menu.cljs:243 +msgid "workspace.header.menu.disable-dynamic-alignment" +msgstr "Disattiva allineamento dinamico" + +#: src/app/main/ui/workspace/main_menu.cljs:373 +msgid "workspace.header.menu.hide-textpalette" +msgstr "Nascondi palette caratteri" + +#: src/app/main/ui/workspace/right_header.cljs:255 +msgid "workspace.header.share" +msgstr "Condividi" + +#: src/app/main/ui/workspace/right_header.cljs:128 +msgid "workspace.header.zoom-fit-all" +msgstr "Adatta zoom a tutto" + +#: src/app/main/ui/workspace/colorpicker.cljs +#, unused +msgid "workspace.libraries.colors.rgb-complementary" +msgstr "RGB Complementare" + +#: src/app/main/ui/workspace/colorpicker.cljs:382 +msgid "workspace.libraries.colors.save-color" +msgstr "Salva stile di colore" + +#: src/app/main/ui/workspace/libraries.cljs:216 +msgid "workspace.libraries.file-library" +msgstr "Libreria del file" + +#: src/app/main/ui/workspace/libraries.cljs:78, src/app/main/ui/workspace/libraries.cljs:96 +msgid "workspace.libraries.graphics" +msgstr "%s grafiche" + +#: src/app/main/ui/workspace/libraries.cljs:304 +msgid "workspace.libraries.more-templates-link" +msgstr "modelli qui" + +#: src/app/main/ui/workspace/libraries.cljs:307 +msgid "workspace.libraries.no-matches-for" +msgstr "Nessun risultato trovato per “%s”" + +#: src/app/main/ui/workspace/libraries.cljs:261 +msgid "workspace.libraries.search-shared-libraries" +msgstr "Cerca librerie condivise" + +#: src/app/main/ui/workspace/libraries.cljs:257 +msgid "workspace.libraries.shared-libraries" +msgstr "LIBRERIE CONDIVISE" + +#: src/app/main/ui/workspace/libraries.cljs:410 +msgid "workspace.libraries.update" +msgstr "Aggiorna" + +#: src/app/main/ui/workspace/libraries.cljs:485 +msgid "workspace.libraries.update.see-all-changes" +msgstr "vedi tutti i cambiamenti" + +#: src/app/main/ui/workspace/libraries.cljs:524 +msgid "workspace.libraries.updates" +msgstr "AGGIORNAMENTI" + +#: src/app/main/ui/workspace/sidebar/options/menus/blur.cljs:91 +msgid "workspace.options.blur-options.add-blur" +msgstr "Aggiungi sfocatura" + +#: src/app/main/ui/workspace/sidebar/options/menus/blur.cljs:86 +msgid "workspace.options.blur-options.title.group" +msgstr "Sfocatura di gruppo" + +#: src/app/main/ui/workspace/sidebar/options/menus/blur.cljs:112 +msgid "workspace.options.blur-options.remove-blur" +msgstr "Elimina sfocatura" + +#: src/app/main/ui/workspace/sidebar/options/menus/blur.cljs:108 +msgid "workspace.options.blur-options.toggle-blur" +msgstr "Attiva/Disattiva sfocatura" + +#: src/app/main/ui/workspace/sidebar/options/menus/component.cljs:172 +msgid "workspace.options.component.edit-annotation" +msgstr "Modifica un'annotazione" + +#: src/app/main/ui/workspace/sidebar/options/menus/component.cljs:609 +msgid "workspace.options.component.main" +msgstr "Principale" + +#: src/app/main/ui/workspace/sidebar/options/menus/constraints.cljs:141, src/app/main/ui/workspace/sidebar/options/menus/constraints.cljs:152 +msgid "workspace.options.constraints.center" +msgstr "Centro" + +#: src/app/main/ui/workspace/sidebar/options/menus/constraints.cljs:229 +msgid "workspace.options.constraints.fix-when-scrolling" +msgstr "Fisso durante lo scorrimento" + +#: src/app/main/ui/workspace/sidebar/options/menus/constraints.cljs:140 +msgid "workspace.options.constraints.leftright" +msgstr "Sinistra e Destra" + +#: src/app/main/ui/workspace/sidebar/options/menus/constraints.cljs:139 +msgid "workspace.options.constraints.right" +msgstr "Destra" + +#: src/app/main/ui/workspace/sidebar/options/menus/constraints.cljs:149 +msgid "workspace.options.constraints.top" +msgstr "Superiore" + +#: src/app/main/ui/workspace/sidebar/options.cljs:179 +msgid "workspace.options.design" +msgstr "Design" + +#: src/app/main/ui/workspace/sidebar/options/menus/exports.cljs, src/app/main/ui/inspect/exports.cljs +#, unused +msgid "workspace.options.export-multiple" +msgstr "Esporta selezione" + +#: src/app/main/ui/workspace/sidebar/options/menus/exports.cljs:195 +msgid "workspace.options.export.add-export" +msgstr "Aggiungi esportazione" + +#: src/app/main/ui/viewer/inspect/exports.cljs:186, src/app/main/ui/workspace/sidebar/options/menus/exports.cljs:236 +msgid "workspace.options.export.suffix" +msgstr "Suffisso" + +#: src/app/main/ui/exports/assets.cljs:248 +msgid "workspace.options.exporting-object-slow" +msgstr "Esportazione inaspettatamente lenta" + +#: src/app/main/ui/workspace/sidebar/options/menus/fill.cljs:150 +msgid "workspace.options.fill.add-fill" +msgstr "Aggiungi colore di riempimento" + +#: src/app/main/ui/workspace/sidebar/options/menus/fill.cljs:163 +msgid "workspace.options.fill.remove-fill" +msgstr "Elimina riempimento" + +#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs:178 +msgid "workspace.options.flows.flow" +msgstr "Flusso" + +#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs:164 +msgid "workspace.options.flows.flow-starts" +msgstr "Inizi flusso" + +#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs:154 +msgid "workspace.options.flows.remove-flow" +msgstr "Rimuovi flusso" + +#: src/app/main/ui/workspace/sidebar/options/menus/frame_grid.cljs:31 +msgid "workspace.options.grid.auto" +msgstr "Auto" + +#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs:413 +msgid "workspace.options.interaction-animation-slide" +msgstr "Scorrimento" + +#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs:680 +msgid "workspace.options.interaction-easing" +msgstr "Easing" + +#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs:41, src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs:371 +msgid "workspace.options.interaction-mouse-leave" +msgstr "Uscita del mouse" + +#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs:376 +msgid "workspace.options.interaction-open-overlay" +msgstr "Apri sovrapposizione" + +#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs:60, src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs:380 +msgid "workspace.options.interaction-open-url" +msgstr "Apri un URL" + +#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs:409 +msgid "workspace.options.interaction-pos-bottom-center" +msgstr "In basso centrato" + +#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs:406 +msgid "workspace.options.interaction-pos-top-center" +msgstr "In alto centrato" + +#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs:407 +msgid "workspace.options.interaction-pos-bottom-left" +msgstr "In basso a sinistra" + +#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs:530 +msgid "workspace.options.interaction-position" +msgstr "Posizione" + +#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs:377 +msgid "workspace.options.interaction-toggle-overlay" +msgstr "Attiva/Disattiva sovrapposizione" + +#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs:509 +msgid "workspace.options.interaction-url" +msgstr "URL" + +#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs:39, src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs:369 +msgid "workspace.options.interaction-while-pressing" +msgstr "Durante la pressione" + +#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs:735 +msgid "workspace.options.interactions.add-interaction" +msgstr "Aggiungi interazione" + +#: src/app/main/ui/workspace/sidebar/options/menus/layer.cljs:137 +msgid "workspace.options.layer-options.blend-mode.color" +msgstr "Colore" + +#: src/app/main/ui/workspace/sidebar/options/menus/layer.cljs:176, src/app/main/ui/workspace/sidebar/options/menus/layer.cljs:182 +msgid "workspace.options.layer-options.toggle-layer" +msgstr "Attiva/Disattiva visibilità livello" + +#: src/app/main/ui/workspace/sidebar/options/menus/layout_item.cljs:515 +msgid "workspace.options.layout-item.layout-item-min-w" +msgstr "Larghezza.Min" + +#: src/app/main/ui/workspace/sidebar/options/menus/layout_item.cljs +#, unused +msgid "workspace.options.layout-item.title.layout-item-min-h" +msgstr "Altezza minima" + +#: src/app/main/ui/workspace/sidebar/options/menus/layout_item.cljs +#, unused +msgid "workspace.options.layout.margin-all" +msgstr "Tutti i lati" + +#: src/app/main/ui/workspace/sidebar/options/menus/color_selection.cljs:159 +msgid "workspace.options.more-colors" +msgstr "Più colori" + +#: src/app/main/ui/workspace/sidebar/options/menus/shadow.cljs:177, src/app/main/ui/workspace/sidebar/options/menus/shadow.cljs:315 +msgid "workspace.options.shadow-options.remove-shadow" +msgstr "Rimuovi ombra" + +#: src/app/main/ui/workspace/sidebar/options/menus/shadow.cljs:173 +msgid "workspace.options.shadow-options.toggle-shadow" +msgstr "Attiva/Disattiva ombra" + +#: src/app/main/ui/workspace/sidebar/options/menus/stroke.cljs +#, unused +msgid "workspace.options.stroke-cap.square-marker" +msgstr "Marcatore quadrato" + +#: src/app/main/ui/workspace/sidebar/options/menus/frame_grid.cljs:164 +msgid "workspace.options.size" +msgstr "Dimensione" + +#: src/app/main/ui/workspace/sidebar/options/menus/measures.cljs:425 +msgid "workspace.options.size-presets" +msgstr "Dimensioni predefinite" + +#: src/app/main/ui/workspace/sidebar/options/rows/stroke_row.cljs:106 +msgid "workspace.options.stroke.mixed" +msgstr "Misto" + +#: src/app/main/ui/workspace/sidebar/options/menus/stroke.cljs:184 +msgid "workspace.options.stroke.remove-stroke" +msgstr "Rimuovi traccia" + +#: src/app/main/ui/workspace/sidebar/options/menus/text.cljs:89 +msgid "workspace.options.text-options.direction-rtl" +msgstr "RTL" + +#: src/app/main/ui/workspace/sidebar/options/menus/text.cljs:61 +msgid "workspace.options.text-options.text-align-justify" +msgstr "Giustifica (%s)" + +#: src/app/main/ui/workspace/sidebar/options/menus/text.cljs:191 +msgid "workspace.options.text-options.title" +msgstr "Testo" + +#: src/app/main/ui/workspace/sidebar/options/menus/text.cljs:190 +msgid "workspace.options.text-options.title-group" +msgstr "Testo di gruppo" + +#: src/app/main/ui/workspace/sidebar/options/menus/text.cljs:189 +msgid "workspace.options.text-options.title-selection" +msgstr "Testo della selezione" + +#: src/app/main/ui/workspace/sidebar/options/menus/measures.cljs:465 +msgid "workspace.options.width" +msgstr "Larghezza" + +#: src/app/main/ui/workspace/sidebar/options/menus/measures.cljs:523 +msgid "workspace.options.x" +msgstr "Asse X" + +#: src/app/main/ui/workspace/viewport/path_actions.cljs:167 +msgid "workspace.path.actions.add-node" +msgstr "Aggiungi nodo (%s)" + +#: src/app/main/ui/workspace/plugins.cljs:196 +msgid "workspace.plugins.error.manifest" +msgstr "Il manifesto del plugin è errato." + +#: src/app/main/data/plugins.cljs:86, src/app/main/ui/workspace/main_menu.cljs:696, src/app/main/ui/workspace/plugins.cljs:82 +msgid "workspace.plugins.error.need-editor" +msgstr "Devi essere un editor per utilizzare questo plugin" + +#: src/app/main/ui/workspace/plugins.cljs:372 +msgid "workspace.plugins.permissions-update.title" +msgstr "AGGIORNA QUESTO PLUGIN" + +#: src/app/main/ui/workspace/plugins.cljs:376 +msgid "workspace.plugins.permissions-update.warning" +msgstr "" +"Il plugin è stato modificato da quando l'hai aperto l'ultima volta. Ora " +"richiede l'accesso a:" + +#: src/app/main/ui/workspace/plugins.cljs:283 +msgid "workspace.plugins.permissions.allow-download" +msgstr "Inizia il download dei file." + +#: src/app/main/ui/workspace/plugins.cljs:276 +msgid "workspace.plugins.permissions.comment-read" +msgstr "Leggi i tuoi commenti e risposte." + +#: src/app/main/ui/workspace/plugins.cljs:442 +msgid "workspace.plugins.try-out.try" +msgstr "PROVA PLUGIN" + +#: src/app/main/ui/workspace/sidebar/options/menus/layout_container.cljs:1004, src/app/main/ui/workspace/sidebar/options/menus/layout_container.cljs:1030 +msgid "workspace.shape.menu.add-layout" +msgstr "Aggiungi layout" + +#: src/app/main/ui/workspace/sidebar/assets/common.cljs:427 +msgid "workspace.shape.menu.create-annotation" +msgstr "Crea annotazione" + +#: src/app/main/ui/workspace/context_menu.cljs:209 +msgid "workspace.shape.menu.flip-horizontal" +msgstr "Capovolgi orizzontalmente" + +#: src/app/main/ui/workspace/context_menu.cljs:205 +msgid "workspace.shape.menu.flip-vertical" +msgstr "Capovolgi verticalmente" + +#: src/app/main/ui/workspace/context_menu.cljs:342 +msgid "workspace.shape.menu.path" +msgstr "Tracciato" + +#: src/app/main/ui/workspace/sidebar/options/menus/layout_container.cljs:1022 +msgid "workspace.shape.menu.remove-layout" +msgstr "Rimuovi layout" + +#: src/app/main/ui/workspace/context_menu.cljs:235 +msgid "workspace.shape.menu.rename" +msgstr "Rinomina" + +#: src/app/main/ui/workspace/context_menu.cljs:175 +msgid "workspace.shape.menu.select-layer" +msgstr "Seleziona livello" + +#: src/app/main/ui/workspace/sidebar/layers.cljs:524, src/app/main/ui/workspace/sidebar.cljs:110, src/app/main/ui/workspace/sidebar.cljs:114, src/app/main/ui/workspace/sidebar.cljs:123 +msgid "workspace.sidebar.layers" +msgstr "Livelli" + +#: src/app/main/ui/workspace/sidebar/layers.cljs:307, src/app/main/ui/workspace/sidebar/layers.cljs:340 +msgid "workspace.sidebar.layers.frames" +msgstr "Tavole da disegno" + +#: src/app/main/ui/workspace/sidebar/layers.cljs:308, src/app/main/ui/workspace/sidebar/layers.cljs:354 +msgid "workspace.sidebar.layers.groups" +msgstr "Gruppi" + +#: src/app/main/ui/workspace/sidebar/layers.cljs:313, src/app/main/ui/workspace/sidebar/layers.cljs:424 +msgid "workspace.sidebar.layers.shapes" +msgstr "Forme" + +#: src/app/main/ui/workspace/sidebar/layers.cljs:290 +msgid "workspace.sidebar.layers.search" +msgstr "Cerca livelli" + +#: src/app/main/ui/workspace/sidebar/layers.cljs:311, src/app/main/ui/workspace/sidebar/layers.cljs:396 +msgid "workspace.sidebar.layers.texts" +msgstr "Testi" + +#: src/app/main/ui/viewer/inspect/attributes/svg.cljs:56, src/app/main/ui/workspace/sidebar/options/menus/svg_attrs.cljs:91 +msgid "workspace.sidebar.options.svg-attrs.title" +msgstr "Attributi SVG importati" + +#: src/app/main/ui/workspace/sidebar/sitemap.cljs:229 +msgid "workspace.sidebar.sitemap.add-page" +msgstr "Aggiungi pagina" + +#: src/app/main/ui/workspace/left_header.cljs:91 +msgid "workspace.sitemap" +msgstr "Sitemap" + +#: src/app/main/ui/workspace/tokens/modals/themes.cljs:47 +msgid "workspace.token.create-new-theme" +msgstr "Crea ora il tuo prima tema." + +#: src/app/main/ui/workspace/tokens/modals/themes.cljs:147 +msgid "workspace.token.delete-theme-title" +msgstr "Elimina tema" + +#: src/app/main/ui/workspace/tokens/modals/themes.cljs:302 +msgid "workspace.token.edit-theme-title" +msgstr "Modifica tema" + +#: src/app/main/ui/workspace/tokens/form.cljs:361 +msgid "workspace.token.edit-token" +msgstr "Modifica token" + +#: src/app/main/ui/workspace/tokens/modals/themes.cljs:133 +msgid "workspace.token.num-sets" +msgstr "%s set" + +#: src/app/main/ui/workspace/tokens/sidebar.cljs:66 +msgid "workspace.token.original-value" +msgstr "Valore originale: " + +#: src/app/main/ui/workspace/tokens/modals/themes.cljs:208 +msgid "workspace.token.save-theme" +msgstr "Salva tema" + +#: src/app/main/ui/workspace/tokens/modals/themes.cljs +#, unused +msgid "workspace.token.theme-name" +msgstr "Tema %s" + +#: src/app/main/ui/workspace/tokens/modals/themes.cljs:39, src/app/main/ui/workspace/tokens/modals/themes.cljs:84 +msgid "workspace.token.themes" +msgstr "Temi" + +#: src/app/main/ui/workspace/palette.cljs:165, src/app/main/ui/workspace/palette.cljs:166 +msgid "workspace.toolbar.color-palette" +msgstr "Palette colori (%s)" + +#: src/app/main/ui/workspace/right_header.cljs:235, src/app/main/ui/workspace/right_header.cljs:236 +msgid "workspace.toolbar.comments" +msgstr "Commenti (%s)" + +#: src/app/main/ui/workspace/top_toolbar.cljs:181, src/app/main/ui/workspace/top_toolbar.cljs:182 +msgid "workspace.toolbar.curve" +msgstr "Curva (%s)" + +#: src/app/main/ui/workspace/sidebar/history.cljs:331 +msgid "workspace.undo.empty" +msgstr "Non ci sono cambiamenti nella cronologia al momento" + +#: src/app/main/ui/workspace/sidebar/history.cljs:110 +msgid "workspace.undo.entry.multiple.color" +msgstr "colori" + +#: src/app/main/ui/workspace/sidebar/history.cljs:113 +msgid "workspace.undo.entry.multiple.frame" +msgstr "tavole da disegno" + +#: src/app/main/ui/workspace/sidebar/history.cljs:115 +msgid "workspace.undo.entry.multiple.media" +msgstr "asset grafici" + +#: src/app/main/ui/workspace/sidebar/history.cljs:121 +msgid "workspace.undo.entry.multiple.text" +msgstr "testi" + +#: src/app/main/ui/workspace/sidebar/versions.cljs:193 +msgid "workspace.versions.autosaved.entry" +msgstr "%s versioni di salvataggio automatico" + +#: src/app/main/ui/workspace/sidebar/versions.cljs:224 +msgid "workspace.versions.button.pin" +msgstr "Fissa versione" + +#: src/app/main/ui/workspace/sidebar/versions.cljs:345, src/app/main/ui/workspace/sidebar/versions.cljs:347 +msgid "workspace.versions.button.save" +msgstr "Salva versione" + +#: src/app/main/ui/workspace/sidebar/versions.cljs:354 +msgid "workspace.versions.empty" +msgstr "Non ci sono ancora versioni" + +#: src/app/main/ui/workspace/sidebar/versions.cljs:190 +msgid "workspace.versions.expand-snapshot" +msgstr "Espandi istantanee" + +#: src/app/main/ui/workspace/sidebar/versions.cljs:327 +msgid "workspace.versions.filter.all" +msgstr "Tutte le versioni" + +#: src/app/main/ui/workspace/sidebar/versions.cljs:326 +msgid "workspace.versions.filter.label" +msgstr "Filtro versioni" + +#: src/app/main/ui/workspace/sidebar/versions.cljs:328 +msgid "workspace.versions.filter.mine" +msgstr "La mie versioni" + +#: src/app/main/ui/workspace/sidebar/versions.cljs:334 +msgid "workspace.versions.filter.user" +msgstr "Versioni di %s" + +#: src/app/main/ui/onboarding/team_choice.cljs:257 +msgid "onboarding.choice.team-up.start-without-a-team" +msgstr "Inizia senza un team" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:94 +msgid "shortcuts.create-component" +msgstr "Crea componente" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:110 +msgid "shortcuts.export-shapes" +msgstr "Esporta forme" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:171 +msgid "shortcuts.select-parent-layer" +msgstr "Seleziona livello genitore" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:174 +msgid "shortcuts.show-pixel-grid" +msgstr "Mostra/Nascondi griglia pixel" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:175 +msgid "shortcuts.show-shortcuts" +msgstr "Mostra/Nascondi scorciatoie" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:173 +msgid "shortcuts.separate-nodes" +msgstr "Separa nodi" + +#: src/app/main/ui/viewer/interactions.cljs:315 +msgid "viewer.header.show-interactions-on-click" +msgstr "Mostra interazioni al click" + +#: src/app/main/ui/workspace/colorpicker.cljs:234 +msgid "workspace.libraries.colors.rgba" +msgstr "RGBA" + +#: src/app/main/ui/workspace/sidebar/options.cljs:187, src/app/main/ui/workspace/sidebar/options.cljs:190 +msgid "workspace.options.inspect" +msgstr "Ispeziona" + +#: src/app/main/ui/workspace/sidebar/options/menus/frame_grid.cljs:236 +msgid "workspace.options.grid.params.type.right" +msgstr "Destra" + +#: src/app/main/ui/workspace/sidebar/options/menus/layout.cljs +#, unused +msgid "workspace.options.layout.right" +msgstr "A destra" + +#: src/app/main/ui/workspace/sidebar/options/menus/layout.cljs +#, unused +msgid "workspace.options.layout.space-around" +msgstr "spazio intorno" + +#: src/app/main/ui/workspace/sidebar/options/menus/layout.cljs +#, unused +msgid "workspace.options.layout.space-between" +msgstr "spazio tra" + +#: src/app/main/ui/workspace/sidebar/options/menus/typography.cljs:184 +msgid "workspace.options.recent-fonts" +msgstr "Recenti" + +#: src/app/main/ui/workspace/context_menu.cljs:286 +msgid "workspace.shape.menu.create-artboard-from-selection" +msgstr "Tavola da disegno da selezione" + +#: src/app/main/ui/workspace/context_menu.cljs:140 +msgid "workspace.shape.menu.copy" +msgstr "Copia" + +#: src/app/main/ui/workspace/sidebar/history.cljs:114 +msgid "workspace.undo.entry.multiple.group" +msgstr "gruppi" + +#: src/app/main/ui/workspace/sidebar/history.cljs:146 +msgid "workspace.undo.entry.move" +msgstr "Oggetti spostati" + +#: src/app/main/ui/workspace/sidebar/history.cljs:111 +msgid "workspace.undo.entry.multiple.component" +msgstr "componenti" + +#: src/app/main/ui/settings/access_tokens.cljs:134 +msgid "dashboard.access-tokens.expiration-60-days" +msgstr "60 giorni" + +#: src/app/main/ui/dashboard/fonts.cljs:445 +msgid "dashboard.fonts.empty-placeholder-viewer-sub" +msgstr "" +"Quando un membro del progetto carica un font personalizzato, verrà mostrato " +"qui." + +#: src/app/main/ui/dashboard/team.cljs:1043 +msgid "dashboard.webhooks.empty.add-one" +msgstr "Premi il bottone \"Aggiungi webhook\" per aggiungerne uno." + +#: src/app/main/ui/dashboard/team.cljs:1042 +msgid "dashboard.webhooks.empty.no-webhooks" +msgstr "Nessun webhook presente." + +#: src/app/main/data/users.cljs:731, src/app/main/ui/auth/login.cljs:102, src/app/main/ui/auth/login.cljs:110 +msgid "errors.profile-blocked" +msgstr "Questo profilo è bloccato" + +#, unused +msgid "errors.validation" +msgstr "Validazione errore" + +#: src/app/main/ui/static.cljs:329 +msgid "not-found.desc-message.doesnt-exist" +msgstr "Questa pagina non esiste" + +#: src/app/main/ui/static.cljs:289 +msgid "not-found.no-permission.already-requested.file" +msgstr "Hai già richiesto l'accesso a questo file." + +#: src/app/main/ui/static.cljs:307 +msgid "not-found.no-permission.file" +msgstr "Non hai accesso a questo file." + +#: src/app/main/ui/static.cljs:317 +msgid "not-found.no-permission.you-can-ask.project" +msgstr "Per accedere a questo progetto, puoi chiedere al proprietario del team." + +#: src/app/main/ui/onboarding/questions.cljs:94 +msgid "onboarding.questions.reasons.alternative" +msgstr "Sto cercando un'alternativa a Figma, XD, ecc" + +#: src/app/main/ui/onboarding/questions.cljs:345 +msgid "onboarding.questions.start-with.prototyping" +msgstr "Prototipazione" + +#: src/app/main/ui/viewer/inspect/exports.cljs:155, src/app/main/ui/workspace/sidebar/options/menus/component.cljs:632, src/app/main/ui/workspace/sidebar/options/menus/constraints.cljs:137, src/app/main/ui/workspace/sidebar/options/menus/constraints.cljs:148, src/app/main/ui/workspace/sidebar/options/menus/exports.cljs:204, src/app/main/ui/workspace/sidebar/options/menus/fill.cljs:161, src/app/main/ui/workspace/sidebar/options/menus/measures.cljs:470, src/app/main/ui/workspace/sidebar/options/menus/measures.cljs:476, src/app/main/ui/workspace/sidebar/options/menus/measures.cljs:494, src/app/main/ui/workspace/sidebar/options/menus/measures.cljs:500, src/app/main/ui/workspace/sidebar/options/menus/measures.cljs:526, src/app/main/ui/workspace/sidebar/options/menus/measures.cljs:537, src/app/main/ui/workspace/sidebar/options/menus/measures.cljs:554, src/app/main/ui/workspace/sidebar/options/menus/measures.cljs:569, src/app/main/ui/workspace/sidebar/options/menus/measures.cljs:576, src/app/main/ui/workspace/sidebar/options/menus/shadow.cljs:312, src/app/main/ui/workspace/sidebar/options/menus/stroke.cljs:182, src/app/main/ui/workspace/sidebar/options/menus/typography.cljs:378, src/app/main/ui/workspace/sidebar/options/menus/typography.cljs:395, src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs:248, src/app/main/ui/workspace/sidebar/options/rows/stroke_row.cljs:172 +msgid "settings.multiple" +msgstr "Misto" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:90 +msgid "shortcuts.bring-forward" +msgstr "Porta avanti" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:143 +msgid "shortcuts.move-unit-right" +msgstr "Sposta a destra" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:141 +msgid "shortcuts.move-unit-down" +msgstr "Sposta in basso" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:172 +msgid "shortcuts.select-prev" +msgstr "Seleziona livello precedente" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:182 +msgid "shortcuts.text-align-justify" +msgstr "Allinea giustificato" + +#: src/app/main/ui/dashboard/grid.cljs:138, src/app/main/ui/dashboard/grid.cljs:170, src/app/main/ui/workspace/sidebar/assets/colors.cljs:487, src/app/main/ui/workspace/sidebar/assets.cljs:147 +msgid "workspace.assets.colors" +msgstr "Colori" + +#: src/app/main/ui/workspace/context_menu.cljs:607 +msgid "workspace.context-menu.grid-track.column.add-before" +msgstr "Aggiungi 1 colonna a sinistra" + +#: src/app/main/ui/workspace/main_menu.cljs:803 +msgid "workspace.header.menu.option.edit" +msgstr "Modifica" + +#: src/app/main/ui/workspace/main_menu.cljs:792 +msgid "workspace.header.menu.option.file" +msgstr "File" + +#: src/app/main/ui/workspace/sidebar/options/menus/text.cljs:311 +msgid "workspace.libraries.text.multiple-typography" +msgstr "Elementi tipografici multipli" + +#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs:745 +msgid "workspace.options.add-interaction" +msgstr "Clicca il bottone + per aggiungere interazioni." + +#: src/app/main/ui/workspace/sidebar/options/menus/exports.cljs:207, src/app/main/ui/workspace/sidebar/options/menus/exports.cljs:242 +msgid "workspace.options.export.remove-export" +msgstr "Rimuovi esportazione" + +#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs:464, src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs:465, src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs:470, src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs:669, src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs:671, src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs:675 +msgid "workspace.options.interaction-ms" +msgstr "ms" + +#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs +#, unused +msgid "workspace.options.interaction-out" +msgstr "Fuori" + +#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs:422 +msgid "workspace.options.interaction-easing-ease" +msgstr "Ease" + +#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs:375 +msgid "workspace.options.interaction-navigate-to" +msgstr "Naviga verso" + +#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs:408 +msgid "workspace.options.interaction-pos-bottom-right" +msgstr "In basso a destra" + +#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs:402 +msgid "workspace.options.interaction-pos-manual" +msgstr "Manuale" + +#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs:403 +msgid "workspace.options.interaction-pos-center" +msgstr "Centrato" + +#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs +#, unused +msgid "workspace.options.interactions.remove-interaction" +msgstr "Rimuovi interazione" + +#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs:404 +msgid "workspace.options.interaction-pos-top-left" +msgstr "In alto a sinistra" + +#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs:405 +msgid "workspace.options.interaction-pos-top-right" +msgstr "In alto a destra" + +#: src/app/main/ui/workspace/sidebar/options/menus/layer.cljs:126 +msgid "workspace.options.layer-options.blend-mode.color-burn" +msgstr "Colore brucia" + +#: src/app/main/ui/viewer/inspect/attributes/shadow.cljs:40, src/app/main/ui/workspace/sidebar/options/menus/shadow.cljs:199, src/app/main/ui/workspace/sidebar/options/menus/shadow.cljs:201 +msgid "workspace.options.shadow-options.blur" +msgstr "Sfoca" + +#: src/app/main/ui/workspace/sidebar/options/menus/measures.cljs:669 +msgid "workspace.options.show-in-viewer" +msgstr "Mostra in modalità visualizzazione" + +#: src/app/main/ui/workspace/sidebar/options/rows/stroke_row.cljs:129 +msgid "workspace.options.stroke-cap.circle-marker-short" +msgstr "Cerchio" + +#: src/app/main/ui/workspace/sidebar/options/menus/stroke.cljs +#, unused +msgid "workspace.options.stroke-cap.triangle-arrow" +msgstr "Freccia triangolo" + +#: src/app/main/ui/workspace/sidebar/options/menus/stroke.cljs:171 +msgid "workspace.options.stroke.add-stroke" +msgstr "Aggiungi colore traccia" + +#: src/app/main/ui/workspace/sidebar/options/menus/text.cljs:113 +msgid "workspace.options.text-options.align-middle" +msgstr "Allinea verticalmente al centro" + +#: src/app/main/ui/workspace/context_menu.cljs:346, src/app/main/ui/workspace/sidebar/options/menus/bool.cljs:75 +msgid "workspace.shape.menu.difference" +msgstr "Differenza" + +#: src/app/main/ui/workspace/tokens/sidebar.cljs:194, src/app/main/ui/workspace/tokens/sidebar.cljs:210 +msgid "workspace.token.create-one" +msgstr "Creane uno." + +#: src/app/main/ui/workspace/tokens/theme_select.cljs:72 +msgid "workspace.token.edit-themes" +msgstr "Modifica temi" + +#: src/app/main/ui/workspace/tokens/modals/themes.cljs:318 +msgid "workspace.token.set-selection-theme" +msgstr "" +"Definisci quali set token dovrebbe essere usati come parte di questo tema:" + +#: src/app/main/ui/workspace/tokens/sets.cljs:172 +msgid "workspace.token.select-set" +msgstr "Seleziona set." + +#: src/app/main/ui/workspace/sidebar.cljs:117, src/app/main/ui/workspace/sidebar.cljs:126 +msgid "workspace.toolbar.assets" +msgstr "Asset" + +#: src/app/main/ui/workspace/sidebar/versions.cljs:187 +msgid "workspace.versions.autosaved.version" +msgstr "Salvataggio automatico %s" + +#: src/app/main/ui/workspace/sidebar/versions.cljs:219 +msgid "workspace.versions.button.restore" +msgstr "Ripristina versione" + +#: src/app/main/ui/workspace/sidebar/versions.cljs:283 +msgid "workspace.versions.restore-warning" +msgstr "Vuoi ripristinare questa versione?" + +#: src/app/main/ui/workspace/sidebar/versions.cljs:340 +msgid "workspace.versions.loading" +msgstr "Caricamento…" + +#: src/app/main/ui/auth/login.cljs:290 +msgid "auth.login-account-title" +msgstr "Accedi al mio account" + +#, unused +msgid "auth.terms-privacy-agreement" +msgstr "" +"Quando crei un nuovo account, accetti i nostri termini di servizio e la " +"politica sulla privacy." + +#: src/app/main/errors.cljs:233 +msgid "errors.team-feature-mismatch" +msgstr "Rilevata funzione incompatibile '%s'" + +#: src/app/main/ui/dashboard/team.cljs:830, src/app/main/ui/dashboard/team.cljs:989 +msgid "errors.webhooks.ssl-validation" +msgstr "Errore nella validazione SSL." + +#: src/app/main/ui/workspace/colorpicker.cljs:226 +msgid "media.solid" +msgstr "Solido" + +#: src/app/main/ui/settings/access_tokens.cljs:125 +msgid "modals.create-access-token.name.label" +msgstr "Nome" + +#: src/app/main/ui/settings/access_tokens.cljs:127 +msgid "modals.create-access-token.name.placeholder" +msgstr "Il nome può aiutare a capire a cosa serve il token" + +#: src/app/main/ui/settings/access_tokens.cljs:131 +msgid "modals.create-access-token.expiration-date.label" +msgstr "Data di scadenza" + +#: src/app/main/ui/dashboard/team.cljs:979 +msgid "modals.delete-webhook.accept" +msgstr "Elimina webhook" + +#: src/app/main/ui/dashboard/team.cljs:875 +msgid "modals.edit-webhook.title" +msgstr "Modifica webhook" + +#: src/app/main/ui/dashboard/change_owner.cljs:58 +msgid "modals.leave-and-reassign.forbidden" +msgstr "" +"Non puoi lasciare il team se non c'è un altro membro da promuovere a " +"proprietario. Potresti voler eliminare il team." + +#: src/app/main/ui/delete_shared.cljs:43 +msgid "modals.move-shared-confirm.title" +msgid_plural "modals.move-shared-confirm.title" +msgstr[0] "Sposta libreria" +msgstr[1] "Sposta librerie" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:177 +msgid "shortcuts.snap-pixel-grid" +msgstr "Aggancia alla griglia pixel" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:192 +msgid "shortcuts.toggle-history" +msgstr "Attiva/Disattiva cronologia" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:193 +msgid "shortcuts.toggle-layers" +msgstr "Attiva/Disattiva livelli" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:195 +msgid "shortcuts.toggle-layout-grid" +msgstr "Aggiungi/Rimuovi grid layout" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:197 +msgid "shortcuts.toggle-lock-size" +msgstr "Blocca proporzioni" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:198 +msgid "shortcuts.toggle-rulers" +msgstr "Mostra/Nascondi righelli" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:213 +msgid "shortcuts.zoom-selected" +msgstr "Zoom su selezione" + +#: src/app/main/ui/auth/verify_token.cljs:67, src/app/main/ui/auth.cljs:34 +msgid "title.default" +msgstr "Penpot - Libertà di design per i team" + +#: src/app/main/ui/settings/access_tokens.cljs:281 +msgid "title.settings.access-tokens" +msgstr "Profilo - Token di accesso" + +#: src/app/main/ui/settings/password.cljs:103 +msgid "title.settings.password" +msgstr "Password - Penpot" + +#: src/app/main/ui/dashboard/team.cljs:524 +msgid "title.team-members" +msgstr "Membri - %s - Penpot" + +#: src/app/main/ui/dashboard/team.cljs:1027 +msgid "title.team-webhooks" +msgstr "Webhook - %s - Penpot" + +#: src/app/main/ui/workspace.cljs:198 +msgid "title.workspace" +msgstr "%s - Penpot" + +#: src/app/main/ui/viewer/interactions.cljs:296 +msgid "viewer.header.dont-show-interactions" +msgstr "Non mostrare le interazioni" + +#: src/app/main/ui/workspace/sidebar/options/menus/align.cljs:58 +msgid "workspace.align.hcenter" +msgstr "Allinea orizzontalmente al centro (%s)" + +#: src/app/main/ui/workspace/sidebar/options/menus/align.cljs:74 +msgid "workspace.align.hdistribute" +msgstr "Distribuisci spaziatura orizzontale (%s)" + +#: src/app/main/ui/workspace/sidebar/options/menus/align.cljs:50 +msgid "workspace.align.hleft" +msgstr "Allinea a sinistra (%s)" + +#: src/app/main/ui/workspace/sidebar/options/menus/align.cljs:99 +msgid "workspace.align.vbottom" +msgstr "Allinea in basso (%s)" + +#: src/app/main/ui/workspace/sidebar/assets/colors.cljs:255, src/app/main/ui/workspace/sidebar/assets/components.cljs:580, src/app/main/ui/workspace/sidebar/assets/graphics.cljs:428, src/app/main/ui/workspace/sidebar/assets/typographies.cljs:452 +msgid "workspace.assets.group" +msgstr "Gruppo" + +#: src/app/main/ui/workspace/sidebar/assets/groups.cljs:137 +msgid "workspace.assets.group-name" +msgstr "Nome gruppo" + +#: src/app/main/ui/workspace/sidebar/assets/graphics.cljs:384, src/app/main/ui/workspace/sidebar/assets.cljs:143 +msgid "workspace.assets.graphics" +msgstr "Grafiche" + +#, unused +msgid "workspace.assets.open-library" +msgstr "Apri file libreria" + +#: src/app/main/ui/workspace/sidebar/assets/groups.cljs:128 +msgid "workspace.assets.rename-group" +msgstr "Rinomina gruppo" + +#: src/app/main/ui/workspace/context_menu.cljs:610 +msgid "workspace.context-menu.grid-track.column.delete-shapes" +msgstr "Elimina colonna e forme" + +#: src/app/main/ui/workspace/header.cljs +#, unused +msgid "workspace.header.menu.disable-scale-text" +msgstr "Disattiva ridimensionamento testo" + +#: src/app/main/ui/workspace/main_menu.cljs:212 +msgid "workspace.header.menu.disable-snap-ruler-guides" +msgstr "Disattiva allineamento alle guide righello" + +#: src/app/main/ui/workspace/main_menu.cljs:198 +msgid "workspace.header.menu.enable-scale-content" +msgstr "Attiva ridimensionamento proporzionale" + +#: src/app/main/ui/workspace/main_menu.cljs:197 +msgid "workspace.header.menu.disable-scale-content" +msgstr "Disattiva ridimensionamento proporzionale" + +#: src/app/main/ui/workspace/main_menu.cljs:342 +msgid "workspace.header.menu.hide-guides" +msgstr "Nascondi guide" + +#: src/app/main/ui/workspace/main_menu.cljs:213 +msgid "workspace.header.menu.enable-snap-ruler-guides" +msgstr "Allinea alle guide righello" + +#: src/app/main/ui/workspace/main_menu.cljs:388 +msgid "workspace.header.menu.hide-artboard-names" +msgstr "Nascondi nomi delle tavole da disegno" + +#: src/app/main/ui/viewer/header.cljs:98, src/app/main/ui/workspace/right_header.cljs:125 +msgid "workspace.header.reset-zoom" +msgstr "Reimposta" + +#: src/app/main/ui/workspace/main_menu.cljs:283 +msgid "workspace.header.menu.toggle-light-theme" +msgstr "Passa al tema chiaro" + +#: src/app/main/ui/workspace/main_menu.cljs:457 +msgid "workspace.header.menu.undo" +msgstr "Annulla" + +#: src/app/main/ui/workspace/header.cljs +#, unused +msgid "workspace.header.save-error" +msgstr "Errore durante il salvataggio" + +#: src/app/main/ui/workspace/right_header.cljs:57 +msgid "workspace.header.saved" +msgstr "Salvato" + +#: src/app/main/ui/workspace/right_header.cljs:260 +msgid "workspace.header.viewer" +msgstr "Modalità di visualizzazione (%s)" + +#: src/app/main/ui/workspace/viewport/grid_layout_editor.cljs:62 +msgid "workspace.layout_grid.editor.top-bar.locate" +msgstr "Individua" + +#: src/app/main/ui/workspace/libraries.cljs:81, src/app/main/ui/workspace/libraries.cljs:100 +msgid "workspace.libraries.colors" +msgstr "%s colori" + +#: src/app/main/ui/workspace/colorpicker.cljs +#, unused +msgid "workspace.libraries.colors.hsv" +msgstr "HSV" + +#: src/app/main/ui/workspace/viewport/grid_layout_editor.cljs:65 +msgid "workspace.layout_grid.editor.top-bar.done" +msgstr "Fatto" + +#: src/app/main/ui/workspace/libraries.cljs:291 +msgid "workspace.libraries.loading" +msgstr "Caricamento…" + +#: src/app/main/ui/workspace/libraries.cljs:283 +msgid "workspace.libraries.shared-library-btn" +msgstr "Connetti libreria" + +#: src/app/main/ui/workspace/libraries.cljs:250 +msgid "workspace.libraries.unlink-library-btn" +msgstr "Disconnetti libreria" + +#: src/app/main/ui/viewer/inspect/annotation.cljs:19, src/app/main/ui/workspace/sidebar/options/menus/component.cljs:181 +msgid "workspace.options.component.annotation" +msgstr "Annotazione" + +#: src/app/main/ui/workspace/sidebar/options/menus/constraints.cljs:138 +msgid "workspace.options.constraints.left" +msgstr "Sinistra" + +#: src/app/main/ui/exports/assets.cljs:245 +msgid "workspace.options.exporting-object-error" +msgstr "Esportazione fallita" + +#: src/app/main/ui/workspace/sidebar/options/menus/frame_grid.cljs:320 +msgid "workspace.options.guides.title" +msgstr "Guide" + +#: src/app/main/ui/workspace/sidebar/options/menus/layer.cljs:124 +msgid "workspace.options.layer-options.blend-mode.darken" +msgstr "Scurisci" + +#: src/app/main/ui/workspace/sidebar/options/menus/layer.cljs:138 +msgid "workspace.options.layer-options.blend-mode.luminosity" +msgstr "Luminosità" + +#: src/app/main/ui/workspace/sidebar/options/menus/layer.cljs:129 +msgid "workspace.options.layer-options.blend-mode.color-dodge" +msgstr "Colore scherma" + +#: src/app/main/ui/workspace/context_menu.cljs:496, src/app/main/ui/workspace/sidebar/options/menus/layout_container.cljs:764, src/app/main/ui/workspace/sidebar/options/menus/layout_container.cljs:1052 +msgid "workspace.shape.menu.delete" +msgstr "Elimina" + +#: src/app/main/ui/settings/access-tokens.cljs +#, unused +msgid "dashboard.access-tokens.create-success" +msgstr "Token di accesso creato con successo." + +#: src/app/main/ui/settings/access_tokens.cljs:143 +msgid "dashboard.access-tokens.token-will-expire" +msgstr "Il token scadrà il %s" + +#: src/app/main/ui/settings/access_tokens.cljs:187 +msgid "dashboard.access-tokens.personal.description" +msgstr "" +"I token di accesso personali funzionano come alternativa al nostro sistema " +"di autenticazione login/password e può essere usato per consentire ad " +"un'applicazione di accedere alle API di Penpot interne" + +#: src/app/main/ui/dashboard/fonts.cljs:188 +#, markdown +msgid "dashboard.fonts.warning-text" +msgstr "" +"Abbiamo rilevato un possibile problema nei tuoi font relativo alle metriche " +"verticali per diversi sistemi operativi. Per verificarlo, puoi utilizzare " +"servizi per le metriche verticali dei font come [questo](https://vertical-" +"metrics.netlify.app/). Inoltre, ti consigliamo di utilizzare " +"[Transfonter](https://transfonter.org/) per generare webfont e correggere " +"errori. " + +#: src/app/main/ui/dashboard/team.cljs:899 +msgid "dashboard.webhooks.active" +msgstr "È attivo" + +#: src/app/main/ui/dashboard/team.cljs:923 +msgid "dashboard.webhooks.create" +msgstr "Crea webhook" + +#: src/app/main/ui/dashboard/team.cljs:813 +msgid "dashboard.webhooks.create.success" +msgstr "Webhook creato con successo." + +#: src/app/main/ui/dashboard/team.cljs:920 +msgid "dashboard.webhooks.description" +msgstr "" +"I webhook sono un modo semplice per consentire ad altri siti web e app di " +"essere notificati quando si verificano determinati eventi su Penpot. " +"Invieremo una richiesta POST a ciascuno degli URL che fornisci." + +#, unused +msgid "dashboard.webhooks.update.success" +msgstr "Webhook aggiornato con successo." + +#: src/app/main/ui/workspace/plugins.cljs:336, src/app/main/ui/workspace/plugins.cljs:390 +msgid "ds.confirm-allow" +msgstr "Acconsenti" + +#: src/app/main/ui/auth/register.cljs, src/app/main/ui/dashboard/team_form.cljs, src/app/main/ui/onboarding/team_choice.cljs, src/app/main/ui/setti ngs/access_tokens.cljs, src/app/main/ui/settings/feedback.cljs, src/app/main/ui/settings/profile.cljs, src/app/main/ui/workspace/sidebar/assets.cljs +#, unused +msgid "errors.field-max-length" +msgstr "Deve contenere al massimo 1 carattere." + +#: src/app/main/ui/auth/register.cljs, src/app/main/ui/auth/login.cljs, src/app/main/ui/auth/recovery_request.cljs +#, unused +msgid "errors.invalid-email" +msgstr "Inserisci una email valida" + +#: src/app/main/ui/dashboard/team.cljs:986 +msgid "errors.webhooks.last-delivery" +msgstr "Errore nell'ultimo invio." + +#: src/app/main/ui/dashboard/team.cljs:826 +msgid "errors.webhooks.unexpected" +msgstr "Errore inaspettato durante la validazione" + +#: src/app/main/ui/viewer/inspect/right_sidebar.cljs:152 +msgid "inspect.empty.help" +msgstr "" +"Per ulteriori informazioni su l'ispezione, visita il centro di supporto di " +"Penpot" + +#: src/app/main/ui/static.cljs:61 +msgid "labels.copyright" +msgstr "Kaleidos @2024" + +#: src/app/main/ui/static.cljs:55, src/app/main/ui/static.cljs:133 +msgid "labels.login" +msgstr "Accesso" + +#, unused +msgid "labels.ok" +msgstr "Ok" + +#: src/app/main/ui/auth/verify_token.cljs:97, src/app/main/ui/dashboard/grid.cljs:104, src/app/main/ui/dashboard/grid.cljs:124, src/app/main/ui/dashboard/import.cljs:253, src/app/main/ui/dashboard/placeholder.cljs:52, src/app/main/ui/ds/product/loader.cljs:52, src/app/main/ui/exports/files.cljs:62, src/app/main/ui/viewer.cljs:637, src/app/main/ui/workspace.cljs:129 +msgid "labels.loading" +msgstr "Caricamento…" + +#: src/app/main/ui/onboarding/questions.cljs:100, src/app/main/ui/onboarding/questions.cljs:175, src/app/main/ui/onboarding/questions.cljs:251, src/app/main/ui/onboarding/questions.cljs:261, src/app/main/ui/onboarding/questions.cljs:351, src/app/main/ui/onboarding/questions.cljs:408 +msgid "labels.other-short" +msgstr "Altro" + +#: src/app/main/ui/onboarding/questions.cljs:140, src/app/main/ui/onboarding/questions.cljs:209, src/app/main/ui/onboarding/questions.cljs:298, src/app/main/ui/onboarding/questions.cljs:312, src/app/main/ui/onboarding/questions.cljs:383, src/app/main/ui/onboarding/questions.cljs:439 +msgid "labels.other" +msgstr "Altro (specifica)" + +#: src/app/main/ui/onboarding/questions.cljs:51 +msgid "labels.previous" +msgstr "Precedente" + +#: src/app/main/ui/onboarding/questions.cljs:245 +msgid "labels.product-design" +msgstr "Design del prodotto o UX" + +#: src/app/main/ui/onboarding/questions.cljs:250 +msgid "labels.product-management" +msgstr "Gestione del prodotto" + +#: src/app/main/ui/workspace.cljs +#, unused +msgid "labels.reload-file" +msgstr "Ricarica file" + +#: src/app/main/ui/onboarding/questions.cljs:85, src/app/main/ui/onboarding/questions.cljs:244, src/app/main/ui/onboarding/questions.cljs:255, src/app/main/ui/onboarding/questions.cljs:265 +msgid "labels.select-option" +msgstr "Seleziona opzione" + +#: src/app/main/ui/viewer/header.cljs:205 +msgid "labels.share" +msgstr "Condividi" + +#: src/app/main/ui/onboarding/questions.cljs:247 +msgid "labels.student-teacher" +msgstr "Studente o docente" + +#: src/app/main/ui/onboarding/questions.cljs:167 +msgid "labels.sketch" +msgstr "Sketch" + +#: src/app/main/ui/onboarding/questions.cljs:56 +msgid "labels.start" +msgstr "Inizia" + +#: src/app/main/ui/onboarding/questions.cljs:256 +msgid "labels.team-leader" +msgstr "Capo del team" + +#: src/app/main/ui/onboarding/questions.cljs:257 +msgid "labels.team-member" +msgstr "Membro del team" + +#: src/app/main/ui/workspace/libraries.cljs:189 +msgid "modals.publish-empty-library.accept" +msgstr "Pubblica" + +#: src/app/main/ui/workspace/libraries.cljs:188 +msgid "modals.publish-empty-library.message" +msgstr "La tua libreria è vuota. Sei sicuro di volerla pubblicare?" + +#: src/app/main/ui/workspace/libraries.cljs:187 +msgid "modals.publish-empty-library.title" +msgstr "Pubblica libreria vuota" + +#: src/app/main/ui/static.cljs:50, src/app/main/ui/static.cljs:285, src/app/main/ui/static.cljs:291, src/app/main/ui/static.cljs:297, src/app/main/ui/static.cljs:303, src/app/main/ui/static.cljs:312, src/app/main/ui/static.cljs:321 +msgid "not-found.no-permission.go-dashboard" +msgstr "Vai al tuo Penpot" + +#: src/app/main/ui/static.cljs:247, src/app/main/ui/static.cljs:259 +msgid "not-found.no-permission.penpot-file" +msgstr "File Penpot" + +#: src/app/main/ui/static.cljs:284, src/app/main/ui/static.cljs:316 +msgid "not-found.no-permission.project" +msgstr "Non hai accesso a questo progetto." + +#: src/app/main/ui/static.cljs:309, src/app/main/ui/static.cljs:318 +msgid "not-found.no-permission.if-approves" +msgstr "Se il proprietario lo consente, sarai invitato al team." + +#: src/app/main/ui/onboarding/team_choice.cljs:264 +msgid "onboarding.choice.team-up.continue-without-a-team" +msgstr "Continua senza team" + +#: src/app/main/ui/onboarding/team_choice.cljs:193 +msgid "onboarding.choice.team-up.create-team-and-invite" +msgstr "Crea team e invita" + +#: src/app/main/ui/onboarding/team_choice.cljs:197 +msgid "onboarding.choice.team-up.create-team-and-send-invites-description" +msgstr "Puoi inviare gli inviti più tardi" + +#, unused +msgid "onboarding.choice.team-up.create-team-and-send-invites" +msgstr "Crea team e invia inviti" + +#, unused +msgid "onboarding.choice.team-up.create-team-without-inviting" +msgstr "Crea team senza invitare" + +#: src/app/main/ui/onboarding/questions.cljs:267 +msgid "onboarding.questions.team-size.31-50" +msgstr "31-50" + +#: src/app/main/ui/onboarding/questions.cljs:270 +msgid "onboarding.questions.team-size.freelancer" +msgstr "Sono un libero professionista" + +#: src/app/main/ui/onboarding/questions.cljs:266 +msgid "onboarding.questions.team-size.more-than-50" +msgstr "Più di 50" + +#: src/app/main/ui/onboarding/questions.cljs:271 +msgid "onboarding.questions.team-size.personal-project" +msgstr "Sto lavorando a un progetto personale" + +#: src/app/main/ui/onboarding/team_choice.cljs:34 +msgid "onboarding.team-modal.create-team-desc" +msgstr "" +"Un team ti consente di collaborare con altri utenti Penpot lavorando negli " +"stessi file e progetti." + +#: src/app/main/ui/onboarding/team_choice.cljs:39 +msgid "onboarding.team-modal.create-team-feature-1" +msgstr "File e progetti illimitati" + +#: src/app/main/ui/onboarding/team_choice.cljs:47 +msgid "onboarding.team-modal.create-team-feature-3" +msgstr "Gestione ruoli" + +#: src/app/main/ui/onboarding/team_choice.cljs:43 +msgid "onboarding.team-modal.create-team-feature-2" +msgstr "Edizione multiplayer" + +#: src/app/main/ui/onboarding/team_choice.cljs:32 +msgid "onboarding.team-modal.team-definition" +msgstr "Cos'è un team?" + +#: src/app/main/ui/onboarding/team_choice.cljs:51 +msgid "onboarding.team-modal.create-team-feature-4" +msgstr "Membri illimitati" + +#: src/app/main/ui/auth/recovery.cljs:88 +msgid "profile.recovery.go-to-login" +msgstr "Vai all'accesso" + +#: src/app/main/ui/onboarding/templates.cljs:78 +msgid "onboarding.templates.subtitle" +msgstr "Ecco alcuni template." + +#: src/app/main/ui/onboarding/templates.cljs:77 +msgid "onboarding.templates.title" +msgstr "Inizia a progettare" + +#: src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs:224 +msgid "settings.detach" +msgstr "Scollega" + +#: src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs:276 +msgid "settings.select-this-color" +msgstr "Seleziona gli elementi che utilizzano questo stile" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:62 +msgid "shortcut-subsection.navigation-dashboard" +msgstr "Navigazione" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:56 +msgid "shortcut-subsection.alignment" +msgstr "Allineamento" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:57 +msgid "shortcut-subsection.edit" +msgstr "Modifica" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:63 +msgid "shortcut-subsection.navigation-viewer" +msgstr "Navigazione" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:64 +msgid "shortcut-subsection.navigation-workspace" +msgstr "Navigazione" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:65 +msgid "shortcut-subsection.panels" +msgstr "Pannelli" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:74 +msgid "shortcuts.align-bottom" +msgstr "Allinea in basso" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:75 +msgid "shortcuts.align-center" +msgstr "Allinea al centro" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:72 +msgid "shortcuts.add-comment" +msgstr "Commenti" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:73 +msgid "shortcuts.add-node" +msgstr "Aggiungi nodo" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:98 +msgid "shortcuts.delete" +msgstr "Elimina" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:99 +msgid "shortcuts.delete-node" +msgstr "Elimina nodo" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:95 +msgid "shortcuts.create-new-project" +msgstr "Crea nuovo" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:96 +msgid "shortcuts.cut" +msgstr "Taglia" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:103 +msgid "shortcuts.draw-frame" +msgstr "Tavola da disegno" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:104 +msgid "shortcuts.draw-nodes" +msgstr "Disegna tracciato" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:106 +msgid "shortcuts.draw-rect" +msgstr "Rettangolo" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:107 +msgid "shortcuts.draw-text" +msgstr "Testo" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:108 +msgid "shortcuts.duplicate" +msgstr "Duplica" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:109 +msgid "shortcuts.escape" +msgstr "Annulla" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:111 +msgid "shortcuts.fit-all" +msgstr "Adatta zoom a tutto" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:112 +msgid "shortcuts.flip-horizontal" +msgstr "Capovolgi orizzontalmente" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:114 +msgid "shortcuts.font-size-dec" +msgstr "Riduci dimensione carattere" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:117 +msgid "shortcuts.go-to-libs" +msgstr "Vai alle librerie condivise" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:118 +msgid "shortcuts.go-to-search" +msgstr "Cerca" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:113 +msgid "shortcuts.flip-vertical" +msgstr "Capovolgi verticalmente" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:144 +msgid "shortcuts.move-unit-up" +msgstr "Sposta in alto" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:516 +msgid "shortcuts.not-found" +msgstr "Nessuna scorciatoia trovata" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:145 +msgid "shortcuts.next-frame" +msgstr "Tavola da disegno successiva" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:150 +msgid "shortcuts.opacity-4" +msgstr "Imposta opacità al 40%" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:162 +msgid "shortcuts.open-workspace" +msgstr "Vai all'area di lavoro" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:164 +msgid "shortcuts.prev-frame" +msgstr "Tavola da disegno precedente" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:167 +msgid "shortcuts.scale" +msgstr "Ridimensiona" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:152 +msgid "shortcuts.opacity-6" +msgstr "Imposta opacità al 60%" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:155 +msgid "shortcuts.opacity-9" +msgstr "Imposta opacità al 90%" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:160 +msgid "shortcuts.open-interactions" +msgstr "Vai alla sezione interazioni" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:186 +msgid "shortcuts.toggle-alignment" +msgstr "Attiva/Disattiva allineamento dinamico" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:187 +msgid "shortcuts.toggle-assets" +msgstr "Attiva/Disattiva asset" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:179 +msgid "shortcuts.start-measure" +msgstr "Avvia misurazione" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:181 +msgid "shortcuts.text-align-center" +msgstr "Allinea al centro" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:184 +msgid "shortcuts.text-align-right" +msgstr "Allinea a destra" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:496, src/app/main/ui/workspace/sidebar/shortcuts.cljs:505 +msgid "shortcuts.title" +msgstr "Scorciatoie da tastiera" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:191 +msgid "shortcuts.toggle-guides" +msgstr "Mostra/Nascondi guide" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:201 +msgid "shortcuts.toggle-snap-ruler-guide" +msgstr "Aggancia alle guide del righello" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:203 +msgid "shortcuts.toggle-theme" +msgstr "Cambia tema" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:204 +msgid "shortcuts.toggle-visibility" +msgstr "Mostra/Nascondi" + +#: src/app/main/ui/settings/options.cljs:77 +msgid "title.settings.options" +msgstr "Impostazioni - Penpot" + +#: src/app/main/ui.cljs:138 +msgid "viewer.breaking-change.description" +msgstr "" +"Questi link condivisibili non sono più validi. Creane uno nuovo o chiedo al " +"proprietario di crearne uno." + +#: src/app/main/ui/settings/feedback.cljs:107 +msgid "title.settings.feedback" +msgstr "Fornisci feedback - Penpot" + +#: src/app/main/ui/viewer/header.cljs:194 +msgid "viewer.header.fullscreen" +msgstr "Schermo intero" + +#: src/app/main/ui/viewer/interactions.cljs:286 +msgid "viewer.header.interactions" +msgstr "Interazioni" + +#: src/app/main/ui/workspace/sidebar/assets/groups.cljs:138 +msgid "workspace.assets.create-group-hint" +msgstr "" +"I tuoi elementi verrano rinominati automaticamente come \"Nome gruppo / nome " +"elemento\"" + +#: src/app/main/ui/workspace/sidebar/assets/components.cljs:527 +msgid "workspace.assets.grid-view" +msgstr "Vista a griglia" + +#: src/app/main/ui/workspace/sidebar/assets/components.cljs:523 +msgid "workspace.assets.list-view" +msgstr "Vista a elenco" + +#: src/app/main/ui/workspace/sidebar/assets.cljs:187 +msgid "workspace.assets.sort" +msgstr "Ordina" + +#: src/app/main/ui/workspace/context_menu.cljs:545, src/app/main/ui/workspace/sidebar/assets/components.cljs:571 +msgid "workspace.assets.duplicate" +msgstr "Duplica" + +#: src/app/main/ui/workspace/sidebar/assets/colors.cljs:247, src/app/main/ui/workspace/sidebar/assets/typographies.cljs:443 +msgid "workspace.assets.edit" +msgstr "Modifica" + +#: src/app/main/ui/workspace/sidebar/assets.cljs:171 +msgid "workspace.assets.filter" +msgstr "Filtra" + +#: src/app/main/ui/workspace/sidebar/options/menus/typography.cljs:533 +msgid "workspace.assets.typography.go-to-edit" +msgstr "Vai alla libreria dello stile del file per modificare" + +#: src/app/main/ui/workspace/sidebar/options/menus/typography.cljs:523 +msgid "workspace.assets.typography.letter-spacing" +msgstr "Spaziatura tra lettere" + +#: src/app/main/ui/workspace/sidebar/assets/groups.cljs:65 +msgid "workspace.assets.ungroup" +msgstr "Separa" + +#: src/app/main/ui/workspace/context_menu.cljs:648 +msgid "workspace.context-menu.grid-cells.area" +msgstr "Crea area" + +#: src/app/main/ui/workspace/context_menu.cljs:643 +msgid "workspace.context-menu.grid-cells.merge" +msgstr "Unisci celle" + +#: src/app/main/ui/workspace/context_menu.cljs:608 +msgid "workspace.context-menu.grid-track.column.add-after" +msgstr "Aggiungi 1 colonna a destra" + +#: src/app/main/ui/workspace/context_menu.cljs:616 +msgid "workspace.context-menu.grid-track.row.delete" +msgstr "Elimina riga" + +#: src/app/main/ui/workspace/context_menu.cljs:615 +msgid "workspace.context-menu.grid-track.row.add-after" +msgstr "Aggiungi 1 riga sotto" + +#: src/app/main/ui/workspace/context_menu.cljs:614 +msgid "workspace.context-menu.grid-track.row.add-before" +msgstr "Aggiungi 1 riga sopra" + +#, unused +msgid "workspace.focus.selection" +msgstr "Selezione" + +#: src/app/main/ui/workspace/main_menu.cljs:259 +msgid "workspace.header.menu.enable-snap-pixel-grid" +msgstr "Attiva allineamento al poxel" + +#: src/app/main/ui/workspace/context_menu.cljs:617 +msgid "workspace.context-menu.grid-track.row.delete-shapes" +msgstr "Elimina riga e forme" + +#: src/app/main/ui/workspace/main_menu.cljs:360 +msgid "workspace.header.menu.show-palette" +msgstr "Mostra palette colori" + +#: src/app/main/ui/workspace/main_menu.cljs:284 +msgid "workspace.header.menu.toggle-dark-theme" +msgstr "Passa al tema scuro" + +#: src/app/main/ui/viewer/header.cljs:79, src/app/main/ui/workspace/right_header.cljs:108 +msgid "workspace.header.zoom" +msgstr "Zoom" + +#: src/app/main/ui/viewer/header.cljs:102 +msgid "workspace.header.zoom-fit" +msgstr "Adatta - Riduci per adattare" + +#: src/app/main/ui/viewer/header.cljs:109 +msgid "workspace.header.zoom-fill" +msgstr "Riempi - Ridimensiona per riempire" + +#: src/app/main/ui/workspace/main_menu.cljs:849 +msgid "workspace.header.menu.option.help-info" +msgstr "Aiuto e informazioni" + +#: src/app/main/ui/workspace/main_menu.cljs:343 +msgid "workspace.header.menu.show-guides" +msgstr "Mostra guide" + +#: src/app/main/ui/workspace/right_header.cljs:135 +msgid "workspace.header.zoom-selected" +msgstr "Zoom su selezione" + +#: src/app/main/ui/workspace/sidebar/options/menus/grid_cell.cljs:273, src/app/main/ui/workspace/sidebar/options/menus/grid_cell.cljs:275, src/app/main/ui/workspace/sidebar/options/menus/layout_container.cljs:607 +msgid "workspace.layout_grid.editor.options.edit-grid" +msgstr "Modifica griglia" + +#: src/app/main/ui/workspace/libraries.cljs +#, unused +msgid "workspace.libraries.add" +msgstr "Aggiungi" + +#: src/app/main/ui/viewer/header.cljs:116 +msgid "workspace.header.zoom-full-screen" +msgstr "Schermo intero" + +#: src/app/main/ui/workspace/color_palette.cljs:129 +msgid "workspace.libraries.colors.empty-palette" +msgstr "Non ci sono ancora stili di colore nella tua libreria" + +#: src/app/main/ui/workspace/text_palette.cljs:153 +msgid "workspace.libraries.colors.empty-typography-palette" +msgstr "Non ci sono ancora stili di carattere nella tua libreria" + +#: src/app/main/ui/workspace/color_palette_ctx_menu.cljs:60, src/app/main/ui/workspace/colorpicker/libraries.cljs:73, src/app/main/ui/workspace/text_palette_ctx_menu.cljs:50 +msgid "workspace.libraries.colors.file-library" +msgstr "Libreria del file" + +#: src/app/main/ui/workspace/color_palette_ctx_menu.cljs:82, src/app/main/ui/workspace/colorpicker/libraries.cljs:72 +msgid "workspace.libraries.colors.recent-colors" +msgstr "Colori recenti" + +#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs +#, unused +msgid "workspace.options.interaction-in" +msgstr "In" + +#: src/app/main/ui/workspace/sidebar/options/menus/layer.cljs:125 +msgid "workspace.options.layer-options.blend-mode.multiply" +msgstr "Moltiplica" + +#: src/app/main/ui/workspace/sidebar/options/menus/layer.cljs:131 +msgid "workspace.options.layer-options.blend-mode.soft-light" +msgstr "Luce soffusa" + +#: src/app/main/ui/workspace/sidebar/options/menus/layer.cljs:130 +msgid "workspace.options.layer-options.blend-mode.overlay" +msgstr "Sovrapponi" + +#: src/app/main/ui/workspace/sidebar/options/menus/layer.cljs:136 +msgid "workspace.options.layer-options.blend-mode.saturation" +msgstr "Saturazione" + +#: src/app/main/ui/workspace/sidebar/options/menus/layer.cljs:128 +msgid "workspace.options.layer-options.blend-mode.screen" +msgstr "Scolora" + +#: src/app/main/ui/workspace/sidebar/options/menus/layer.cljs +#, unused +msgid "workspace.options.layer-options.title.group" +msgstr "Livelli di gruppo" + +#: src/app/main/ui/workspace/sidebar/options/menus/layout_item.cljs:564 +msgid "workspace.options.layout-item.layout-item-max-h" +msgstr "Altezza.Max" + +#: src/app/main/ui/workspace/sidebar/options/menus/layout_item.cljs +#, unused +msgid "workspace.options.layout-item.advanced-ops" +msgstr "Opzioni avanzate" + +#: src/app/main/ui/workspace/sidebar/options/menus/layout_item.cljs +#, unused +msgid "workspace.options.layout-item.title.layout-item-max-w" +msgstr "Larghezza massima" + +#: src/app/main/ui/workspace/sidebar/options/menus/layout_item.cljs +#, unused +msgid "workspace.options.layout-item.title.layout-item-min-w" +msgstr "Larghezza minima" + +#: src/app/main/ui/workspace/sidebar/options/menus/layout.cljs +#, unused +msgid "workspace.options.layout.bottom" +msgstr "In basso" + +#: src/app/main/ui/workspace/sidebar/options/menus/layout.cljs +#, unused +msgid "workspace.options.layout.direction.column" +msgstr "Colonna" + +#: src/app/main/ui/workspace/sidebar/options/menus/layout.cljs +#, unused +msgid "workspace.options.layout.direction.column-reverse" +msgstr "Colonna invertita" + +#: src/app/main/ui/workspace/sidebar/options/menus/layout.cljs +#, unused +msgid "workspace.options.layout.direction.row" +msgstr "Riga" + +#: src/app/main/ui/workspace/sidebar/options/menus/layout.cljs +#, unused +msgid "workspace.options.layout.direction.row-reverse" +msgstr "Riga invertita" + +#: src/app/main/ui/workspace/sidebar/options/menus/layout.cljs +#, unused +msgid "workspace.options.layout.gap" +msgstr "Spazio" + +#: src/app/main/ui/workspace/sidebar/options/menus/layout.cljs +#, unused +msgid "workspace.options.layout.left" +msgstr "A sinistra" + +#: src/app/main/ui/workspace/sidebar/options/menus/layout_item.cljs +#, unused +msgid "workspace.options.layout.margin" +msgstr "Margine" + +#: src/app/main/ui/workspace/sidebar/options/menus/layout.cljs +#, unused +msgid "workspace.options.layout.padding-all" +msgstr "Tutti i lati" + +#: src/app/main/ui/workspace/sidebar/options/menus/layout.cljs +#, unused +msgid "workspace.options.layout.padding-simple" +msgstr "Margine interno semplice" + +#: src/app/main/ui/workspace/sidebar/options/menus/layout_item.cljs +#, unused +msgid "workspace.options.layout.margin-simple" +msgstr "Margine semplice" + +#: src/app/main/ui/workspace/sidebar/options/menus/layout.cljs +#, unused +msgid "workspace.options.layout.top" +msgstr "In alto" + +#: src/app/main/ui/workspace/sidebar/options/menus/layout.cljs +#, unused +msgid "workspace.options.layout.padding" +msgstr "Margine interno" + +#: src/app/main/ui/workspace/sidebar/options/shapes/frame.cljs, src/app/main/ui/workspace/sidebar/options/menus/measures.cljs +#, unused +msgid "workspace.options.position" +msgstr "Posizione" + +#: src/app/main/ui/workspace/sidebar/options/menus/measures.cljs:565, src/app/main/ui/workspace/sidebar/options/menus/measures.cljs:588 +msgid "workspace.options.radius" +msgstr "Raggio" + +#: src/app/main/ui/workspace/sidebar/options/menus/measures.cljs:602 +msgid "workspace.options.radius-top-left" +msgstr "Superiore sinistro" + +#: src/app/main/ui/workspace/sidebar/options.cljs:183 +msgid "workspace.options.prototype" +msgstr "Prototipo" + +#: src/app/main/ui/workspace/sidebar/options/menus/measures.cljs:611 +msgid "workspace.options.radius-top-right" +msgstr "Superiore destro" + +#: src/app/main/ui/exports/assets.cljs:290 +msgid "workspace.options.retry" +msgstr "Riprova" + +#: src/app/main/ui/workspace/sidebar/options/menus/measures.cljs:547 +msgid "workspace.options.rotation" +msgstr "Rotazione" + +#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs:749 +msgid "workspace.options.select-a-shape" +msgstr "" +"Seleziona una forma, una tavola da disegno o un gruppo per trascinare una " +"connessione verso un'altra tavola." + +#: src/app/main/ui/workspace/sidebar/options/menus/typography.cljs:181 +msgid "workspace.options.search-font" +msgstr "Cerca carattere" + +#: src/app/main/ui/workspace/sidebar/options/menus/shadow.cljs:295 +msgid "workspace.options.shadow-options.title.multiple" +msgstr "Ombre della selezione" + +#: src/app/main/ui/workspace/sidebar/options/menus/fill.cljs:197 +msgid "workspace.options.show-fill-on-export" +msgstr "Mostra in esportazione" + +#: src/app/main/ui/workspace/sidebar/options/menus/fill.cljs:48 +msgid "workspace.options.selection-fill" +msgstr "Riempimento di selezione" + +#: src/app/main/ui/workspace/sidebar/options/menus/shadow.cljs:145 +msgid "workspace.options.shadow-options.drop-shadow" +msgstr "Ombra esterna" + +#: src/app/main/ui/viewer/inspect/attributes/shadow.cljs:38, src/app/main/ui/workspace/sidebar/options/menus/shadow.cljs:187 +msgid "workspace.options.shadow-options.offsetx" +msgstr "X" + +#: src/app/main/ui/viewer/inspect/attributes/shadow.cljs:41, src/app/main/ui/workspace/sidebar/options/menus/shadow.cljs:212, src/app/main/ui/workspace/sidebar/options/menus/shadow.cljs:214 +msgid "workspace.options.shadow-options.spread" +msgstr "Diffusione" + +#: src/app/main/ui/workspace/sidebar/options/menus/shadow.cljs:297 +msgid "workspace.options.shadow-options.title" +msgstr "Ombra" + +#: src/app/main/ui/workspace/sidebar/options/rows/stroke_row.cljs:87 +msgid "workspace.options.stroke.center" +msgstr "Centro" + +#: src/app/main/ui/workspace/sidebar/options/menus/stroke.cljs:192 +msgid "workspace.options.stroke-color" +msgstr "Colore traccia" + +#: src/app/main/ui/workspace/sidebar/options/rows/stroke_row.cljs:105 +msgid "workspace.options.stroke.dashed" +msgstr "Tratteggiato" + +#: src/app/main/ui/workspace/sidebar/options/rows/stroke_row.cljs:104 +msgid "workspace.options.stroke.dotted" +msgstr "Puntinato" + +#: src/app/main/ui/workspace/sidebar/options/rows/stroke_row.cljs:88 +msgid "workspace.options.stroke.inner" +msgstr "Interno" + +#: src/app/main/ui/workspace/sidebar/options/menus/text.cljs:151 +msgid "workspace.options.text-options.grow-auto-height" +msgstr "Altezza automatica" + +#: src/app/main/ui/workspace/sidebar/options/menus/text.cljs:147 +msgid "workspace.options.text-options.grow-auto-width" +msgstr "Larghezza automatica" + +#: src/app/main/ui/workspace/sidebar/options/menus/typography.cljs:387 +msgid "workspace.options.text-options.letter-spacing" +msgstr "Spaziatura tra lettere" + +#: src/app/main/ui/workspace/sidebar/options/menus/typography.cljs:369 +msgid "workspace.options.text-options.line-height" +msgstr "Interlinea" + +#: src/app/main/ui/workspace/sidebar/options/menus/typography.cljs +#, unused +msgid "workspace.options.text-options.lowercase" +msgstr "Minuscolo" + +#: src/app/main/ui/workspace/sidebar/options/menus/text.cljs, src/app/main/ui/workspace/sidebar/options/menus/typography.cljs +#, unused +msgid "workspace.options.text-options.none" +msgstr "Nessuno" + +#: src/app/main/ui/workspace/sidebar/options/menus/text.cljs:49 +msgid "workspace.options.text-options.text-align-left" +msgstr "Allinea a sinistra (%s)" + +#: src/app/main/ui/workspace/viewport/path_actions.cljs:152 +msgid "workspace.path.actions.draw-nodes" +msgstr "Disegna nodi (%s)" + +#: src/app/main/ui/workspace/viewport/path_actions.cljs:204 +msgid "workspace.path.actions.make-corner" +msgstr "Concerti in angolo (%s)" + +#: src/app/main/ui/workspace/viewport/path_actions.cljs:211 +msgid "workspace.path.actions.make-curve" +msgstr "Converti in curva (%s)" + +#: src/app/main/ui/workspace/viewport/path_actions.cljs:182 +msgid "workspace.path.actions.merge-nodes" +msgstr "Fondi nodi (%s)" + +#: src/app/main/ui/workspace/viewport/path_actions.cljs:159 +msgid "workspace.path.actions.move-nodes" +msgstr "Sposta nodo (%s)" + +#: src/app/main/ui/workspace/viewport/path_actions.cljs:196 +msgid "workspace.path.actions.separate-nodes" +msgstr "Separa nodi (%s)" + +#: src/app/main/ui/workspace/viewport/path_actions.cljs:218 +msgid "workspace.path.actions.snap-nodes" +msgstr "Aggancia nodi (%s)" + +#: src/app/main/ui/workspace/main_menu.cljs:837 +msgid "workspace.plugins.menu.title" +msgstr "Plugin" + +#: src/app/main/ui/workspace/plugins.cljs:202 +#, markdown +msgid "workspace.plugins.discover" +msgstr "Scopri [altri plugin](%s)" + +#: src/app/main/ui/workspace/plugins.cljs:218 +msgid "workspace.plugins.installed-plugins" +msgstr "Plugin installati" + +#: src/app/main/ui/workspace/plugins.cljs:83 +msgid "workspace.plugins.button-open" +msgstr "Apri" + +#: src/app/main/ui/workspace/main_menu.cljs:651 +msgid "workspace.plugins.menu.plugins-manager" +msgstr "Manager dei plugin" + +#: src/app/main/ui/workspace/plugins.cljs:243 +msgid "workspace.plugins.permissions.content-read" +msgstr "Leggi il contenuto dei file a cui gli utenti hanno accesso." + +#: src/app/main/ui/workspace/plugins.cljs:323 +msgid "workspace.plugins.permissions.disclaimer" +msgstr "" +"Tieni presente che questo plugin è creato da una terza parte, quindi " +"assicurati di fidarti prima di concedere l'accesso. La tua privacy e " +"sicurezza dei dati sono importanti per noi. Se hai dubbi, contatta il " +"supporto." + +#: src/app/main/ui/workspace/plugins.cljs:263 +msgid "workspace.plugins.permissions.library-read" +msgstr "Leggere le tue librerie e asset." + +#: src/app/main/ui/workspace/plugins.cljs:257 +msgid "workspace.plugins.permissions.library-write" +msgstr "Leggere e modificare le tue librerie e asset." + +#: src/app/main/ui/workspace/plugins.cljs:237 +msgid "workspace.plugins.permissions.content-write" +msgstr "Leggi e modifica il contenuto dei file a cui gli utenti hanno accesso." + +#: src/app/main/ui/workspace/plugins.cljs:250 +msgid "workspace.plugins.permissions.user-read" +msgstr "Leggere le informazioni del profilo dell'utente attuale." + +#, unused +msgid "workspace.plugins.success" +msgstr "Plugin caricato correttamente." + +#: src/app/main/ui/workspace/plugins.cljs:177 +msgid "workspace.plugins.title" +msgstr "Plugin" + +#: src/app/main/ui/workspace/plugins.cljs:316 +msgid "workspace.plugins.permissions.title" +msgstr "IL PLUGIN '%s' VUOLE ACCEDERE A:" + +#: src/app/main/ui/workspace/context_menu.cljs:455 +msgid "workspace.shape.menu.add-grid" +msgstr "Aggiungi grid layout" + +#: src/app/main/ui/workspace/context_menu.cljs:194 +msgid "workspace.shape.menu.back" +msgstr "Porta in fondo" + +#: src/app/main/ui/workspace/context_menu.cljs:479 +msgid "workspace.shape.menu.create-multiple-components" +msgstr "Crea componenti multipli" + +#: src/app/main/ui/workspace/context_menu.cljs:143 +msgid "workspace.shape.menu.cut" +msgstr "Taglia" + +#: src/app/main/ui/workspace/context_menu.cljs:191 +msgid "workspace.shape.menu.backward" +msgstr "Porta indietro" + +#: src/app/main/ui/workspace/sidebar/assets/common.cljs:431 +msgid "workspace.shape.menu.detach-instances-in-bulk" +msgstr "Scollega istanze" + +#: src/app/main/ui/workspace/context_menu.cljs:475 +msgid "workspace.shape.menu.create-component" +msgstr "Crea componente" + +#: src/app/main/ui/workspace/context_menu.cljs:185 +msgid "workspace.shape.menu.forward" +msgstr "Porta avanti" + +#: src/app/main/ui/workspace/context_menu.cljs:272 +msgid "workspace.shape.menu.group" +msgstr "Raggruppa" + +#: src/app/main/ui/workspace/context_menu.cljs:149 +msgid "workspace.shape.menu.duplicate" +msgstr "Duplica" + +#: src/app/main/ui/workspace/context_menu.cljs:332 +msgid "workspace.shape.menu.edit" +msgstr "Modifica" + +#: src/app/main/ui/workspace/context_menu.cljs:374, src/app/main/ui/workspace/sidebar/layer_item.cljs:145 +msgid "workspace.shape.menu.hide" +msgstr "Nascondi" + +#: src/app/main/ui/workspace/context_menu.cljs:562, src/app/main/ui/workspace/main_menu.cljs:414 +msgid "workspace.shape.menu.hide-ui" +msgstr "Mostra/Nascondi UI" + +#: src/app/main/ui/workspace/context_menu.cljs:359, src/app/main/ui/workspace/sidebar/options/menus/bool.cljs:89 +msgid "workspace.shape.menu.flatten" +msgstr "Appiattisci" + +#: src/app/main/ui/workspace/context_menu.cljs:277 +msgid "workspace.shape.menu.mask" +msgstr "Maschera" + +#: src/app/main/ui/workspace/context_menu.cljs:445 +msgid "workspace.shape.menu.remove-grid" +msgstr "Rimuovi grid layout" + +#: src/app/main/ui/workspace/sidebar/assets/common.cljs:436 +msgid "workspace.shape.menu.reset-overrides" +msgstr "Reimposta modifiche" + +#: src/app/main/ui/workspace/context_menu.cljs:146, src/app/main/ui/workspace/context_menu.cljs:559 +msgid "workspace.shape.menu.paste" +msgstr "Incolla" + +#: src/app/main/ui/workspace/context_menu.cljs:442 +msgid "workspace.shape.menu.remove-flex" +msgstr "Rimuovi flex layout" + +#: src/app/main/ui/workspace/context_menu.cljs:343, src/app/main/ui/workspace/sidebar/options/menus/bool.cljs:70 +msgid "workspace.shape.menu.union" +msgstr "Unione" + +#: src/app/main/ui/workspace/context_menu.cljs:371, src/app/main/ui/workspace/sidebar/layer_item.cljs:144 +msgid "workspace.shape.menu.show" +msgstr "Mostra" + +#: src/app/main/ui/workspace/sidebar/assets/common.cljs:424 +msgid "workspace.shape.menu.show-in-assets" +msgstr "Mostra nel pannello degli asset" + +#: src/app/main/ui/workspace/context_menu.cljs:379, src/app/main/ui/workspace/sidebar/layer_item.cljs:152, src/app/main/ui/workspace/sidebar/options/menus/layer.cljs:195 +msgid "workspace.shape.menu.unlock" +msgstr "Sblocca" + +#: src/app/main/ui/workspace/sidebar/assets/common.cljs:445 +msgid "workspace.shape.menu.update-main" +msgstr "Aggiorna componente principale" + +#: src/app/main/ui/components/tab_container.cljs:52, src/app/main/ui/workspace/sidebar.cljs:46 +msgid "workspace.sidebar.collapse" +msgstr "Comprimi barra laterale" + +#: src/app/main/ui/workspace/right_header.cljs:246, src/app/main/ui/workspace/right_header.cljs:247 +#, fuzzy +msgid "workspace.sidebar.history" +msgstr "Cronologia (%s)" + +#: src/app/main/ui/workspace/top_toolbar.cljs:143, src/app/main/ui/workspace/top_toolbar.cljs:144 +msgid "workspace.toolbar.frame" +msgstr "Tavola da disegno (%s)" + +#: src/app/main/ui/workspace/top_toolbar.cljs:161, src/app/main/ui/workspace/top_toolbar.cljs:162 +msgid "workspace.toolbar.ellipse" +msgstr "Ellisse (%s)" + +#: src/app/main/ui/workspace/top_toolbar.cljs:60, src/app/main/ui/workspace/top_toolbar.cljs:61 +msgid "workspace.toolbar.image" +msgstr "Immagine (%s)" + +#: src/app/main/ui/workspace/top_toolbar.cljs:190, src/app/main/ui/workspace/top_toolbar.cljs:191 +msgid "workspace.toolbar.path" +msgstr "Tracciato (%s)" + +#: src/app/main/ui/workspace/top_toolbar.cljs:201, src/app/main/ui/workspace/top_toolbar.cljs:202 +msgid "workspace.toolbar.plugins" +msgstr "Plugin (%s)" + +#: src/app/main/ui/workspace/top_toolbar.cljs:152, src/app/main/ui/workspace/top_toolbar.cljs:153 +msgid "workspace.toolbar.rect" +msgstr "Rettangolo (%s)" + +#: src/app/main/ui/workspace/top_toolbar.cljs:219, src/app/main/ui/workspace/top_toolbar.cljs:220 +msgid "workspace.toolbar.toggle-toolbar" +msgstr "Attiva/Disattiva barra degli strumenti" + +#: src/app/main/ui/workspace/sidebar/history.cljs:109 +msgid "workspace.undo.entry.multiple.circle" +msgstr "cerchi" + +#: src/app/main/ui/workspace/viewport/top_bar.cljs:39 +msgid "workspace.top-bar.read-only.done" +msgstr "Fatto" + +#: src/app/main/ui/workspace/viewport/top_bar.cljs:36 +#, markdown +msgid "workspace.top-bar.view-only" +msgstr "**Ispezione codice** (Solo visualizzazione)" + +#: src/app/main/ui/workspace/sidebar/history.cljs:120 +msgid "workspace.undo.entry.multiple.shape" +msgstr "forme" + +#: src/app/main/ui/workspace/sidebar/history.cljs:116 +msgid "workspace.undo.entry.multiple.multiple" +msgstr "oggetti" + +#: src/app/main/ui/workspace/sidebar/history.cljs:119 +msgid "workspace.undo.entry.multiple.rect" +msgstr "rettangoli" + +#: src/app/main/ui/workspace/sidebar/history.cljs:122 +msgid "workspace.undo.entry.multiple.typography" +msgstr "asset tipografici" + +#: src/app/main/ui/workspace/sidebar/history.cljs:143 +msgid "workspace.undo.entry.new" +msgstr "Nuovo %s" + +#: src/app/main/ui/workspace/sidebar/history.cljs:123 +msgid "workspace.undo.entry.single.circle" +msgstr "cerchio" + +#: src/app/main/ui/workspace/sidebar/history.cljs:124 +msgid "workspace.undo.entry.single.color" +msgstr "colore" + +#: src/app/main/ui/workspace/sidebar/history.cljs:125 +msgid "workspace.undo.entry.single.component" +msgstr "componente" + +#: src/app/main/ui/workspace/sidebar/history.cljs:128 +msgid "workspace.undo.entry.single.group" +msgstr "gruppo" + +#: src/app/main/ui/workspace/sidebar/history.cljs:129 +msgid "workspace.undo.entry.single.image" +msgstr "immagine" + +#: src/app/main/ui/workspace/sidebar/history.cljs:130 +msgid "workspace.undo.entry.single.media" +msgstr "asset grafico" + +#: src/app/main/ui/workspace/sidebar/history.cljs:126 +msgid "workspace.undo.entry.single.curve" +msgstr "curva" + +#: src/app/main/ui/workspace/sidebar/history.cljs:127 +msgid "workspace.undo.entry.single.frame" +msgstr "tavola da disegno" + +#: src/app/main/ui/workspace/sidebar/history.cljs:136 +msgid "workspace.undo.entry.single.text" +msgstr "testo" + +#: src/app/main/ui/workspace/sidebar/history.cljs:131 +msgid "workspace.undo.entry.single.multiple" +msgstr "oggetto" + +#: src/app/main/ui/workspace/sidebar/history.cljs:132 +msgid "workspace.undo.entry.single.page" +msgstr "pagina" + +#: src/app/main/ui/workspace/sidebar/history.cljs:133 +msgid "workspace.undo.entry.single.path" +msgstr "tracciato" + +#: src/app/main/ui/workspace/sidebar/history.cljs:134 +msgid "workspace.undo.entry.single.rect" +msgstr "rettangolo" + +#: src/app/main/ui/workspace/sidebar/history.cljs:335 +#, unused +msgid "workspace.undo.title" +msgstr "Cronologia" + +#: src/app/main/data/workspace/libraries.cljs:1145 +msgid "workspace.updates.more-info" +msgstr "Maggiori informazioni" + +#, unused +msgid "workspace.viewport.click-to-close-path" +msgstr "Clicca per chiudere il tracciato" + +#: src/app/main/ui/workspace/sidebar/history.cljs:137 +msgid "workspace.undo.entry.single.typography" +msgstr "asset tipografico" + +#: src/app/main/ui/workspace/sidebar/history.cljs:147 +msgid "workspace.undo.entry.unknown" +msgstr "Operazione su %s" + +#: src/app/main/data/common.cljs:130 +msgid "modals.add-shared-confirm-empty.hint" +msgstr "" +"La tua libreria è vuota. Una volta aggiunta come libreria condivisa, le " +"risorse che crei saranno disponibili per essere utilizzate tra i tuoi file. " +"Sei sicuro di volerla pubblicare?" + +#: src/app/main/ui/auth/login.cljs:293 +msgid "auth.login-tagline" +msgstr "" +"Penpot è lo strumento di design open-source gratuito per la collaborazione " +"nel Design e Sviluppo" + +#, unused +msgid "dashboard.import.analyze-error.components-v2" +msgstr "File con componenti V2 attivati ma questo team non li supporta ancora." + +#: src/app/main/data/users.cljs:735, src/app/main/ui/auth/register.cljs:54 +msgid "errors.email-domain-not-allowed" +msgstr "Dominio non consentito" + +#: src/app/main/data/users.cljs:733 +msgid "errors.auth-provider-not-allowed" +msgstr "Provider di autenticazione non consentito per questo profilo" + +#: src/app/main/ui/viewer/inspect/right_sidebar.cljs:127 +msgid "inspect.tabs.code.selected.frame" +msgstr "Tavola da disegno" + +#, unused +msgid "onboarding.welcome.alt" +msgstr "Penpot" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:78 +msgid "shortcuts.align-left" +msgstr "Allinea a sinistra" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:79 +msgid "shortcuts.align-right" +msgstr "Allinea a destra" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:115 +msgid "shortcuts.font-size-inc" +msgstr "Aumenta dimensione carattere" + +#: src/app/main/ui/workspace/right_header.cljs:120, src/app/main/ui/workspace/sidebar/shortcuts.cljs:122 +msgid "shortcuts.increase-zoom" +msgstr "Aumenta zoom" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:120 +msgid "shortcuts.h-distribute" +msgstr "Distribuisci orizzontalmente" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:121 +msgid "shortcuts.hide-ui" +msgstr "Mostra / Nascondi UI" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:151 +msgid "shortcuts.opacity-5" +msgstr "Imposta opacità al 50%" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:153 +msgid "shortcuts.opacity-7" +msgstr "Imposta opacità al 70%" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:154 +msgid "shortcuts.opacity-8" +msgstr "Imposta opacità all'80%" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:170 +msgid "shortcuts.select-next" +msgstr "Seleziona livello successivo" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:200 +msgid "shortcuts.toggle-snap-guides" +msgstr "Aggancia alle guide" + +#: src/app/main/ui/workspace/sidebar/shortcuts.cljs:206 +msgid "shortcuts.underline" +msgstr "Attiva/Disattiva sottolineatura" + +#: src/app/main/ui/dashboard/fonts.cljs:38 +msgid "title.dashboard.font-providers" +msgstr "Fornitori dei caratteri - %s - Penpot" + +#: src/app/main/ui/dashboard/files.cljs:170 +msgid "title.dashboard.files" +msgstr "%s - Penpot" + +#: src/app/main/ui/dashboard/fonts.cljs:37 +msgid "title.dashboard.fonts" +msgstr "Caratteri - %s - Penpot" + +#: src/app/main/ui/dashboard/projects.cljs:343 +msgid "title.dashboard.projects" +msgstr "Progetti - %s - Penpot" + +#: src/app/main/ui/viewer.cljs:420 +msgid "title.viewer" +msgstr "%s - Modalità di visualizzazione - Penpot" + +#: src/app/main/ui/viewer/header.cljs:342 +msgid "viewer.header.comments-section" +msgstr "Commenti (%s)" + +#: src/app/main/ui/viewer/share_link.cljs:189 +msgid "viewer.header.share.copy-link" +msgstr "Copia link" + +#: src/app/main/ui/viewer/interactions.cljs:304 +msgid "viewer.header.show-interactions" +msgstr "Mostra interazioni" + +#: src/app/main/ui/dashboard/team.cljs:985 +msgid "webhooks.last-delivery.success" +msgstr "L'ultimo invio è avvenuto con successo." + +#: src/app/main/ui/workspace/sidebar/options/menus/align.cljs:91 +msgid "workspace.align.vcenter" +msgstr "Allinea verticalmente al centro (%s)" + +#: src/app/main/ui/workspace/sidebar/options/menus/align.cljs:104 +msgid "workspace.align.vdistribute" +msgstr "Distribuisci spaziatura verticale (%s)" + +#: src/app/main/ui/dashboard/grid.cljs:134, src/app/main/ui/dashboard/grid.cljs:149, src/app/main/ui/workspace/sidebar/assets/components.cljs:511, src/app/main/ui/workspace/sidebar/assets.cljs:138 +msgid "workspace.assets.components" +msgstr "Componenti" + +#: src/app/main/ui/workspace/context_menu.cljs:543, src/app/main/ui/workspace/sidebar/assets/colors.cljs:243, src/app/main/ui/workspace/sidebar/assets/components.cljs:565, src/app/main/ui/workspace/sidebar/assets/graphics.cljs:421, src/app/main/ui/workspace/sidebar/assets/groups.cljs:62, src/app/main/ui/workspace/sidebar/assets/typographies.cljs:438 +msgid "workspace.assets.rename" +msgstr "Rinomina" + +#: src/app/main/ui/workspace/sidebar/assets.cljs:168 +msgid "workspace.assets.search" +msgstr "Cerca asset" + +#: src/app/main/ui/workspace/sidebar/assets.cljs +#, unused +msgid "workspace.assets.shared-library" +msgstr "Librerie condivise" + +#: src/app/main/ui/dashboard/grid.cljs:142, src/app/main/ui/dashboard/grid.cljs:197, src/app/main/ui/workspace/sidebar/assets/typographies.cljs:400, src/app/main/ui/workspace/sidebar/assets.cljs:151 +msgid "workspace.assets.typography" +msgstr "Elementi tipografici" + +#: src/app/main/ui/workspace/viewport/grid_layout_editor.cljs:59 +msgid "workspace.layout_grid.editor.title" +msgstr "Modifica della griglia" + +#: src/app/main/ui/workspace/sidebar/options/menus/layout_container.cljs:1295 +msgid "workspace.layout_grid.editor.options.exit" +msgstr "Esci" + +#: src/app/main/ui/workspace/sidebar/options/menus/layout_container.cljs:478 +msgid "workspace.layout_grid.editor.padding.expand" +msgstr "Mostra opzioni di padding su 4 lati" + +#: src/app/main/ui/workspace/sidebar/options/menus/layout_container.cljs:1321 +msgid "workspace.layout_grid.editor.top-bar.locate.tooltip" +msgstr "Individua grid layout" + +#: src/app/main/ui/workspace/sidebar/options/menus/component.cljs:471 +msgid "workspace.options.component.swap.empty" +msgstr "Non ci sono ancora asset in questo libreria" + +#: src/app/main/ui/workspace/sidebar/options/menus/component.cljs:427 +msgid "workspace.options.component.swap" +msgstr "Sostituisci componente" + +#: src/app/main/ui/workspace/sidebar/options/menus/constraints.cljs:151 +msgid "workspace.options.constraints.topbottom" +msgstr "Superiore e Inferiore" + +#: src/app/main/ui/viewer/inspect/exports.cljs:147 +msgid "workspace.options.export" +msgstr "Esporta" + +#: src/app/main/ui/workspace/sidebar/options/menus/frame_grid.cljs:250 +msgid "workspace.options.grid.params.height" +msgstr "Altezza" + +#: src/app/main/ui/workspace/sidebar/options/menus/frame_grid.cljs +#, unused +msgid "workspace.options.grid.params.rows" +msgstr "Righe" + +#: src/app/main/ui/workspace/sidebar/options/menus/frame_grid.cljs:220, src/app/main/ui/workspace/sidebar/options/menus/frame_grid.cljs:294 +msgid "workspace.options.grid.params.set-default" +msgstr "Imposta come predefinito" + +#: src/app/main/ui/workspace/sidebar/options/menus/frame_grid.cljs +#, unused +msgid "workspace.options.grid.params.size" +msgstr "Dimensione" + +#: src/app/main/ui/workspace/sidebar/options/menus/frame_grid.cljs +#, unused +msgid "workspace.options.grid.params.columns" +msgstr "Colonne" + +#: src/app/main/ui/workspace/sidebar/options/menus/frame_grid.cljs:231 +msgid "workspace.options.grid.params.type.top" +msgstr "Alto" + +#: src/app/main/ui/workspace/sidebar/options/menus/frame_grid.cljs +#, unused +msgid "workspace.options.grid.params.type" +msgstr "Tipo" + +#: src/app/main/ui/workspace/sidebar/options/menus/frame_grid.cljs:232 +msgid "workspace.options.grid.params.type.left" +msgstr "Sinistra" + +#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs:424 +msgid "workspace.options.interaction-easing-ease-out" +msgstr "Ease out" + +#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs:423 +msgid "workspace.options.interaction-easing-ease-in" +msgstr "Ease in" + +#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs:40, src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs:370 +msgid "workspace.options.interaction-mouse-enter" +msgstr "Entrata del mouse" + +#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs:58, src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs:385, src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs:399, src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs:400 +msgid "workspace.options.interaction-self" +msgstr "se stesso" + +#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs:55 +msgid "workspace.options.interaction-toggle-overlay-dest" +msgstr "Attiva/Disattiva la sovrapposizione: %s" + +#: src/app/main/ui/workspace/sidebar/options/menus/layer.cljs:132 +msgid "workspace.options.layer-options.blend-mode.hard-light" +msgstr "Luce intensa" + +#: src/app/main/ui/workspace/sidebar/options/menus/layer.cljs:135 +msgid "workspace.options.layer-options.blend-mode.hue" +msgstr "Tonalità" + +#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs:451 +msgid "workspace.options.interaction-trigger" +msgstr "Trigger" + +#: src/app/main/ui/workspace/sidebar/options/menus/layer.cljs:127 +msgid "workspace.options.layer-options.blend-mode.lighten" +msgstr "Schiarisci" + +#: src/app/main/ui/workspace/sidebar/options/rows/stroke_row.cljs:103 +msgid "workspace.options.stroke.solid" +msgstr "Solido" + +#: src/app/main/ui/workspace/sidebar/options/menus/text.cljs:117 +msgid "workspace.options.text-options.align-bottom" +msgstr "Allinea in basso" + +#: src/app/main/ui/workspace/sidebar/options/menus/component.cljs, src/app/main/ui/workspace/context_menu.cljs +#, unused +msgid "workspace.shape.menu.go-main" +msgstr "Vai al componente principale" + +#: src/app/main/ui/workspace/context_menu.cljs:222 +msgid "workspace.shape.menu.thumbnail-remove" +msgstr "Rimuovi miniatura" + +#: src/app/main/ui/workspace/sidebar/assets/common.cljs:442, src/app/main/ui/workspace/sidebar/assets/components.cljs:585 +msgid "workspace.shape.menu.show-main" +msgstr "Mostra componente principale" + +#: src/app/main/ui/workspace/context_menu.cljs:224 +msgid "workspace.shape.menu.thumbnail-set" +msgstr "Imposta come miniatura" + +#, unused +msgid "media.gradient" +msgstr "Gradiente" + +#: src/app/main/data/workspace/media.cljs:272, src/app/main/ui/components/color_bullet.cljs:32, src/app/main/ui/components/color_bullet.cljs:45, src/app/main/ui/viewer/inspect/attributes/common.cljs:66, src/app/main/ui/workspace/colorpicker.cljs:231, src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs:240 +msgid "media.image" +msgstr "Immagine" + +#: src/app/main/ui/viewer/inspect/attributes/common.cljs:77 +msgid "media.image.short" +msgstr "Img" + +#: src/app/main/ui/workspace/colorpicker.cljs:337 +msgid "media.keep-aspect-ratio" +msgstr "Mantieni proporzioni" + +#: src/app/main/ui/workspace/context_menu.cljs:651 +msgid "workspace.context-menu.grid-cells.create-board" +msgstr "Crea tavola da disegno" diff --git a/frontend/translations/lv.po b/frontend/translations/lv.po index 732ad1551c..8973eaf1dc 100644 --- a/frontend/translations/lv.po +++ b/frontend/translations/lv.po @@ -1,7 +1,7 @@ msgid "" msgstr "" -"PO-Revision-Date: 2024-11-14 11:14+0000\n" -"Last-Translator: Anonymous \n" +"PO-Revision-Date: 2024-11-20 09:00+0000\n" +"Last-Translator: Edgars Andersons \n" "Language-Team: Latvian \n" "Language: lv\n" @@ -584,7 +584,8 @@ msgstr "Ak vai! Šo datni nevarēja ievietot" #, unused msgid "dashboard.import.analyze-error.components-v2" -msgstr "Datne ar v2 sastāvdaļām ir aktivizēta, bet šī komanda to vēl neatbalsta." +msgstr "" +"Datne ar v2 sastāvdaļām ir aktivizēta, bet šī komanda to vēl nenodrošina." #: src/app/main/ui/dashboard/import.cljs:292 msgid "dashboard.import.import-error" @@ -5584,9 +5585,12 @@ msgid "workspace.plugins.permissions.content-write" msgstr "Lasīt un mainīt datņu, kurām lietotājiem ir piekļuve, saturu." #: src/app/main/ui/workspace/plugins.cljs:323 -#, fuzzy msgid "workspace.plugins.permissions.disclaimer" -msgstr "Jāņem vērā, ka šo spraudni ir izveidojusi trešā puse." +msgstr "" +"Lūgums ņemt vērā, ka šo spraudni izveidoja trešā puse, tāpēc pirms piekļuves " +"nodrošināšanas jāpārliecinās par tās uzticamību. Mums ir svarīga Tavu datu " +"privātums un drošība. Ja ir kādas neskaidrības, lūgums sazināties ar " +"atbalstu." #: src/app/main/ui/workspace/plugins.cljs:263 msgid "workspace.plugins.permissions.library-read" @@ -5597,9 +5601,8 @@ msgid "workspace.plugins.permissions.library-write" msgstr "Lasīt un mainīt bibliotēkas un līdzekļus." #: src/app/main/ui/workspace/plugins.cljs:316 -#, fuzzy msgid "workspace.plugins.permissions.title" -msgstr "ŠIS SPRAUDNIS PIEPRASA PIEKĻUVI:" +msgstr "SPRAUDNIS \"%s\" PIEPRASA PIEKĻUVI:" #: src/app/main/ui/workspace/plugins.cljs:250 msgid "workspace.plugins.permissions.user-read" @@ -6117,3 +6120,439 @@ msgstr "Atjaunināt" #, unused msgid "workspace.viewport.click-to-close-path" msgstr "Jānoklikšķina, lai aizvērtu ceļu" + +#: src/app/main/ui/dashboard/files.cljs:190, src/app/main/ui/dashboard/projects.cljs:284 +msgid "dashboard.empty-placeholder-drafts-subtitle" +msgstr "" +"Tiklīdz projekta dalībnieks izveidos melnrakstu, tas šeit tiks parādīts." + +#: src/app/main/ui/dashboard/files.cljs:186, src/app/main/ui/dashboard/projects.cljs:280 +msgid "dashboard.empty-placeholder-files-title" +msgstr "Vēl nav nevienas datnes." + +#: src/app/main/ui/dashboard/files.cljs:191, src/app/main/ui/dashboard/projects.cljs:285 +msgid "dashboard.empty-placeholder-files-subtitle" +msgstr "Tiklīdz projekta dalībnieks izveidos datni, tā šeit tiks parādīta." + +#: src/app/main/ui/dashboard/placeholder.cljs +#, markdown, unused +msgid "dashboard.empty-placeholder-libraries-subtitle" +msgstr "" +"Šeit parādīsies projektam pievienotās bibliotēkas. Mēģini kopīgot savas " +"datnes vai pievienot no mūsu [bibliotēkām un sagatavēm](https://penpot.app/" +"libraries-templates)!" + +#: src/app/main/ui/dashboard/placeholder.cljs:32 +msgid "dashboard.empty-placeholder-libraries-title" +msgstr "Vēl nav nevienas bibliotēkas." + +#: src/app/main/ui/dashboard/placeholder.cljs:35 +msgid "dashboard.empty-placeholder-libraries-subtitle-viewer-role" +msgstr "Šeit parādīsies projektam pievienotās bibliotēkas." + +#: src/app/main/ui/dashboard/placeholder.cljs:39 +#, markdown +msgid "dashboard.empty-placeholder-libraries" +msgstr "" +"Šeit parādīsies projektam pievienotās bibliotēkas. Mēģini kopīgot savas " +"datnes vai pievienot no mūsu [bibliotēkām un sagatavēm](https://penpot.app/" +"libraries-templates)!" + +#: src/app/main/ui/dashboard/team.cljs:944 +msgid "dashboard.webhooks.cant-edit" +msgstr "Var izdzēst vai mainīt tikai paša izveidotās tīmekļa aizķeres." + +#: src/app/main/ui/comments.cljs:340, src/app/main/ui/workspace/sidebar/options/menus/text.cljs:295, src/app/main/ui/workspace/sidebar/options/menus/text.cljs:324 +msgid "labels.options" +msgstr "Iespējas" + +#: src/app/main/ui/workspace/tokens/sidebar.cljs:229 +msgid "labels.sets" +msgstr "Kopas" + +#: src/app/main/ui/workspace/sidebar/assets/components.cljs:532 +msgid "workspace.assets.components.add-component" +msgstr "Pievienot sastāvdaļu" + +#: src/app/main/ui/workspace/sidebar/options/menus/blur.cljs:108 +msgid "workspace.options.blur-options.toggle-blur" +msgstr "Pārslēgt aizmiglojumu" + +#: src/app/main/ui/workspace/sidebar/options/menus/frame_grid.cljs:323 +msgid "workspace.options.guides.add-guide" +msgstr "Pievienot vadlīniju" + +#: src/app/main/ui/workspace/sidebar/options/menus/frame_grid.cljs:187 +msgid "workspace.options.guides.remove-guide" +msgstr "Noņemt vadlīniju" + +#: src/app/main/ui/workspace/sidebar/options/menus/frame_grid.cljs:183 +msgid "workspace.options.guides.toggle-guide" +msgstr "Pārslēgt vadlīniju" + +#: src/app/main/ui/workspace/sidebar/options/menus/shadow.cljs:173 +msgid "workspace.options.shadow-options.toggle-shadow" +msgstr "Pārslēgt ēnu" + +#: src/app/main/ui/workspace/sidebar/options/menus/stroke.cljs:171 +msgid "workspace.options.stroke.add-stroke" +msgstr "Pievienot vilkuma krāsu" + +#: src/app/main/ui/workspace/plugins.cljs:372 +msgid "workspace.plugins.permissions-update.title" +msgstr "ATJAUNINĀT ŠO SPRAUDNI" + +#: src/app/main/ui/workspace/plugins.cljs:376 +msgid "workspace.plugins.permissions-update.warning" +msgstr "" +"Spraudnis kopš pēdējās atvēršanas reizes ir mainīts. Tam tagad ir vajadzīga " +"piekļuve:" + +#: src/app/main/ui/workspace/plugins.cljs:86 +msgid "workspace.plugins.remove-plugin" +msgstr "Noņemt spraudni" + +#: src/app/main/ui/workspace/tokens/modals/themes.cljs:142 +msgid "workspace.token.no-sets" +msgstr "Nav kopu" + +#: src/app/main/ui/workspace/tokens/modals/themes.cljs:133 +msgid "workspace.token.num-sets" +msgstr "%s kopas" + +#: src/app/main/ui/workspace/tokens/sidebar.cljs:66 +msgid "workspace.token.original-value" +msgstr "Sākotnējā vērtība: " + +#: src/app/main/ui/workspace/tokens/sets.cljs:172 +msgid "workspace.token.select-set" +msgstr "Atlasīt kopu." + +#: src/app/main/ui/dashboard/fonts.cljs:444 +msgid "dashboard.fonts.empty-placeholder-viewer" +msgstr "Vēl nav neviena pielāgota fonta." + +#: src/app/main/data/common.cljs:206 +msgid "dashboard.permissions-change.owner" +msgstr "Tu tagad esi šīs komandas īpašnieks." + +#: src/app/main/data/common.cljs:203 +msgid "dashboard.permissions-change.viewer" +msgstr "Tev tagad šajā komandā ir skatīšanās tiesības." + +#: src/app/main/ui/workspace/sidebar/versions.cljs:149, src/app/main/ui/workspace/sidebar/versions.cljs:288 +msgid "labels.restore" +msgstr "Atjaunot" + +#: src/app/main/ui/workspace/tokens/sidebar.cljs:187 +msgid "labels.themes" +msgstr "Izskati" + +#: src/app/main/ui/dashboard/team.cljs:216 +msgid "modals.invite-team-member.text" +msgstr "" +"Komandā var uzaicināt dalībniekus, lai viņi varētu piekļūt šai un citām " +"komandas datnēm." + +#: src/app/main/ui/workspace/sidebar/assets/colors.cljs:495 +msgid "workspace.assets.colors.add-color" +msgstr "Pievienot krāsu" + +#: src/app/main/ui/workspace/libraries.cljs:300 +msgid "workspace.libraries.more-templates" +msgstr "Var meklēt " + +#: src/app/main/ui/workspace/libraries.cljs:304 +msgid "workspace.libraries.more-templates-link" +msgstr "vairāk sagatavju šeit" + +#: src/app/main/ui/workspace/sidebar/options/menus/blur.cljs:91 +msgid "workspace.options.blur-options.add-blur" +msgstr "Pievienot aizmiglojumu" + +#: src/app/main/ui/workspace/sidebar/options/menus/fill.cljs:150 +msgid "workspace.options.fill.add-fill" +msgstr "Pievienot aizpildījuma krāsu" + +#: src/app/main/ui/workspace/sidebar/options/menus/fill.cljs:163 +msgid "workspace.options.fill.remove-fill" +msgstr "Noņemt aizpildījumu" + +#: src/app/main/ui/workspace/sidebar/options/menus/layer.cljs:176, src/app/main/ui/workspace/sidebar/options/menus/layer.cljs:182 +msgid "workspace.options.layer-options.toggle-layer" +msgstr "Pārslēgt slāņa redzamību" + +#: src/app/main/ui/workspace/sidebar/options/menus/shadow.cljs:177, src/app/main/ui/workspace/sidebar/options/menus/shadow.cljs:315 +msgid "workspace.options.shadow-options.remove-shadow" +msgstr "Noņemt ēnu" + +#: src/app/main/ui/workspace/sidebar/options/menus/stroke.cljs:184 +msgid "workspace.options.stroke.remove-stroke" +msgstr "Noņemt vilkumu" + +#: src/app/main/data/plugins.cljs:86, src/app/main/ui/workspace/main_menu.cljs:696, src/app/main/ui/workspace/plugins.cljs:82 +msgid "workspace.plugins.error.need-editor" +msgstr "Jābūt redaktoram, lai izmantotu šo spraudni" + +#: src/app/main/ui/workspace/plugins.cljs:283 +msgid "workspace.plugins.permissions.allow-download" +msgstr "Uzsākt datņu lejupielādi." + +#: src/app/main/ui/workspace/plugins.cljs:276 +msgid "workspace.plugins.permissions.comment-read" +msgstr "Lasīt savas piebildes un atbildes." + +#: src/app/main/ui/workspace/plugins.cljs:270 +msgid "workspace.plugins.permissions.comment-write" +msgstr "Lasīt un mainīt savas piebildes un atbildēt savā vārdā." + +#: src/app/main/ui/workspace/plugins.cljs:436 +msgid "workspace.plugins.try-out.cancel" +msgstr "NE TAGAD" + +#: src/app/main/ui/workspace/tokens/sets.cljs:216 +msgid "workspace.token.no-sets-create" +msgstr "Vēl nav nevienas kopas. Vispirms ir jāizveido kāda." + +#: src/app/main/ui/workspace/tokens/sidebar.cljs:239 +msgid "workspace.token.no-sets-yet" +msgstr "Šeit vēl nav nevienas kopas." + +#: src/app/main/ui/workspace/sidebar/versions.cljs:187 +msgid "workspace.versions.autosaved.version" +msgstr "Automātiski saglabāts %s" + +#: src/app/main/ui/workspace/sidebar/versions.cljs:224 +msgid "workspace.versions.button.pin" +msgstr "Piespraust versiju" + +#: src/app/main/ui/workspace/sidebar/versions.cljs:345, src/app/main/ui/workspace/sidebar/versions.cljs:347 +msgid "workspace.versions.button.save" +msgstr "Saglabāt versiju" + +#: src/app/main/ui/workspace/sidebar/versions.cljs:190 +msgid "workspace.versions.expand-snapshot" +msgstr "Izvērst momentuzņēmumus" + +#: src/app/main/ui/workspace/sidebar/versions.cljs:327 +msgid "workspace.versions.filter.all" +msgstr "Visas versijas" + +#: src/app/main/ui/workspace/sidebar/versions.cljs:326 +msgid "workspace.versions.filter.label" +msgstr "Versiju atlasīšana" + +#: src/app/main/ui/workspace/sidebar/versions.cljs:328 +msgid "workspace.versions.filter.mine" +msgstr "Manas versijas" + +#: src/app/main/ui/workspace/sidebar/versions.cljs:334 +msgid "workspace.versions.filter.user" +msgstr "%s versijas" + +#: src/app/main/ui/workspace/sidebar/versions.cljs:283 +msgid "workspace.versions.restore-warning" +msgstr "Vai atjaunot šo versiju?" + +#: src/app/main/ui/workspace/sidebar/versions.cljs:207 +msgid "workspace.versions.snapshot-menu" +msgstr "Atvērt momentuzņēmumu izvēlni" + +#: src/app/main/ui/workspace/sidebar/versions.cljs:138 +msgid "workspace.versions.version-menu" +msgstr "Atvērt versiju izvēlni" + +#: src/app/main/ui/dashboard/files.cljs:185, src/app/main/ui/dashboard/projects.cljs:279 +msgid "dashboard.empty-placeholder-drafts-title" +msgstr "Vēl nav neviena melnraksta." + +#: src/app/main/ui/dashboard/fonts.cljs:445 +msgid "dashboard.fonts.empty-placeholder-viewer-sub" +msgstr "" +"Tiklīdz projekta dalībnieks augšupielādēs pielāgotu fontu, tas šeit tiks " +"parādīts." + +#: src/app/main/data/common.cljs:205 +msgid "dashboard.permissions-change.admin" +msgstr "Tu tagad esi šīs komandas pārvaldītājs." + +#: src/app/main/data/common.cljs:204 +msgid "dashboard.permissions-change.editor" +msgstr "Tu tagad esi šīs komandas redaktors." + +#: src/app/main/data/common.cljs:233 +msgid "dashboard.removed-from-team" +msgstr "Tu vairs neesi daļa no komandas \"%s\"." + +#: src/app/main/ui/workspace/sidebar/options/menus/exports.cljs:195 +msgid "workspace.options.export.add-export" +msgstr "Pievienot izguvi" + +#: src/app/main/ui/workspace/sidebar/assets/typographies.cljs:408 +msgid "workspace.assets.typography.add-typography" +msgstr "Pievienot tipogrāfiju" + +#: src/app/main/ui/workspace/sidebar/options/menus/blur.cljs:112 +msgid "workspace.options.blur-options.remove-blur" +msgstr "Noņemt aizmiglojumu" + +#: src/app/main/ui/workspace/right_header.cljs:255 +msgid "workspace.header.share" +msgstr "Kopīgot" + +#: src/app/main/ui/workspace/sidebar/options/menus/exports.cljs:207, src/app/main/ui/workspace/sidebar/options/menus/exports.cljs:242 +msgid "workspace.options.export.remove-export" +msgstr "Noņemt izguvi" + +#: src/app/main/ui/workspace/sidebar/options/menus/shadow.cljs:302 +msgid "workspace.options.shadow-options.add-shadow" +msgstr "Pievienot ēnu" + +#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs:154 +msgid "workspace.options.flows.remove-flow" +msgstr "Noņemt plūsmu" + +#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs:735 +msgid "workspace.options.interactions.add-interaction" +msgstr "Pievienot mijiedarbību" + +#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs +#, unused +msgid "workspace.options.interactions.remove-interaction" +msgstr "Noņemt mijiedarbību" + +#: src/app/main/ui/workspace/plugins.cljs:196 +msgid "workspace.plugins.error.manifest" +msgstr "Spraudņa deklarācija ir nepareiza." + +#: src/app/main/ui/workspace/sidebar/versions.cljs:193 +msgid "workspace.versions.autosaved.entry" +msgstr "%s automātiskās saglabāšanas versijas" + +#: src/app/main/ui/workspace/sidebar/versions.cljs:219 +msgid "workspace.versions.button.restore" +msgstr "Atjaunot versiju" + +#: src/app/main/ui/workspace/sidebar/versions.cljs:354 +msgid "workspace.versions.empty" +msgstr "Vēl nav nevienas versijas" + +#: src/app/main/ui/workspace/sidebar/versions.cljs:340 +msgid "workspace.versions.loading" +msgstr "Ielādē..." + +#: src/app/main/ui/dashboard/team.cljs:181, src/app/main/ui/onboarding/team_choice.cljs:100 +msgid "errors.maximum-invitations-by-request-reached" +msgstr "" +"Sasniegts lielākais pieļaujamais e-pasta adrešu skaits (%s), ko var " +"uzaicināt vienā pieprasījumā" + +#: src/app/main/ui/workspace/sidebar/options/menus/layout_container.cljs:1051 +#, unused +msgid "labels.add" +msgstr "Pievienot" + +#: src/app/main/ui/workspace/tokens/sets.cljs:153 +msgid "labels.collapse" +msgstr "Sakļaut" + +#: src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs:271 +msgid "settings.remove-color" +msgstr "Noņemt krāsu" + +#: src/app/main/ui/workspace/plugins.cljs:425 +msgid "workspace.plugins.try-out.title" +msgstr "SPRAUDNIS \"%s\" IR UZSTĀDĪTS." + +#: src/app/main/ui/workspace/tokens/modals/themes.cljs:147 +msgid "workspace.token.delete-theme-title" +msgstr "Izdzēst izskatu" + +#: src/app/main/ui/workspace/tokens/modals/themes.cljs:302 +msgid "workspace.token.edit-theme-title" +msgstr "Labot izskatu" + +#: src/app/main/ui/workspace/tokens/theme_select.cljs:88 +msgid "workspace.token.no-active-theme" +msgstr "Nav izvēlēts izskats" + +#: src/app/main/ui/workspace/tokens/modals/themes.cljs:208 +msgid "workspace.token.save-theme" +msgstr "Saglabāt izskatu" + +#: src/app/main/ui/workspace/tokens/modals/themes.cljs +#, unused +msgid "workspace.token.theme-name" +msgstr "Izskats \"%s\"" + +#: src/app/main/ui/workspace/tokens/modals/themes.cljs:39, src/app/main/ui/workspace/tokens/modals/themes.cljs:84 +msgid "workspace.token.themes" +msgstr "Izskati" + +#: src/app/main/ui/workspace/plugins.cljs:429 +msgid "workspace.plugins.try-out.message" +msgstr "" +"Vēlies izmēģināt? Tas tiks atvērts jaunā melnrakstā Tavai pašreizējai " +"komandai. (Ja nē, vienmēr to var atrast jebkuras datnes uzstādītajos " +"spraudņos.)" + +#: src/app/main/ui/workspace/plugins.cljs:442 +msgid "workspace.plugins.try-out.try" +msgstr "IZMĒĢINĀT SPRAUDNI" + +#: src/app/main/ui/workspace/sidebar/options/menus/layout_container.cljs:1022 +msgid "workspace.shape.menu.remove-layout" +msgstr "Noņemt izkārtojumu" + +#: src/app/main/ui/workspace/context_menu.cljs:235 +msgid "workspace.shape.menu.rename" +msgstr "Pārdēvēt" + +#: src/app/main/ui/workspace/sidebar/sitemap.cljs:229 +msgid "workspace.sidebar.sitemap.add-page" +msgstr "Pievienot lapu" + +#: src/app/main/ui/workspace/tokens/theme_select.cljs:84 +msgid "workspace.token.active-themes" +msgstr "%s aktīvi izskati" + +#: src/app/main/ui/workspace/tokens/sidebar.cljs +#, unused +msgid "workspace.token.add set" +msgstr "Pievienot kopu" + +#: src/app/main/ui/workspace/tokens/modals/themes.cljs:310 +msgid "workspace.token.back-to-themes" +msgstr "Atpakaļ uz izskatu sarakstu" + +#: src/app/main/ui/workspace/tokens/modals/themes.cljs:47 +msgid "workspace.token.create-new-theme" +msgstr "Tagad izveido savu pirmo izskatu!" + +#: src/app/main/ui/workspace/tokens/modals/themes.cljs:52 +msgid "workspace.token.new-theme" +msgstr "Jauns izskats" + +#: src/app/main/ui/workspace/tokens/sidebar.cljs:191 +msgid "workspace.token.no-themes" +msgstr "Šeit nav izskatu." + +#: src/app/main/ui/workspace/tokens/modals/themes.cljs:43 +msgid "workspace.token.no-themes-currently" +msgstr "Pašlaik nav izskatu." + +#: src/app/main/ui/workspace/tokens/sidebar.cljs:194, src/app/main/ui/workspace/tokens/sidebar.cljs:210 +msgid "workspace.token.create-one" +msgstr "Izveidot kādu." + +#: src/app/main/ui/workspace/tokens/modals/themes.cljs:155, src/app/main/ui/workspace/tokens/modals/themes.cljs:239 +msgid "workspace.token.create-theme-title" +msgstr "Izveidot izskatu" + +#: src/app/main/ui/workspace/tokens/theme_select.cljs:72 +msgid "workspace.token.edit-themes" +msgstr "Labot izskatus" + +#: src/app/main/ui/workspace/sidebar/options/menus/layout_container.cljs:1004, src/app/main/ui/workspace/sidebar/options/menus/layout_container.cljs:1030 +msgid "workspace.shape.menu.add-layout" +msgstr "Pievienot izkārtojumu" diff --git a/frontend/translations/nl.po b/frontend/translations/nl.po index d2a91aa0bf..a20abd162e 100644 --- a/frontend/translations/nl.po +++ b/frontend/translations/nl.po @@ -1,7 +1,7 @@ msgid "" msgstr "" -"PO-Revision-Date: 2024-11-14 11:14+0000\n" -"Last-Translator: Anonymous \n" +"PO-Revision-Date: 2024-11-16 13:00+0000\n" +"Last-Translator: Stephan Paternotte \n" "Language-Team: Dutch \n" "Language: nl\n" @@ -5589,9 +5589,12 @@ msgid "workspace.plugins.permissions.content-write" msgstr "Lees en wijzig de inhoud van bestanden waartoe gebruikers toegang hebben." #: src/app/main/ui/workspace/plugins.cljs:323 -#, fuzzy msgid "workspace.plugins.permissions.disclaimer" -msgstr "Merk op dat deze plug-in is gemaakt door een externe partij." +msgstr "" +"Houd er rekening mee dat deze plug-in is gemaakt door een externe partij, " +"dus zorg ervoor dat je deze vertrouwt voordat je toegang verleent. Privacy " +"van jouw gegevens en beveiliging zijn belangrijk voor ons. Als je je zorgen " +"maakt, neem dan contact op met ondersteuning." #: src/app/main/ui/workspace/plugins.cljs:263 msgid "workspace.plugins.permissions.library-read" @@ -5602,9 +5605,8 @@ msgid "workspace.plugins.permissions.library-write" msgstr "Jouw bibliotheken en middelen lezen en aanpassen." #: src/app/main/ui/workspace/plugins.cljs:316 -#, fuzzy msgid "workspace.plugins.permissions.title" -msgstr "DEZE PLUGIN WIL TOEGANG TOT:" +msgstr "PLUG-IN '%s' WIL TOEGANG TOT:" #: src/app/main/ui/workspace/plugins.cljs:250 msgid "workspace.plugins.permissions.user-read" @@ -6122,3 +6124,462 @@ msgstr "Bijwerken" #, unused msgid "workspace.viewport.click-to-close-path" msgstr "Klik om het pad te sluiten" + +#: src/app/main/ui/dashboard/files.cljs:185, src/app/main/ui/dashboard/projects.cljs:279 +msgid "dashboard.empty-placeholder-drafts-title" +msgstr "Nog geen concepten." + +#: src/app/main/ui/dashboard/files.cljs:186, src/app/main/ui/dashboard/projects.cljs:280 +msgid "dashboard.empty-placeholder-files-title" +msgstr "Nog geen bestanden." + +#: src/app/main/ui/dashboard/placeholder.cljs:39 +#, markdown +msgid "dashboard.empty-placeholder-libraries" +msgstr "" +"Hier verschijnen bibliotheken die aan het project zijn toegevoegd. Probeer " +"je bestanden te delen of voeg ze toe vanuit onze [Bibliotheken en sjablonen] " +"(https://penpot.app/libraries-templates)." + +#: src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs:271 +msgid "settings.remove-color" +msgstr "Kleur verwijderen" + +#: src/app/main/ui/workspace/sidebar/assets/colors.cljs:495 +msgid "workspace.assets.colors.add-color" +msgstr "Kleur toevoegen" + +#: src/app/main/ui/workspace/sidebar/assets/components.cljs:532 +msgid "workspace.assets.components.add-component" +msgstr "Component toevoegen" + +#: src/app/main/ui/workspace/libraries.cljs:300 +msgid "workspace.libraries.more-templates" +msgstr "Je kun hier " + +#: src/app/main/ui/workspace/sidebar/options/menus/exports.cljs:195 +msgid "workspace.options.export.add-export" +msgstr "Export toevoegen" + +#: src/app/main/ui/workspace/sidebar/options/menus/exports.cljs:207, src/app/main/ui/workspace/sidebar/options/menus/exports.cljs:242 +msgid "workspace.options.export.remove-export" +msgstr "Export verwijderen" + +#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs:154 +msgid "workspace.options.flows.remove-flow" +msgstr "Stroomdiagram verwijderen" + +#: src/app/main/ui/workspace/sidebar/options/menus/frame_grid.cljs:323 +msgid "workspace.options.guides.add-guide" +msgstr "Hulplijn toevoegen" + +#: src/app/main/ui/workspace/sidebar/options/menus/frame_grid.cljs:187 +msgid "workspace.options.guides.remove-guide" +msgstr "Hulplijn verwijderen" + +#: src/app/main/ui/workspace/sidebar/options/menus/stroke.cljs:171 +msgid "workspace.options.stroke.add-stroke" +msgstr "Streekkleur toevoegen" + +#: src/app/main/ui/workspace/plugins.cljs:376 +msgid "workspace.plugins.permissions-update.warning" +msgstr "" +"De plug-in is gewijzigd sinds je hem voor het laatst hebt geopend. Het wil " +"nu ook toegang krijgen tot:" + +#: src/app/main/ui/workspace/plugins.cljs:283 +msgid "workspace.plugins.permissions.allow-download" +msgstr "Bestandsdownloads starten." + +#: src/app/main/ui/workspace/plugins.cljs:276 +msgid "workspace.plugins.permissions.comment-read" +msgstr "Jouw opmerkingen en antwoorden lezen." + +#: src/app/main/ui/workspace/tokens/modals/themes.cljs:47 +msgid "workspace.token.create-new-theme" +msgstr "Maak nu je eerste thema aan." + +#: src/app/main/ui/workspace/tokens/sidebar.cljs:194, src/app/main/ui/workspace/tokens/sidebar.cljs:210 +msgid "workspace.token.create-one" +msgstr "Maak er een aan." + +#: src/app/main/ui/workspace/tokens/modals/themes.cljs:155, src/app/main/ui/workspace/tokens/modals/themes.cljs:239 +msgid "workspace.token.create-theme-title" +msgstr "Thema aanmaken" + +#: src/app/main/ui/workspace/tokens/form.cljs:362 +msgid "workspace.token.create-token" +msgstr "Nieuw %s token aanmaken" + +#: src/app/main/ui/workspace/tokens/modals/themes.cljs:147 +msgid "workspace.token.delete-theme-title" +msgstr "Thema verwijderen" + +#: src/app/main/ui/workspace/tokens/modals/themes.cljs +#, unused +msgid "workspace.token.theme-name" +msgstr "Thema %s" + +#: src/app/main/ui/workspace/tokens/form.cljs:193, src/app/main/ui/workspace/tokens/form.cljs:196, src/app/main/ui/workspace/tokens/sidebar.cljs:67 +msgid "workspace.token.resolved-value" +msgstr "Besloten waarde: " + +#: src/app/main/ui/workspace/tokens/modals/themes.cljs:208 +msgid "workspace.token.save-theme" +msgstr "Thema opslaan" + +#: src/app/main/ui/workspace/tokens/sets.cljs:172 +msgid "workspace.token.select-set" +msgstr "Verzameling kiezen." + +#: src/app/main/ui/workspace/tokens/modals/themes.cljs:318 +msgid "workspace.token.set-selection-theme" +msgstr "" +"Bepaal welke tokenverzamelingen moeten worden gebruikt als onderdeel van " +"deze thema-optie:" + +#: src/app/main/ui/workspace/sidebar/versions.cljs:193 +msgid "workspace.versions.autosaved.entry" +msgstr "%s autom. opgeslagen versies" + +#: src/app/main/ui/workspace/sidebar/versions.cljs:187 +msgid "workspace.versions.autosaved.version" +msgstr "Autom. opgeslagen %s" + +#: src/app/main/ui/workspace/sidebar/versions.cljs:224 +msgid "workspace.versions.button.pin" +msgstr "Versie vastmaken" + +#: src/app/main/ui/workspace/sidebar/versions.cljs:219 +msgid "workspace.versions.button.restore" +msgstr "Versie herstellen" + +#: src/app/main/ui/workspace/sidebar/versions.cljs:354 +msgid "workspace.versions.empty" +msgstr "Er zijn nog geen versies" + +#: src/app/main/ui/dashboard/files.cljs:190, src/app/main/ui/dashboard/projects.cljs:284 +msgid "dashboard.empty-placeholder-drafts-subtitle" +msgstr "" +"Zodra een projectlid een concept heeft gemaakt, wordt het hier weergegeven." + +#: src/app/main/ui/dashboard/files.cljs:191, src/app/main/ui/dashboard/projects.cljs:285 +msgid "dashboard.empty-placeholder-files-subtitle" +msgstr "" +"Zodra een projectlid een bestand heeft gemaakt, wordt het hier weergegeven." + +#: src/app/main/ui/dashboard/placeholder.cljs:35 +msgid "dashboard.empty-placeholder-libraries-subtitle-viewer-role" +msgstr "Hier verschijnen bibliotheken die aan het project zijn toegevoegd." + +#: src/app/main/ui/dashboard/placeholder.cljs:32 +msgid "dashboard.empty-placeholder-libraries-title" +msgstr "Nog geen bibliotheken." + +#: src/app/main/ui/dashboard/fonts.cljs:444 +msgid "dashboard.fonts.empty-placeholder-viewer" +msgstr "Nog geen aangepaste lettertypen." + +#: src/app/main/data/common.cljs:205 +msgid "dashboard.permissions-change.admin" +msgstr "Je bent nu een beheerder van dit team." + +#: src/app/main/data/common.cljs:204 +msgid "dashboard.permissions-change.editor" +msgstr "Je bent nu redacteur van dit team." + +#: src/app/main/data/common.cljs:206 +msgid "dashboard.permissions-change.owner" +msgstr "Je bent nu eigenaar van dit team." + +#: src/app/main/data/common.cljs:203 +msgid "dashboard.permissions-change.viewer" +msgstr "Je bent nu een lezer in dit team." + +#: src/app/main/data/common.cljs:233 +msgid "dashboard.removed-from-team" +msgstr "Je maakt geen deel meer uit van het team “%s“." + +#: src/app/main/ui/dashboard/team.cljs:181, src/app/main/ui/onboarding/team_choice.cljs:100 +msgid "errors.maximum-invitations-by-request-reached" +msgstr "" +"Het maximale (%s) aantal e-mails dat in één verzoek kan worden uitgenodigd, " +"is bereikt" + +#: src/app/main/ui/workspace/tokens/sets.cljs:153 +msgid "labels.collapse" +msgstr "Samenvouwen" + +#: src/app/main/ui/comments.cljs:340, src/app/main/ui/workspace/sidebar/options/menus/text.cljs:295, src/app/main/ui/workspace/sidebar/options/menus/text.cljs:324 +msgid "labels.options" +msgstr "Opties" + +#: src/app/main/ui/workspace/sidebar/versions.cljs:149, src/app/main/ui/workspace/sidebar/versions.cljs:288 +msgid "labels.restore" +msgstr "Herstellen" + +#: src/app/main/ui/workspace/tokens/sidebar.cljs:229 +msgid "labels.sets" +msgstr "Verzamelingen" + +#: src/app/main/ui/workspace/tokens/sidebar.cljs:187 +msgid "labels.themes" +msgstr "Thema's" + +#: src/app/main/ui/workspace/sidebar/assets/typographies.cljs:408 +msgid "workspace.assets.typography.add-typography" +msgstr "Typografie toevoegen" + +#: src/app/main/ui/workspace/right_header.cljs:255 +msgid "workspace.header.share" +msgstr "Delen" + +#: src/app/main/ui/workspace/libraries.cljs:304 +msgid "workspace.libraries.more-templates-link" +msgstr "meer sjablonen zoeken" + +#: src/app/main/ui/workspace/sidebar/options/menus/blur.cljs:91 +msgid "workspace.options.blur-options.add-blur" +msgstr "Vervaging toevoegen" + +#: src/app/main/ui/workspace/sidebar/options/menus/blur.cljs:112 +msgid "workspace.options.blur-options.remove-blur" +msgstr "Vervaging verwijderen" + +#: src/app/main/ui/workspace/sidebar/options/menus/blur.cljs:108 +msgid "workspace.options.blur-options.toggle-blur" +msgstr "Vervaging wisselen" + +#: src/app/main/ui/workspace/sidebar/options/menus/fill.cljs:150 +msgid "workspace.options.fill.add-fill" +msgstr "Vulkleur toevoegen" + +#: src/app/main/ui/workspace/sidebar/options/menus/fill.cljs:163 +msgid "workspace.options.fill.remove-fill" +msgstr "Vulling verwijderen" + +#: src/app/main/ui/workspace/sidebar/options/menus/frame_grid.cljs:183 +msgid "workspace.options.guides.toggle-guide" +msgstr "Hulplijn wisselen" + +#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs:735 +msgid "workspace.options.interactions.add-interaction" +msgstr "Interactie toevoegen" + +#: src/app/main/ui/workspace/sidebar/options/menus/shadow.cljs:177, src/app/main/ui/workspace/sidebar/options/menus/shadow.cljs:315 +msgid "workspace.options.shadow-options.remove-shadow" +msgstr "Schaduw verwijderen" + +#: src/app/main/ui/workspace/sidebar/options/menus/stroke.cljs:184 +msgid "workspace.options.stroke.remove-stroke" +msgstr "Streek verwijderen" + +#: src/app/main/ui/workspace/plugins.cljs:196 +msgid "workspace.plugins.error.manifest" +msgstr "Het plug-in-manifest is onjuist." + +#: src/app/main/data/plugins.cljs:86, src/app/main/ui/workspace/main_menu.cljs:696, src/app/main/ui/workspace/plugins.cljs:82 +msgid "workspace.plugins.error.need-editor" +msgstr "Je moet een redacteur zijn om deze plug-in te gebruiken" + +#: src/app/main/ui/workspace/plugins.cljs:372 +msgid "workspace.plugins.permissions-update.title" +msgstr "DEZE PLUGIN UPDATEN" + +#: src/app/main/ui/workspace/plugins.cljs:270 +msgid "workspace.plugins.permissions.comment-write" +msgstr "Lees en wijzig jouw opmerkingen en antwoord in jouw naam." + +#: src/app/main/ui/workspace/plugins.cljs:86 +msgid "workspace.plugins.remove-plugin" +msgstr "Plug-in verwijderen" + +#: src/app/main/ui/workspace/plugins.cljs:436 +msgid "workspace.plugins.try-out.cancel" +msgstr "NIET NU" + +#: src/app/main/ui/workspace/plugins.cljs:429 +msgid "workspace.plugins.try-out.message" +msgstr "" +"Wil je even kijken? Het wordt geopend in een nieuw concept voor je huidige " +"team. (Zo niet, dan vindt je het altijd in de geïnstalleerde plug-ins van " +"elk bestand.)" + +#: src/app/main/ui/workspace/plugins.cljs:425 +msgid "workspace.plugins.try-out.title" +msgstr "PLUG-IN '%s' IS GEÏNSTALLEERD VOOR JE GEBRUIKER!" + +#: src/app/main/ui/workspace/plugins.cljs:442 +msgid "workspace.plugins.try-out.try" +msgstr "PLUG-IN UITPROBEREN" + +#: src/app/main/ui/workspace/sidebar/options/menus/layout_container.cljs:1004, src/app/main/ui/workspace/sidebar/options/menus/layout_container.cljs:1030 +msgid "workspace.shape.menu.add-layout" +msgstr "Lay-out toevoegen" + +#: src/app/main/ui/workspace/sidebar/options/menus/layout_container.cljs:1022 +msgid "workspace.shape.menu.remove-layout" +msgstr "Lay-out verwijderen" + +#: src/app/main/ui/workspace/context_menu.cljs:235 +msgid "workspace.shape.menu.rename" +msgstr "Naam wijzigen" + +#: src/app/main/ui/workspace/sidebar/sitemap.cljs:229 +msgid "workspace.sidebar.sitemap.add-page" +msgstr "Pagina toevoegen" + +#: src/app/main/ui/workspace/tokens/theme_select.cljs:84 +msgid "workspace.token.active-themes" +msgstr "%s actieve thema's" + +#: src/app/main/ui/workspace/tokens/modals/themes.cljs:310 +msgid "workspace.token.back-to-themes" +msgstr "Terug naar themalijst" + +#: src/app/main/ui/workspace/tokens/modals/themes.cljs:302 +msgid "workspace.token.edit-theme-title" +msgstr "Thema bewerken" + +#: src/app/main/ui/workspace/tokens/theme_select.cljs:72 +msgid "workspace.token.edit-themes" +msgstr "Thema's bewerken" + +#: src/app/main/ui/workspace/tokens/sets.cljs:186 +msgid "workspace.token.grouping-set-alert" +msgstr "Groepering van tokenverzamelingen is nog niet ondersteund." + +#: src/app/main/ui/workspace/tokens/modals/themes.cljs:142 +msgid "workspace.token.no-sets" +msgstr "Geen verzamelingen" + +#: src/app/main/ui/workspace/tokens/sets.cljs:216 +msgid "workspace.token.no-sets-create" +msgstr "Er zijn nog geen verzamelingen gedefinieerd. Maak er eerst een aan." + +#: src/app/main/ui/workspace/tokens/sidebar.cljs:239 +msgid "workspace.token.no-sets-yet" +msgstr "Er zijn nog geen verzamelingen." + +#: src/app/main/ui/workspace/tokens/sidebar.cljs:191 +msgid "workspace.token.no-themes" +msgstr "Er zijn geen thema's." + +#: src/app/main/ui/workspace/tokens/modals/themes.cljs:133 +msgid "workspace.token.num-sets" +msgstr "%s verzamelingen" + +#: src/app/main/ui/workspace/tokens/sidebar.cljs:66 +msgid "workspace.token.original-value" +msgstr "Oorspronkelijke waarde: " + +#: src/app/main/ui/workspace/sidebar/versions.cljs:345, src/app/main/ui/workspace/sidebar/versions.cljs:347 +msgid "workspace.versions.button.save" +msgstr "Versie opslaan" + +#: src/app/main/ui/workspace/sidebar/versions.cljs:190 +msgid "workspace.versions.expand-snapshot" +msgstr "Snapshots uitbreiden" + +#: src/app/main/ui/workspace/sidebar/versions.cljs:327 +msgid "workspace.versions.filter.all" +msgstr "Alle versies" + +#: src/app/main/ui/workspace/sidebar/versions.cljs:326 +msgid "workspace.versions.filter.label" +msgstr "Versiefilter" + +#: src/app/main/ui/workspace/sidebar/versions.cljs:334 +msgid "workspace.versions.filter.user" +msgstr "%s's versies" + +#: src/app/main/ui/workspace/sidebar/versions.cljs:340 +msgid "workspace.versions.loading" +msgstr "Laden…" + +#: src/app/main/ui/workspace/sidebar/versions.cljs:283 +msgid "workspace.versions.restore-warning" +msgstr "Wil je deze versie herstellen?" + +#: src/app/main/ui/workspace/sidebar/versions.cljs:207 +msgid "workspace.versions.snapshot-menu" +msgstr "Snapshot-menu openen" + +#: src/app/main/ui/workspace/sidebar/versions.cljs:138 +msgid "workspace.versions.version-menu" +msgstr "Versie-menu openen" + +#: src/app/main/ui/dashboard/placeholder.cljs +#, markdown, unused +msgid "dashboard.empty-placeholder-libraries-subtitle" +msgstr "" +"Hier verschijnen bibliotheken die aan het project zijn toegevoegd. Probeer " +"je bestanden te delen of voeg ze toe vanuit onze [Bibliotheken en sjablonen] " +"(https://penpot.app/libraries-templates)." + +#: src/app/main/ui/dashboard/fonts.cljs:445 +msgid "dashboard.fonts.empty-placeholder-viewer-sub" +msgstr "" +"Zodra een projectlid een aangepast lettertype heeft geüpload, wordt het hier " +"weergegeven." + +#: src/app/main/ui/dashboard/team.cljs:944 +msgid "dashboard.webhooks.cant-edit" +msgstr "Je kunt alleen door jou gemaakte webhooks verwijderen of wijzigen." + +#: src/app/main/ui/workspace/sidebar/options/menus/layout_container.cljs:1051 +#, unused +msgid "labels.add" +msgstr "Toevoegen" + +#: src/app/main/ui/dashboard/team.cljs:216 +msgid "modals.invite-team-member.text" +msgstr "" +"Je kunt leden uitnodigen voor het team zodat ze toegang hebben tot dit " +"bestand en alle teambestanden." + +#: src/app/main/ui/workspace/sidebar/options/menus/shadow.cljs:173 +msgid "workspace.options.shadow-options.toggle-shadow" +msgstr "Schaduw wisselen" + +#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs +#, unused +msgid "workspace.options.interactions.remove-interaction" +msgstr "Interactie verwijderen" + +#: src/app/main/ui/workspace/sidebar/options/menus/layer.cljs:176, src/app/main/ui/workspace/sidebar/options/menus/layer.cljs:182 +msgid "workspace.options.layer-options.toggle-layer" +msgstr "Laagzichtbaarheid wisselen" + +#: src/app/main/ui/workspace/sidebar/options/menus/shadow.cljs:302 +msgid "workspace.options.shadow-options.add-shadow" +msgstr "Schaduw toevoegen" + +#: src/app/main/ui/workspace/tokens/sidebar.cljs +#, unused +msgid "workspace.token.add set" +msgstr "Verzameling toevoegen" + +#: src/app/main/ui/workspace/tokens/form.cljs:361 +msgid "workspace.token.edit-token" +msgstr "Token bewerken" + +#: src/app/main/ui/workspace/tokens/modals/themes.cljs:52 +msgid "workspace.token.new-theme" +msgstr "Nieuw thema" + +#: src/app/main/ui/workspace/tokens/theme_select.cljs:88 +msgid "workspace.token.no-active-theme" +msgstr "Geen thema actief" + +#: src/app/main/ui/workspace/tokens/modals/themes.cljs:43 +msgid "workspace.token.no-themes-currently" +msgstr "Je hebt momenteel geen thema's." + +#: src/app/main/ui/workspace/tokens/modals/themes.cljs:39, src/app/main/ui/workspace/tokens/modals/themes.cljs:84 +msgid "workspace.token.themes" +msgstr "Thema's" + +#: src/app/main/ui/workspace/sidebar/versions.cljs:328 +msgid "workspace.versions.filter.mine" +msgstr "Mijn versies" diff --git a/frontend/translations/pl.po b/frontend/translations/pl.po index 961a019c8b..6a5bcc7647 100644 --- a/frontend/translations/pl.po +++ b/frontend/translations/pl.po @@ -1,16 +1,16 @@ msgid "" msgstr "" -"PO-Revision-Date: 2024-06-17 08:07+0000\n" -"Last-Translator: Anonymous \n" -"Language-Team: Polish " -"\n" +"PO-Revision-Date: 2024-11-16 13:00+0000\n" +"Last-Translator: Nicola Bortoletto \n" +"Language-Team: Polish \n" "Language: pl\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%10>=2 && n%10<=4 && " -"(n%100<10 || n%100>=20) ? 1 : 2);\n" -"X-Generator: Weblate 5.6-dev\n" +"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 " +"|| n%100>=20) ? 1 : 2);\n" +"X-Generator: Weblate 5.9-dev\n" #: src/app/main/ui/auth/register.cljs:133, src/app/main/ui/static.cljs:154, src/app/main/ui/viewer/login.cljs:98 msgid "auth.already-have-account" @@ -4852,3 +4852,7 @@ msgstr "Aktualizuj" #, unused msgid "workspace.viewport.click-to-close-path" msgstr "Kliknij, aby zamknąć ścieżkę" + +#: src/app/main/ui/workspace/sidebar/assets/typographies.cljs:408 +msgid "workspace.assets.typography.add-typography" +msgstr "" diff --git a/frontend/translations/th.po b/frontend/translations/th.po index 9511968215..b3e89b943e 100644 --- a/frontend/translations/th.po +++ b/frontend/translations/th.po @@ -1,6 +1,860 @@ msgid "" msgstr "" -"X-Generator: Weblate\n" +"PO-Revision-Date: 2024-12-28 16:02+0000\n" +"Last-Translator: Late Night Defender \n" +"Language-Team: Thai " +"\n" +"Language: th\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.10-dev\n" + +#: src/app/main/ui/auth/login.cljs:310, src/app/main/ui/auth/register.cljs:101, src/app/main/ui/auth/register.cljs:240, src/app/main/ui/static.cljs:144, src/app/main/ui/viewer/login.cljs:91 +msgid "auth.register-submit" +msgstr "สร้างบัญชี" + +#: src/app/main/ui/dashboard/sidebar.cljs:571 +msgid "dashboard.delete-team" +msgstr "ลบทีม" + +#: src/app/main/ui/dashboard/file_menu.cljs:328, src/app/main/ui/workspace/main_menu.cljs:621 +msgid "dashboard.download-standard-file" +msgstr "ดาวน์โหลดไฟล์มาตรฐาน (.svg + .json)" + +#: src/app/main/ui/dashboard/file_menu.cljs:40, src/app/main/ui/dashboard/fonts.cljs:34, src/app/main/ui/dashboard/libraries.cljs:44, src/app/main/ui/dashboard/projects.cljs:341, src/app/main/ui/dashboard/search.cljs:31, src/app/main/ui/dashboard/sidebar.cljs:312, src/app/main/ui/dashboard/team.cljs:526, src/app/main/ui/dashboard/team.cljs:766, src/app/main/ui/dashboard/team.cljs:1029, src/app/main/ui/dashboard/team.cljs:1076 +msgid "dashboard.your-penpot" +msgstr "Penpot ของคุณ" + +#: src/app/main/ui/viewer/share_link.cljs:271 +msgid "common.share-link.view-all" +msgstr "เลือกทั้งหมด" + +#: src/app/main/ui/viewer/share_link.cljs:185 +msgid "common.share-link.placeholder" +msgstr "ลิงก์ที่สามารถแชร์ได้จะปรากฏที่นี่" + +#: src/app/main/ui/auth/login.cljs:224 +msgid "auth.login-with-google-submit" +msgstr "Google" + +#: src/app/main/ui/dashboard/projects.cljs:88 +msgid "dasboard.team-hero.management" +msgstr "การจัดการทีม" + +#: src/app/main/ui/dashboard/fonts.cljs:444 +msgid "dashboard.fonts.empty-placeholder-viewer" +msgstr "ยังไม่มีฟอนต์ที่กำหนดเอง" + +#: src/app/main/data/common.cljs:205 +msgid "dashboard.permissions-change.admin" +msgstr "คุณเป็นแอดมินในทีมนี้แล้ว" + +#: src/app/main/ui/auth/verify_token.cljs:81, src/app/main/ui/settings/change_email.cljs:29 +msgid "errors.email-already-exists" +msgstr "อีเมลถูกใช้ไปแล้ว" + +#: src/app/main/data/users.cljs:735, src/app/main/ui/auth/register.cljs:54 +msgid "errors.email-domain-not-allowed" +msgstr "โดเมนนี้ไม่ได้รับอนุญาต" + +#: src/app/main/ui/auth/register.cljs, src/app/main/ui/dashboard/team_form.cljs, src/app/main/ui/onboarding/team_choice.cljs, src/app/main/ui/setti ngs/access_tokens.cljs, src/app/main/ui/settings/feedback.cljs, src/app/main/ui/settings/profile.cljs, src/app/main/ui/workspace/sidebar/assets.cljs +#, unused +msgid "errors.field-max-length" +msgstr "ต้องมีไม่เกิน 1 ตัวอักษร" + +#: src/app/main/ui/inspect/attributes/layout.cljs +#, unused +msgid "inspect.attributes.layout.left" +msgstr "ซ้าย" + +#: src/app/main/ui/viewer/inspect/attributes/text.cljs:134, src/app/main/ui/workspace/sidebar/options/menus/typography.cljs:384 +msgid "inspect.attributes.typography.letter-spacing" +msgstr "ระยะห่างระหว่างตัวอักษร" + +#: src/app/main/ui/viewer/inspect/attributes/shadow.cljs:57 +msgid "inspect.attributes.shadow" +msgstr "เงา" + +#: src/app/main/ui/dashboard/files.cljs:186, src/app/main/ui/dashboard/projects.cljs:280 +msgid "dashboard.empty-placeholder-files-title" +msgstr "ยังไม่มีไฟล์" + +#: src/app/main/ui/dashboard/placeholder.cljs:32 +msgid "dashboard.empty-placeholder-libraries-title" +msgstr "ยังไม่มีไลบรารี" + +#: src/app/main/data/common.cljs:204 +msgid "dashboard.permissions-change.editor" +msgstr "คุณเป็นเอดิเตอร์ในทีมนี้แล้ว" + +#: src/app/main/data/common.cljs:206 +msgid "dashboard.permissions-change.owner" +msgstr "คุณเป็นเจ้าของในทีมนี้แล้ว" + +#, unused +msgid "errors.field-min-length" +msgstr "ต้องมีอย่างน้อย 1 ตัวอักษร" + +#: src/app/main/ui/components/color_input.cljs:57 +msgid "errors.invalid-color" +msgstr "สีไม่ถูกต้อง" + +#: src/app/main/ui/auth/register.cljs, src/app/main/ui/auth/login.cljs, src/app/main/ui/auth/recovery_request.cljs +#, unused +msgid "errors.invalid-email" +msgstr "กรุณาใส่อีเมลที่ถูกต้อง" + +#: src/app/main/ui/dashboard/fonts.cljs:53, src/app/main/ui/dashboard/sidebar.cljs:811 +msgid "labels.fonts" +msgstr "ฟอนต์" + +#: src/app/main/ui/settings/password.cljs:84 +msgid "labels.new-password" +msgstr "รหัสผ่านใหม่" + +#: src/app/main/ui/auth/register.cljs:133, src/app/main/ui/static.cljs:154, src/app/main/ui/viewer/login.cljs:98 +msgid "auth.already-have-account" +msgstr "มีบัญชีแล้ว?" + +#: src/app/main/ui/auth/recovery_request.cljs:113, src/app/main/ui/auth/register.cljs:274 +msgid "auth.check-mail" +msgstr "ตรวจสอบอีเมลของคุณ" + +#: src/app/main/ui/auth/register.cljs:277 +msgid "auth.check-your-email" +msgstr "ตรวจสอบอีเมลของคุณและคลิกลิงก์เพื่อยืนยันและเริ่มใช้งาน Penpot" + +#: src/app/main/ui/auth/recovery.cljs:67 +msgid "auth.confirm-password" +msgstr "ยืนยันรหัสผ่าน" + +#: src/app/main/ui/auth/register.cljs:145 +msgid "auth.create-demo-account" +msgstr "สร้างบัญชีสาธิตการใช้งาน" + +#: src/app/main/ui/auth/login.cljs:197, src/app/main/ui/viewer/login.cljs:84 +msgid "auth.forgot-password" +msgstr "ลืมรหัสผ่าน?" + +#: src/app/main/ui/auth/login.cljs:203 +msgid "auth.login-submit" +msgstr "ลงชื่อเข้าใช้" + +#: src/app/main/ui/auth/login.cljs:42 +msgid "auth.demo-warning" +msgstr "" +"บริการนี้มีไว้สำหรับสาธิตการใช้งาน ห้ามใช้สำหรับชิ้นงานจริง เนื่องจากข้อมูลจะถูกลบเป็นระยะ ๆ" + +#: src/app/main/ui/auth/register.cljs:231 +msgid "auth.fullname" +msgstr "ชื่อเต็ม" + +#: src/app/main/ui/auth/login.cljs:290 +msgid "auth.login-account-title" +msgstr "ลงชื่อเข้าใช้บัญชีของฉัน" + +#: src/app/main/ui/auth/register.cljs:137, src/app/main/ui/static.cljs:157, src/app/main/ui/viewer/login.cljs:101 +msgid "auth.login-here" +msgstr "ลงชื่อเข้าใช้ที่นี่" + +#: src/app/main/ui/auth/login.cljs:230 +msgid "auth.login-with-github-submit" +msgstr "GitHub" + +#: src/app/main/ui/auth/login.cljs:236 +msgid "auth.login-with-gitlab-submit" +msgstr "GitLab" + +#: src/app/main/ui/auth/login.cljs:209 +msgid "auth.login-with-ldap-submit" +msgstr "LDAP" + +#: src/app/main/ui/auth/login.cljs:242, src/app/main/ui/auth/login.cljs:263 +msgid "auth.login-with-oidc-submit" +msgstr "OpenID" + +#: src/app/main/ui/auth/recovery.cljs:60 +msgid "auth.new-password" +msgstr "พิมพ์รหัสผ่านใหม่" + +#: src/app/main/ui/auth/recovery.cljs:36 +msgid "auth.notifications.password-changed-successfully" +msgstr "เปลี่ยนรหัสผ่านแล้ว" + +#: src/app/main/ui/auth/login.cljs:187, src/app/main/ui/auth/register.cljs:95 +msgid "auth.password" +msgstr "รหัสผ่าน" + +#: src/app/main/ui/auth/recovery_request.cljs:50 +msgid "auth.notifications.profile-not-verified" +msgstr "โปรไฟล์นี้ยังไม่ได้รับการยืนยัน กรุณายืนยันโปรไฟล์ก่อนดำเนินการต่อ" + +#: src/app/main/ui/auth/recovery_request.cljs:33 +msgid "auth.notifications.recovery-token-sent" +msgstr "ลิงก์กู้คืนรหัสผ่านถูกส่งไปยังกล่องข้อความของคุณแล้ว" + +#: src/app/main/ui/auth/verify_token.cljs:46 +msgid "auth.notifications.team-invitation-accepted" +msgstr "เข้าร่วมทีมสำเร็จ" + +#: src/app/main/ui/auth/register.cljs:94 +msgid "auth.password-length-hint" +msgstr "อย่างน้อย 8 ตัวอักษร" + +#: src/app/main/ui/auth/register.cljs:298 +msgid "auth.privacy-policy" +msgstr "นโยบายความเป็นส่วนตัว" + +#: src/app/main/ui/auth/recovery_request.cljs:82 +msgid "auth.recovery-request-submit" +msgstr "กู้คืนรหัสผ่าน" + +#: src/app/main/ui/auth/recovery_request.cljs:94 +msgid "auth.recovery-request-title" +msgstr "ลืมรหัสผ่าน?" + +#: src/app/main/ui/auth/recovery.cljs:71 +msgid "auth.recovery-submit" +msgstr "เปลี่ยนรหัสผ่านของคุณ" + +#: src/app/main/ui/auth/login.cljs:306, src/app/main/ui/static.cljs:140, src/app/main/ui/viewer/login.cljs:87 +msgid "auth.register" +msgstr "ยังไม่มีบัญชี?" + +#: src/app/main/ui/auth/register.cljs:253 +msgid "auth.register-account-title" +msgstr "ชื่อของคุณ" + +#: src/app/main/ui/auth/register.cljs:122 +msgid "auth.register-title" +msgstr "สร้างบัญชี" + +#: src/app/main/ui/auth/register.cljs:290, src/app/main/ui/dashboard/sidebar.cljs:1022, src/app/main/ui/workspace/main_menu.cljs:154 +msgid "auth.terms-of-service" +msgstr "เงื่อนไขการให้บริการ" + +#: src/app/main/ui/auth/register.cljs:275 +msgid "auth.verification-email-sent" +msgstr "เราได้ส่งอีเมลยืนยันให้กับ" + +#: src/app/main/ui/auth/login.cljs:180, src/app/main/ui/auth/recovery_request.cljs:77, src/app/main/ui/auth/register.cljs:88 +msgid "auth.work-email" +msgstr "อีเมลทำงาน" + +#: src/app/main/ui/viewer/share_link.cljs:306, src/app/main/ui/viewer/share_link.cljs:316 +msgid "common.share-link.all-users" +msgstr "ผู้ใช้ Penpot ทั้งหมด" + +#: src/app/main/ui/viewer/share_link.cljs:209, src/app/main/ui/viewer/share_link.cljs:216 +msgid "common.share-link.destroy-link" +msgstr "ทำลายลิงก์" + +#: src/app/main/ui/viewer/share_link.cljs:223 +msgid "common.share-link.get-link" +msgstr "สร้างลิงก์" + +#: src/app/main/ui/viewer/share_link.cljs:139 +msgid "common.share-link.link-copied-success" +msgstr "คัดลอกลิงก์แล้ว" + +#: src/app/main/ui/viewer/share_link.cljs:300 +msgid "common.share-link.permissions-can-comment" +msgstr "สามารถคอมเมนต์" + +#: src/app/main/ui/viewer/share_link.cljs:310 +msgid "common.share-link.permissions-can-inspect" +msgstr "สามารถตรวจดูโคด" + +#: src/app/main/ui/viewer/share_link.cljs:305, src/app/main/ui/viewer/share_link.cljs:315 +msgid "common.share-link.team-members" +msgstr "สมาชิกในทีมเท่านั้น" + +#: src/app/main/ui/settings/access_tokens.cljs:136 +msgid "dashboard.access-tokens.expiration-180-days" +msgstr "180 วัน" + +#: src/app/main/ui/settings/access_tokens.cljs:133 +msgid "dashboard.access-tokens.expiration-30-days" +msgstr "30 วัน" + +#: src/app/main/ui/settings/access_tokens.cljs:134 +msgid "dashboard.access-tokens.expiration-60-days" +msgstr "60 วัน" + +#: src/app/main/ui/settings/access_tokens.cljs:271 +msgid "dashboard.access-tokens.expired-on" +msgstr "หมดอายุแล้วเมื่อ %s" + +#: src/app/main/ui/settings/access_tokens.cljs:272 +msgid "dashboard.access-tokens.expires-on" +msgstr "จะหมดอายุเมื่อ %s" + +#: src/app/main/ui/settings/access_tokens.cljs:135 +msgid "dashboard.access-tokens.expiration-90-days" +msgstr "90 วัน" + +#: src/app/main/ui/settings/access_tokens.cljs:270 +msgid "dashboard.access-tokens.no-expiration" +msgstr "ไม่มีวันหมดอายุ" + +#: src/app/main/ui/settings/profile.cljs:72 +msgid "dashboard.change-email" +msgstr "เปลี่ยนอีเมล" + +#: src/app/main/data/dashboard.cljs:771, src/app/main/data/dashboard.cljs:991 +msgid "dashboard.copy-suffix" +msgstr "(คัดลอก)" + +#: src/app/main/ui/dashboard/sidebar.cljs:338 +msgid "dashboard.create-new-team" +msgstr "สร้างทีมใหม่" + +#: src/app/main/ui/components/context_menu_a11y.cljs:284, src/app/main/ui/dashboard/sidebar.cljs:646 +msgid "dashboard.default-team-name" +msgstr "Penpot ของคุณ" + +#: src/app/main/ui/dashboard/file_menu.cljs:318, src/app/main/ui/dashboard/file_menu.cljs:323, src/app/main/ui/workspace/main_menu.cljs:603, src/app/main/ui/workspace/main_menu.cljs:612 +msgid "dashboard.download-binary-file" +msgstr "ดาวน์โหลดไฟล์ Penpot (.penpot)" + +#: src/app/main/ui/workspace/main_menu.cljs:629 +msgid "dashboard.export-frames" +msgstr "ส่งออกบอร์ดเป็น PDF" + +#: src/app/main/ui/exports/assets.cljs:206 +msgid "dashboard.export-frames.title" +msgstr "ส่งออกเป็น PDF" + +#: src/app/main/ui/workspace/main_menu.cljs:591 +msgid "dashboard.export-shapes" +msgstr "ส่งออก" + +#: src/app/main/ui/exports/files.cljs:148 +msgid "dashboard.export.title" +msgstr "ส่งออกไฟล์" + +#: src/app/main/ui/dashboard/fonts.cljs:441 +msgid "dashboard.fonts.empty-placeholder" +msgstr "ฟอนต์ที่กำหนดเองที่คุณอัปโหลดจะปรากฏที่นี่" + +#: src/app/main/ui/dashboard/fonts.cljs:195 +msgid "dashboard.fonts.fonts-added" +msgid_plural "dashboard.fonts.fonts-added" +msgstr[0] "เพิ่มแล้ว %s ฟอนต์" + +#: src/app/main/ui/dashboard/fonts.cljs:203 +msgid "dashboard.fonts.upload-all" +msgstr "อัปโหลดทั้งหมด" + +#: src/app/main/ui/dashboard/import.cljs:452, src/app/main/ui/dashboard/project_menu.cljs:108 +msgid "dashboard.import" +msgstr "นำเข้าไฟล์ Penpot" + +#: src/app/main/ui/dashboard/import.cljs:288, src/app/worker/import.cljs:843, src/app/worker/import.cljs:846 +msgid "dashboard.import.analyze-error" +msgstr "ไม่สามารถนำเข้าไฟล์นี้ได้" + +#: src/app/main/ui/dashboard/import.cljs:129 +msgid "dashboard.import.progress.process-colors" +msgstr "กำลังประมวลผลสี" + +#: src/app/main/ui/dashboard/import.cljs:126 +msgid "dashboard.import.progress.process-page" +msgstr "กำลังประมวลผลหน้า: %s" + +#: src/app/main/ui/dashboard/import.cljs:123 +msgid "dashboard.import.progress.upload-media" +msgstr "กำลังอัปโหลดไฟล์: %s" + +#: src/app/main/ui/dashboard/sidebar.cljs:547, src/app/main/ui/dashboard/sidebar.cljs:556, src/app/main/ui/dashboard/sidebar.cljs:563, src/app/main/ui/dashboard/team.cljs:341 +msgid "dashboard.leave-team" +msgstr "ออกจากทีม" + +#: src/app/main/ui/dashboard/templates.cljs:82, src/app/main/ui/dashboard/templates.cljs:157 +msgid "dashboard.libraries-and-templates" +msgstr "ไลบรารีและเทมเพลต" + +#: src/app/main/ui/dashboard/libraries.cljs:55 +msgid "dashboard.libraries-title" +msgstr "ไลบรารี" + +#: src/app/main/ui/dashboard/file_menu.cljs:254 +msgid "dashboard.move-to-multi" +msgstr "ย้าน %s ไฟล์ไปยัง" + +#: src/app/main/ui/dashboard/file_menu.cljs:233 +msgid "dashboard.move-to-other-team" +msgstr "ย้ายไปยังทีมอื่น" + +#: src/app/main/ui/dashboard/file_menu.cljs:301, src/app/main/ui/dashboard/project_menu.cljs:100 +msgid "dashboard.move-to" +msgstr "ย้ายไปยัง" + +#: src/app/main/ui/settings/password.cljs:36 +msgid "dashboard.notifications.password-saved" +msgstr "บันทึกรหัสผ่านแล้ว" + +#: src/app/main/ui/auth/verify_token.cljs:32 +msgid "dashboard.notifications.email-changed-successfully" +msgstr "อัปเดตอีเมลสำเร็จแล้ว" + +#: src/app/main/ui/dashboard/file_menu.cljs:284 +msgid "dashboard.open-in-new-tab" +msgstr "เปิดไฟล์ในแท็บใหม่" + +#: src/app/main/ui/dashboard/files.cljs:114, src/app/main/ui/dashboard/projects.cljs:260, src/app/main/ui/dashboard/projects.cljs:261 +msgid "dashboard.options" +msgstr "ตัวเลือก" + +#: src/app/main/ui/settings/password.cljs:94, src/app/main/ui/settings/password.cljs:107 +msgid "dashboard.password-change" +msgstr "เปลี่ยนรหัสผ่าน" + +#: src/app/main/ui/settings/profile.cljs:75 +msgid "dashboard.save-settings" +msgstr "บันทึกการตั้งค่า" + +#: src/app/main/ui/dashboard/sidebar.cljs:246, src/app/main/ui/dashboard/sidebar.cljs:247 +msgid "dashboard.search-placeholder" +msgstr "ค้นหา…" + +#: src/app/main/ui/settings/options.cljs:53 +msgid "dashboard.select-ui-language" +msgstr "เลือกภาษาของ UI" + +#: src/app/main/ui/settings/options.cljs:60 +msgid "dashboard.select-ui-theme" +msgstr "เลือกธีม" + +#: src/app/main/ui/dashboard/projects.cljs:303 +msgid "dashboard.show-all-files" +msgstr "แสดงไฟล์ทั้งหมด" + +#: src/app/main/ui/dashboard/team.cljs:1090 +msgid "dashboard.team-info" +msgstr "ข้อมูลของทีม" + +#: src/app/main/ui/settings/options.cljs:58 +msgid "dashboard.theme-change" +msgstr "ธีมของ UI" + +#: src/app/main/ui/dashboard/search.cljs:43 +msgid "dashboard.title-search" +msgstr "ผลการค้นหา" + +#: src/app/main/ui/dashboard/team.cljs:1108 +msgid "dashboard.team-members" +msgstr "สมาชิกของทีม" + +#: src/app/main/ui/dashboard/team.cljs:1123 +msgid "dashboard.team-projects" +msgstr "โปรเจกต์ของทีม" + +#: src/app/main/ui/settings/options.cljs:68 +msgid "dashboard.update-settings" +msgstr "อัปเดตการตั้งค่า" + +#: src/app/main/ui/dashboard/team.cljs:890 +msgid "dashboard.webhooks.content-type" +msgstr "ประเภทเนื้อหา" + +#: src/app/main/ui/dashboard/team.cljs:923 +msgid "dashboard.webhooks.create" +msgstr "สร้าง Webhook" + +#: src/app/main/ui/dashboard/team.cljs:813 +msgid "dashboard.webhooks.create.success" +msgstr "สร้าง Webhook แล้ว" + +#, unused +msgid "dashboard.webhooks.update.success" +msgstr "อัปเดต Webhook แล้ว" + +#: src/app/main/ui/settings.cljs:31 +msgid "dashboard.your-account-title" +msgstr "บัญชีของคุณ" + +#: src/app/main/ui/settings/profile.cljs:67 +msgid "dashboard.your-email" +msgstr "อีเมล" + +#: src/app/main/ui/settings/profile.cljs:59 +msgid "dashboard.your-name" +msgstr "ชื่อของคุณ" + +#: src/app/main/ui/workspace/plugins.cljs:336, src/app/main/ui/workspace/plugins.cljs:390 +msgid "ds.confirm-allow" +msgstr "อนุญาต" + +#: src/app/main/ui/confirm.cljs:36, src/app/main/ui/workspace/plugins.cljs:330, src/app/main/ui/workspace/plugins.cljs:384 +msgid "ds.confirm-cancel" +msgstr "ยกเลิก" + +#: src/app/main/ui/settings/password.cljs +#, unused +msgid "errors.password-too-short" +msgstr "รหัสผ่านต้องมีอย่างน้อย 8 ตัวอักษร" + +#: src/app/main/ui/auth/login.cljs:114, src/app/main/ui/auth/login.cljs:118 +msgid "errors.wrong-credentials" +msgstr "อีเมลหรือรหัสผ่านไม่ถูกต้อง" + +#: src/app/main/ui/settings/password.cljs +#, unused +msgid "errors.wrong-old-password" +msgstr "รหัสผ่านเดิมไม่ถูกต้อง" + +#: src/app/main/ui/settings/feedback.cljs:85 +msgid "feedback.discourse-title" +msgstr "ชุมชน Penpot" + +#: src/app/main/ui/settings/feedback.cljs:65 +msgid "feedback.title" +msgstr "อีเมล" + +#: src/app/main/ui/inspect/attributes/layout.cljs +#, unused +msgid "inspect.attributes.layout.height" +msgstr "ความสูง" + +#: src/app/main/ui/inspect/attributes/stroke.cljs +#, unused +msgid "inspect.attributes.stroke.width" +msgstr "ความกว้าง" + +#: src/app/main/ui/viewer/inspect/attributes/text.cljs:107, src/app/main/ui/workspace/sidebar/options/menus/typography.cljs:315 +msgid "inspect.attributes.typography.font-size" +msgstr "ขนาดฟอนต์" + +#: src/app/main/ui/viewer/inspect/right_sidebar.cljs:100 +msgid "inspect.tabs.code" +msgstr "โคด" + +#: src/app/main/ui/viewer/inspect/right_sidebar.cljs:127 +msgid "inspect.tabs.code.selected.frame" +msgstr "บอร์ด" + +#: src/app/main/ui/viewer/inspect/right_sidebar.cljs:133 +msgid "inspect.tabs.code.selected.svg-raw" +msgstr "SVG" + +#: src/app/main/ui/settings/password.cljs:91 +msgid "labels.confirm-password" +msgstr "ยืนยันรหัสผ่าน" + +#: src/app/main/ui/dashboard/sidebar.cljs:985, src/app/main/ui/workspace/main_menu.cljs:114 +msgid "labels.community" +msgstr "ชุมชน" + +#: src/app/main/ui/dashboard/team.cljs:678 +msgid "labels.copy-invitation-link" +msgstr "คัดลอกลิงก์" + +#: src/app/main/ui/static.cljs:61 +msgid "labels.copyright" +msgstr "Kaleidos @2024" + +#, unused +msgid "labels.custom-fonts" +msgstr "ฟอนต์ที่กำหนดเอง" + +#: src/app/main/ui/dashboard/team_form.cljs:101, src/app/main/ui/dashboard/team_form.cljs:121 +msgid "labels.create-team" +msgstr "สร้างทีมใหม่" + +#: src/app/main/ui/settings/sidebar.cljs:73 +msgid "labels.dashboard" +msgstr "แดชบอร์ด" + +#: src/app/main/ui/comments.cljs:356, src/app/main/ui/dashboard/fonts.cljs:253, src/app/main/ui/dashboard/team.cljs:940, src/app/main/ui/workspace/sidebar/options/menus/component.cljs:205, src/app/main/ui/workspace/tokens/sidebar.cljs:199 +msgid "labels.edit" +msgstr "แก้ไข" + +#: src/app/main/ui/dashboard/team.cljs:126, src/app/main/ui/dashboard/team.cljs:307, src/app/main/ui/dashboard/team.cljs:551, src/app/main/ui/dashboard/team.cljs:584, src/app/main/ui/onboarding/team_choice.cljs:65 +msgid "labels.editor" +msgstr "เอดิเตอร์" + +#: src/app/main/ui/exports/assets.cljs:177 +msgid "labels.export" +msgstr "ส่งออก" + +#: src/app/main/ui/onboarding/questions.cljs:165 +msgid "labels.figma" +msgstr "Figma" + +#: src/app/main/ui/onboarding/questions.cljs:248 +msgid "labels.graphic-design" +msgstr "กราฟิกดีไซน์" + +#: src/app/main/ui/settings/options.cljs:48 +msgid "labels.language" +msgstr "ภาษา" + +#: src/app/main/ui/dashboard/sidebar.cljs:1008, src/app/main/ui/workspace/main_menu.cljs:138 +msgid "labels.libraries-and-templates" +msgstr "ไลบรารีและเทมเพลต" + +#: src/app/main/ui/auth/verify_token.cljs:97, src/app/main/ui/dashboard/grid.cljs:104, src/app/main/ui/dashboard/grid.cljs:124, src/app/main/ui/dashboard/import.cljs:253, src/app/main/ui/dashboard/placeholder.cljs:52, src/app/main/ui/ds/product/loader.cljs:52, src/app/main/ui/exports/files.cljs:62, src/app/main/ui/viewer.cljs:637, src/app/main/ui/workspace.cljs:129 +msgid "labels.loading" +msgstr "กำลังโหลด…" + +#: src/app/main/ui/dashboard/sidebar.cljs:1040 +msgid "labels.logout" +msgstr "ลงชื่อออก" + +#: src/app/main/ui/dashboard/team.cljs:499 +msgid "labels.member" +msgstr "สมาชิก" + +#: src/app/main/ui/dashboard/sidebar.cljs:510, src/app/main/ui/dashboard/team.cljs:94, src/app/main/ui/dashboard/team.cljs:102 +msgid "labels.members" +msgstr "สมาชิก" + +#: src/app/main/ui/settings/password.cljs:77 +msgid "labels.old-password" +msgstr "รหัสผ่านเดิม" + +#, unused +msgid "labels.or" +msgstr "หรือ" + +#: src/app/main/ui/dashboard/team.cljs:314, src/app/main/ui/dashboard/team.cljs:549, src/app/main/ui/dashboard/team.cljs:1114 +msgid "labels.owner" +msgstr "เจ้าของ" + +#: src/app/main/ui/settings/sidebar.cljs:87 +msgid "labels.password" +msgstr "รหัสผ่าน" + +#: src/app/main/ui/settings/profile.cljs:125, src/app/main/ui/settings/sidebar.cljs:82 +msgid "labels.profile" +msgstr "โปรไฟล์" + +#: src/app/main/ui/dashboard/sidebar.cljs:784 +msgid "labels.projects" +msgstr "โปรเจกต์" + +#: src/app/main/ui/viewer/share_link.cljs:173 +msgid "common.share-link.title" +msgstr "แชร์โปรโตไทป์" + +#: src/app/main/ui/auth/register.cljs:124 +msgid "auth.register-tagline" +msgstr "" +"ด้วยบัญชี Penpot ฟรี คุณสามารถสร้างทีมได้อย่างไม่จำกัดและทำงานร่วมกับดีไซเนอร์และนักพัฒนาคนอื่น " +"ๆ กี่โปรเจกต์ก็ได้ " + +#: src/app/main/ui/auth/login.cljs:293 +msgid "auth.login-tagline" +msgstr "" +"Penpot เป็นเครื่องมือออกแบบที่ฟรีและโอเพนซอร์สสำหรับการดีไซน์และโค้ดร่วมกัน" + +#: src/app/main/ui/auth/register.cljs:254 +msgid "auth.register-account-tagline" +msgstr "เราควรเรียกคุณในแดชบอร์ดและอีเมลว่าอะไรดี" + +#: src/app/main/ui/auth.cljs +#, unused +msgid "auth.sidebar-tagline" +msgstr "โซลูชันโอเพนซอร์สสำหรับการออกแบบและโปรโตไทป์" + +#, unused +msgid "auth.terms-privacy-agreement" +msgstr "" +"เมื่อคุณสร้างบัญชี คุณยอมรับข้อกำหนดการให้บริการและนโยบายความเป็นส่วนตัว" + +#: src/app/main/ui/viewer/share_link.cljs:233 +msgid "common.share-link.manage-ops" +msgstr "จัดการสิทธิ์" + +#: src/app/main/ui/viewer/share_link.cljs:279 +msgid "common.share-link.page-shared" +msgid_plural "common.share-link.page-shared" +msgstr[0] "แชร์แล้ว %s หน้า" + +#: src/app/main/ui/viewer/share_link.cljs:195 +msgid "common.share-link.permissions-hint" +msgstr "ทุกคนที่มีลิงก์สามารถเข้าถึงได้" + +#: src/app/main/ui/dashboard/placeholder.cljs:39 +#, markdown +msgid "dashboard.empty-placeholder-libraries" +msgstr "" +"ไลบรารีที่เพิ่มให้กับโปรเจกต์จะปรากฏที่นี่ ลองแชร์ไฟล์ของคุณหรือเพิ่มจาก[ไลบรารีและเทมเพลต]" +"(https://penpot.app/libraries-templates)ของเรา" + +#: src/app/main/ui/dashboard/file_menu.cljs:269 +msgid "dashboard.export-standard-multi" +msgstr "ดาวน์โหลด %s ไฟล์มาตรฐาน (.svg + .json)" + +#: src/app/main/ui/dashboard/fonts.cljs:445 +msgid "dashboard.fonts.empty-placeholder-viewer-sub" +msgstr "เมื่อสมาชิกโปรเจกต์เพิ่มฟอนต์ที่กำหนดเอง จะปรากฏที่นี่" + +#: src/app/main/ui/dashboard/import.cljs:466 +msgid "dashboard.import.import-message" +msgid_plural "dashboard.import.import-message" +msgstr[0] "นำเข้าสำเร็จแล้ว %s ไฟล์" + +#: src/app/main/ui/dashboard/files.cljs:185, src/app/main/ui/dashboard/projects.cljs:279 +msgid "dashboard.empty-placeholder-drafts-title" +msgstr "ยังไม่มีแบบร่าง" + +#: src/app/main/ui/dashboard/files.cljs:191, src/app/main/ui/dashboard/projects.cljs:285 +msgid "dashboard.empty-placeholder-files-subtitle" +msgstr "เมื่อสมาชิกของโปรเจกต์สร้างไฟล์ จะแสดงผลที่นี่" + +#: src/app/main/ui/dashboard/placeholder.cljs:35 +msgid "dashboard.empty-placeholder-libraries-subtitle-viewer-role" +msgstr "ไลบรารีที่เพิ่มลงในโปรเจกต์จะปรากฏที่นี่" + +#: src/app/main/ui/dashboard/files.cljs:190, src/app/main/ui/dashboard/projects.cljs:284 +msgid "dashboard.empty-placeholder-drafts-subtitle" +msgstr "เมื่อสมาชิกโปรเจกต์สร้างแบบร่าง จะปรากฏที่นี่" + +#: src/app/main/ui/exports/assets.cljs:194 +msgid "dashboard.export-shapes.title" +msgstr "ส่งออกส่วนที่เลือก" + +#: src/app/main/ui/dashboard/placeholder.cljs +#, markdown, unused +msgid "dashboard.empty-placeholder-libraries-subtitle" +msgstr "" +"ไลบรารีที่เพิ่มให้กับโปรเจกต์จะปรากฏที่นี่ ลองแชร์ไฟล์ของคุณหรือเพิ่มจาก[ไลบรารีและเทมเพลต]" +"(https://penpot.app/libraries-templates)ของเรา" + +#: src/app/main/ui/auth/register.cljs:157 +#, markdown +msgid "auth.terms-and-privacy-agreement" +msgstr "ฉันยอมรับ [ข้อกำหนดการให้บริการ](%s)และ[นโยบายความเป็นส่วนตัว](%s)" + +#: src/app/main/ui/viewer/share_link.cljs:200 +msgid "common.share-link.confirm-deletion-link-description" +msgstr "คุณแน่ใจหรือไม่ว่าต้องการลบลิงก์นี้? หากคุณลบ จะไม่มีใครสามารถเปิดได้" + +#: src/app/main/ui/viewer/share_link.cljs:261, src/app/main/ui/viewer/share_link.cljs:291 +msgid "common.share-link.current-tag" +msgstr "(ปัจจุบัน)" + +#: src/app/main/ui/viewer/share_link.cljs:243 +msgid "common.share-link.permissions-pages" +msgstr "หน้าที่ต้องการแชร์" + +#: src/app/main/ui/dashboard/projects.cljs +#, fuzzy, unused +msgid "dasboard.tutorial-hero.info" +msgstr "เรียนรู้การใช้งาน Penpot เบื้องต้นด้วยการลงมือทำจริง" + +#: src/app/main/ui/settings/access_tokens.cljs:104 +msgid "dashboard.access-tokens.copied-success" +msgstr "คัดลอกโทเคนแล้ว" + +#: src/app/main/ui/settings/access_tokens.cljs:191 +msgid "dashboard.access-tokens.create" +msgstr "สร้างโทเคนใหม่" + +#: src/app/main/ui/settings/access-tokens.cljs +#, unused +msgid "dashboard.access-tokens.create-success" +msgstr "สร้างโทเคนสำหรับการเข้าถึงสำเร็จแล้ว" + +#: src/app/main/ui/settings/access_tokens.cljs:289 +msgid "dashboard.access-tokens.empty.add-one" +msgstr "กดปุ่ม \"สร้างโทเคนใหม่\" เพื่อสร้างโทเคน" + +#: src/app/main/ui/settings/access_tokens.cljs:288 +msgid "dashboard.access-tokens.empty.no-access-tokens" +msgstr "คุณยังไม่มีโทเคนที่สร้างไว้" + +#: src/app/main/ui/settings/access_tokens.cljs:132 +msgid "dashboard.access-tokens.expiration-never" +msgstr "ไม่มีวันหมดอายุ" + +#: src/app/main/ui/settings/access_tokens.cljs:186 +msgid "dashboard.access-tokens.personal" +msgstr "โทเคนการเข้าถึงส่วนบุคคล" + +#: src/app/main/ui/settings/access_tokens.cljs:187 +msgid "dashboard.access-tokens.personal.description" +msgstr "" +"โทเคนการเข้าถึงส่วนบุคคลจะทำงานใกล้เคียงกับการยืนยันตัวตนด้วยชื่อผู้ใช้/รหัสผ่าน " +"และสามารถใช้ในการอนุญาตให้แอปพลิเคชันเข้าถึง API ภายในของ Penpot ได้" + +#: src/app/main/ui/settings/access_tokens.cljs:143 +msgid "dashboard.access-tokens.token-will-expire" +msgstr "โทเคนนี้จะหมดอายุใน %s" + +#: src/app/main/ui/settings/access_tokens.cljs:144 +msgid "dashboard.access-tokens.token-will-not-expire" +msgstr "โทเคนนี้ไม่มีวันหมดอายุ" + +#: src/app/main/ui/dashboard/file_menu.cljs:259, src/app/main/ui/dashboard/file_menu.cljs:264 +msgid "dashboard.export-binary-multi" +msgstr "ดาวน์โหลด %s ไฟล์ Penpot (.penpot)" + +#, unused +msgid "dashboard.export-multi" +msgstr "ส่งออก %s ไฟล์ Penpot" + +#: src/app/main/ui/workspace/sidebar/options/menus/typography.cljs:311 +msgid "dashboard.fonts.deleted-placeholder" +msgstr "ฟอนต์ที่หายไป" + +#: src/app/main/ui/dashboard/fonts.cljs:183 +#, markdown +msgid "dashboard.fonts.hero-text2" +msgstr "" +"คุณควรอัปโหลดเฉพาะฟอนต์ที่คุณเป็นเจ้าของหรือมีสิทธิ์ในการใช้งานใน Penpot " +"ดูรายละอียดเพิ่มเติมในส่วนเนื้อหาของ[ข้อกำหนดการให้บริการของ Penpot](https://penpot.app/" +"terms.html) นอกจากนี้คุณอาจต้องการอ่านเพิ่มเติมเกี่ยวกับ[ลิขสิทธิ์ฟอนต์](https://" +"www.typography.com/faq)" + +#: src/app/main/ui/dashboard/import.cljs:292 +msgid "dashboard.import.import-error" +msgstr "พบปัญหาในการนำเข้าไฟล์ ไฟล์นี้จึงไม่ถูกนำเข้า" + +#: src/app/main/ui/dashboard/import.cljs:461 +msgid "dashboard.import.import-warning" +msgstr "บางไฟล์มีวัตถุที่ไม่ถูกต้อง ซึ่งถูกนำออกให้แล้ว" + +#: src/app/main/ui/dashboard/import.cljs:138, src/app/main/ui/dashboard/import.cljs:141 +msgid "dashboard.import.progress.process-components" +msgstr "กำลังประมวลผลคอมโพเนนต์" + +#: src/app/main/ui/dashboard/import.cljs:135 +msgid "dashboard.import.progress.process-media" +msgstr "กำลังประมวลผลสื่อ" + +#: src/app/main/ui/dashboard/import.cljs:120 +msgid "dashboard.import.progress.upload-data" +msgstr "กำลังอัปโหลดข้อมูลไปยังเซิร์ฟเวอร์ (%s/%s)" + +#: src/app/main/ui/dashboard/import.cljs:358 +msgid "dashboard.libraries-and-templates.import-error" +msgstr "พบปัญหาในการนำเข้าเทมเพลต เทมเพลตนี้จึงไม่ถูกนำเข้า" + +#: src/app/main/ui/dashboard/placeholder.cljs:54 +msgid "dashboard.loading-files" +msgstr "กำลังโหลดไฟล์ของคุณ…" + +#: src/app/main/ui/dashboard/fonts.cljs:435 +msgid "dashboard.loading-fonts" +msgstr "กำลังโหลดฟอนต์ของคุณ…" + +#: src/app/main/data/dashboard.cljs:735, src/app/main/data/dashboard.cljs:1192 +msgid "dashboard.new-project-prefix" +msgstr "สร้างโปรเจกต์ใหม่" + +#: src/app/main/data/dashboard.cljs:966, src/app/main/data/dashboard.cljs:1189 +msgid "dashboard.new-file-prefix" +msgstr "สร้างไฟล์ใหม่" + +#: src/app/main/ui/dashboard/projects.cljs:57 +msgid "dashboard.new-project" +msgstr "+ สร้างโปรเจกต์ใหม่" + +#: src/app/main/ui/dashboard/files.cljs:101, src/app/main/ui/dashboard/projects.cljs:251, src/app/main/ui/dashboard/projects.cljs:252 +msgid "dashboard.new-file" +msgstr "+ สร้างไฟล์ใหม่" diff --git a/frontend/translations/ukr_UA.po b/frontend/translations/ukr_UA.po index 073ba2f942..ec2a1bed44 100644 --- a/frontend/translations/ukr_UA.po +++ b/frontend/translations/ukr_UA.po @@ -1,7 +1,7 @@ msgid "" msgstr "" -"PO-Revision-Date: 2024-11-14 11:14+0000\n" -"Last-Translator: Anonymous \n" +"PO-Revision-Date: 2024-12-19 18:02+0000\n" +"Last-Translator: Denys Kisil \n" "Language-Team: Ukrainian \n" "Language: ukr_UA\n" @@ -10,38 +10,40 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && " "n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" -"X-Generator: Weblate 5.9-dev\n" +"X-Generator: Weblate 5.9.2-dev\n" #: src/app/main/ui/auth/register.cljs:133, src/app/main/ui/static.cljs:154, src/app/main/ui/viewer/login.cljs:98 msgid "auth.already-have-account" -msgstr "Уже маєте аккаунт?" +msgstr "Уже маєте обліковий запис?" #: src/app/main/ui/auth/recovery_request.cljs:113, src/app/main/ui/auth/register.cljs:274 msgid "auth.check-mail" -msgstr "Перевірте свою електронну пошту" +msgstr "Перевірте свою електрону скриньку" #: src/app/main/ui/auth/register.cljs:277 msgid "auth.check-your-email" -msgstr "Підтвердіть акаунт за посиланням в листі та почніть користування Penpot." +msgstr "" +"Підтвердьте обліковий запис за посиланням в листі та почніть користуватись " +"Penpot." #: src/app/main/ui/auth/recovery.cljs:67 msgid "auth.confirm-password" -msgstr "Підтвердіть пароль" +msgstr "Підтвердьте пароль" #: src/app/main/ui/auth/register.cljs:145 msgid "auth.create-demo-account" -msgstr "Створити демомнстраційний аккаунт" +msgstr "Створити обліковий запис для демо" #: src/app/main/ui/auth/register.cljs, src/app/main/ui/auth/login.cljs #, unused msgid "auth.create-demo-profile" -msgstr "Бажаєте просто спробувати?" +msgstr "Хочете лише спробувати?" #: src/app/main/ui/auth/login.cljs:42 msgid "auth.demo-warning" msgstr "" -"Це демонстраційний варіант сервісу, не використовувати для реальної роботи, " -"проєкти періодично стиратимуться." +"Це демонстраційний варіант сервісу, не використовуйте для реальної роботи, " +"створені проєкти періодично очищуватимуться." #: src/app/main/ui/auth/login.cljs:197, src/app/main/ui/viewer/login.cljs:84 msgid "auth.forgot-password" @@ -53,7 +55,7 @@ msgstr "Повне ім'я" #: src/app/main/ui/auth/login.cljs:290 msgid "auth.login-account-title" -msgstr "Увійти до мого аккаунту" +msgstr "Увійти до мого облікового запису" #: src/app/main/ui/auth/register.cljs:137, src/app/main/ui/static.cljs:157, src/app/main/ui/viewer/login.cljs:101 msgid "auth.login-here" @@ -100,7 +102,7 @@ msgstr "Пароль успішно змінено" #: src/app/main/ui/auth/recovery_request.cljs:50 msgid "auth.notifications.profile-not-verified" msgstr "" -"Профіль не підтверджено, будь ласка, спершу підтвердіть його перш ніж " +"Профіль не підтверджено, будь ласка, спершу підтвердьте його перш ніж " "продовжити." #: src/app/main/ui/auth/recovery_request.cljs:33 @@ -141,7 +143,7 @@ msgstr "Змініть свій пароль" #: src/app/main/ui/auth/login.cljs:306, src/app/main/ui/static.cljs:140, src/app/main/ui/viewer/login.cljs:87 msgid "auth.register" -msgstr "Ще не маєте акаунта?" +msgstr "Не маєте облікового запису?" #: src/app/main/ui/auth/register.cljs:254 msgid "auth.register-account-tagline" @@ -153,18 +155,18 @@ msgstr "Ваше ім'я" #: src/app/main/ui/auth/login.cljs:310, src/app/main/ui/auth/register.cljs:101, src/app/main/ui/auth/register.cljs:240, src/app/main/ui/static.cljs:144, src/app/main/ui/viewer/login.cljs:91 msgid "auth.register-submit" -msgstr "Створити акаунт" +msgstr "Створити обліковий запис" #: src/app/main/ui/auth/register.cljs:124 msgid "auth.register-tagline" msgstr "" -"З безкоштовний аккаунтом Penpot ви зможете створювати необмежену кількість " -"команд та співпрацювати з іншими дизайнерами та розробниками над будь-якою " -"кількістю проєктів. " +"З безкоштовний обліковим записом Penpot ви зможете створювати необмежену " +"кількість команд та співпрацювати з іншими дизайнерами та розробниками над " +"будь-якою кількістю проєктів. " #: src/app/main/ui/auth/register.cljs:122 msgid "auth.register-title" -msgstr "Створити акаунт" +msgstr "Створити обліковий запис" #: src/app/main/ui/auth.cljs #, unused @@ -185,12 +187,12 @@ msgstr "Умови користування" #, unused msgid "auth.terms-privacy-agreement" msgstr "" -"Створюючи аккаунт, ви погоджуєтеся з нашими умовами користування та " +"Створюючи обліковий запис, ви погоджуєтеся з нашими умовами користування та " "політикою конфіденційності." #: src/app/main/ui/auth/register.cljs:275 msgid "auth.verification-email-sent" -msgstr "Ми надіслали лист для підтвердження акаунту на" +msgstr "Ми надіслали лист для підтвердження облікового запису на" #: src/app/main/ui/auth/login.cljs:180, src/app/main/ui/auth/recovery_request.cljs:77, src/app/main/ui/auth/register.cljs:88 msgid "auth.work-email" @@ -221,7 +223,7 @@ msgstr "(поточне)" #: src/app/main/ui/viewer/share_link.cljs:209, src/app/main/ui/viewer/share_link.cljs:216 msgid "common.share-link.destroy-link" -msgstr "Знищити посилання" +msgstr "Стерти посилання" #: src/app/main/ui/viewer/share_link.cljs:223 msgid "common.share-link.get-link" @@ -244,11 +246,11 @@ msgstr[2] "%s сторінок було поширено" #: src/app/main/ui/viewer/share_link.cljs:300 msgid "common.share-link.permissions-can-comment" -msgstr "Можна коментувати" +msgstr "Можуть додавати коментарі" #: src/app/main/ui/viewer/share_link.cljs:310 msgid "common.share-link.permissions-can-inspect" -msgstr "Можна переглядати код" +msgstr "Можуть переглядати код" #: src/app/main/ui/viewer/share_link.cljs:195 msgid "common.share-link.permissions-hint" @@ -264,7 +266,7 @@ msgstr "Посилання для спільного використання з #: src/app/main/ui/viewer/share_link.cljs:305, src/app/main/ui/viewer/share_link.cljs:315 msgid "common.share-link.team-members" -msgstr "Лише члени команди" +msgstr "Лише учасники команди" #: src/app/main/ui/viewer/share_link.cljs:173 msgid "common.share-link.title" @@ -295,9 +297,7 @@ msgstr "Об'єднуйтесь!" #: src/app/main/ui/dashboard/projects.cljs #, unused msgid "dasboard.tutorial-hero.info" -msgstr "" -"Вивчайте основи Penpot, отримуючи задоволення від цього практичного " -"посібника." +msgstr "Вивчайте основи Penpot із задоволення, використовуючи ці посібники." #: src/app/main/ui/dashboard/projects.cljs #, unused @@ -343,7 +343,7 @@ msgstr "Натисніть на кнопку \"Згенерувати новий #: src/app/main/ui/settings/access_tokens.cljs:288 msgid "dashboard.access-tokens.empty.no-access-tokens" -msgstr "У вас, поки що, немає токенів." +msgstr "Ви ще не створили жодного токену." #: src/app/main/ui/settings/access_tokens.cljs:136 msgid "dashboard.access-tokens.expiration-180-days" @@ -384,9 +384,9 @@ msgstr "Персональні токени доступу" #: src/app/main/ui/settings/access_tokens.cljs:187 msgid "dashboard.access-tokens.personal.description" msgstr "" -"Персональні токени доступу виступають альтернативою нашій системі " -"автентифікації \"логін/пароль\" та можуть бути використаними для надання " -"застосунку доступу до внутрішнього API Penpot" +"Персональні токени доступу є альтернативою нашій системі автентифікації " +"\"логін/пароль\" та можуть бути використаними для надання застосунку доступу " +"до внутрішнього API Penpot" #: src/app/main/ui/settings/access_tokens.cljs:143 msgid "dashboard.access-tokens.token-will-expire" @@ -410,7 +410,7 @@ msgstr "(копія)" #: src/app/main/ui/dashboard/sidebar.cljs:338 msgid "dashboard.create-new-team" -msgstr "+ Створити нову команду" +msgstr "Створити нову команду" #: src/app/main/ui/components/context_menu_a11y.cljs:284, src/app/main/ui/dashboard/sidebar.cljs:646 msgid "dashboard.default-team-name" @@ -484,19 +484,19 @@ msgstr "Завантажити %s стандартних файоів (.svg + .j #: src/app/main/ui/exports/files.cljs:157 msgid "dashboard.export.detail" -msgstr "* Може міститикомпоненти, графіку, кольори та/або типографіку." +msgstr "* Може містити компоненти, графіки, кольори та/або типографіки." #: src/app/main/ui/exports/files.cljs:156 msgid "dashboard.export.explain" msgstr "" "Файли, які ви хочете експортувати, використовують спільні бібліотеки. Що ви " -"плануєте зробити з їхніми ресурсами?" +"плануєте зробити з їхніми ресурсами*?" #: src/app/main/ui/exports/files.cljs:165 msgid "dashboard.export.options.all.message" msgstr "" -"файли з спільними бібліотеками буде включено до експорту зі збереженням " -"з'язків між ними." +"файли з спільними бібліотеками буде додано до експорту зі збереженням " +"зв'язків між ними." #: src/app/main/ui/exports/files.cljs:166 msgid "dashboard.export.options.all.title" @@ -505,12 +505,12 @@ msgstr "Експортувати спільні бібліотеки" #: src/app/main/ui/exports/files.cljs:167 msgid "dashboard.export.options.detach.message" msgstr "" -"Спільні бібліотеки не буде включено до експорту, і до бібліотеки не буде " +"Спільні бібліотеки не буде додано до експорту, і до бібліотеки не буде " "додано ресурсів. " #: src/app/main/ui/exports/files.cljs:168 msgid "dashboard.export.options.detach.title" -msgstr "Поводитись з ресурсами спільної бібліотеки як з базовими об'єктами" +msgstr "Розглядати ресурси спільної бібліотеки як базові об'єкти" #: src/app/main/ui/exports/files.cljs:169 msgid "dashboard.export.options.merge.message" @@ -550,9 +550,9 @@ msgstr[2] "% s шрифтів було додано" msgid "dashboard.fonts.hero-text1" msgstr "" "Будь-який веб-шрифт, який ви завантажите сюди, буде додано до списку " -"сімейств шрифтів, доступного у текстових властивостях файлів цієї команди. " +"сімейств шрифтів, доступного у властивостях тексту файлів цієї команди. " "Шрифти з однаковою назвою сімейства будуть згруповані в **одне сімейство " -"шрифтів**. Ви можете завантажувати шрифти у таких форматах: **TTF, OTF і " +"шрифтів**. Ви можете вивантажувати шрифти у таких форматах: **TTF, OTF і " "WOFF** (потрібен лише один)." #: src/app/main/ui/dashboard/fonts.cljs:183 @@ -560,10 +560,10 @@ msgstr "" msgid "dashboard.fonts.hero-text2" msgstr "" "Ви повинні завантажувати лише ті шрифти, якими ви володієте або маєте " -"ліцензію на використання в Penpot. Дізнайтеся більше в розділі \"Права на " -"контент\" в [Умовах користування Penpot](https://penpot.app/terms.html). Ви " -"також можете прочитати про [ліцензування " -"шрифтів](https://www.typography.com/faq)." +"ліцензію на використання в Penpot. Дізнайтеся більше в розділі \"Content " +"Rights\" в [Умовах користування Penpot](https://penpot.app/terms.html). Ви " +"також можете прочитати про [ліцензування шрифтів](https://www.typography.com/" +"faq)." #: src/app/main/ui/dashboard/fonts.cljs:203 msgid "dashboard.fonts.upload-all" @@ -675,7 +675,7 @@ msgstr "Перенести в" #: src/app/main/ui/dashboard/file_menu.cljs:254 msgid "dashboard.move-to-multi" -msgstr "Перемістити файли (%s)" +msgstr "Перемістити (%s) файлів до" #: src/app/main/ui/dashboard/file_menu.cljs:233 msgid "dashboard.move-to-other-team" @@ -707,7 +707,7 @@ msgstr "Закріплені проєкти з'являться тут" #: src/app/main/ui/auth/verify_token.cljs:32 msgid "dashboard.notifications.email-changed-successfully" -msgstr "Адресу вашої пошти було успішно змінено" +msgstr "Адресу вашої електронної пошти було успішно змінено" #: src/app/main/ui/auth/verify_token.cljs:26 msgid "dashboard.notifications.email-verified-successfully" @@ -719,7 +719,7 @@ msgstr "Пароль успішно збережено!" #: src/app/main/ui/dashboard/team.cljs:1119 msgid "dashboard.num-of-members" -msgstr "%s членів" +msgstr "%s учасників" #: src/app/main/ui/dashboard/file_menu.cljs:284 msgid "dashboard.open-in-new-tab" @@ -814,7 +814,7 @@ msgstr "Відомості про команду" #: src/app/main/ui/dashboard/team.cljs:1108 msgid "dashboard.team-members" -msgstr "Члени команди" +msgstr "Учасники команди" #: src/app/main/ui/dashboard/team.cljs:1123 msgid "dashboard.team-projects" @@ -881,11 +881,11 @@ msgstr "Вебхук успішно оновлено." #: src/app/main/ui/settings.cljs:31 msgid "dashboard.your-account-title" -msgstr "Ваш аккаунт" +msgstr "Ваш обліковий запис" #: src/app/main/ui/settings/profile.cljs:67 msgid "dashboard.your-email" -msgstr "Електрона адреса" +msgstr "Електрона пошта" #: src/app/main/ui/settings/profile.cljs:59 msgid "dashboard.your-name" @@ -953,11 +953,11 @@ msgstr "Ваш браузер не може зробити це" #: src/app/main/ui/auth/verify_token.cljs:81, src/app/main/ui/settings/change_email.cljs:29 msgid "errors.email-already-exists" -msgstr "Електронна адреса вже використовується" +msgstr "Електронна пошта вже використовується" #: src/app/main/ui/auth/verify_token.cljs:86 msgid "errors.email-already-validated" -msgstr "Електронна адреса вже підтверджена." +msgstr "Електронна пошта вже підтверджена." #, unused msgid "errors.email-as-password" @@ -970,8 +970,7 @@ msgstr "Цей домен не дозволений" #: src/app/main/ui/auth/recovery_request.cljs:57, src/app/main/ui/auth/register.cljs:57, src/app/main/ui/auth/register.cljs:60, src/app/main/ui/dashboard/team.cljs:615, src/app/main/ui/settings/change_email.cljs:37 msgid "errors.email-has-permanent-bounces" msgstr "" -"Електрона адреса \"%s\" має багато скарг про постійне повернення " -"повідомлень." +"Електрона пошта \"%s\" має багато скарг про постійне повернення повідомлень." #: src/app/main/ui/dashboard/team.cljs:190, src/app/main/ui/onboarding/team_choice.cljs:109 msgid "errors.email-spam-or-permanent-bounces" @@ -1134,7 +1133,7 @@ msgstr "Помилка під'єднання, адреса недосяжна" #: src/app/main/ui/dashboard/team.cljs:828 msgid "errors.webhooks.invalid-uri" -msgstr "Адреса не пройшла перевірку." +msgstr "Посилання не пройшло перевірку." #: src/app/main/ui/dashboard/team.cljs:986 msgid "errors.webhooks.last-delivery" @@ -1158,7 +1157,7 @@ msgstr "Неочікуваний статус %s" #: src/app/main/ui/auth/login.cljs:114, src/app/main/ui/auth/login.cljs:118 msgid "errors.wrong-credentials" -msgstr "Електрона адреса або пароль неправильні." +msgstr "Електрона пошта або пароль неправильні." #: src/app/main/ui/settings/password.cljs #, unused @@ -1190,12 +1189,12 @@ msgstr "Тема" #: src/app/main/ui/settings/feedback.cljs:66 msgid "feedback.subtitle" msgstr "" -"Будь ласка, опишіть причину вашого листа, вказавши чи є це проблемою, ідеєю " -"або сумнів. Член нашої команди відповість якомогашвидше." +"Будь ласка, опишіть причину листа, вказавши чи є причина скаргою, ідеєю чи " +"сумнівами. Учасник нашої команди відповість вам якомогашвидше." #: src/app/main/ui/settings/feedback.cljs:65 msgid "feedback.title" -msgstr "Електрона адреса" +msgstr "Електрона пошта" #: src/app/main/ui/settings/feedback.cljs:102 msgid "feedback.twitter-go-to" @@ -1207,7 +1206,7 @@ msgstr "Ми готові допомогти з вашими технічним #: src/app/main/ui/settings/feedback.cljs:95 msgid "feedback.twitter-title" -msgstr "Аккаунт служби підтримки в X" +msgstr "Обліковий запис служби підтримки в X" #: src/app/main/ui/settings/password.cljs:29 msgid "generic.error" @@ -1277,7 +1276,7 @@ msgstr "Обертання" #: src/app/main/ui/inspect/attributes/layout.cljs #, unused msgid "inspect.attributes.layout.top" -msgstr "Зверху" +msgstr "Згори" #: src/app/main/ui/inspect/attributes/layout.cljs #, unused @@ -1298,7 +1297,7 @@ msgstr "Обведення" #, permanent, unused msgid "inspect.attributes.stroke.alignment.center" -msgstr "Центр" +msgstr "По центру" #, permanent, unused msgid "inspect.attributes.stroke.alignment.inner" @@ -1762,7 +1761,7 @@ msgstr "Член" #: src/app/main/ui/dashboard/sidebar.cljs:510, src/app/main/ui/dashboard/team.cljs:94, src/app/main/ui/dashboard/team.cljs:102 msgid "labels.members" -msgstr "Члени" +msgstr "Учасники" #: src/app/main/ui/settings/password.cljs:84 msgid "labels.new-password" @@ -2111,7 +2110,7 @@ msgstr "Додати \"%s\" як Спільну Бібліотеку" #: src/app/main/ui/workspace/nudge.cljs:60 msgid "modals.big-nudge" -msgstr "Сильний поштовх" +msgstr "Велике зміщення" #: src/app/main/ui/settings/change_email.cljs:111 msgid "modals.change-email.confirm-email" @@ -2125,7 +2124,7 @@ msgstr "" #: src/app/main/ui/settings/change_email.cljs:104 msgid "modals.change-email.new-email" -msgstr "Нова електрона адреса" +msgstr "Нова електрона пошта" #: src/app/main/ui/settings/change_email.cljs:119 msgid "modals.change-email.submit" @@ -2141,7 +2140,7 @@ msgstr "Скопіювати токен" #: src/app/main/ui/settings/access_tokens.cljs:131 msgid "modals.create-access-token.expiration-date.label" -msgstr "Термін придатності" +msgstr "Термін дії" #: src/app/main/ui/settings/access_tokens.cljs:125 msgid "modals.create-access-token.name.label" @@ -2169,7 +2168,7 @@ msgstr "Створити вебхук" #: src/app/main/ui/dashboard/team.cljs:887 msgid "modals.create-webhook.url.label" -msgstr "Адреса майданчику" +msgstr "Посилання на Payload" #: src/app/main/ui/dashboard/team.cljs:888 msgid "modals.create-webhook.url.placeholder" @@ -2189,15 +2188,15 @@ msgstr "Видалити токен" #: src/app/main/ui/settings/delete_account.cljs:59 msgid "modals.delete-account.cancel" -msgstr "Скасувати та лишити мій аккаунт" +msgstr "Скасувати та лишити мій обліковий запис" #: src/app/main/ui/settings/delete_account.cljs:64 msgid "modals.delete-account.confirm" -msgstr "Так, видалити мій аккаунт" +msgstr "Так, видалити мій обліковий запис" #: src/app/main/ui/settings/delete_account.cljs:53 msgid "modals.delete-account.info" -msgstr "Видаливши аккаунт, ви втратите усі свої проєкти та архіви." +msgstr "Видаливши обліковий запис, ви втратите усі свої проєкти та архіви." #: src/app/main/ui/settings/delete_account.cljs:46 msgid "modals.delete-account.title" @@ -2470,7 +2469,7 @@ msgstr[2] "Перемістити бібліотеки" #: src/app/main/ui/workspace/main_menu.cljs:271, src/app/main/ui/workspace/nudge.cljs:47 msgid "modals.nudge-title" -msgstr "Кількість поштовхів" +msgstr "Кількість зміщень" #: src/app/main/ui/dashboard/team.cljs:370 msgid "modals.promote-owner-confirm.accept" @@ -2523,7 +2522,7 @@ msgstr "Видалити \"%s\" як Спільну Бібліотеку" #: src/app/main/ui/workspace/nudge.cljs:53 msgid "modals.small-nudge" -msgstr "Малий поштовх" +msgstr "Мале зміщення" #: src/app/main/ui/delete_shared.cljs:47 msgid "modals.unpublish-shared-confirm.message" @@ -3633,7 +3632,7 @@ msgstr "Перейти в повноекраний режим" #: src/app/main/ui/workspace/sidebar/shortcuts.cljs:191 msgid "shortcuts.toggle-guides" -msgstr "Показати/приховати посібники" +msgstr "Показати/приховати орієнтири" #: src/app/main/ui/workspace/sidebar/shortcuts.cljs:192 msgid "shortcuts.toggle-history" @@ -3665,11 +3664,11 @@ msgstr "Показати / приховати лінійки" #: src/app/main/ui/workspace/sidebar/shortcuts.cljs:200 msgid "shortcuts.toggle-snap-guides" -msgstr "Прив'язувати до направляючих" +msgstr "Прив'язувати до орієнтирів" #: src/app/main/ui/workspace/sidebar/shortcuts.cljs:201 msgid "shortcuts.toggle-snap-ruler-guide" -msgstr "Прив'язувати до лінійок-направляючих" +msgstr "Прив'язувати до орієнтирів лінійок" #: src/app/main/ui/workspace/sidebar/shortcuts.cljs:202 msgid "shortcuts.toggle-textpalette" @@ -3855,7 +3854,7 @@ msgstr "Остання доставка була успішною." #: src/app/main/ui/workspace/sidebar/options/menus/align.cljs:58 msgid "workspace.align.hcenter" -msgstr "Виривняти по центру горизонтально (%s)" +msgstr "Вирівняти по центру горизонтально (%s)" #: src/app/main/ui/workspace/sidebar/options/menus/align.cljs:74 msgid "workspace.align.hdistribute" @@ -4138,7 +4137,7 @@ msgstr "Вимкнути масштабування тексту" #: src/app/main/ui/workspace/main_menu.cljs:228 msgid "workspace.header.menu.disable-snap-guides" -msgstr "Вимкнути прив'язку до направляючих" +msgstr "Зробити неактивною прив'язку до орієнтирів" #: src/app/main/ui/workspace/main_menu.cljs:258 msgid "workspace.header.menu.disable-snap-pixel-grid" @@ -4146,7 +4145,7 @@ msgstr "Вимкнути прив'язку до пікселів" #: src/app/main/ui/workspace/main_menu.cljs:212 msgid "workspace.header.menu.disable-snap-ruler-guides" -msgstr "Вимкнути прив'язку до лінійок-направляючих" +msgstr "Зробити неактивною прив'язку до орієнтирів лінійок" #: src/app/main/ui/workspace/main_menu.cljs:244 msgid "workspace.header.menu.enable-dynamic-alignment" @@ -4163,7 +4162,7 @@ msgstr "Увімкнути масштабування тексту" #: src/app/main/ui/workspace/main_menu.cljs:229 msgid "workspace.header.menu.enable-snap-guides" -msgstr "Прив'язати до направляючих" +msgstr "Прив'язати до орієнтирів" #: src/app/main/ui/workspace/main_menu.cljs:259 msgid "workspace.header.menu.enable-snap-pixel-grid" @@ -4171,7 +4170,7 @@ msgstr "Увімкнути прив'язку до пікселів" #: src/app/main/ui/workspace/main_menu.cljs:213 msgid "workspace.header.menu.enable-snap-ruler-guides" -msgstr "Прив'язати до лінійок-направляючих" +msgstr "Прив'язати до орієнтирів лінійок" #: src/app/main/ui/workspace/main_menu.cljs:388 msgid "workspace.header.menu.hide-artboard-names" @@ -4179,7 +4178,7 @@ msgstr "Приховати імена дошок" #: src/app/main/ui/workspace/main_menu.cljs:342 msgid "workspace.header.menu.hide-guides" -msgstr "Приховати посібники" +msgstr "Приховати орієнтири" #: src/app/main/ui/workspace/main_menu.cljs:359 msgid "workspace.header.menu.hide-palette" @@ -4231,7 +4230,7 @@ msgstr "Показати імена дошок" #: src/app/main/ui/workspace/main_menu.cljs:343 msgid "workspace.header.menu.show-guides" -msgstr "Показати вказівки" +msgstr "Показати орієнтири" #: src/app/main/ui/workspace/main_menu.cljs:360 msgid "workspace.header.menu.show-palette" @@ -4525,7 +4524,7 @@ msgstr "У цій бібліотеці, поки що, немає ресурсі #: src/app/main/ui/workspace/sidebar/options/menus/constraints.cljs:163 msgid "workspace.options.constraints" -msgstr "Обмежити" +msgstr "Положення" #: src/app/main/ui/workspace/sidebar/options/menus/constraints.cljs:150 msgid "workspace.options.constraints.bottom" @@ -4533,11 +4532,11 @@ msgstr "Низ" #: src/app/main/ui/workspace/sidebar/options/menus/constraints.cljs:141, src/app/main/ui/workspace/sidebar/options/menus/constraints.cljs:152 msgid "workspace.options.constraints.center" -msgstr "Центр" +msgstr "По центру" #: src/app/main/ui/workspace/sidebar/options/menus/constraints.cljs:229 msgid "workspace.options.constraints.fix-when-scrolling" -msgstr "Виправити при прокручуванні" +msgstr "Фіксувати при прокручуванні" #: src/app/main/ui/workspace/sidebar/options/menus/constraints.cljs:138 msgid "workspace.options.constraints.left" @@ -4553,15 +4552,15 @@ msgstr "Праворуч" #: src/app/main/ui/workspace/sidebar/options/menus/constraints.cljs:142, src/app/main/ui/workspace/sidebar/options/menus/constraints.cljs:153 msgid "workspace.options.constraints.scale" -msgstr "Масштаб" +msgstr "Масштабувати" #: src/app/main/ui/workspace/sidebar/options/menus/constraints.cljs:149 msgid "workspace.options.constraints.top" -msgstr "Верх" +msgstr "По верху" #: src/app/main/ui/workspace/sidebar/options/menus/constraints.cljs:151 msgid "workspace.options.constraints.topbottom" -msgstr "Верх & низ" +msgstr "По верху та низу" #: src/app/main/ui/workspace/sidebar/options.cljs:179 msgid "workspace.options.design" @@ -4683,7 +4682,7 @@ msgstr "Низ" #: src/app/main/ui/workspace/sidebar/options/menus/frame_grid.cljs:233 msgid "workspace.options.grid.params.type.center" -msgstr "Центр" +msgstr "По центру" #: src/app/main/ui/workspace/sidebar/options/menus/frame_grid.cljs:232 msgid "workspace.options.grid.params.type.left" @@ -4699,7 +4698,7 @@ msgstr "Розтягування" #: src/app/main/ui/workspace/sidebar/options/menus/frame_grid.cljs:231 msgid "workspace.options.grid.params.type.top" -msgstr "Верх" +msgstr "По верху" #: src/app/main/ui/workspace/sidebar/options/menus/frame_grid.cljs:215, src/app/main/ui/workspace/sidebar/options/menus/frame_grid.cljs:292 msgid "workspace.options.grid.params.use-default" @@ -4727,7 +4726,7 @@ msgstr "Рамка групи" #: src/app/main/ui/workspace/sidebar/options/menus/frame_grid.cljs:320 msgid "workspace.options.guides.title" -msgstr "Направляючі" +msgstr "Орієнтири" #: src/app/main/ui/workspace/sidebar/options/menus/measures.cljs:489 msgid "workspace.options.height" @@ -4989,7 +4988,7 @@ msgstr "Відтінок" #: src/app/main/ui/workspace/sidebar/options/menus/layer.cljs:127 msgid "workspace.options.layer-options.blend-mode.lighten" -msgstr "Освітлення" +msgstr "Освітленн" #: src/app/main/ui/workspace/sidebar/options/menus/layer.cljs:138 msgid "workspace.options.layer-options.blend-mode.luminosity" @@ -5085,7 +5084,7 @@ msgstr "Ліворуч" #: src/app/main/ui/workspace/sidebar/options/menus/layout_item.cljs #, unused msgid "workspace.options.layout.margin" -msgstr "Відступ" +msgstr "Зовнішній відступ" #: src/app/main/ui/workspace/sidebar/options/menus/layout_item.cljs #, unused @@ -5095,7 +5094,7 @@ msgstr "Всі сторони" #: src/app/main/ui/workspace/sidebar/options/menus/layout_item.cljs #, unused msgid "workspace.options.layout.margin-simple" -msgstr "Простий відступ" +msgstr "Простий зовнішній відступ" #: src/app/main/ui/workspace/sidebar/options/menus/layout.cljs #, unused @@ -5180,14 +5179,15 @@ msgid "workspace.plugins.menu.title" msgstr "Плагіни" #: src/app/main/ui/workspace/plugins.cljs:323 -#, fuzzy msgid "workspace.plugins.permissions.disclaimer" -msgstr "Зауважте, що плагін створено третьою особою." +msgstr "" +"Зауважте, що плагін створено третьою особою, тож впевніться що ви довіряєте " +"йому перш ніж надавати дозволи. Для нас важлива приватність та безпека ваших " +"даних. Якщо маєте якісь сумніви, то просимо зв'язатись з підтримкою." #: src/app/main/ui/workspace/plugins.cljs:316 -#, fuzzy msgid "workspace.plugins.permissions.title" -msgstr "ЦЕЙ ПЛАГІН ЗАПИТУЄ ДОСТУП НА:" +msgstr "'%s' ПЛАГІН ЗАПИТУЄ ДОСТУП НА:" #: src/app/main/ui/workspace/plugins.cljs:250 msgid "workspace.plugins.permissions.user-read" @@ -5239,7 +5239,7 @@ msgstr "Вирізати" #: src/app/main/ui/workspace/context_menu.cljs:496, src/app/main/ui/workspace/sidebar/options/menus/layout_container.cljs:764, src/app/main/ui/workspace/sidebar/options/menus/layout_container.cljs:1052 msgid "workspace.shape.menu.delete" -msgstr "Видалити це" +msgstr "Вилучити" #: src/app/main/ui/workspace/sidebar/assets/common.cljs:432 msgid "workspace.shape.menu.detach-instance" @@ -5685,3 +5685,910 @@ msgstr "Оновити" #, unused msgid "workspace.viewport.click-to-close-path" msgstr "Натисність щоб закінчити шлях" + +#: src/app/main/ui/dashboard/files.cljs:190, src/app/main/ui/dashboard/projects.cljs:284 +msgid "dashboard.empty-placeholder-drafts-subtitle" +msgstr "Як тільки учасник проєкту створить чернетку, вона з'явиться тут." + +#: src/app/main/ui/dashboard/files.cljs:186, src/app/main/ui/dashboard/projects.cljs:280 +msgid "dashboard.empty-placeholder-files-title" +msgstr "Файлів ще немає." + +#: src/app/main/ui/dashboard/placeholder.cljs:39 +#, markdown +msgid "dashboard.empty-placeholder-libraries" +msgstr "" +"Додані до проєкту бібліотеки з'являться тут. Можете поширити власні файли чи " +"додати з нашої [сторінки Бібліотек та шаблонів](https://penpot.app/libraries-" +"templates)." + +#: src/app/main/ui/dashboard/files.cljs:185, src/app/main/ui/dashboard/projects.cljs:279 +msgid "dashboard.empty-placeholder-drafts-title" +msgstr "Чернеток ще немає." + +#: src/app/main/ui/dashboard/files.cljs:191, src/app/main/ui/dashboard/projects.cljs:285 +msgid "dashboard.empty-placeholder-files-subtitle" +msgstr "Як тільки учасник проєкту створить файл, він буде відображений тут." + +#: src/app/main/ui/dashboard/placeholder.cljs:32 +msgid "dashboard.empty-placeholder-libraries-title" +msgstr "Бібліотек ще немає." + +#: src/app/main/data/common.cljs:206 +msgid "dashboard.permissions-change.owner" +msgstr "Відтепер ви власник цієї команди." + +#: src/app/main/data/common.cljs:203 +msgid "dashboard.permissions-change.viewer" +msgstr "Відтепер ви спостерігач у цій команді." + +#: src/app/main/data/common.cljs:205 +msgid "dashboard.permissions-change.admin" +msgstr "Відтепер ви адміністратор цієї команди." + +#: src/app/main/data/common.cljs:204 +msgid "dashboard.permissions-change.editor" +msgstr "Відтепер ви редактор цієї команди." + +#: src/app/main/data/common.cljs:233 +msgid "dashboard.removed-from-team" +msgstr "Більше ви не є частиною команди \"%s\"." + +#: src/app/main/ui/comments.cljs:340, src/app/main/ui/workspace/sidebar/options/menus/text.cljs:295, src/app/main/ui/workspace/sidebar/options/menus/text.cljs:324 +msgid "labels.options" +msgstr "Параметри" + +#: src/app/main/ui/delete_shared.cljs:52 +msgid "modals.unpublish-shared-confirm.accept" +msgid_plural "modals.unpublish-shared-confirm.accept" +msgstr[0] "Зняти з публікації поширену сторінку" +msgstr[1] "Зняти з публікації декілька поширених сторінок" +msgstr[2] "Зняти з публікації поширені сторінки" + +#: src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs:271 +msgid "settings.remove-color" +msgstr "Видалити колір" + +#: src/app/main/ui/dashboard/placeholder.cljs +#, markdown, unused +msgid "dashboard.empty-placeholder-libraries-subtitle" +msgstr "" +"Додані до проєкту бібліотеки з'являться тут. Можете поширити власні файли чи " +"додати з нашої [сторінки Бібліотек та шаблонів](https://penpot.app/libraries-" +"templates)." + +#: src/app/main/ui/dashboard/fonts.cljs:445 +msgid "dashboard.fonts.empty-placeholder-viewer-sub" +msgstr "" +"Як тільки учасник проєкту завантажить користувацький шрифт, його буде " +"відображено тут." + +#: src/app/main/ui/workspace/sidebar/versions.cljs:149, src/app/main/ui/workspace/sidebar/versions.cljs:288 +msgid "labels.restore" +msgstr "Відновити" + +#: src/app/main/ui/workspace/sidebar/assets/colors.cljs:495 +msgid "workspace.assets.colors.add-color" +msgstr "Додати колір" + +#: src/app/main/ui/workspace/sidebar/assets/components.cljs:532 +msgid "workspace.assets.components.add-component" +msgstr "Додати компонент" + +#: src/app/main/ui/workspace/right_header.cljs:255 +msgid "workspace.header.share" +msgstr "Поділитись" + +#: src/app/main/ui/workspace/libraries.cljs:304 +msgid "workspace.libraries.more-templates-link" +msgstr "більше шаблонів тут" + +#: src/app/main/ui/workspace/sidebar/options/menus/blur.cljs:91 +msgid "workspace.options.blur-options.add-blur" +msgstr "Додати розмиття" + +#: src/app/main/ui/workspace/sidebar/options/menus/blur.cljs:112 +msgid "workspace.options.blur-options.remove-blur" +msgstr "Видалити розмиття" + +#: src/app/main/ui/workspace/sidebar/options/menus/blur.cljs:108 +msgid "workspace.options.blur-options.toggle-blur" +msgstr "Перемикання розмивання" + +#: src/app/main/ui/workspace/sidebar/options/menus/exports.cljs:195 +msgid "workspace.options.export.add-export" +msgstr "Додати експортування" + +#: src/app/main/ui/workspace/sidebar/options/menus/exports.cljs:207, src/app/main/ui/workspace/sidebar/options/menus/exports.cljs:242 +msgid "workspace.options.export.remove-export" +msgstr "Видалити експортування" + +#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs:735 +msgid "workspace.options.interactions.add-interaction" +msgstr "Додати взаємодію" + +#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs +#, unused +msgid "workspace.options.interactions.remove-interaction" +msgstr "Видалити взаємодію" + +#: src/app/main/ui/dashboard/placeholder.cljs:35 +msgid "dashboard.empty-placeholder-libraries-subtitle-viewer-role" +msgstr "Додані до проєкту бібліотеки з'являться тут." + +#: src/app/main/ui/dashboard/fonts.cljs:444 +msgid "dashboard.fonts.empty-placeholder-viewer" +msgstr "Користувацьких шрифтів ще немає." + +#: src/app/main/ui/dashboard/team.cljs:944 +msgid "dashboard.webhooks.cant-edit" +msgstr "Ви можете видаляти або редагувати лише створені вами вебхуки." + +#: src/app/main/ui/workspace/tokens/sidebar.cljs:229 +msgid "labels.sets" +msgstr "Набори" + +#: src/app/main/ui/workspace/sidebar/options/menus/layout_container.cljs:1051 +#, unused +msgid "labels.add" +msgstr "Додати" + +#: src/app/main/ui/workspace/tokens/sidebar.cljs:187 +msgid "labels.themes" +msgstr "Теми" + +#: src/app/main/ui/dashboard/team.cljs:216 +msgid "modals.invite-team-member.text" +msgstr "" +"Ви можете запросити учасників до команди для того щоб вони мали доступ до " +"цього та інших файлів команди." + +#: src/app/main/ui/workspace/sidebar/assets/typographies.cljs:408 +msgid "workspace.assets.typography.add-typography" +msgstr "Додати типографіку" + +#: src/app/main/ui/workspace/libraries.cljs:300 +msgid "workspace.libraries.more-templates" +msgstr "Ви можете шукати " + +#: src/app/main/ui/workspace/sidebar/options/menus/fill.cljs:150 +msgid "workspace.options.fill.add-fill" +msgstr "Додати колір заливки" + +#: src/app/main/ui/workspace/sidebar/options/menus/fill.cljs:163 +msgid "workspace.options.fill.remove-fill" +msgstr "Видалити заливку" + +#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs:154 +msgid "workspace.options.flows.remove-flow" +msgstr "Видалити потік" + +#: src/app/main/ui/workspace/sidebar/options/menus/layer.cljs +#, unused +msgid "workspace.options.layer-options.title.group" +msgstr "Згрупувати шари" + +#: src/app/main/ui/workspace/sidebar/options/menus/layout.cljs +#, unused +msgid "workspace.options.layout.gap" +msgstr "Відступ" + +#: src/app/main/ui/workspace/sidebar/options/menus/layout.cljs +#, unused +msgid "workspace.options.layout.padding-all" +msgstr "Усі сторони" + +#: src/app/main/ui/workspace/sidebar/options/menus/layout.cljs +#, unused +msgid "workspace.options.layout.top" +msgstr "Згори" + +#: src/app/main/ui/workspace/sidebar/options/menus/color_selection.cljs:159 +msgid "workspace.options.more-colors" +msgstr "Більше кольорів" + +#: src/app/main/ui/workspace/sidebar/options/menus/layer.cljs:161 +msgid "workspace.options.opacity" +msgstr "Непрозорість" + +#: src/app/main/ui/dashboard/team.cljs:181, src/app/main/ui/onboarding/team_choice.cljs:100 +msgid "errors.maximum-invitations-by-request-reached" +msgstr "" +"Дрсягнуто максимальної кількості поштових скриньок, на які можна надіслати " +"запрошення (максимум %s скриньок)" + +#: src/app/main/ui/workspace/tokens/sets.cljs:153 +msgid "labels.collapse" +msgstr "Згорнути" + +#: src/app/main/ui/workspace/sidebar/options/menus/frame_grid.cljs:323 +msgid "workspace.options.guides.add-guide" +msgstr "Додати орієнтир" + +#: src/app/main/ui/workspace/sidebar/options/menus/frame_grid.cljs:187 +msgid "workspace.options.guides.remove-guide" +msgstr "Видалити орієнтир" + +#: src/app/main/ui/workspace/sidebar/options/menus/frame_grid.cljs:183 +msgid "workspace.options.guides.toggle-guide" +msgstr "Перемкнути орієнтир" + +#: src/app/main/ui/workspace/sidebar/options/menus/layer.cljs:176, src/app/main/ui/workspace/sidebar/options/menus/layer.cljs:182 +msgid "workspace.options.layer-options.toggle-layer" +msgstr "Перемкнути видімість шару" + +#: src/app/main/ui/workspace/sidebar/options/menus/layout_item.cljs +#, unused +msgid "workspace.options.layout-item.advanced-ops" +msgstr "Додаткові параметри" + +#: src/app/main/ui/workspace/sidebar/options/menus/layout.cljs +#, unused +msgid "workspace.options.layout.right" +msgstr "Праворуч" + +#: src/app/main/ui/workspace/sidebar/options/menus/color_selection.cljs:136 +msgid "workspace.options.more-lib-colors" +msgstr "Більше кольорів бібліотеки" + +#: src/app/main/ui/workspace/sidebar/options/menus/layout_item.cljs:531 +msgid "workspace.options.layout-item.layout-item-max-w" +msgstr "Макс. Ширина" + +#: src/app/main/ui/workspace/sidebar/options/menus/layout.cljs +#, unused +msgid "workspace.options.layout.padding" +msgstr "Внутрішній відступ" + +#: src/app/main/ui/workspace/sidebar/options/menus/layer.cljs +#, unused +msgid "workspace.options.layer-options.title.multiple" +msgstr "Обрані шари" + +#: src/app/main/ui/workspace/sidebar/options/menus/layout_item.cljs:564 +msgid "workspace.options.layout-item.layout-item-max-h" +msgstr "Макс. Висота" + +#: src/app/main/ui/workspace/sidebar/options/menus/layout.cljs +#, unused +msgid "workspace.options.layout.padding-simple" +msgstr "Простий внутрішній відступ" + +#: src/app/main/ui/workspace/sidebar/options/menus/layout.cljs +#, unused +msgid "workspace.options.layout.space-around" +msgstr "простір навколо" + +#: src/app/main/ui/workspace/sidebar/options/menus/layout.cljs +#, unused +msgid "workspace.options.layout.space-between" +msgstr "простір між" + +#: src/app/main/ui/workspace/sidebar/options/shapes/frame.cljs, src/app/main/ui/workspace/sidebar/options/menus/measures.cljs +#, unused +msgid "workspace.options.position" +msgstr "Розташування" + +#: src/app/main/ui/workspace/sidebar/options/menus/measures.cljs:547 +msgid "workspace.options.rotation" +msgstr "Обернення" + +#: src/app/main/ui/workspace/sidebar/options/menus/measures.cljs:611 +msgid "workspace.options.radius-top-right" +msgstr "Верхнього правого" + +#: src/app/main/ui/workspace/sidebar/options/menus/fill.cljs:48 +msgid "workspace.options.selection-fill" +msgstr "Заливка обраного" + +#: src/app/main/ui/workspace/sidebar/options/menus/shadow.cljs:145 +msgid "workspace.options.shadow-options.drop-shadow" +msgstr "Падаюча тінь" + +#: src/app/main/ui/workspace/sidebar/options/menus/shadow.cljs:297 +msgid "workspace.options.shadow-options.title" +msgstr "Тінь" + +#: src/app/main/ui/workspace/sidebar/options/menus/shadow.cljs:296 +msgid "workspace.options.shadow-options.title.group" +msgstr "Групова тінь" + +#: src/app/main/ui/workspace/sidebar/options/menus/measures.cljs:425 +msgid "workspace.options.size-presets" +msgstr "Шаблони розміру" + +#: src/app/main/ui/workspace/sidebar/options/menus/stroke.cljs:43 +msgid "workspace.options.stroke" +msgstr "Обведення" + +#: src/app/main/ui/workspace/sidebar/options/menus/stroke.cljs +#, unused +msgid "workspace.options.stroke-cap.diamond-marker" +msgstr "Ромбоподібний маркер" + +#: src/app/main/ui/workspace/sidebar/options/menus/text.cljs:109 +msgid "workspace.options.text-options.align-top" +msgstr "Вирівняти по верху" + +#: src/app/main/ui/workspace/sidebar/options/menus/text.cljs:143 +msgid "workspace.options.text-options.grow-fixed" +msgstr "Фіксована" + +#: src/app/main/ui/workspace/sidebar/options/menus/text.cljs, src/app/main/ui/workspace/sidebar/options/menus/typography.cljs +#, unused +msgid "workspace.options.text-options.none" +msgstr "Жоден" + +#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs:753 +msgid "workspace.options.use-play-button" +msgstr "" +"Використовуйте кнопку програвання в заголовку, щоб запустити перегляд " +"прототипів." + +#: src/app/main/ui/workspace/sidebar/options/menus/measures.cljs:640 +msgid "workspace.options.radius.single-corners" +msgstr "Незалежні кути" + +#: src/app/main/ui/workspace/sidebar/options/menus/stroke.cljs:192 +msgid "workspace.options.stroke-color" +msgstr "Колір обведення" + +#: src/app/main/ui/workspace/sidebar/options.cljs:183 +msgid "workspace.options.prototype" +msgstr "Прототип" + +#: src/app/main/ui/workspace/sidebar/options/menus/text.cljs:61 +msgid "workspace.options.text-options.text-align-justify" +msgstr "За шириною (%s)" + +#: src/app/main/ui/workspace/sidebar/options/menus/measures.cljs:620 +msgid "workspace.options.radius-bottom-left" +msgstr "Нижнього лівого кута" + +#: src/app/main/ui/workspace/sidebar/options/menus/stroke.cljs:184 +msgid "workspace.options.stroke.remove-stroke" +msgstr "Видалити обведення" + +#: src/app/main/ui/workspace/sidebar/options/menus/text.cljs:117 +msgid "workspace.options.text-options.align-bottom" +msgstr "Вирівняти по низу" + +#: src/app/main/ui/workspace/sidebar/options/menus/text.cljs:84 +msgid "workspace.options.text-options.direction-ltr" +msgstr "LTR" + +#: src/app/main/ui/workspace/plugins.cljs:192 +msgid "workspace.plugins.error.url" +msgstr "Плагіну не існує чи посилання неправильне." + +#: src/app/main/ui/workspace/plugins.cljs:196 +msgid "workspace.plugins.error.manifest" +msgstr "Маніфест плагіну неправильний." + +#: src/app/main/ui/workspace/plugins.cljs:425 +msgid "workspace.plugins.try-out.title" +msgstr "'%s' ПЛАГІН ВСТАНОВЛЕНО ДЛЯ ВАШОГО КОРИСТУВАЧА!" + +#: src/app/main/ui/workspace/plugins.cljs:429 +msgid "workspace.plugins.try-out.message" +msgstr "" +"Хочете переглянути? Буде створено нову чернетку для цієї команди. (Якщо ні, " +"ви можете завжди знайти це у встановлених плагінах будь-якого файлу.)" + +#: src/app/main/ui/workspace/tokens/modals/themes.cljs:43 +msgid "workspace.token.no-themes-currently" +msgstr "Наразі у вас немає жодної теми." + +#: src/app/main/ui/workspace/tokens/modals/themes.cljs:318 +msgid "workspace.token.set-selection-theme" +msgstr "" +"Визначити які набори токенів повинні бути використані як частину цього " +"варіанту теми:" + +#: src/app/main/ui/workspace/tokens/modals/themes.cljs +#, unused +msgid "workspace.token.theme-name" +msgstr "Тема %s" + +#: src/app/main/ui/workspace/sidebar/versions.cljs:193 +msgid "workspace.versions.autosaved.entry" +msgstr "%s версії автозбереження" + +#: src/app/main/ui/workspace/sidebar/versions.cljs:326 +msgid "workspace.versions.filter.label" +msgstr "Фільтр версій" + +#: src/app/main/ui/workspace/sidebar/versions.cljs:328 +msgid "workspace.versions.filter.mine" +msgstr "Мої версії" + +#: src/app/main/ui/workspace/sidebar/versions.cljs:334 +msgid "workspace.versions.filter.user" +msgstr "Версії %s" + +#: src/app/main/ui/workspace/sidebar/options/menus/measures.cljs:565, src/app/main/ui/workspace/sidebar/options/menus/measures.cljs:588 +msgid "workspace.options.radius" +msgstr "Радіус" + +#: src/app/main/ui/workspace/sidebar/options/menus/measures.cljs:629 +msgid "workspace.options.radius-bottom-right" +msgstr "Нижнього правого кута" + +#: src/app/main/ui/workspace/sidebar/options/menus/interactions.cljs:749 +msgid "workspace.options.select-a-shape" +msgstr "" +"Оберіть фігуру, дошку чи групу щоб перетягнути з'єднання до іншої дошки." + +#: src/app/main/ui/workspace/sidebar/options/menus/shadow.cljs:302 +msgid "workspace.options.shadow-options.add-shadow" +msgstr "Додати тінь" + +#: src/app/main/ui/viewer/inspect/attributes/shadow.cljs:40, src/app/main/ui/workspace/sidebar/options/menus/shadow.cljs:199, src/app/main/ui/workspace/sidebar/options/menus/shadow.cljs:201 +msgid "workspace.options.shadow-options.blur" +msgstr "Розмиття" + +#: src/app/main/ui/workspace/sidebar/options/menus/stroke.cljs:171 +msgid "workspace.options.stroke.add-stroke" +msgstr "Додати колір обведення" + +#: src/app/main/ui/workspace/sidebar/options/rows/stroke_row.cljs:104 +msgid "workspace.options.stroke.dotted" +msgstr "Точковий" + +#: src/app/main/ui/workspace/sidebar/options/menus/shadow.cljs:177, src/app/main/ui/workspace/sidebar/options/menus/shadow.cljs:315 +msgid "workspace.options.shadow-options.remove-shadow" +msgstr "Видалити тінь" + +#: src/app/main/ui/workspace/sidebar/options/menus/shadow.cljs:295 +msgid "workspace.options.shadow-options.title.multiple" +msgstr "Тінь виділеного" + +#: src/app/main/ui/workspace/sidebar/options/menus/shadow.cljs:173 +msgid "workspace.options.shadow-options.toggle-shadow" +msgstr "Перемкнути тінь" + +#: src/app/main/ui/workspace/sidebar/options/menus/fill.cljs:197 +msgid "workspace.options.show-fill-on-export" +msgstr "Показати в експортованому" + +#: src/app/main/ui/workspace/sidebar/options/menus/typography.cljs:387 +msgid "workspace.options.text-options.letter-spacing" +msgstr "Міжлітеральний відступ" + +#: src/app/main/ui/workspace/sidebar/options/menus/text.cljs:53 +msgid "workspace.options.text-options.text-align-center" +msgstr "Вирівняти по центру (%s)" + +#: src/app/main/ui/workspace/sidebar/options/menus/text.cljs:189 +msgid "workspace.options.text-options.title-selection" +msgstr "Вибраний текст" + +#: src/app/main/ui/workspace/sidebar/options/menus/typography.cljs +#, unused +msgid "workspace.options.text-options.titlecase" +msgstr "Регістр заголовку" + +#: src/app/main/ui/workspace/sidebar/options/menus/text.cljs:173 +msgid "workspace.options.text-options.underline" +msgstr "Підкреслення (%s)" + +#: src/app/main/data/plugins.cljs:86, src/app/main/ui/workspace/main_menu.cljs:696, src/app/main/ui/workspace/plugins.cljs:82 +msgid "workspace.plugins.error.need-editor" +msgstr "Щоб використовувати цей плагін, ви маєте бути редактором" + +#: src/app/main/ui/workspace/plugins.cljs:283 +msgid "workspace.plugins.permissions.allow-download" +msgstr "Завантаження файлів розпочато." + +#: src/app/main/ui/workspace/plugins.cljs:276 +msgid "workspace.plugins.permissions.comment-read" +msgstr "Читати ваші коментарі та відповіді." + +#: src/app/main/ui/workspace/context_menu.cljs:235 +msgid "workspace.shape.menu.rename" +msgstr "Перейменувати" + +#: src/app/main/ui/workspace/context_menu.cljs:286 +msgid "workspace.shape.menu.create-artboard-from-selection" +msgstr "Виділене на дошку" + +#: src/app/main/ui/workspace/plugins.cljs:270 +msgid "workspace.plugins.permissions.comment-write" +msgstr "Читати та змінювати ваші коментарі та відповіді від вашого імені." + +#: src/app/main/ui/workspace/plugins.cljs:86 +msgid "workspace.plugins.remove-plugin" +msgstr "Видалити плагін" + +#: src/app/main/ui/workspace/plugins.cljs:436 +msgid "workspace.plugins.try-out.cancel" +msgstr "НЕ ЗАРАЗ" + +#: src/app/main/ui/workspace/plugins.cljs:442 +msgid "workspace.plugins.try-out.try" +msgstr "СПРОБУВАТИ ПЛАГІН" + +#: src/app/main/ui/workspace/sidebar/options/menus/layout_container.cljs:1022 +msgid "workspace.shape.menu.remove-layout" +msgstr "Видалити макет" + +#: src/app/main/ui/workspace/sidebar/sitemap.cljs:229 +msgid "workspace.sidebar.sitemap.add-page" +msgstr "Додати сторінку" + +#: src/app/main/ui/workspace/tokens/theme_select.cljs:84 +msgid "workspace.token.active-themes" +msgstr "%s активних тем" + +#: src/app/main/ui/workspace/tokens/sidebar.cljs +#, unused +msgid "workspace.token.add set" +msgstr "Додати набір" + +#: src/app/main/ui/workspace/tokens/modals/themes.cljs:47 +msgid "workspace.token.create-new-theme" +msgstr "Створити свою першу тему зараз." + +#: src/app/main/ui/workspace/tokens/sidebar.cljs:194, src/app/main/ui/workspace/tokens/sidebar.cljs:210 +msgid "workspace.token.create-one" +msgstr "Створити його." + +#: src/app/main/ui/workspace/tokens/form.cljs:362 +msgid "workspace.token.create-token" +msgstr "Створити новий %s токен" + +#: src/app/main/ui/workspace/tokens/modals/themes.cljs:147 +msgid "workspace.token.delete-theme-title" +msgstr "Видалити тему" + +#: src/app/main/ui/workspace/tokens/modals/themes.cljs:302 +msgid "workspace.token.edit-theme-title" +msgstr "Редагувати тему" + +#: src/app/main/ui/workspace/tokens/form.cljs:361 +msgid "workspace.token.edit-token" +msgstr "Редагувати токен" + +#: src/app/main/ui/workspace/tokens/sets.cljs:186 +msgid "workspace.token.grouping-set-alert" +msgstr "Групування наборів токенів поки не підтримується." + +#: src/app/main/ui/workspace/tokens/theme_select.cljs:88 +msgid "workspace.token.no-active-theme" +msgstr "Немає активної теми" + +#: src/app/main/ui/workspace/tokens/modals/themes.cljs:142 +msgid "workspace.token.no-sets" +msgstr "Немає наборів" + +#: src/app/main/ui/workspace/tokens/sets.cljs:216 +msgid "workspace.token.no-sets-create" +msgstr "Ще не оголошено жодного набору. Створіть перший." + +#: src/app/main/ui/workspace/tokens/sidebar.cljs:239 +msgid "workspace.token.no-sets-yet" +msgstr "Тут ще немає наборів." + +#: src/app/main/ui/workspace/tokens/modals/themes.cljs:133 +msgid "workspace.token.num-sets" +msgstr "%s наборів" + +#: src/app/main/ui/workspace/tokens/sidebar.cljs:66 +msgid "workspace.token.original-value" +msgstr "Початкове значення: " + +#: src/app/main/ui/workspace/tokens/form.cljs:193, src/app/main/ui/workspace/tokens/form.cljs:196, src/app/main/ui/workspace/tokens/sidebar.cljs:67 +msgid "workspace.token.resolved-value" +msgstr "Розв'язане значення: " + +#: src/app/main/ui/workspace/tokens/modals/themes.cljs:208 +msgid "workspace.token.save-theme" +msgstr "Зберегти тему" + +#: src/app/main/ui/workspace/tokens/sets.cljs:172 +msgid "workspace.token.select-set" +msgstr "Обрати набір." + +#: src/app/main/ui/workspace/tokens/modals/themes.cljs:39, src/app/main/ui/workspace/tokens/modals/themes.cljs:84 +msgid "workspace.token.themes" +msgstr "Теми" + +#: src/app/main/ui/workspace/sidebar/versions.cljs:187 +msgid "workspace.versions.autosaved.version" +msgstr "Автозбережено %s" + +#: src/app/main/ui/workspace/sidebar/versions.cljs:224 +msgid "workspace.versions.button.pin" +msgstr "Прикріпити версію" + +#: src/app/main/ui/workspace/sidebar/versions.cljs:345, src/app/main/ui/workspace/sidebar/versions.cljs:347 +msgid "workspace.versions.button.save" +msgstr "Зберегти версію" + +#: src/app/main/ui/workspace/sidebar/versions.cljs:354 +msgid "workspace.versions.empty" +msgstr "Тут ще немає жодної версії" + +#: src/app/main/ui/workspace/sidebar/versions.cljs:327 +msgid "workspace.versions.filter.all" +msgstr "Усі версії" + +#: src/app/main/ui/workspace/sidebar/versions.cljs:340 +msgid "workspace.versions.loading" +msgstr "Завантаження..." + +#: src/app/main/ui/workspace/sidebar/versions.cljs:283 +msgid "workspace.versions.restore-warning" +msgstr "Ви бажаєте відновити ці версії?" + +#: src/app/main/ui/workspace/sidebar/versions.cljs:207 +msgid "workspace.versions.snapshot-menu" +msgstr "Відкрити меню знятків" + +#: src/app/main/ui/workspace/sidebar/versions.cljs:138 +msgid "workspace.versions.version-menu" +msgstr "Відкрити меню версій" + +#: src/app/main/ui/workspace/sidebar/options/menus/measures.cljs:602 +msgid "workspace.options.radius-top-left" +msgstr "Верхнього лівого" + +#: src/app/main/ui/workspace/sidebar/options/menus/typography.cljs:181 +msgid "workspace.options.search-font" +msgstr "Пошук шрифту" + +#: src/app/main/ui/workspace/sidebar/options/rows/stroke_row.cljs:132 +msgid "workspace.options.stroke-cap.round" +msgstr "Округле" + +#: src/app/main/ui/workspace/sidebar/options/rows/stroke_row.cljs:124 +msgid "workspace.options.stroke-cap.none" +msgstr "Жодний" + +#: src/app/main/ui/workspace/sidebar/options/menus/stroke.cljs +#, unused +msgid "workspace.options.stroke-cap.line-arrow" +msgstr "Лінійна стрілка" + +#: src/app/main/ui/workspace/sidebar/options/rows/stroke_row.cljs:126 +msgid "workspace.options.stroke-cap.line-arrow-short" +msgstr "Стрілка" + +#: src/app/main/ui/workspace/sidebar/options/rows/stroke_row.cljs:165 +msgid "workspace.options.stroke-width" +msgstr "Довжина обведення" + +#: src/app/main/ui/workspace/sidebar/options/rows/stroke_row.cljs:87 +msgid "workspace.options.stroke.center" +msgstr "По центру" + +#: src/app/main/ui/workspace/sidebar/options/rows/stroke_row.cljs:88 +msgid "workspace.options.stroke.inner" +msgstr "Всередину" + +#: src/app/main/ui/workspace/sidebar/options/rows/stroke_row.cljs:106 +msgid "workspace.options.stroke.mixed" +msgstr "Комбіноване" + +#: src/app/main/ui/workspace/sidebar/options/rows/stroke_row.cljs:89 +msgid "workspace.options.stroke.outer" +msgstr "Назовні" + +#: src/app/main/ui/workspace/sidebar/options/rows/stroke_row.cljs:103 +msgid "workspace.options.stroke.solid" +msgstr "Жирне" + +#: src/app/main/ui/workspace/context_menu.cljs:404 +msgid "workspace.shape.menu.flow-start" +msgstr "Початок потоку" + +#: src/app/main/ui/workspace/sidebar/options/menus/measures.cljs:639 +msgid "workspace.options.radius.all-corners" +msgstr "Усі кути" + +#: src/app/main/ui/workspace/sidebar/options/menus/typography.cljs:184 +msgid "workspace.options.recent-fonts" +msgstr "Нещодавній" + +#: src/app/main/ui/exports/assets.cljs:290 +msgid "workspace.options.retry" +msgstr "Спробувати ще раз" + +#: src/app/main/ui/workspace/sidebar/options/menus/stroke.cljs:41 +msgid "workspace.options.selection-stroke" +msgstr "Обведення виділення" + +#: src/app/main/ui/workspace/sidebar/options/menus/color_selection.cljs:118 +msgid "workspace.options.selection-color" +msgstr "Обрані кольори" + +#: src/app/main/ui/viewer/inspect/attributes/shadow.cljs:38, src/app/main/ui/workspace/sidebar/options/menus/shadow.cljs:187 +msgid "workspace.options.shadow-options.offsetx" +msgstr "Вісь X" + +#: src/app/main/ui/viewer/inspect/attributes/shadow.cljs:39, src/app/main/ui/workspace/sidebar/options/menus/shadow.cljs:225 +msgid "workspace.options.shadow-options.offsety" +msgstr "Вісь Y" + +#: src/app/main/ui/workspace/sidebar/options/menus/measures.cljs:669 +msgid "workspace.options.show-in-viewer" +msgstr "Показати у режимі перегляду" + +#: src/app/main/ui/workspace/sidebar/options/menus/frame_grid.cljs:164 +msgid "workspace.options.size" +msgstr "Розмір" + +#: src/app/main/ui/workspace/sidebar/options/menus/stroke.cljs +#, unused +msgid "workspace.options.stroke-cap.circle-marker" +msgstr "Маркер кола" + +#: src/app/main/ui/workspace/sidebar/options/rows/stroke_row.cljs:130 +msgid "workspace.options.stroke-cap.diamond-marker-short" +msgstr "Ромб" + +#: src/app/main/ui/workspace/sidebar/options/rows/stroke_row.cljs:133 +msgid "workspace.options.stroke-cap.square" +msgstr "Квадратне" + +#: src/app/main/ui/workspace/sidebar/options/rows/stroke_row.cljs:129 +msgid "workspace.options.stroke-cap.circle-marker-short" +msgstr "Коло" + +#: src/app/main/ui/workspace/sidebar/options/menus/stroke.cljs +#, unused +msgid "workspace.options.stroke-cap.square-marker" +msgstr "Квадратний маркер" + +#: src/app/main/ui/workspace/sidebar/options/rows/stroke_row.cljs:128 +msgid "workspace.options.stroke-cap.square-marker-short" +msgstr "Прямокутне" + +#: src/app/main/ui/workspace/sidebar/options/menus/stroke.cljs +#, unused +msgid "workspace.options.stroke-cap.triangle-arrow" +msgstr "Трикутна стрілка" + +#: src/app/main/ui/workspace/sidebar/options/rows/stroke_row.cljs:127 +msgid "workspace.options.stroke-cap.triangle-arrow-short" +msgstr "Трикутне" + +#: src/app/main/ui/workspace/sidebar/options/rows/stroke_row.cljs:105 +msgid "workspace.options.stroke.dashed" +msgstr "Пунктирний" + +#: src/app/main/ui/workspace/sidebar/options/menus/text.cljs:113 +msgid "workspace.options.text-options.align-middle" +msgstr "Вирівняти по середині" + +#: src/app/main/ui/workspace/sidebar/options/menus/text.cljs:89 +msgid "workspace.options.text-options.direction-rtl" +msgstr "RTL" + +#: src/app/main/ui/workspace/sidebar/options/menus/text.cljs:151 +msgid "workspace.options.text-options.grow-auto-height" +msgstr "Автоматична висота" + +#: src/app/main/ui/workspace/sidebar/options/menus/typography.cljs:369 +msgid "workspace.options.text-options.line-height" +msgstr "Висота рядка" + +#: src/app/main/ui/workspace/sidebar/options/menus/text.cljs:147 +msgid "workspace.options.text-options.grow-auto-width" +msgstr "Автоматична ширина" + +#: src/app/main/ui/workspace/sidebar/options/menus/text.cljs:178 +msgid "workspace.options.text-options.strikethrough" +msgstr "Закреслення (%s)" + +#: src/app/main/ui/workspace/sidebar/options/menus/text.cljs:49 +msgid "workspace.options.text-options.text-align-left" +msgstr "Вирівняти ліворуч (%s)" + +#: src/app/main/ui/workspace/sidebar/options/menus/text.cljs:57 +msgid "workspace.options.text-options.text-align-right" +msgstr "Вирівняти праворуч (%s)" + +#: src/app/main/ui/workspace/sidebar/options/menus/text.cljs:191 +msgid "workspace.options.text-options.title" +msgstr "Текст" + +#: src/app/main/ui/workspace/sidebar/options/menus/typography.cljs +#, unused +msgid "workspace.options.text-options.lowercase" +msgstr "нижній реєстр" + +#: src/app/main/ui/workspace/sidebar/options/menus/text.cljs:190 +msgid "workspace.options.text-options.title-group" +msgstr "Груповий текст" + +#: src/app/main/ui/workspace/sidebar/options/menus/typography.cljs +#, unused +msgid "workspace.options.text-options.uppercase" +msgstr "ВЕРХНІЙ РЕГІСТР" + +#: src/app/main/ui/workspace/sidebar/options/menus/measures.cljs:465 +msgid "workspace.options.width" +msgstr "Ширина" + +#: src/app/main/ui/workspace/plugins.cljs:243 +msgid "workspace.plugins.permissions.content-read" +msgstr "Читати вміст файлів до яких користувачі мають доступ." + +#: src/app/main/ui/workspace/plugins.cljs:237 +msgid "workspace.plugins.permissions.content-write" +msgstr "Читати та модифікувати вміст файлів, до яких користувачі мають доступ." + +#: src/app/main/ui/workspace/plugins.cljs:263 +msgid "workspace.plugins.permissions.library-read" +msgstr "Читати ваші бібліотеки та матеріали." + +#: src/app/main/ui/workspace/plugins.cljs:257 +msgid "workspace.plugins.permissions.library-write" +msgstr "Читати та модифікувати ваші бібліотеки та матеріали." + +#: src/app/main/ui/workspace/context_menu.cljs:194 +msgid "workspace.shape.menu.back" +msgstr "Розмістити позаду" + +#: src/app/main/ui/workspace/context_menu.cljs:191 +msgid "workspace.shape.menu.backward" +msgstr "Перемістити назад" + +#: src/app/main/ui/workspace/tokens/modals/themes.cljs:155, src/app/main/ui/workspace/tokens/modals/themes.cljs:239 +msgid "workspace.token.create-theme-title" +msgstr "Створити тему" + +#: src/app/main/ui/workspace/tokens/modals/themes.cljs:52 +msgid "workspace.token.new-theme" +msgstr "Нова тема" + +#: src/app/main/ui/workspace/context_menu.cljs:402 +msgid "workspace.shape.menu.delete-flow-start" +msgstr "Видалити початок потоку" + +#: src/app/main/ui/workspace/sidebar/options/menus/layout_container.cljs:1004, src/app/main/ui/workspace/sidebar/options/menus/layout_container.cljs:1030 +msgid "workspace.shape.menu.add-layout" +msgstr "Додати макет" + +#: src/app/main/ui/workspace/plugins.cljs:372 +msgid "workspace.plugins.permissions-update.title" +msgstr "ОНОВИТИ ЦЕЙ ПЛАГІН" + +#: src/app/main/ui/workspace/plugins.cljs:376 +msgid "workspace.plugins.permissions-update.warning" +msgstr "" +"Плагін було модифіковано після вашого останнього використання. Тепер він " +"також хоче отримати доступ до:" + +#: src/app/main/ui/workspace/sidebar/options/menus/shadow.cljs:146 +msgid "workspace.options.shadow-options.inner-shadow" +msgstr "Внутрішня тінь" + +#: src/app/main/ui/workspace/sidebar/versions.cljs:219 +msgid "workspace.versions.button.restore" +msgstr "Відновити версію" + +#: src/app/main/ui/workspace/sidebar/options/menus/shadow.cljs:239 +msgid "workspace.options.shadow-options.color" +msgstr "Колір тіні" + +#: src/app/main/ui/viewer/inspect/attributes/shadow.cljs:41, src/app/main/ui/workspace/sidebar/options/menus/shadow.cljs:212, src/app/main/ui/workspace/sidebar/options/menus/shadow.cljs:214 +msgid "workspace.options.shadow-options.spread" +msgstr "Розтягнення" + +#: src/app/main/ui/workspace/sidebar/versions.cljs:190 +msgid "workspace.versions.expand-snapshot" +msgstr "Розгорнути знятки" + +#: src/app/main/ui/workspace/tokens/sidebar.cljs:191 +msgid "workspace.token.no-themes" +msgstr "Тут немає тем." + +#: src/app/main/ui/workspace/tokens/modals/themes.cljs:310 +msgid "workspace.token.back-to-themes" +msgstr "Повернутись до списку тем" + +#: src/app/main/ui/workspace/tokens/theme_select.cljs:72 +msgid "workspace.token.edit-themes" +msgstr "Редагувати теми" diff --git a/frontend/vendor/mousetrap/index.js b/frontend/vendor/mousetrap/index.js index 07a5cb9b06..0dd2e96b31 100644 --- a/frontend/vendor/mousetrap/index.js +++ b/frontend/vendor/mousetrap/index.js @@ -986,10 +986,10 @@ Mousetrap.prototype.stopCallback = function (e, element, combo) { // stop for input, select, textarea and button const shouldStop = element.tagName == "INPUT" || - element.tagName == "SELECT" || - element.tagName == "TEXTAREA" || - (element.tagName == "BUTTON" && combo.includes("tab")) || - (element.contentEditable && element.contentEditable == "true"); + element.tagName == "SELECT" || + element.tagName == "TEXTAREA" || + (element.tagName == "BUTTON" && combo.includes("tab")) || + (element.contentEditable && (element.contentEditable == "true" || element.contentEditable === "plaintext-only")); return shouldStop; } diff --git a/render-wasm/docs/serialization.md b/render-wasm/docs/serialization.md index 741ba57885..6ef7912c05 100644 --- a/render-wasm/docs/serialization.md +++ b/render-wasm/docs/serialization.md @@ -39,3 +39,29 @@ Gradient stops are serialized in a `Uint8Array`, each stop taking **5 bytes**. **Red**, **Green**, **Blue** and **Alpha** are the RGBA components of the stop. **Stop offset** is the offset, being integer values ranging from `0` to `100` (both inclusive). + +## StrokeCap + +Stroke caps are serialized as `u8`: + +| Value | Field | +| ----- | --------- | +| 1 | Line | +| 2 | Triangle | +| 3 | Rectangle | +| 4 | Circle | +| 5 | Diamond | +| 6 | Round | +| 7 | Square | +| _ | None | + +## StrokeStyle + +Stroke styles are serialized as `u8`: + +| Value | Field | +| ----- | ------ | +| 1 | Dotted | +| 2 | Dashed | +| 3 | Mixed | +| _ | Solid | diff --git a/render-wasm/src/main.rs b/render-wasm/src/main.rs index 32f516dd93..a16fd3648e 100644 --- a/render-wasm/src/main.rs +++ b/render-wasm/src/main.rs @@ -245,7 +245,7 @@ pub extern "C" fn add_shape_fill_stops(ptr: *mut shapes::RawStopData, n_stops: u unsafe { let buffer = Vec::::from_raw_parts(ptr, len, len); shape - .add_gradient_stops(buffer) + .add_fill_gradient_stops(buffer) .expect("could not add gradient stops"); mem::free_bytes(); } @@ -346,6 +346,137 @@ pub extern "C" fn set_shape_path_content() { } } +#[no_mangle] +pub extern "C" fn add_shape_center_stroke(width: f32, style: u8, cap_start: u8, cap_end: u8) { + let state = unsafe { STATE.as_mut() }.expect("got an invalid state pointer"); + if let Some(shape) = state.current_shape() { + shape.add_stroke(shapes::Stroke::new_center_stroke( + width, style, cap_start, cap_end, + )); + } +} + +#[no_mangle] +pub extern "C" fn add_shape_inner_stroke(width: f32, style: u8, cap_start: u8, cap_end: u8) { + let state = unsafe { STATE.as_mut() }.expect("got an invalid state pointer"); + if let Some(shape) = state.current_shape() { + shape.add_stroke(shapes::Stroke::new_inner_stroke( + width, style, cap_start, cap_end, + )) + } +} + +#[no_mangle] +pub extern "C" fn add_shape_outer_stroke(width: f32, style: u8, cap_start: u8, cap_end: u8) { + let state = unsafe { STATE.as_mut() }.expect("got an invalid state pointer"); + if let Some(shape) = state.current_shape() { + shape.add_stroke(shapes::Stroke::new_outer_stroke( + width, style, cap_start, cap_end, + )) + } +} + +#[no_mangle] +pub extern "C" fn add_shape_stroke_solid_fill(raw_color: u32) { + let state = unsafe { STATE.as_mut() }.expect("got an invalid state pointer"); + if let Some(shape) = state.current_shape() { + let color = skia::Color::new(raw_color); + shape + .set_stroke_fill(shapes::Fill::Solid(color)) + .expect("could not add stroke solid fill"); + } +} + +#[no_mangle] +pub extern "C" fn add_shape_stroke_linear_fill( + start_x: f32, + start_y: f32, + end_x: f32, + end_y: f32, + opacity: f32, +) { + let state = unsafe { STATE.as_mut() }.expect("got an invalid state pointer"); + if let Some(shape) = state.current_shape() { + shape + .set_stroke_fill(shapes::Fill::new_linear_gradient( + (start_x, start_y), + (end_x, end_y), + opacity, + )) + .expect("could not add stroke linear fill"); + } +} + +#[no_mangle] +pub extern "C" fn add_shape_stroke_radial_fill( + start_x: f32, + start_y: f32, + end_x: f32, + end_y: f32, + opacity: f32, + width: f32, +) { + let state = unsafe { STATE.as_mut() }.expect("got an invalid state pointer"); + if let Some(shape) = state.current_shape() { + shape + .set_stroke_fill(shapes::Fill::new_radial_gradient( + (start_x, start_y), + (end_x, end_y), + opacity, + width, + )) + .expect("could not add stroke radial fill"); + } +} + +#[no_mangle] +pub extern "C" fn add_shape_stroke_stops(ptr: *mut shapes::RawStopData, n_stops: u32) { + let state = unsafe { STATE.as_mut() }.expect("got an invalid state pointer"); + + if let Some(shape) = state.current_shape() { + let len = n_stops as usize; + + unsafe { + let buffer = Vec::::from_raw_parts(ptr, len, len); + shape + .add_stroke_gradient_stops(buffer) + .expect("could not add gradient stops"); + mem::free_bytes(); + } + } +} + +#[no_mangle] +pub extern "C" fn add_shape_image_stroke( + a: u32, + b: u32, + c: u32, + d: u32, + alpha: f32, + width: i32, + height: i32, +) { + let state = unsafe { STATE.as_mut() }.expect("got an invalid state pointer"); + let id = uuid_from_u32_quartet(a, b, c, d); + if let Some(shape) = state.current_shape() { + shape + .set_stroke_fill(shapes::Fill::new_image_fill( + id, + (alpha * 0xff as f32).floor() as u8, + (width, height), + )) + .expect("could not add stroke image fill"); + } +} + +#[no_mangle] +pub extern "C" fn clear_shape_strokes() { + let state = unsafe { STATE.as_mut() }.expect("got an invalid state pointer"); + if let Some(shape) = state.current_shape() { + shape.clear_strokes(); + } +} + fn main() { init_gl(); } diff --git a/render-wasm/src/shapes.rs b/render-wasm/src/shapes.rs index 78ff1f4138..4943d8e64b 100644 --- a/render-wasm/src/shapes.rs +++ b/render-wasm/src/shapes.rs @@ -2,18 +2,20 @@ use crate::math; use skia_safe as skia; use uuid::Uuid; -use crate::render::BlendMode; +use crate::render::{BlendMode, Renderable}; mod fills; mod images; mod matrix; mod paths; mod renderable; +mod strokes; pub use fills::*; pub use images::*; use matrix::*; pub use paths::*; +pub use strokes::*; #[derive(Debug, Clone, PartialEq)] pub enum Kind { @@ -35,6 +37,7 @@ pub struct Shape { rotation: f32, clip_content: bool, fills: Vec, + strokes: Vec, blend_mode: BlendMode, opacity: f32, hidden: bool, @@ -51,6 +54,7 @@ impl Shape { rotation: 0., clip_content: true, fills: vec![], + strokes: vec![], blend_mode: BlendMode::default(), opacity: 1., hidden: false, @@ -114,7 +118,7 @@ impl Shape { self.fills.clear(); } - pub fn add_gradient_stops(&mut self, buffer: Vec) -> Result<(), String> { + pub fn add_fill_gradient_stops(&mut self, buffer: Vec) -> Result<(), String> { let fill = self.fills.last_mut().ok_or("Shape has no fills")?; let gradient = match fill { Fill::LinearGradient(g) => Ok(g), @@ -129,6 +133,40 @@ impl Shape { Ok(()) } + pub fn strokes(&self) -> std::slice::Iter { + self.strokes.iter() + } + + pub fn add_stroke(&mut self, s: Stroke) { + self.strokes.push(s) + } + + pub fn set_stroke_fill(&mut self, f: Fill) -> Result<(), String> { + let stroke = self.strokes.last_mut().ok_or("Shape has no strokes")?; + stroke.fill = f; + Ok(()) + } + + pub fn add_stroke_gradient_stops(&mut self, buffer: Vec) -> Result<(), String> { + let stroke = self.strokes.last_mut().ok_or("Shape has no strokes")?; + let fill = &mut stroke.fill; + let gradient = match fill { + Fill::LinearGradient(g) => Ok(g), + Fill::RadialGradient(g) => Ok(g), + _ => Err("Active stroke is not a gradient"), + }?; + + for stop in buffer.into_iter() { + gradient.add_stop(stop.color(), stop.offset()); + } + + Ok(()) + } + + pub fn clear_strokes(&mut self) { + self.strokes.clear(); + } + pub fn set_path_segments(&mut self, buffer: Vec) -> Result<(), String> { let p = Path::try_from(buffer)?; self.kind = Kind::Path(p); @@ -138,6 +176,21 @@ impl Shape { pub fn set_blend_mode(&mut self, mode: BlendMode) { self.blend_mode = mode; } + + fn to_path_transform(&self) -> Option { + match self.kind { + Kind::Path(_) => { + let center = self.bounds().center(); + let mut matrix = skia::Matrix::new_identity(); + matrix.pre_translate(center); + matrix.pre_concat(&self.transform.no_translation().to_skia_matrix().invert()?); + matrix.pre_translate(-center); + + Some(matrix) + } + _ => None, + } + } } #[cfg(test)] diff --git a/render-wasm/src/shapes/images.rs b/render-wasm/src/shapes/images.rs index 50980027a1..bbf5d600c3 100644 --- a/render-wasm/src/shapes/images.rs +++ b/render-wasm/src/shapes/images.rs @@ -1,71 +1,3 @@ -use crate::math; -use crate::shapes::Kind; use skia_safe as skia; pub type Image = skia::Image; - -pub fn draw_image_in_container( - canvas: &skia::Canvas, - image: &Image, - size: (i32, i32), - kind: &Kind, - paint: &skia::Paint, -) { - let width = size.0 as f32; - let height = size.1 as f32; - let image_aspect_ratio = width / height; - - let container = match kind { - Kind::Rect(r) => r.to_owned(), - Kind::Circle(r) => r.to_owned(), - Kind::Path(p) => p.to_skia_path().bounds().to_owned(), - }; - - // Container size - let container_width = container.width(); - let container_height = container.height(); - let container_aspect_ratio = container_width / container_height; - - // Calculate scale to ensure the image covers the container - let scale = if image_aspect_ratio > container_aspect_ratio { - // Image is widther, scale based on height to cover container - container_height / height - } else { - // Image is taller, scale based on width to cover container - container_width / width - }; - - // Scaled size of the image - let scaled_width = width * scale; - let scaled_height = height * scale; - - // Calculate offset to center the image in the container - let offset_x = container.left + (container_width - scaled_width) / 2.0; - let offset_y = container.top + (container_height - scaled_height) / 2.0; - - let dest_rect = math::Rect::from_xywh(offset_x, offset_y, scaled_width, scaled_height); - - // Save the current canvas state - canvas.save(); - - // Set the clipping rectangle to the container bounds - match kind { - Kind::Rect(_) => { - canvas.clip_rect(container, skia::ClipOp::Intersect, true); - } - Kind::Circle(_) => { - let mut oval_path = skia::Path::new(); - oval_path.add_oval(container, None); - canvas.clip_path(&oval_path, skia::ClipOp::Intersect, true); - } - Kind::Path(p) => { - canvas.clip_path(&p.to_skia_path(), skia::ClipOp::Intersect, true); - } - } - - // Draw the image with the calculated destination rectangle - canvas.draw_image_rect(image, None, dest_rect, &paint); - - // Restore the canvas to remove the clipping - canvas.restore(); -} diff --git a/render-wasm/src/shapes/matrix.rs b/render-wasm/src/shapes/matrix.rs index bd353b910d..294b9da066 100644 --- a/render-wasm/src/shapes/matrix.rs +++ b/render-wasm/src/shapes/matrix.rs @@ -1,6 +1,6 @@ use skia_safe as skia; -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone, Copy, PartialEq)] pub struct Matrix { pub a: f32, pub b: f32, @@ -47,6 +47,15 @@ impl Matrix { res } + pub fn no_translation(&self) -> Self { + let mut res = Self::identity(); + res.c = self.c; + res.b = self.b; + res.a = self.a; + res.d = self.d; + res + } + fn translation(&self) -> (f32, f32) { (self.e, self.f) } diff --git a/render-wasm/src/shapes/paths.rs b/render-wasm/src/shapes/paths.rs index ae2367fb7f..1e77b9ccc2 100644 --- a/render-wasm/src/shapes/paths.rs +++ b/render-wasm/src/shapes/paths.rs @@ -73,12 +73,26 @@ impl TryFrom for Segment { pub struct Path { segments: Vec, skia_path: skia::Path, + open: bool, +} + +fn starts_and_ends_at_same_point(path: &skia::Path) -> bool { + if path.count_points() < 2 { + return false; // A path with fewer than 2 points cannot be closed + } + + let start_point = path.get_point(0); // First point of the path + let end_point = path.get_point(path.count_points() - 1); // Last point of the path + + // Compare the start and end points + start_point == end_point } impl TryFrom> for Path { type Error = String; fn try_from(value: Vec) -> Result { + let mut open = true; let segments = value .into_iter() .map(|raw| Segment::try_from(raw)) @@ -98,13 +112,20 @@ impl TryFrom> for Path { } Segment::Close => { skia_path.close(); + open = false; } } } + if !skia_path.is_last_contour_closed() && starts_and_ends_at_same_point(&skia_path) { + skia_path.close(); + open = false; + } + Ok(Path { segments, skia_path, + open, }) } } @@ -113,4 +134,8 @@ impl Path { pub fn to_skia_path(&self) -> skia::Path { self.skia_path.snapshot() } + + pub fn is_open(&self) -> bool { + self.open + } } diff --git a/render-wasm/src/shapes/renderable.rs b/render-wasm/src/shapes/renderable.rs index ef124c272c..5bbecab4f6 100644 --- a/render-wasm/src/shapes/renderable.rs +++ b/render-wasm/src/shapes/renderable.rs @@ -1,7 +1,7 @@ use skia_safe as skia; use uuid::Uuid; -use super::{draw_image_in_container, Fill, Kind, Shape}; +use super::{Fill, Image, Kind, Path, Shape, Stroke, StrokeCap, StrokeKind}; use crate::math::Rect; use crate::render::{ImageStore, Renderable}; @@ -10,7 +10,7 @@ impl Renderable for Shape { let transform = self.transform.to_skia_matrix(); // Check transform-matrix code from common/src/app/common/geom/shapes/transforms.cljc - let center = self.selrect.center(); + let center = self.bounds().center(); let mut matrix = skia::Matrix::new_identity(); matrix.pre_translate(center); matrix.pre_concat(&transform); @@ -19,12 +19,26 @@ impl Renderable for Shape { surface.canvas().concat(&matrix); for fill in self.fills().rev() { - render_fill(surface, images, fill, self.selrect, &self.kind); + render_fill( + surface, + images, + fill, + self.selrect, + &self.kind, + self.to_path_transform().as_ref(), + ); } - let mut paint = skia::Paint::default(); - paint.set_blend_mode(self.blend_mode.into()); - paint.set_alpha_f(self.opacity); + for stroke in self.strokes().rev() { + render_stroke( + surface, + images, + stroke, + self.selrect, + &self.kind, + self.to_path_transform().as_ref(), + ); + } Ok(()) } @@ -60,17 +74,20 @@ fn render_fill( fill: &Fill, selrect: Rect, kind: &Kind, + path_transform: Option<&skia::Matrix>, ) { match (fill, kind) { (Fill::Image(image_fill), kind) => { let image = images.get(&image_fill.id()); if let Some(image) = image { - draw_image_in_container( + draw_image_fill_in_container( surface.canvas(), &image, image_fill.size(), kind, &fill.to_paint(&selrect), + &selrect, + path_transform, ); } } @@ -81,9 +98,429 @@ fn render_fill( surface.canvas().draw_oval(rect, &fill.to_paint(&selrect)); } (_, Kind::Path(path)) => { - surface - .canvas() - .draw_path(&path.to_skia_path(), &fill.to_paint(&selrect)); + surface.canvas().draw_path( + &path.to_skia_path().transform(path_transform.unwrap()), + &fill.to_paint(&selrect), + ); } } } + +fn render_stroke( + surface: &mut skia::Surface, + images: &ImageStore, + stroke: &Stroke, + selrect: Rect, + kind: &Kind, + path_transform: Option<&skia::Matrix>, +) { + if let Fill::Image(image_fill) = &stroke.fill { + if let Some(image) = images.get(&image_fill.id()) { + draw_image_stroke_in_container( + surface.canvas(), + &image, + stroke, + image_fill.size(), + kind, + &selrect, + path_transform, + ); + } + } else { + match kind { + Kind::Rect(rect) => draw_stroke_on_rect(surface.canvas(), stroke, rect, &selrect), + Kind::Circle(rect) => draw_stroke_on_circle(surface.canvas(), stroke, rect, &selrect), + Kind::Path(path) => { + draw_stroke_on_path(surface.canvas(), stroke, path, &selrect, path_transform); + } + } + } +} + +fn draw_stroke_on_rect(canvas: &skia::Canvas, stroke: &Stroke, rect: &Rect, selrect: &Rect) { + // Draw the different kind of strokes for a rect is perry straightforward, we just need apply a stroke to: + // - The same rect if it's a center stroke + // - A bigger rect if it's an outer stroke + // - A smaller rect if it's an outer stroke + let stroke_rect = stroke.outer_rect(rect); + canvas.draw_rect(&stroke_rect, &stroke.to_paint(selrect)); +} + +fn draw_stroke_on_circle(canvas: &skia::Canvas, stroke: &Stroke, rect: &Rect, selrect: &Rect) { + // Draw the different kind of strokes for an oval is perry straightforward, we just need apply a stroke to: + // - The same oval if it's a center stroke + // - A bigger oval if it's an outer stroke + // - A smaller oval if it's an outer stroke + let stroke_rect = stroke.outer_rect(rect); + canvas.draw_oval(&stroke_rect, &stroke.to_paint(selrect)); +} + +fn handle_stroke_cap( + canvas: &skia::Canvas, + cap: StrokeCap, + width: f32, + paint: &mut skia::Paint, + p1: &skia::Point, + p2: &skia::Point, +) { + paint.set_style(skia::PaintStyle::Fill); + paint.set_blend_mode(skia::BlendMode::Src); + match cap { + StrokeCap::None => {} + StrokeCap::Line => { + paint.set_style(skia::PaintStyle::Stroke); + draw_arrow_cap(canvas, &paint, p1, p2, width * 4.); + } + StrokeCap::Triangle => { + draw_triangle_cap(canvas, &paint, p1, p2, width * 4.); + } + StrokeCap::Rectangle => { + draw_square_cap(canvas, &paint, p1, p2, width * 4., 0.); + } + StrokeCap::Circle => { + canvas.draw_circle((p1.x, p1.y), width * 2., &paint); + } + StrokeCap::Diamond => { + draw_square_cap(canvas, &paint, p1, p2, width * 4., 45.); + } + StrokeCap::Round => { + canvas.draw_circle((p1.x, p1.y), width / 2.0, &paint); + } + StrokeCap::Square => { + draw_square_cap(canvas, &paint, p1, p2, width, 0.); + } + } +} + +fn handle_stroke_caps( + path: &mut skia::Path, + stroke: &Stroke, + selrect: &Rect, + canvas: &skia::Canvas, + is_open: bool, +) { + let points_count = path.count_points(); + let mut points = vec![skia::Point::default(); points_count]; + let c_points = path.get_points(&mut points); + + // Closed shapes don't have caps + if c_points >= 2 && is_open { + let first_point = points.first().unwrap(); + let last_point = points.last().unwrap(); + + let kind = stroke.render_kind(is_open); + let mut paint_stroke = stroke.to_stroked_paint(kind.clone(), selrect); + + handle_stroke_cap( + canvas, + stroke.cap_start, + stroke.width, + &mut paint_stroke, + first_point, + &points[1], + ); + handle_stroke_cap( + canvas, + stroke.cap_end, + stroke.width, + &mut paint_stroke, + last_point, + &points[points_count - 2], + ); + } +} + +fn draw_square_cap( + canvas: &skia::Canvas, + paint: &skia::Paint, + center: &skia::Point, + direction: &skia::Point, + size: f32, + extra_rotation: f32, +) { + let dx = direction.x - center.x; + let dy = direction.y - center.y; + let angle = dy.atan2(dx); + + let mut matrix = skia::Matrix::new_identity(); + matrix.pre_rotate( + angle.to_degrees() + extra_rotation, + skia::Point::new(center.x, center.y), + ); + + let half_size = size / 2.0; + let rect = skia::Rect::from_xywh(center.x - half_size, center.y - half_size, size, size); + + let points = [ + skia::Point::new(rect.left(), rect.top()), + skia::Point::new(rect.right(), rect.top()), + skia::Point::new(rect.right(), rect.bottom()), + skia::Point::new(rect.left(), rect.bottom()), + ]; + + let mut transformed_points = points.clone(); + matrix.map_points(&mut transformed_points, &points); + + let mut path = skia::Path::new(); + path.move_to(skia::Point::new(center.x, center.y)); + path.move_to(transformed_points[0]); + path.line_to(transformed_points[1]); + path.line_to(transformed_points[2]); + path.line_to(transformed_points[3]); + path.close(); + canvas.draw_path(&path, paint); +} + +fn draw_arrow_cap( + canvas: &skia::Canvas, + paint: &skia::Paint, + center: &skia::Point, + direction: &skia::Point, + size: f32, +) { + let dx = direction.x - center.x; + let dy = direction.y - center.y; + let angle = dy.atan2(dx); + + let mut matrix = skia::Matrix::new_identity(); + matrix.pre_rotate( + angle.to_degrees() - 90., + skia::Point::new(center.x, center.y), + ); + + let half_height = size / 2.; + let points = [ + skia::Point::new(center.x, center.y - half_height), + skia::Point::new(center.x - size, center.y + half_height), + skia::Point::new(center.x + size, center.y + half_height), + ]; + + let mut transformed_points = points.clone(); + matrix.map_points(&mut transformed_points, &points); + + let mut path = skia::Path::new(); + path.move_to(transformed_points[1]); + path.line_to(transformed_points[0]); + path.line_to(transformed_points[2]); + path.move_to(skia::Point::new(center.x, center.y)); + path.line_to(transformed_points[0]); + + canvas.draw_path(&path, paint); +} + +fn draw_triangle_cap( + canvas: &skia::Canvas, + paint: &skia::Paint, + center: &skia::Point, + direction: &skia::Point, + size: f32, +) { + let dx = direction.x - center.x; + let dy = direction.y - center.y; + let angle = dy.atan2(dx); + + let mut matrix = skia::Matrix::new_identity(); + matrix.pre_rotate( + angle.to_degrees() - 90., + skia::Point::new(center.x, center.y), + ); + + let half_height = size / 2.; + let points = [ + skia::Point::new(center.x, center.y - half_height), + skia::Point::new(center.x - size, center.y + half_height), + skia::Point::new(center.x + size, center.y + half_height), + ]; + + let mut transformed_points = points.clone(); + matrix.map_points(&mut transformed_points, &points); + + let mut path = skia::Path::new(); + path.move_to(transformed_points[0]); + path.line_to(transformed_points[1]); + path.line_to(transformed_points[2]); + path.close(); + + canvas.draw_path(&path, paint); +} + +fn draw_stroke_on_path( + canvas: &skia::Canvas, + stroke: &Stroke, + path: &Path, + selrect: &Rect, + path_transform: Option<&skia::Matrix>, +) { + let mut skia_path = path.to_skia_path(); + skia_path.transform(path_transform.unwrap()); + + let kind = stroke.render_kind(path.is_open()); + let paint_stroke = stroke.to_stroked_paint(kind.clone(), selrect); + // Draw the different kind of strokes for a path requires different strategies: + match kind { + // For inner stroke we draw a center stroke (with double width) and clip to the original path (that way the extra outer stroke is removed) + StrokeKind::InnerStroke => { + canvas.clip_path(&skia_path, skia::ClipOp::Intersect, true); + canvas.draw_path(&skia_path, &paint_stroke); + } + // For center stroke we don't need to do anything extra + StrokeKind::CenterStroke => { + canvas.draw_path(&skia_path, &paint_stroke); + handle_stroke_caps(&mut skia_path, stroke, selrect, canvas, path.is_open()); + } + // For outer stroke we draw a center stroke (with double width) and use another path with blend mode clear to remove the inner stroke added + StrokeKind::OuterStroke => { + let mut paint = skia::Paint::default(); + paint.set_blend_mode(skia::BlendMode::SrcOver); + paint.set_anti_alias(true); + let layer_rec = skia::canvas::SaveLayerRec::default().paint(&paint); + canvas.save_layer(&layer_rec); + + canvas.draw_path(&skia_path, &paint_stroke); + + let mut clear_paint = skia::Paint::default(); + clear_paint.set_blend_mode(skia::BlendMode::Clear); + clear_paint.set_anti_alias(true); + canvas.draw_path(&skia_path, &clear_paint); + + canvas.restore(); + } + } +} + +fn calculate_scaled_rect(size: (i32, i32), container: &Rect, delta: f32) -> Rect { + let (width, height) = (size.0 as f32, size.1 as f32); + let image_aspect_ratio = width / height; + + // Container size + let container_width = container.width(); + let container_height = container.height(); + let container_aspect_ratio = container_width / container_height; + + let scale = if image_aspect_ratio > container_aspect_ratio { + container_height / height + } else { + container_width / width + }; + + let scaled_width = width * scale; + let scaled_height = height * scale; + + Rect::from_xywh( + container.left - delta - (scaled_width - container_width) / 2.0, + container.top - delta - (scaled_height - container_height) / 2.0, + scaled_width + (2. * delta) + (scaled_width - container_width), + scaled_height + (2. * delta) + (scaled_width - container_width), + ) +} + +pub fn draw_image_fill_in_container( + canvas: &skia::Canvas, + image: &Image, + size: (i32, i32), + kind: &Kind, + paint: &skia::Paint, + container: &Rect, + path_transform: Option<&skia::Matrix>, +) { + // Compute scaled rect + let dest_rect = calculate_scaled_rect(size, container, 0.); + + // Save the current canvas state + canvas.save(); + + // Set the clipping rectangle to the container bounds + match kind { + Kind::Rect(_) => { + canvas.clip_rect(container, skia::ClipOp::Intersect, true); + } + Kind::Circle(_) => { + let mut oval_path = skia::Path::new(); + oval_path.add_oval(container, None); + canvas.clip_path(&oval_path, skia::ClipOp::Intersect, true); + } + Kind::Path(p) => { + canvas.clip_path( + &p.to_skia_path().transform(path_transform.unwrap()), + skia::ClipOp::Intersect, + true, + ); + } + } + + // Draw the image with the calculated destination rectangle + canvas.draw_image_rect(image, None, dest_rect, &paint); + + // Restore the canvas to remove the clipping + canvas.restore(); +} + +pub fn draw_image_stroke_in_container( + canvas: &skia::Canvas, + image: &Image, + stroke: &Stroke, + size: (i32, i32), + kind: &Kind, + container: &Rect, + path_transform: Option<&skia::Matrix>, +) { + // Helper to handle drawing based on kind + fn draw_kind( + canvas: &skia::Canvas, + kind: &Kind, + stroke: &Stroke, + container: &Rect, + path_transform: Option<&skia::Matrix>, + ) { + let outer_rect = stroke.outer_rect(container); + match kind { + Kind::Rect(rect) => draw_stroke_on_rect(canvas, stroke, rect, &outer_rect), + Kind::Circle(rect) => draw_stroke_on_circle(canvas, stroke, rect, &outer_rect), + Kind::Path(p) => { + let mut path = p.to_skia_path(); + path.transform(path_transform.unwrap()); + let stroke_kind = stroke.render_kind(p.is_open()); + if stroke_kind == StrokeKind::InnerStroke { + canvas.clip_path(&path, skia::ClipOp::Intersect, true); + } + let paint = stroke.to_stroked_paint(stroke_kind, &outer_rect); + canvas.draw_path(&path, &paint); + handle_stroke_caps(&mut path, stroke, &outer_rect, canvas, p.is_open()); + } + } + } + + // Save canvas and layer state + let mut pb = skia::Paint::default(); + pb.set_blend_mode(skia::BlendMode::SrcOver); + pb.set_anti_alias(true); + let layer_rec = skia::canvas::SaveLayerRec::default().paint(&pb); + canvas.save_layer(&layer_rec); + + // Draw the stroke based on the kind, we are using this stroke as a "selector" of the area of the image we want to show. + draw_kind(canvas, kind, stroke, container, path_transform); + + // Draw the image. We are using now the SrcIn blend mode, so the rendered piece of image will the area of the stroke over the image. + let mut image_paint = skia::Paint::default(); + image_paint.set_blend_mode(skia::BlendMode::SrcIn); + image_paint.set_anti_alias(true); + // Compute scaled rect and clip to it + let dest_rect = calculate_scaled_rect(size, container, stroke.delta()); + canvas.clip_rect(dest_rect, skia::ClipOp::Intersect, true); + canvas.draw_image_rect(image, None, dest_rect, &image_paint); + + // Clear outer stroke for paths if necessary. When adding an outer stroke we need to empty the stroke added too in the inner area. + if let Kind::Path(p) = kind { + if stroke.render_kind(p.is_open()) == StrokeKind::OuterStroke { + let mut path = p.to_skia_path(); + path.transform(path_transform.unwrap()); + let mut clear_paint = skia::Paint::default(); + clear_paint.set_blend_mode(skia::BlendMode::Clear); + clear_paint.set_anti_alias(true); + canvas.draw_path(&path, &clear_paint); + } + } + + // Restore canvas state + canvas.restore(); +} diff --git a/render-wasm/src/shapes/strokes.rs b/render-wasm/src/shapes/strokes.rs new file mode 100644 index 0000000000..d5ec04ab82 --- /dev/null +++ b/render-wasm/src/shapes/strokes.rs @@ -0,0 +1,201 @@ +use crate::math; +use crate::shapes::fills::Fill; +use skia_safe as skia; + +#[derive(Debug, Clone, PartialEq)] +pub enum StrokeStyle { + Solid, + Dotted, + Dashed, + Mixed, +} + +impl From for StrokeStyle { + fn from(value: u8) -> Self { + match value { + 1 => StrokeStyle::Dotted, + 2 => StrokeStyle::Dashed, + 3 => StrokeStyle::Mixed, + _ => StrokeStyle::Solid, + } + } +} + +#[derive(Debug, Clone, Copy, PartialEq)] +pub enum StrokeCap { + None, + Line, + Triangle, + Rectangle, + Circle, + Diamond, + Round, + Square, +} + +impl From for StrokeCap { + fn from(value: u8) -> Self { + match value { + 1 => StrokeCap::Line, + 2 => StrokeCap::Triangle, + 3 => StrokeCap::Rectangle, + 4 => StrokeCap::Circle, + 5 => StrokeCap::Diamond, + 6 => StrokeCap::Round, + 7 => StrokeCap::Square, + _ => StrokeCap::None, + } + } +} + +#[derive(Debug, Clone, Copy, PartialEq)] +pub enum StrokeKind { + InnerStroke, + OuterStroke, + CenterStroke, +} + +#[derive(Debug, Clone, PartialEq)] +pub struct Stroke { + pub fill: Fill, + pub width: f32, + pub style: StrokeStyle, + pub cap_end: StrokeCap, + pub cap_start: StrokeCap, + kind: StrokeKind, +} + +impl Stroke { + // Strokes for open shapes should be rendered as if they were centered. + pub fn render_kind(&self, is_open: bool) -> StrokeKind { + if is_open { + StrokeKind::CenterStroke + } else { + self.kind + } + } + + pub fn new_center_stroke(width: f32, style: u8, cap_start: u8, cap_end: u8) -> Self { + let transparent = skia::Color::from_argb(0, 0, 0, 0); + Stroke { + fill: Fill::Solid(transparent), + width: width, + style: StrokeStyle::from(style), + cap_end: StrokeCap::from(cap_end), + cap_start: StrokeCap::from(cap_start), + kind: StrokeKind::CenterStroke, + } + } + + pub fn new_inner_stroke(width: f32, style: u8, cap_start: u8, cap_end: u8) -> Self { + let transparent = skia::Color::from_argb(0, 0, 0, 0); + Stroke { + fill: Fill::Solid(transparent), + width: width, + style: StrokeStyle::from(style), + cap_end: StrokeCap::from(cap_end), + cap_start: StrokeCap::from(cap_start), + kind: StrokeKind::InnerStroke, + } + } + + pub fn new_outer_stroke(width: f32, style: u8, cap_start: u8, cap_end: u8) -> Self { + let transparent = skia::Color::from_argb(0, 0, 0, 0); + Stroke { + fill: Fill::Solid(transparent), + width: width, + style: StrokeStyle::from(style), + cap_end: StrokeCap::from(cap_end), + cap_start: StrokeCap::from(cap_start), + kind: StrokeKind::OuterStroke, + } + } + + pub fn delta(&self) -> f32 { + match self.kind { + StrokeKind::InnerStroke => 0., + StrokeKind::CenterStroke => self.width / 2., + StrokeKind::OuterStroke => self.width, + } + } + + pub fn outer_rect(&self, rect: &math::Rect) -> math::Rect { + match self.kind { + StrokeKind::InnerStroke => math::Rect::from_xywh( + rect.left + (self.width / 2.), + rect.top + (self.width / 2.), + rect.width() - self.width, + rect.height() - self.width, + ), + StrokeKind::CenterStroke => { + math::Rect::from_xywh(rect.left, rect.top, rect.width(), rect.height()) + } + StrokeKind::OuterStroke => math::Rect::from_xywh( + rect.left - (self.width / 2.), + rect.top - (self.width / 2.), + rect.width() + self.width, + rect.height() + self.width, + ), + } + } + + pub fn to_paint(&self, rect: &math::Rect) -> skia::Paint { + let mut paint = self.fill.to_paint(rect); + paint.set_style(skia::PaintStyle::Stroke); + paint.set_stroke_width(self.width); + paint.set_anti_alias(true); + + if self.style != StrokeStyle::Solid { + let path_effect = match self.style { + StrokeStyle::Dotted => { + let mut circle_path = skia::Path::new(); + let width = match self.kind { + StrokeKind::InnerStroke => self.width, + StrokeKind::CenterStroke => self.width / 2.0, + StrokeKind::OuterStroke => self.width, + }; + circle_path.add_circle((0.0, 0.0), width, None); + let advance = self.width + 5.0; + skia::PathEffect::path_1d( + &circle_path, + advance, + 0.0, + skia::path_1d_path_effect::Style::Translate, + ) + } + StrokeStyle::Dashed => { + skia::PathEffect::dash(&[self.width + 10., self.width + 10.], 0.) + } + StrokeStyle::Mixed => skia::PathEffect::dash( + &[ + self.width + 5., + self.width + 5., + self.width + 1., + self.width + 5., + ], + 0., + ), + _ => None, + }; + paint.set_path_effect(path_effect); + } + + paint + } + + pub fn to_stroked_paint(&self, kind: StrokeKind, rect: &math::Rect) -> skia::Paint { + let mut paint = self.to_paint(rect); + match kind { + StrokeKind::InnerStroke => { + paint.set_stroke_width(2. * self.width); + paint + } + + StrokeKind::CenterStroke => paint, + StrokeKind::OuterStroke => { + paint.set_stroke_width(2. * self.width); + paint + } + } + } +}