Compare commits

..
Author SHA1 Message Date
Ryan Di 0bf1b4c4af (un)lock a frame should not affect elements unrelated to the frame 2023-11-22 18:35:05 +08:00
Ryan Di d9d1a3ab99 improve cursor style when frame's locked 2023-11-22 18:28:57 +08:00
Ryan Di c43d9d44f0 update test snapshot 2023-11-22 18:20:31 +08:00
Ryan Di c9af72e2ee fix: lock/unlock elements in frames 2023-11-08 15:48:36 +08:00
Dante CalderonandGitHub 18a7b97515 chore: Fix typo in comment in LocalData file (#7235) 2023-11-04 18:15:09 +01:00
e8def8da8d feat: Support mermaid flowchart and sequence diagrams to excalidraw diagrams 🥳 (#6920)
* feat: integrate mermaidToExcalidraw

* create mermaid to excal dialog

* allow mermaid syntax and export in preview

* fix

* fix webpack config

* fix markdown error by using named export

* center preview

* set elements as selected when inserted onto canvas

* persist mermaid data to storage

* store canvas data in refs

* load mermaid lazily

* tweak design

* compute width, height correctly for arrows

* fix undefined vertex issue

* add mermaid icon in dropdown

* add a note in dialog

* reset preview when error

* show error in preview when error

* show mermaid error messgae react way

* design tweaks

* add example and docs link

* fix

* tweak design to remove scroll bar

* show a spinner unless mermaid loaded

* regenerate ids when needed via programmatic api, this makes sure for mermaid diagrams ids are regenerated

* tweak

* add option to transform viewport to scene coords in transform api

* make opts optional and use 100% zoom when inserting to canvas

* fix arrow bindings in safari and firefox

* fix elements insert position and viewport centering

* fix: Update start/end points by 0.5 so bindings don't overlap with start/end bound element coordinates.

* defer rendering the preview

* tweak text

* fix tests

* remove only

* make design responsive

* fix: show extra tools dropdown in mobile

* fix mobile css

* width auto

* upgrade mermaid-to-excalidraw

* don't pass appState in deps as its not used

* upgrade mermaid-to-excalidraw to fix firefox issue

* use types from mermaid-to-excalidraw

* upgrade mermaid-to-excalidraw

* use stable version of mermaid-to-excalidraw

* upgrade mermaid-to-excalidraw

* fix width of shapes toolbar for smaller screen size and also fix regression of mobile menu

* use i18n

* better api

* enable test coverage in ui

* Add tests

* use common utils to update and get text editor

* updgrade mermaid-to-excalidraw to support sequence diagrams

* fix test

* don't update arrow container height anytime in when redrawing text bounding box

* increase size limit

* increase size limit of vendor to 900kb

* use openDialog for mermaid

* upgrade mermaid-to-excalidraw

* update frame id post generation

* upgrade mermaid-to-excalidraw to add entity codes support

* update size limit

* upgrade mermaid-to-excalidraw package with frame api changes

* upgrade mermaid-to-excalidraw to remove directive and use config

* don't highlight mermaid tool and remove unused api setSelection

* stop using loading state to update text area

* move some styling to scss

* review fixes

* use modifiedTableIcon props and remove stale snap

* css

* dialog css

* fix snap

* use dialog border

* change mermaidToExcalidrawLib to state

* better styling of errors

* make modal bigger

* fix mobile

* update snaps

* fix icon color

* fix dark mode insert button color

* horizontally center spinner

* render canvas conditionally on loaded state

* rd tweaks

* tweak class names

* remove max height

* typo in example

* upgrade mermaid-to-excalidraw

* simplify error state

* fix height & overflow on vertical breakpoint

* fix lint

* show errors in overlay

* set textarea font family

* reduce opacity

* update snap

* upgrade to mermaid  0.1.2

---------

Co-authored-by: dwelle <luzar.david@gmail.com>
2023-11-03 17:41:34 +05:30
David LuzarandGitHub a7db41c5ba fix: align input :hover/:focus with spec (#7225) 2023-11-02 16:06:26 +01:00
David LuzarandGitHub d8166d9e1d fix: dialog remounting on className updates (#7224) 2023-11-02 16:06:15 +01:00
Farzaneh SefidabiandGitHub 81c0259041 docs: add npm downloads rate badge to README.md file (#7127) 2023-11-01 13:27:57 +01:00
Aakansha DoshiandGitHub f5c91c3a0f feat: support frames via programmatic API (#7205)
* update frame id post generation

* support frames via programmatic API

* fix types

* add test for frames

* throw error when element doesn't exist

* naming tweaks

* update the api to use children

* consider max of frame dimensions and calculated bounds of elements

* consider bound elements in frame api
2023-11-01 17:14:04 +05:30
David LuzarandGitHub 9b8de8a12e test: disable flaky test (#7213) 2023-10-31 12:05:08 +01:00
David LuzarandGitHub ea677d4581 feat: make clipboard more robust and reintroduce contextmenu actions (#7198) 2023-10-28 19:29:28 +00:00
Aakansha DoshiandGitHub ec2de7205f fix: don't update label position when dragging labelled arrows (#6891)
* fix: don't update label position when dragging labelled arrows

* lint

* add test

* don't update coords for label when labelled arrow inside frame

* increase locales bundle size limit
2023-10-27 12:06:11 +05:30
d5e3f436dc feat: add approximate elements in bbox detection (#6727)
Co-authored-by: dwelle <luzar.david@gmail.com>
2023-10-26 23:33:00 +02:00
Aakansha DoshiandGitHub dcf4592e79 feat: regenerate ids by default when using transform api and also update bindings by 0.5px to avoid possible overlapping (#7195)
* feat: regenerate ids by default when using transform api and also update bindings by 0.5px to avoid possible overlapping

* type

* increase limit as some past PR(s) increased the bundle size

* review fixes

* update changelog
2023-10-27 00:43:48 +05:30
David LuzarandGitHub d1f8eec174 feat: support giphy.com embed domain (#7192) 2023-10-26 00:00:50 +02:00
David LuzarandGitHub 0f81c30276 fix: frame add/remove/z-index ordering changes (#7194) 2023-10-25 23:16:02 +02:00
f098789d16 fix: element relative position when dragging multiple elements on grid (#7107)
Co-authored-by: dwelle <luzar.david@gmail.com>
2023-10-25 22:48:03 +02:00
David LuzarandGitHub f794b0bb90 fix: freedraw non-solid bg hitbox not working (#7193) 2023-10-25 17:21:01 +02:00
David LuzarandGitHub 104f64f1dc revert: remove bound-arrows from frames (#7190) 2023-10-25 10:39:19 +02:00
71ad3c5356 fix: Actions panel ux improvement (#6850)
Co-authored-by: dwelle <luzar.david@gmail.com>
2023-10-24 18:36:13 +00:00
David LuzarandGitHub afea0df141 feat: renderer tweaks (#6698) 2023-10-20 17:45:37 +02:00
d2a508104e fix: Better fill rendering with latest RoughJS (#7031)
Co-authored-by: dwelle <luzar.david@gmail.com>
2023-10-20 15:08:24 +02:00
3697618266 feat: support props.locked for setActiveTool (#7153)
Co-authored-by: Aakansha Doshi <aakansha1216@gmail.com>
2023-10-20 13:16:23 +02:00
David LuzarandGitHub e7cc2337ea feat: add onChange, onPointerDown, onPointerUp api subs (#7154) 2023-10-20 13:08:22 +02:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
9eb89f9960 build(deps): bump @babel/traverse from 7.18.9 to 7.23.2 in /dev-docs (#7165)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-20 11:31:27 +02:00
Excalidraw BotandGitHub ab1bcc7615 chore: Update translations from Crowdin (#6695) 2023-10-20 11:29:28 +02:00
b1cac35269 feat: Closing of "Save to.." Dialog on Save To Disk (#7168)
Co-authored-by: dwelle <luzar.david@gmail.com>
2023-10-19 17:51:50 +00:00
83f86e2b86 fix: Fix for Strange Symbol Appearing on Canvas after Deleting Grouped Graphics (Issue #7116) (#7170)
Co-authored-by: dwelle <luzar.david@gmail.com>
2023-10-19 12:59:39 +02:00
dependabot[bot]GitHubdependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
7e38cab76e build(deps): bump @babel/traverse from 7.21.4 to 7.23.2 (#7171)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-19 12:33:16 +02:00
David LuzarandGitHub 2cabb1f1f4 fix: attempt to fix flake in wysiwyg tests (#7173) 2023-10-19 12:32:31 +02:00
63650f82d1 feat: Added Copy/Paste from Google Docs (#7136)
Co-authored-by: dwelle <luzar.david@gmail.com>
2023-10-19 12:14:23 +02:00
David LuzarandGitHub dde3dac931 feat: remove bound-arrows from frames (#7157) 2023-10-17 18:18:20 +02:00
David LuzarandGitHub 5b94cffc74 fix: ensure ClipboardItem created in the same tick to fix safari (#7066) 2023-10-16 11:38:57 +02:00
David LuzarandGitHub aaf73c8ff3 fix: double image dialog shown on insert (#7152) 2023-10-16 00:19:46 +02:00
158 changed files with 9767 additions and 3669 deletions
-3
View File
@@ -1,3 +0,0 @@
## 2020-10-13
- Added ability to embed scene source into exported PNG/SVG files so you can import the scene from them (open via `Load` button or drag & drop). #2219
+3
View File
@@ -25,6 +25,9 @@
<a href="https://github.com/excalidraw/excalidraw/blob/master/LICENSE"> <a href="https://github.com/excalidraw/excalidraw/blob/master/LICENSE">
<img alt="Excalidraw is released under the MIT license." src="https://img.shields.io/badge/license-MIT-blue.svg" /> <img alt="Excalidraw is released under the MIT license." src="https://img.shields.io/badge/license-MIT-blue.svg" />
</a> </a>
<a href="https://www.npmjs.com/package/@excalidraw/excalidraw">
<img alt="npm downloads/month" src="https://img.shields.io/npm/dm/@excalidraw/excalidraw" />
</a>
<a href="https://docs.excalidraw.com/docs/introduction/contributing"> <a href="https://docs.excalidraw.com/docs/introduction/contributing">
<img alt="PRs welcome!" src="https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat" /> <img alt="PRs welcome!" src="https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat" />
</a> </a>
+117 -12
View File
@@ -145,6 +145,14 @@
dependencies: dependencies:
"@babel/highlight" "^7.18.6" "@babel/highlight" "^7.18.6"
"@babel/code-frame@^7.22.13":
version "7.22.13"
resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.22.13.tgz#e3c1c099402598483b7a8c46a721d1038803755e"
integrity sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==
dependencies:
"@babel/highlight" "^7.22.13"
chalk "^2.4.2"
"@babel/compat-data@^7.17.7", "@babel/compat-data@^7.18.8": "@babel/compat-data@^7.17.7", "@babel/compat-data@^7.18.8":
version "7.18.8" version "7.18.8"
resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.18.8.tgz#2483f565faca607b8535590e84e7de323f27764d" resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.18.8.tgz#2483f565faca607b8535590e84e7de323f27764d"
@@ -202,6 +210,16 @@
"@jridgewell/gen-mapping" "^0.3.2" "@jridgewell/gen-mapping" "^0.3.2"
jsesc "^2.5.1" jsesc "^2.5.1"
"@babel/generator@^7.23.0":
version "7.23.0"
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.23.0.tgz#df5c386e2218be505b34837acbcb874d7a983420"
integrity sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==
dependencies:
"@babel/types" "^7.23.0"
"@jridgewell/gen-mapping" "^0.3.2"
"@jridgewell/trace-mapping" "^0.3.17"
jsesc "^2.5.1"
"@babel/helper-annotate-as-pure@^7.18.6": "@babel/helper-annotate-as-pure@^7.18.6":
version "7.18.6" version "7.18.6"
resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz#eaa49f6f80d5a33f9a5dd2276e6d6e451be0a6bb" resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz#eaa49f6f80d5a33f9a5dd2276e6d6e451be0a6bb"
@@ -265,6 +283,11 @@
resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz#0c0cee9b35d2ca190478756865bb3528422f51be" resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz#0c0cee9b35d2ca190478756865bb3528422f51be"
integrity sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg== integrity sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==
"@babel/helper-environment-visitor@^7.22.20":
version "7.22.20"
resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz#96159db61d34a29dba454c959f5ae4a649ba9167"
integrity sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==
"@babel/helper-explode-assignable-expression@^7.18.6": "@babel/helper-explode-assignable-expression@^7.18.6":
version "7.18.6" version "7.18.6"
resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.18.6.tgz#41f8228ef0a6f1a036b8dfdfec7ce94f9a6bc096" resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.18.6.tgz#41f8228ef0a6f1a036b8dfdfec7ce94f9a6bc096"
@@ -280,6 +303,14 @@
"@babel/template" "^7.18.6" "@babel/template" "^7.18.6"
"@babel/types" "^7.18.9" "@babel/types" "^7.18.9"
"@babel/helper-function-name@^7.23.0":
version "7.23.0"
resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz#1f9a3cdbd5b2698a670c30d2735f9af95ed52759"
integrity sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==
dependencies:
"@babel/template" "^7.22.15"
"@babel/types" "^7.23.0"
"@babel/helper-hoist-variables@^7.18.6": "@babel/helper-hoist-variables@^7.18.6":
version "7.18.6" version "7.18.6"
resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz#d4d2c8fb4baeaa5c68b99cc8245c56554f926678" resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz#d4d2c8fb4baeaa5c68b99cc8245c56554f926678"
@@ -287,6 +318,13 @@
dependencies: dependencies:
"@babel/types" "^7.18.6" "@babel/types" "^7.18.6"
"@babel/helper-hoist-variables@^7.22.5":
version "7.22.5"
resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz#c01a007dac05c085914e8fb652b339db50d823bb"
integrity sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==
dependencies:
"@babel/types" "^7.22.5"
"@babel/helper-member-expression-to-functions@^7.18.9": "@babel/helper-member-expression-to-functions@^7.18.9":
version "7.18.9" version "7.18.9"
resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.18.9.tgz#1531661e8375af843ad37ac692c132841e2fd815" resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.18.9.tgz#1531661e8375af843ad37ac692c132841e2fd815"
@@ -374,11 +412,28 @@
dependencies: dependencies:
"@babel/types" "^7.18.6" "@babel/types" "^7.18.6"
"@babel/helper-split-export-declaration@^7.22.6":
version "7.22.6"
resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz#322c61b7310c0997fe4c323955667f18fcefb91c"
integrity sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==
dependencies:
"@babel/types" "^7.22.5"
"@babel/helper-string-parser@^7.22.5":
version "7.22.5"
resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz#533f36457a25814cf1df6488523ad547d784a99f"
integrity sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==
"@babel/helper-validator-identifier@^7.18.6": "@babel/helper-validator-identifier@^7.18.6":
version "7.18.6" version "7.18.6"
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz#9c97e30d31b2b8c72a1d08984f2ca9b574d7a076" resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz#9c97e30d31b2b8c72a1d08984f2ca9b574d7a076"
integrity sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g== integrity sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g==
"@babel/helper-validator-identifier@^7.22.20":
version "7.22.20"
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz#c4ae002c61d2879e724581d96665583dbc1dc0e0"
integrity sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==
"@babel/helper-validator-option@^7.18.6": "@babel/helper-validator-option@^7.18.6":
version "7.18.6" version "7.18.6"
resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz#bf0d2b5a509b1f336099e4ff36e1a63aa5db4db8" resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz#bf0d2b5a509b1f336099e4ff36e1a63aa5db4db8"
@@ -412,11 +467,25 @@
chalk "^2.0.0" chalk "^2.0.0"
js-tokens "^4.0.0" js-tokens "^4.0.0"
"@babel/highlight@^7.22.13":
version "7.22.20"
resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.22.20.tgz#4ca92b71d80554b01427815e06f2df965b9c1f54"
integrity sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==
dependencies:
"@babel/helper-validator-identifier" "^7.22.20"
chalk "^2.4.2"
js-tokens "^4.0.0"
"@babel/parser@^7.12.7", "@babel/parser@^7.18.6", "@babel/parser@^7.18.8", "@babel/parser@^7.18.9": "@babel/parser@^7.12.7", "@babel/parser@^7.18.6", "@babel/parser@^7.18.8", "@babel/parser@^7.18.9":
version "7.18.9" version "7.18.9"
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.18.9.tgz#f2dde0c682ccc264a9a8595efd030a5cc8fd2539" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.18.9.tgz#f2dde0c682ccc264a9a8595efd030a5cc8fd2539"
integrity sha512-9uJveS9eY9DJ0t64YbIBZICtJy8a5QrDEVdiLCG97fVLpDTpGX7t8mMSb6OWw6Lrnjqj4O8zwjELX3dhoMgiBg== integrity sha512-9uJveS9eY9DJ0t64YbIBZICtJy8a5QrDEVdiLCG97fVLpDTpGX7t8mMSb6OWw6Lrnjqj4O8zwjELX3dhoMgiBg==
"@babel/parser@^7.22.15", "@babel/parser@^7.23.0":
version "7.23.0"
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.23.0.tgz#da950e622420bf96ca0d0f2909cdddac3acd8719"
integrity sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==
"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.18.6": "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.18.6":
version "7.18.6" version "7.18.6"
resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.18.6.tgz#da5b8f9a580acdfbe53494dba45ea389fb09a4d2" resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.18.6.tgz#da5b8f9a580acdfbe53494dba45ea389fb09a4d2"
@@ -1147,19 +1216,28 @@
"@babel/parser" "^7.18.6" "@babel/parser" "^7.18.6"
"@babel/types" "^7.18.6" "@babel/types" "^7.18.6"
"@babel/traverse@^7.12.9", "@babel/traverse@^7.18.8", "@babel/traverse@^7.18.9": "@babel/template@^7.22.15":
version "7.18.9" version "7.22.15"
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.18.9.tgz#deeff3e8f1bad9786874cb2feda7a2d77a904f98" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.22.15.tgz#09576efc3830f0430f4548ef971dde1350ef2f38"
integrity sha512-LcPAnujXGwBgv3/WHv01pHtb2tihcyW1XuL9wd7jqh1Z8AQkTd+QVjMrMijrln0T7ED3UXLIy36P9Ao7W75rYg== integrity sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==
dependencies: dependencies:
"@babel/code-frame" "^7.18.6" "@babel/code-frame" "^7.22.13"
"@babel/generator" "^7.18.9" "@babel/parser" "^7.22.15"
"@babel/helper-environment-visitor" "^7.18.9" "@babel/types" "^7.22.15"
"@babel/helper-function-name" "^7.18.9"
"@babel/helper-hoist-variables" "^7.18.6" "@babel/traverse@^7.12.9", "@babel/traverse@^7.18.8", "@babel/traverse@^7.18.9":
"@babel/helper-split-export-declaration" "^7.18.6" version "7.23.2"
"@babel/parser" "^7.18.9" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.23.2.tgz#329c7a06735e144a506bdb2cad0268b7f46f4ad8"
"@babel/types" "^7.18.9" integrity sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==
dependencies:
"@babel/code-frame" "^7.22.13"
"@babel/generator" "^7.23.0"
"@babel/helper-environment-visitor" "^7.22.20"
"@babel/helper-function-name" "^7.23.0"
"@babel/helper-hoist-variables" "^7.22.5"
"@babel/helper-split-export-declaration" "^7.22.6"
"@babel/parser" "^7.23.0"
"@babel/types" "^7.23.0"
debug "^4.1.0" debug "^4.1.0"
globals "^11.1.0" globals "^11.1.0"
@@ -1171,6 +1249,15 @@
"@babel/helper-validator-identifier" "^7.18.6" "@babel/helper-validator-identifier" "^7.18.6"
to-fast-properties "^2.0.0" to-fast-properties "^2.0.0"
"@babel/types@^7.22.15", "@babel/types@^7.22.5", "@babel/types@^7.23.0":
version "7.23.0"
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.23.0.tgz#8c1f020c9df0e737e4e247c0619f58c68458aaeb"
integrity sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==
dependencies:
"@babel/helper-string-parser" "^7.22.5"
"@babel/helper-validator-identifier" "^7.22.20"
to-fast-properties "^2.0.0"
"@colors/colors@1.5.0": "@colors/colors@1.5.0":
version "1.5.0" version "1.5.0"
resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9" resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9"
@@ -1670,6 +1757,11 @@
resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78" resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78"
integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w== integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==
"@jridgewell/resolve-uri@^3.1.0":
version "3.1.1"
resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz#c08679063f279615a3326583ba3a90d1d82cc721"
integrity sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==
"@jridgewell/set-array@^1.0.0", "@jridgewell/set-array@^1.0.1": "@jridgewell/set-array@^1.0.0", "@jridgewell/set-array@^1.0.1":
version "1.1.2" version "1.1.2"
resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72"
@@ -1688,6 +1780,19 @@
resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24" resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24"
integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==
"@jridgewell/sourcemap-codec@^1.4.14":
version "1.4.15"
resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32"
integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==
"@jridgewell/trace-mapping@^0.3.17":
version "0.3.20"
resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz#72e45707cf240fa6b081d0366f8265b0cd10197f"
integrity sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==
dependencies:
"@jridgewell/resolve-uri" "^3.1.0"
"@jridgewell/sourcemap-codec" "^1.4.14"
"@jridgewell/trace-mapping@^0.3.7", "@jridgewell/trace-mapping@^0.3.9": "@jridgewell/trace-mapping@^0.3.7", "@jridgewell/trace-mapping@^0.3.9":
version "0.3.14" version "0.3.14"
resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.14.tgz#b231a081d8f66796e475ad588a1ef473112701ed" resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.14.tgz#b231a081d8f66796e475ad588a1ef473112701ed"
@@ -80,7 +80,8 @@ export const ExportToExcalidrawPlus: React.FC<{
appState: Partial<AppState>; appState: Partial<AppState>;
files: BinaryFiles; files: BinaryFiles;
onError: (error: Error) => void; onError: (error: Error) => void;
}> = ({ elements, appState, files, onError }) => { onSuccess: () => void;
}> = ({ elements, appState, files, onError, onSuccess }) => {
const { t } = useI18n(); const { t } = useI18n();
return ( return (
<Card color="primary"> <Card color="primary">
@@ -107,6 +108,7 @@ export const ExportToExcalidrawPlus: React.FC<{
try { try {
trackEvent("export", "eplus", `ui (${getFrame()})`); trackEvent("export", "eplus", `ui (${getFrame()})`);
await exportToExcalidrawPlus(elements, appState, files); await exportToExcalidrawPlus(elements, appState, files);
onSuccess();
} catch (error: any) { } catch (error: any) {
console.error(error); console.error(error);
if (error.name !== "AbortError") { if (error.name !== "AbortError") {
+1 -1
View File
@@ -6,7 +6,7 @@
* *
* - DataState refers to full state of the app: appState, elements, images, * - DataState refers to full state of the app: appState, elements, images,
* though some state is saved separately (collab username, library) for one * though some state is saved separately (collab username, library) for one
* reason or another. We also save different data to different sotrage * reason or another. We also save different data to different storage
* (localStorage, indexedDB). * (localStorage, indexedDB).
*/ */
+1 -1
View File
@@ -131,5 +131,5 @@ export class Debug {
}; };
}; };
} }
//@ts-ignore
window.debug = Debug; window.debug = Debug;
+8 -3
View File
@@ -608,7 +608,7 @@ const ExcalidrawWrapper = () => {
canvas: HTMLCanvasElement, canvas: HTMLCanvasElement,
) => { ) => {
if (exportedElements.length === 0) { if (exportedElements.length === 0) {
return window.alert(t("alerts.cannotExportEmptyCanvas")); throw new Error(t("alerts.cannotExportEmptyCanvas"));
} }
if (canvas) { if (canvas) {
try { try {
@@ -624,7 +624,7 @@ const ExcalidrawWrapper = () => {
); );
if (errorMessage) { if (errorMessage) {
setErrorMessage(errorMessage); throw new Error(errorMessage);
} }
if (url) { if (url) {
@@ -634,7 +634,7 @@ const ExcalidrawWrapper = () => {
if (error.name !== "AbortError") { if (error.name !== "AbortError") {
const { width, height } = canvas; const { width, height } = canvas;
console.error(error, { width, height }); console.error(error, { width, height });
setErrorMessage(error.message); throw new Error(error.message);
} }
} }
} }
@@ -714,6 +714,11 @@ const ExcalidrawWrapper = () => {
}, },
}); });
}} }}
onSuccess={() => {
excalidrawAPI?.updateScene({
appState: { openDialog: null },
});
}}
/> />
); );
}, },
+4 -3
View File
@@ -20,6 +20,7 @@
}, },
"dependencies": { "dependencies": {
"@braintree/sanitize-url": "6.0.2", "@braintree/sanitize-url": "6.0.2",
"@excalidraw/mermaid-to-excalidraw": "0.1.2",
"@excalidraw/laser-pointer": "1.2.0", "@excalidraw/laser-pointer": "1.2.0",
"@excalidraw/random-username": "1.0.0", "@excalidraw/random-username": "1.0.0",
"@radix-ui/react-popover": "1.0.3", "@radix-ui/react-popover": "1.0.3",
@@ -49,11 +50,11 @@
"png-chunk-text": "1.0.0", "png-chunk-text": "1.0.0",
"png-chunks-encode": "1.0.0", "png-chunks-encode": "1.0.0",
"png-chunks-extract": "1.0.0", "png-chunks-extract": "1.0.0",
"points-on-curve": "0.2.0", "points-on-curve": "1.0.1",
"pwacompat": "2.0.17", "pwacompat": "2.0.17",
"react": "18.2.0", "react": "18.2.0",
"react-dom": "18.2.0", "react-dom": "18.2.0",
"roughjs": "4.5.2", "roughjs": "4.6.4",
"sass": "1.51.0", "sass": "1.51.0",
"socket.io-client": "2.3.1", "socket.io-client": "2.3.1",
"tunnel-rat": "0.1.2" "tunnel-rat": "0.1.2"
@@ -125,7 +126,7 @@
"test": "yarn test:app", "test": "yarn test:app",
"test:coverage": "vitest --coverage", "test:coverage": "vitest --coverage",
"test:coverage:watch": "vitest --coverage --watch", "test:coverage:watch": "vitest --coverage --watch",
"test:ui": "yarn test --ui", "test:ui": "yarn test --ui --coverage.enabled=true",
"autorelease": "node scripts/autorelease.js", "autorelease": "node scripts/autorelease.js",
"prerelease": "node scripts/prerelease.js", "prerelease": "node scripts/prerelease.js",
"build:preview": "yarn build && vite preview --port 5000", "build:preview": "yarn build && vite preview --port 5000",
+62 -15
View File
@@ -3,33 +3,43 @@ import { register } from "./register";
import { import {
copyTextToSystemClipboard, copyTextToSystemClipboard,
copyToClipboard, copyToClipboard,
createPasteEvent,
probablySupportsClipboardBlob, probablySupportsClipboardBlob,
probablySupportsClipboardWriteText, probablySupportsClipboardWriteText,
readSystemClipboard,
} from "../clipboard"; } from "../clipboard";
import { actionDeleteSelected } from "./actionDeleteSelected"; import { actionDeleteSelected } from "./actionDeleteSelected";
import { exportCanvas } from "../data/index"; import { exportCanvas } from "../data/index";
import { getNonDeletedElements, isTextElement } from "../element"; import { getNonDeletedElements, isTextElement } from "../element";
import { t } from "../i18n"; import { t } from "../i18n";
import { isFirefox } from "../constants";
export const actionCopy = register({ export const actionCopy = register({
name: "copy", name: "copy",
trackEvent: { category: "element" }, trackEvent: { category: "element" },
perform: (elements, appState, _, app) => { perform: async (elements, appState, event: ClipboardEvent | null, app) => {
const elementsToCopy = app.scene.getSelectedElements({ const elementsToCopy = app.scene.getSelectedElements({
selectedElementIds: appState.selectedElementIds, selectedElementIds: appState.selectedElementIds,
includeBoundTextElement: true, includeBoundTextElement: true,
includeElementsInFrames: true, includeElementsInFrames: true,
}); });
copyToClipboard(elementsToCopy, app.files); try {
await copyToClipboard(elementsToCopy, app.files, event);
} catch (error: any) {
return {
commitToHistory: false,
appState: {
...appState,
errorMessage: error.message,
},
};
}
return { return {
commitToHistory: false, commitToHistory: false,
}; };
}, },
predicate: (elements, appState, appProps, app) => {
return app.device.isMobile && !!navigator.clipboard;
},
contextItemLabel: "labels.copy", contextItemLabel: "labels.copy",
// don't supply a shortcut since we handle this conditionally via onCopy event // don't supply a shortcut since we handle this conditionally via onCopy event
keyTest: undefined, keyTest: undefined,
@@ -38,15 +48,55 @@ export const actionCopy = register({
export const actionPaste = register({ export const actionPaste = register({
name: "paste", name: "paste",
trackEvent: { category: "element" }, trackEvent: { category: "element" },
perform: (elements: any, appStates: any, data, app) => { perform: async (elements, appState, data, app) => {
app.pasteFromClipboard(null); let types;
try {
types = await readSystemClipboard();
} catch (error: any) {
if (error.name === "AbortError" || error.name === "NotAllowedError") {
// user probably aborted the action. Though not 100% sure, it's best
// to not annoy them with an error message.
return false;
}
console.error(`actionPaste ${error.name}: ${error.message}`);
if (isFirefox) {
return {
commitToHistory: false,
appState: {
...appState,
errorMessage: t("hints.firefox_clipboard_write"),
},
};
}
return {
commitToHistory: false,
appState: {
...appState,
errorMessage: t("errors.asyncPasteFailedOnRead"),
},
};
}
try {
app.pasteFromClipboard(createPasteEvent({ types }));
} catch (error: any) {
console.error(error);
return {
commitToHistory: false,
appState: {
...appState,
errorMessage: t("errors.asyncPasteFailedOnParse"),
},
};
}
return { return {
commitToHistory: false, commitToHistory: false,
}; };
}, },
predicate: (elements, appState, appProps, app) => {
return app.device.isMobile && !!navigator.clipboard;
},
contextItemLabel: "labels.paste", contextItemLabel: "labels.paste",
// don't supply a shortcut since we handle this conditionally via onCopy event // don't supply a shortcut since we handle this conditionally via onCopy event
keyTest: undefined, keyTest: undefined,
@@ -55,13 +105,10 @@ export const actionPaste = register({
export const actionCut = register({ export const actionCut = register({
name: "cut", name: "cut",
trackEvent: { category: "element" }, trackEvent: { category: "element" },
perform: (elements, appState, data, app) => { perform: (elements, appState, event: ClipboardEvent | null, app) => {
actionCopy.perform(elements, appState, data, app); actionCopy.perform(elements, appState, event, app);
return actionDeleteSelected.perform(elements, appState); return actionDeleteSelected.perform(elements, appState);
}, },
predicate: (elements, appState, appProps, app) => {
return app.device.isMobile && !!navigator.clipboard;
},
contextItemLabel: "labels.cut", contextItemLabel: "labels.cut",
keyTest: (event) => event[KEYS.CTRL_OR_CMD] && event.key === KEYS.X, keyTest: (event) => event[KEYS.CTRL_OR_CMD] && event.key === KEYS.X,
}); });
+1
View File
@@ -46,6 +46,7 @@ const deleteSelectedElements = (
appState: { appState: {
...appState, ...appState,
selectedElementIds: {}, selectedElementIds: {},
selectedGroupIds: {},
}, },
}; };
}; };
+8 -8
View File
@@ -10,17 +10,12 @@ const shouldLock = (elements: readonly ExcalidrawElement[]) =>
export const actionToggleElementLock = register({ export const actionToggleElementLock = register({
name: "toggleElementLock", name: "toggleElementLock",
trackEvent: { category: "element" }, trackEvent: { category: "element" },
predicate: (elements, appState, _, app) => {
const selectedElements = app.scene.getSelectedElements(appState);
return !selectedElements.some(
(element) => element.locked && element.frameId,
);
},
perform: (elements, appState, _, app) => { perform: (elements, appState, _, app) => {
// Frames and their children should not be selected at the same time.
// Therefore, there's no need to include elements in frame in the selection.
const selectedElements = app.scene.getSelectedElements({ const selectedElements = app.scene.getSelectedElements({
selectedElementIds: appState.selectedElementIds, selectedElementIds: appState.selectedElementIds,
includeBoundTextElement: true, includeBoundTextElement: true,
includeElementsInFrames: true,
}); });
if (!selectedElements.length) { if (!selectedElements.length) {
@@ -31,7 +26,12 @@ export const actionToggleElementLock = register({
const selectedElementsMap = arrayToMap(selectedElements); const selectedElementsMap = arrayToMap(selectedElements);
return { return {
elements: elements.map((element) => { elements: elements.map((element) => {
if (!selectedElementsMap.has(element.id)) { if (
!selectedElementsMap.has(element.id) &&
(!element.frameId ||
// lock frame children if frame is selected
(element.frameId && !selectedElementsMap.has(element.frameId)))
) {
return element; return element;
} }
+9 -1
View File
@@ -191,7 +191,15 @@ export const actionSaveFileToDisk = register({
}, },
app.files, app.files,
); );
return { commitToHistory: false, appState: { ...appState, fileHandle } }; return {
commitToHistory: false,
appState: {
...appState,
openDialog: null,
fileHandle,
toast: { message: t("toast.fileSaved") },
},
};
} catch (error: any) { } catch (error: any) {
if (error?.name !== "AbortError") { if (error?.name !== "AbortError") {
console.error(error); console.error(error);
+1 -4
View File
@@ -170,7 +170,6 @@ export const actionFinalize = register({
: activeTool, : activeTool,
activeEmbeddable: null, activeEmbeddable: null,
draggingElement: null, draggingElement: null,
selectionElement: null,
multiElement: null, multiElement: null,
editingElement: null, editingElement: null,
startBoundElement: null, startBoundElement: null,
@@ -197,9 +196,7 @@ export const actionFinalize = register({
keyTest: (event, appState) => keyTest: (event, appState) =>
(event.key === KEYS.ESCAPE && (event.key === KEYS.ESCAPE &&
(appState.editingLinearElement !== null || (appState.editingLinearElement !== null ||
(!appState.selectionElement && (!appState.draggingElement && appState.multiElement === null))) ||
!appState.draggingElement &&
appState.multiElement === null))) ||
((event.key === KEYS.ESCAPE || event.key === KEYS.ENTER) && ((event.key === KEYS.ESCAPE || event.key === KEYS.ENTER) &&
appState.multiElement !== null), appState.multiElement !== null),
PanelComponent: ({ appState, updateData, data }) => ( PanelComponent: ({ appState, updateData, data }) => (
-1
View File
@@ -21,7 +21,6 @@ const writeData = (
!appState.multiElement && !appState.multiElement &&
!appState.resizingElement && !appState.resizingElement &&
!appState.editingElement && !appState.editingElement &&
!appState.selectionElement &&
!appState.draggingElement !appState.draggingElement
) { ) {
const data = updater(); const data = updater();
+167
View File
@@ -0,0 +1,167 @@
import { Excalidraw } from "../packages/excalidraw/index";
import { queryByTestId } from "@testing-library/react";
import { render } from "../tests/test-utils";
import { UI } from "../tests/helpers/ui";
import { API } from "../tests/helpers/api";
import { COLOR_PALETTE, DEFAULT_ELEMENT_BACKGROUND_PICKS } from "../colors";
import { FONT_FAMILY, STROKE_WIDTH } from "../constants";
const { h } = window;
describe("element locking", () => {
beforeEach(async () => {
await render(<Excalidraw />);
});
describe("properties when tool selected", () => {
it("should show active background top picks", () => {
UI.clickTool("rectangle");
const color = DEFAULT_ELEMENT_BACKGROUND_PICKS[1];
// just in case we change it in the future
expect(color).not.toBe(COLOR_PALETTE.transparent);
h.setState({
currentItemBackgroundColor: color,
});
const activeColor = queryByTestId(
document.body,
`color-top-pick-${color}`,
);
expect(activeColor).toHaveClass("active");
});
it("should show fill style when background non-transparent", () => {
UI.clickTool("rectangle");
const color = DEFAULT_ELEMENT_BACKGROUND_PICKS[1];
// just in case we change it in the future
expect(color).not.toBe(COLOR_PALETTE.transparent);
h.setState({
currentItemBackgroundColor: color,
currentItemFillStyle: "hachure",
});
const hachureFillButton = queryByTestId(document.body, `fill-hachure`);
expect(hachureFillButton).toHaveClass("active");
h.setState({
currentItemFillStyle: "solid",
});
const solidFillStyle = queryByTestId(document.body, `fill-solid`);
expect(solidFillStyle).toHaveClass("active");
});
it("should not show fill style when background transparent", () => {
UI.clickTool("rectangle");
h.setState({
currentItemBackgroundColor: COLOR_PALETTE.transparent,
currentItemFillStyle: "hachure",
});
const hachureFillButton = queryByTestId(document.body, `fill-hachure`);
expect(hachureFillButton).toBe(null);
});
it("should show horizontal text align for text tool", () => {
UI.clickTool("text");
h.setState({
currentItemTextAlign: "right",
});
const centerTextAlign = queryByTestId(document.body, `align-right`);
expect(centerTextAlign).toBeChecked();
});
});
describe("properties when elements selected", () => {
it("should show active styles when single element selected", () => {
const rect = API.createElement({
type: "rectangle",
backgroundColor: "red",
fillStyle: "cross-hatch",
});
h.elements = [rect];
API.setSelectedElements([rect]);
const crossHatchButton = queryByTestId(document.body, `fill-cross-hatch`);
expect(crossHatchButton).toHaveClass("active");
});
it("should not show fill style selected element's background is transparent", () => {
const rect = API.createElement({
type: "rectangle",
backgroundColor: COLOR_PALETTE.transparent,
fillStyle: "cross-hatch",
});
h.elements = [rect];
API.setSelectedElements([rect]);
const crossHatchButton = queryByTestId(document.body, `fill-cross-hatch`);
expect(crossHatchButton).toBe(null);
});
it("should highlight common stroke width of selected elements", () => {
const rect1 = API.createElement({
type: "rectangle",
strokeWidth: STROKE_WIDTH.thin,
});
const rect2 = API.createElement({
type: "rectangle",
strokeWidth: STROKE_WIDTH.thin,
});
h.elements = [rect1, rect2];
API.setSelectedElements([rect1, rect2]);
const thinStrokeWidthButton = queryByTestId(
document.body,
`strokeWidth-thin`,
);
expect(thinStrokeWidthButton).toBeChecked();
});
it("should not highlight any stroke width button if no common style", () => {
const rect1 = API.createElement({
type: "rectangle",
strokeWidth: STROKE_WIDTH.thin,
});
const rect2 = API.createElement({
type: "rectangle",
strokeWidth: STROKE_WIDTH.bold,
});
h.elements = [rect1, rect2];
API.setSelectedElements([rect1, rect2]);
expect(queryByTestId(document.body, `strokeWidth-thin`)).not.toBe(null);
expect(
queryByTestId(document.body, `strokeWidth-thin`),
).not.toBeChecked();
expect(
queryByTestId(document.body, `strokeWidth-bold`),
).not.toBeChecked();
expect(
queryByTestId(document.body, `strokeWidth-extraBold`),
).not.toBeChecked();
});
it("should show properties of different element types when selected", () => {
const rect = API.createElement({
type: "rectangle",
strokeWidth: STROKE_WIDTH.bold,
});
const text = API.createElement({
type: "text",
fontFamily: FONT_FAMILY.Cascadia,
});
h.elements = [rect, text];
API.setSelectedElements([rect, text]);
expect(queryByTestId(document.body, `strokeWidth-bold`)).toBeChecked();
expect(queryByTestId(document.body, `font-family-code`)).toBeChecked();
});
});
});
+84 -27
View File
@@ -1,4 +1,4 @@
import { AppState } from "../../src/types"; import { AppState, Primitive } from "../../src/types";
import { import {
DEFAULT_ELEMENT_BACKGROUND_COLOR_PALETTE, DEFAULT_ELEMENT_BACKGROUND_COLOR_PALETTE,
DEFAULT_ELEMENT_BACKGROUND_PICKS, DEFAULT_ELEMENT_BACKGROUND_PICKS,
@@ -51,6 +51,7 @@ import {
DEFAULT_FONT_SIZE, DEFAULT_FONT_SIZE,
FONT_FAMILY, FONT_FAMILY,
ROUNDNESS, ROUNDNESS,
STROKE_WIDTH,
VERTICAL_ALIGN, VERTICAL_ALIGN,
} from "../constants"; } from "../constants";
import { import {
@@ -82,7 +83,6 @@ import { getLanguage, t } from "../i18n";
import { KEYS } from "../keys"; import { KEYS } from "../keys";
import { randomInteger } from "../random"; import { randomInteger } from "../random";
import { import {
canChangeRoundness,
canHaveArrowheads, canHaveArrowheads,
getCommonAttributeOfSelectedElements, getCommonAttributeOfSelectedElements,
getSelectedElements, getSelectedElements,
@@ -118,25 +118,44 @@ export const changeProperty = (
}); });
}; };
export const getFormValue = function <T>( export const getFormValue = function <T extends Primitive>(
elements: readonly ExcalidrawElement[], elements: readonly ExcalidrawElement[],
appState: AppState, appState: AppState,
getAttribute: (element: ExcalidrawElement) => T, getAttribute: (element: ExcalidrawElement) => T,
defaultValue: T, isRelevantElement: true | ((element: ExcalidrawElement) => boolean),
defaultValue: T | ((isSomeElementSelected: boolean) => T),
): T { ): T {
const editingElement = appState.editingElement; const editingElement = appState.editingElement;
const nonDeletedElements = getNonDeletedElements(elements); const nonDeletedElements = getNonDeletedElements(elements);
return (
(editingElement && getAttribute(editingElement)) ?? let ret: T | null = null;
(isSomeElementSelected(nonDeletedElements, appState)
? getCommonAttributeOfSelectedElements( if (editingElement) {
nonDeletedElements, ret = getAttribute(editingElement);
}
if (!ret) {
const hasSelection = isSomeElementSelected(nonDeletedElements, appState);
if (hasSelection) {
ret =
getCommonAttributeOfSelectedElements(
isRelevantElement === true
? nonDeletedElements
: nonDeletedElements.filter((el) => isRelevantElement(el)),
appState, appState,
getAttribute, getAttribute,
) ) ??
: defaultValue) ?? (typeof defaultValue === "function"
defaultValue ? defaultValue(true)
); : defaultValue);
} else {
ret =
typeof defaultValue === "function" ? defaultValue(false) : defaultValue;
}
}
return ret;
}; };
const offsetElementAfterFontResize = ( const offsetElementAfterFontResize = (
@@ -247,6 +266,7 @@ export const actionChangeStrokeColor = register({
elements, elements,
appState, appState,
(element) => element.strokeColor, (element) => element.strokeColor,
true,
appState.currentItemStrokeColor, appState.currentItemStrokeColor,
)} )}
onChange={(color) => updateData({ currentItemStrokeColor: color })} onChange={(color) => updateData({ currentItemStrokeColor: color })}
@@ -289,6 +309,7 @@ export const actionChangeBackgroundColor = register({
elements, elements,
appState, appState,
(element) => element.backgroundColor, (element) => element.backgroundColor,
true,
appState.currentItemBackgroundColor, appState.currentItemBackgroundColor,
)} )}
onChange={(color) => updateData({ currentItemBackgroundColor: color })} onChange={(color) => updateData({ currentItemBackgroundColor: color })}
@@ -338,23 +359,28 @@ export const actionChangeFillStyle = register({
} (${getShortcutKey("Alt-Click")})`, } (${getShortcutKey("Alt-Click")})`,
icon: allElementsZigZag ? FillZigZagIcon : FillHachureIcon, icon: allElementsZigZag ? FillZigZagIcon : FillHachureIcon,
active: allElementsZigZag ? true : undefined, active: allElementsZigZag ? true : undefined,
testId: `fill-hachure`,
}, },
{ {
value: "cross-hatch", value: "cross-hatch",
text: t("labels.crossHatch"), text: t("labels.crossHatch"),
icon: FillCrossHatchIcon, icon: FillCrossHatchIcon,
testId: `fill-cross-hatch`,
}, },
{ {
value: "solid", value: "solid",
text: t("labels.solid"), text: t("labels.solid"),
icon: FillSolidIcon, icon: FillSolidIcon,
testId: `fill-solid`,
}, },
]} ]}
value={getFormValue( value={getFormValue(
elements, elements,
appState, appState,
(element) => element.fillStyle, (element) => element.fillStyle,
appState.currentItemFillStyle, (element) => element.hasOwnProperty("fillStyle"),
(hasSelection) =>
hasSelection ? null : appState.currentItemFillStyle,
)} )}
onClick={(value, event) => { onClick={(value, event) => {
const nextValue = const nextValue =
@@ -393,26 +419,31 @@ export const actionChangeStrokeWidth = register({
group="stroke-width" group="stroke-width"
options={[ options={[
{ {
value: 1, value: STROKE_WIDTH.thin,
text: t("labels.thin"), text: t("labels.thin"),
icon: StrokeWidthBaseIcon, icon: StrokeWidthBaseIcon,
testId: "strokeWidth-thin",
}, },
{ {
value: 2, value: STROKE_WIDTH.bold,
text: t("labels.bold"), text: t("labels.bold"),
icon: StrokeWidthBoldIcon, icon: StrokeWidthBoldIcon,
testId: "strokeWidth-bold",
}, },
{ {
value: 4, value: STROKE_WIDTH.extraBold,
text: t("labels.extraBold"), text: t("labels.extraBold"),
icon: StrokeWidthExtraBoldIcon, icon: StrokeWidthExtraBoldIcon,
testId: "strokeWidth-extraBold",
}, },
]} ]}
value={getFormValue( value={getFormValue(
elements, elements,
appState, appState,
(element) => element.strokeWidth, (element) => element.strokeWidth,
appState.currentItemStrokeWidth, (element) => element.hasOwnProperty("strokeWidth"),
(hasSelection) =>
hasSelection ? null : appState.currentItemStrokeWidth,
)} )}
onChange={(value) => updateData(value)} onChange={(value) => updateData(value)}
/> />
@@ -461,7 +492,9 @@ export const actionChangeSloppiness = register({
elements, elements,
appState, appState,
(element) => element.roughness, (element) => element.roughness,
appState.currentItemRoughness, (element) => element.hasOwnProperty("roughness"),
(hasSelection) =>
hasSelection ? null : appState.currentItemRoughness,
)} )}
onChange={(value) => updateData(value)} onChange={(value) => updateData(value)}
/> />
@@ -509,7 +542,9 @@ export const actionChangeStrokeStyle = register({
elements, elements,
appState, appState,
(element) => element.strokeStyle, (element) => element.strokeStyle,
appState.currentItemStrokeStyle, (element) => element.hasOwnProperty("strokeStyle"),
(hasSelection) =>
hasSelection ? null : appState.currentItemStrokeStyle,
)} )}
onChange={(value) => updateData(value)} onChange={(value) => updateData(value)}
/> />
@@ -549,6 +584,7 @@ export const actionChangeOpacity = register({
elements, elements,
appState, appState,
(element) => element.opacity, (element) => element.opacity,
true,
appState.currentItemOpacity, appState.currentItemOpacity,
) ?? undefined ) ?? undefined
} }
@@ -607,7 +643,12 @@ export const actionChangeFontSize = register({
} }
return null; return null;
}, },
appState.currentItemFontSize || DEFAULT_FONT_SIZE, (element) =>
isTextElement(element) || getBoundTextElement(element) !== null,
(hasSelection) =>
hasSelection
? null
: appState.currentItemFontSize || DEFAULT_FONT_SIZE,
)} )}
onChange={(value) => updateData(value)} onChange={(value) => updateData(value)}
/> />
@@ -692,21 +733,25 @@ export const actionChangeFontFamily = register({
value: FontFamilyValues; value: FontFamilyValues;
text: string; text: string;
icon: JSX.Element; icon: JSX.Element;
testId: string;
}[] = [ }[] = [
{ {
value: FONT_FAMILY.Virgil, value: FONT_FAMILY.Virgil,
text: t("labels.handDrawn"), text: t("labels.handDrawn"),
icon: FreedrawIcon, icon: FreedrawIcon,
testId: "font-family-virgil",
}, },
{ {
value: FONT_FAMILY.Helvetica, value: FONT_FAMILY.Helvetica,
text: t("labels.normal"), text: t("labels.normal"),
icon: FontFamilyNormalIcon, icon: FontFamilyNormalIcon,
testId: "font-family-normal",
}, },
{ {
value: FONT_FAMILY.Cascadia, value: FONT_FAMILY.Cascadia,
text: t("labels.code"), text: t("labels.code"),
icon: FontFamilyCodeIcon, icon: FontFamilyCodeIcon,
testId: "font-family-code",
}, },
]; ];
@@ -729,7 +774,12 @@ export const actionChangeFontFamily = register({
} }
return null; return null;
}, },
appState.currentItemFontFamily || DEFAULT_FONT_FAMILY, (element) =>
isTextElement(element) || getBoundTextElement(element) !== null,
(hasSelection) =>
hasSelection
? null
: appState.currentItemFontFamily || DEFAULT_FONT_FAMILY,
)} )}
onChange={(value) => updateData(value)} onChange={(value) => updateData(value)}
/> />
@@ -806,7 +856,10 @@ export const actionChangeTextAlign = register({
} }
return null; return null;
}, },
appState.currentItemTextAlign, (element) =>
isTextElement(element) || getBoundTextElement(element) !== null,
(hasSelection) =>
hasSelection ? null : appState.currentItemTextAlign,
)} )}
onChange={(value) => updateData(value)} onChange={(value) => updateData(value)}
/> />
@@ -882,7 +935,9 @@ export const actionChangeVerticalAlign = register({
} }
return null; return null;
}, },
VERTICAL_ALIGN.MIDDLE, (element) =>
isTextElement(element) || getBoundTextElement(element) !== null,
(hasSelection) => (hasSelection ? null : VERTICAL_ALIGN.MIDDLE),
)} )}
onChange={(value) => updateData(value)} onChange={(value) => updateData(value)}
/> />
@@ -947,9 +1002,9 @@ export const actionChangeRoundness = register({
appState, appState,
(element) => (element) =>
hasLegacyRoundness ? null : element.roundness ? "round" : "sharp", hasLegacyRoundness ? null : element.roundness ? "round" : "sharp",
(canChangeRoundness(appState.activeTool.type) && (element) => element.hasOwnProperty("roundness"),
appState.currentItemRoundness) || (hasSelection) =>
null, hasSelection ? null : appState.currentItemRoundness,
)} )}
onChange={(value) => updateData(value)} onChange={(value) => updateData(value)}
/> />
@@ -1043,6 +1098,7 @@ export const actionChangeArrowhead = register({
isLinearElement(element) && canHaveArrowheads(element.type) isLinearElement(element) && canHaveArrowheads(element.type)
? element.startArrowhead ? element.startArrowhead
: appState.currentItemStartArrowhead, : appState.currentItemStartArrowhead,
true,
appState.currentItemStartArrowhead, appState.currentItemStartArrowhead,
)} )}
onChange={(value) => updateData({ position: "start", type: value })} onChange={(value) => updateData({ position: "start", type: value })}
@@ -1089,6 +1145,7 @@ export const actionChangeArrowhead = register({
isLinearElement(element) && canHaveArrowheads(element.type) isLinearElement(element) && canHaveArrowheads(element.type)
? element.endArrowhead ? element.endArrowhead
: appState.currentItemEndArrowhead, : appState.currentItemEndArrowhead,
true,
appState.currentItemEndArrowhead, appState.currentItemEndArrowhead,
)} )}
onChange={(value) => updateData({ position: "end", type: value })} onChange={(value) => updateData({ position: "end", type: value })}
+3 -3
View File
@@ -119,10 +119,10 @@ export class ActionManager {
return true; return true;
} }
executeAction( executeAction<T extends Action>(
action: Action, action: T,
source: ActionSource = "api", source: ActionSource = "api",
value: any = null, value: Parameters<T["perform"]>[2] = null,
) { ) {
const elements = this.getElementsIncludingDeleted(); const elements = this.getElementsIncludingDeleted();
const appState = this.getAppState(); const appState = this.getAppState();
+186 -17
View File
@@ -1,27 +1,196 @@
import { parseClipboard } from "./clipboard"; import {
createPasteEvent,
parseClipboard,
serializeAsClipboardJSON,
} from "./clipboard";
import { API } from "./tests/helpers/api";
describe("Test parseClipboard", () => { describe("parseClipboard()", () => {
it("should parse valid json correctly", async () => { it("should parse JSON as plaintext if not excalidraw-api/clipboard data", async () => {
let text = "123"; let text;
let clipboardData;
let clipboardData = await parseClipboard({ // -------------------------------------------------------------------------
//@ts-ignore
clipboardData: {
getData: () => text,
},
});
text = "123";
clipboardData = await parseClipboard(
createPasteEvent({ types: { "text/plain": text } }),
);
expect(clipboardData.text).toBe(text); expect(clipboardData.text).toBe(text);
// -------------------------------------------------------------------------
text = "[123]"; text = "[123]";
clipboardData = await parseClipboard(
createPasteEvent({ types: { "text/plain": text } }),
);
expect(clipboardData.text).toBe(text);
clipboardData = await parseClipboard({ // -------------------------------------------------------------------------
//@ts-ignore
clipboardData: {
getData: () => text,
},
});
text = JSON.stringify({ val: 42 });
clipboardData = await parseClipboard(
createPasteEvent({ types: { "text/plain": text } }),
);
expect(clipboardData.text).toBe(text); expect(clipboardData.text).toBe(text);
}); });
it("should parse valid excalidraw JSON if inside text/plain", async () => {
const rect = API.createElement({ type: "rectangle" });
const json = serializeAsClipboardJSON({ elements: [rect], files: null });
const clipboardData = await parseClipboard(
createPasteEvent({
types: {
"text/plain": json,
},
}),
);
expect(clipboardData.elements).toEqual([rect]);
});
it("should parse valid excalidraw JSON if inside text/html", async () => {
const rect = API.createElement({ type: "rectangle" });
let json;
let clipboardData;
// -------------------------------------------------------------------------
json = serializeAsClipboardJSON({ elements: [rect], files: null });
clipboardData = await parseClipboard(
createPasteEvent({
types: {
"text/html": json,
},
}),
);
expect(clipboardData.elements).toEqual([rect]);
// -------------------------------------------------------------------------
json = serializeAsClipboardJSON({ elements: [rect], files: null });
clipboardData = await parseClipboard(
createPasteEvent({
types: {
"text/html": `<div> ${json}</div>`,
},
}),
);
expect(clipboardData.elements).toEqual([rect]);
// -------------------------------------------------------------------------
});
it("should parse <image> `src` urls out of text/html", async () => {
let clipboardData;
// -------------------------------------------------------------------------
clipboardData = await parseClipboard(
createPasteEvent({
types: {
"text/html": `<img src="https://example.com/image.png" />`,
},
}),
);
expect(clipboardData.mixedContent).toEqual([
{
type: "imageUrl",
value: "https://example.com/image.png",
},
]);
// -------------------------------------------------------------------------
clipboardData = await parseClipboard(
createPasteEvent({
types: {
"text/html": `<div><img src="https://example.com/image.png" /></div><a><img src="https://example.com/image2.png" /></a>`,
},
}),
);
expect(clipboardData.mixedContent).toEqual([
{
type: "imageUrl",
value: "https://example.com/image.png",
},
{
type: "imageUrl",
value: "https://example.com/image2.png",
},
]);
});
it("should parse text content alongside <image> `src` urls out of text/html", async () => {
const clipboardData = await parseClipboard(
createPasteEvent({
types: {
"text/html": `<a href="https://example.com">hello </a><div><img src="https://example.com/image.png" /></div><b>my friend!</b>`,
},
}),
);
expect(clipboardData.mixedContent).toEqual([
{
type: "text",
// trimmed
value: "hello",
},
{
type: "imageUrl",
value: "https://example.com/image.png",
},
{
type: "text",
value: "my friend!",
},
]);
});
it("should parse spreadsheet from either text/plain and text/html", async () => {
let clipboardData;
// -------------------------------------------------------------------------
clipboardData = await parseClipboard(
createPasteEvent({
types: {
"text/plain": `a b
1 2
4 5
7 10`,
},
}),
);
expect(clipboardData.spreadsheet).toEqual({
title: "b",
labels: ["1", "4", "7"],
values: [2, 5, 10],
});
// -------------------------------------------------------------------------
clipboardData = await parseClipboard(
createPasteEvent({
types: {
"text/html": `a b
1 2
4 5
7 10`,
},
}),
);
expect(clipboardData.spreadsheet).toEqual({
title: "b",
labels: ["1", "4", "7"],
values: [2, 5, 10],
});
// -------------------------------------------------------------------------
clipboardData = await parseClipboard(
createPasteEvent({
types: {
"text/html": `<html>
<body>
<!--StartFragment--><google-sheets-html-origin><style type="text/css"><!--td {border: 1px solid #cccccc;}br {mso-data-placement:same-cell;}--></style><table xmlns="http://www.w3.org/1999/xhtml" cellspacing="0" cellpadding="0" dir="ltr" border="1" style="table-layout:fixed;font-size:10pt;font-family:Arial;width:0px;border-collapse:collapse;border:none"><colgroup><col width="100"/><col width="100"/></colgroup><tbody><tr style="height:21px;"><td style="overflow:hidden;padding:2px 3px 2px 3px;vertical-align:bottom;" data-sheets-value="{&quot;1&quot;:2,&quot;2&quot;:&quot;a&quot;}">a</td><td style="overflow:hidden;padding:2px 3px 2px 3px;vertical-align:bottom;" data-sheets-value="{&quot;1&quot;:2,&quot;2&quot;:&quot;b&quot;}">b</td></tr><tr style="height:21px;"><td style="overflow:hidden;padding:2px 3px 2px 3px;vertical-align:bottom;text-align:right;" data-sheets-value="{&quot;1&quot;:3,&quot;3&quot;:1}">1</td><td style="overflow:hidden;padding:2px 3px 2px 3px;vertical-align:bottom;text-align:right;" data-sheets-value="{&quot;1&quot;:3,&quot;3&quot;:2}">2</td></tr><tr style="height:21px;"><td style="overflow:hidden;padding:2px 3px 2px 3px;vertical-align:bottom;text-align:right;" data-sheets-value="{&quot;1&quot;:3,&quot;3&quot;:4}">4</td><td style="overflow:hidden;padding:2px 3px 2px 3px;vertical-align:bottom;text-align:right;" data-sheets-value="{&quot;1&quot;:3,&quot;3&quot;:5}">5</td></tr><tr style="height:21px;"><td style="overflow:hidden;padding:2px 3px 2px 3px;vertical-align:bottom;text-align:right;" data-sheets-value="{&quot;1&quot;:3,&quot;3&quot;:7}">7</td><td style="overflow:hidden;padding:2px 3px 2px 3px;vertical-align:bottom;text-align:right;" data-sheets-value="{&quot;1&quot;:3,&quot;3&quot;:10}">10</td></tr></tbody></table><!--EndFragment-->
</body>
</html>`,
"text/plain": `a b
1 2
4 5
7 10`,
},
}),
);
expect(clipboardData.spreadsheet).toEqual({
title: "b",
labels: ["1", "4", "7"],
values: [2, 5, 10],
});
});
}); });
+263 -91
View File
@@ -3,14 +3,18 @@ import {
NonDeletedExcalidrawElement, NonDeletedExcalidrawElement,
} from "./element/types"; } from "./element/types";
import { BinaryFiles } from "./types"; import { BinaryFiles } from "./types";
import { SVG_EXPORT_TAG } from "./scene/export";
import { tryParseSpreadsheet, Spreadsheet, VALID_SPREADSHEET } from "./charts"; import { tryParseSpreadsheet, Spreadsheet, VALID_SPREADSHEET } from "./charts";
import { EXPORT_DATA_TYPES, MIME_TYPES } from "./constants"; import {
ALLOWED_PASTE_MIME_TYPES,
EXPORT_DATA_TYPES,
MIME_TYPES,
} from "./constants";
import { isInitializedImageElement } from "./element/typeChecks"; import { isInitializedImageElement } from "./element/typeChecks";
import { deepCopyElement } from "./element/newElement"; import { deepCopyElement } from "./element/newElement";
import { mutateElement } from "./element/mutateElement"; import { mutateElement } from "./element/mutateElement";
import { getContainingFrame } from "./frame"; import { getContainingFrame } from "./frame";
import { isPromiseLike, isTestEnv } from "./utils"; import { isMemberOf, isPromiseLike } from "./utils";
import { t } from "./i18n";
type ElementsClipboard = { type ElementsClipboard = {
type: typeof EXPORT_DATA_TYPES.excalidrawClipboard; type: typeof EXPORT_DATA_TYPES.excalidrawClipboard;
@@ -18,17 +22,23 @@ type ElementsClipboard = {
files: BinaryFiles | undefined; files: BinaryFiles | undefined;
}; };
export type PastedMixedContent = { type: "text" | "imageUrl"; value: string }[];
export interface ClipboardData { export interface ClipboardData {
spreadsheet?: Spreadsheet; spreadsheet?: Spreadsheet;
elements?: readonly ExcalidrawElement[]; elements?: readonly ExcalidrawElement[];
files?: BinaryFiles; files?: BinaryFiles;
text?: string; text?: string;
mixedContent?: PastedMixedContent;
errorMessage?: string; errorMessage?: string;
programmaticAPI?: boolean; programmaticAPI?: boolean;
} }
let CLIPBOARD = ""; type AllowedPasteMimeTypes = typeof ALLOWED_PASTE_MIME_TYPES[number];
let PREFER_APP_CLIPBOARD = false;
type ParsedClipboardEvent =
| { type: "text"; value: string }
| { type: "mixedContent"; value: PastedMixedContent };
export const probablySupportsClipboardReadText = export const probablySupportsClipboardReadText =
"clipboard" in navigator && "readText" in navigator.clipboard; "clipboard" in navigator && "readText" in navigator.clipboard;
@@ -58,10 +68,61 @@ const clipboardContainsElements = (
return false; return false;
}; };
export const copyToClipboard = async ( export const createPasteEvent = ({
elements: readonly NonDeletedExcalidrawElement[], types,
files: BinaryFiles | null, files,
) => { }: {
types?: { [key in AllowedPasteMimeTypes]?: string };
files?: File[];
}) => {
if (!types && !files) {
console.warn("createPasteEvent: no types or files provided");
}
const event = new ClipboardEvent("paste", {
clipboardData: new DataTransfer(),
});
if (types) {
for (const [type, value] of Object.entries(types)) {
try {
event.clipboardData?.setData(type, value);
if (event.clipboardData?.getData(type) !== value) {
throw new Error(`Failed to set "${type}" as clipboardData item`);
}
} catch (error: any) {
throw new Error(error.message);
}
}
}
if (files) {
let idx = -1;
for (const file of files) {
idx++;
try {
event.clipboardData?.items.add(file);
if (event.clipboardData?.files[idx] !== file) {
throw new Error(
`Failed to set file "${file.name}" as clipboardData item`,
);
}
} catch (error: any) {
throw new Error(error.message);
}
}
}
return event;
};
export const serializeAsClipboardJSON = ({
elements,
files,
}: {
elements: readonly NonDeletedExcalidrawElement[];
files: BinaryFiles | null;
}) => {
const framesToCopy = new Set( const framesToCopy = new Set(
elements.filter((element) => element.type === "frame"), elements.filter((element) => element.type === "frame"),
); );
@@ -83,7 +144,7 @@ export const copyToClipboard = async (
); );
} }
// select binded text elements when copying // select bound text elements when copying
const contents: ElementsClipboard = { const contents: ElementsClipboard = {
type: EXPORT_DATA_TYPES.excalidrawClipboard, type: EXPORT_DATA_TYPES.excalidrawClipboard,
elements: elements.map((element) => { elements: elements.map((element) => {
@@ -102,34 +163,20 @@ export const copyToClipboard = async (
}), }),
files: files ? _files : undefined, files: files ? _files : undefined,
}; };
const json = JSON.stringify(contents);
if (isTestEnv()) { return JSON.stringify(contents);
return json;
}
CLIPBOARD = json;
try {
PREFER_APP_CLIPBOARD = false;
await copyTextToSystemClipboard(json);
} catch (error: any) {
PREFER_APP_CLIPBOARD = true;
console.error(error);
}
}; };
const getAppClipboard = (): Partial<ElementsClipboard> => { export const copyToClipboard = async (
if (!CLIPBOARD) { elements: readonly NonDeletedExcalidrawElement[],
return {}; files: BinaryFiles | null,
} /** supply if available to make the operation more certain to succeed */
clipboardEvent?: ClipboardEvent | null,
try { ) => {
return JSON.parse(CLIPBOARD); await copyTextToSystemClipboard(
} catch (error: any) { serializeAsClipboardJSON({ elements, files }),
console.error(error); clipboardEvent,
return {}; );
}
}; };
const parsePotentialSpreadsheet = ( const parsePotentialSpreadsheet = (
@@ -142,22 +189,137 @@ const parsePotentialSpreadsheet = (
return null; return null;
}; };
/** /** internal, specific to parsing paste events. Do not reuse. */
* Retrieves content from system clipboard (either from ClipboardEvent or function parseHTMLTree(el: ChildNode) {
* via async clipboard API if supported) let result: PastedMixedContent = [];
*/ for (const node of el.childNodes) {
export const getSystemClipboard = async ( if (node.nodeType === 3) {
event: ClipboardEvent | null, const text = node.textContent?.trim();
): Promise<string> => { if (text) {
try { result.push({ type: "text", value: text });
const text = event }
? event.clipboardData?.getData("text/plain") } else if (node instanceof HTMLImageElement) {
: probablySupportsClipboardReadText && const url = node.getAttribute("src");
(await navigator.clipboard.readText()); if (url && url.startsWith("http")) {
result.push({ type: "imageUrl", value: url });
}
} else {
result = result.concat(parseHTMLTree(node));
}
}
return result;
}
return (text || "").trim(); const maybeParseHTMLPaste = (
event: ClipboardEvent,
): { type: "mixedContent"; value: PastedMixedContent } | null => {
const html = event.clipboardData?.getData("text/html");
if (!html) {
return null;
}
try {
const doc = new DOMParser().parseFromString(html, "text/html");
const content = parseHTMLTree(doc.body);
if (content.length) {
return { type: "mixedContent", value: content };
}
} catch (error: any) {
console.error(`error in parseHTMLFromPaste: ${error.message}`);
}
return null;
};
export const readSystemClipboard = async () => {
const types: { [key in AllowedPasteMimeTypes]?: string } = {};
try {
if (navigator.clipboard?.readText) {
return { "text/plain": await navigator.clipboard?.readText() };
}
} catch (error: any) {
// @ts-ignore
if (navigator.clipboard?.read) {
console.warn(
`navigator.clipboard.readText() failed (${error.message}). Failling back to navigator.clipboard.read()`,
);
} else {
throw error;
}
}
let clipboardItems: ClipboardItems;
try {
clipboardItems = await navigator.clipboard?.read();
} catch (error: any) {
if (error.name === "DataError") {
console.warn(
`navigator.clipboard.read() error, clipboard is probably empty: ${error.message}`,
);
return types;
}
throw error;
}
for (const item of clipboardItems) {
for (const type of item.types) {
if (!isMemberOf(ALLOWED_PASTE_MIME_TYPES, type)) {
continue;
}
try {
types[type] = await (await item.getType(type)).text();
} catch (error: any) {
console.warn(
`Cannot retrieve ${type} from clipboardItem: ${error.message}`,
);
}
}
}
if (Object.keys(types).length === 0) {
console.warn("No clipboard data found from clipboard.read().");
return types;
}
return types;
};
/**
* Parses "paste" ClipboardEvent.
*/
const parseClipboardEvent = async (
event: ClipboardEvent,
isPlainPaste = false,
): Promise<ParsedClipboardEvent> => {
try {
const mixedContent = !isPlainPaste && event && maybeParseHTMLPaste(event);
if (mixedContent) {
if (mixedContent.value.every((item) => item.type === "text")) {
return {
type: "text",
value:
event.clipboardData?.getData("text/plain") ||
mixedContent.value
.map((item) => item.value)
.join("\n")
.trim(),
};
}
return mixedContent;
}
const text = event.clipboardData?.getData("text/plain");
return { type: "text", value: (text || "").trim() };
} catch { } catch {
return ""; return { type: "text", value: "" };
} }
}; };
@@ -165,34 +327,32 @@ export const getSystemClipboard = async (
* Attempts to parse clipboard. Prefers system clipboard. * Attempts to parse clipboard. Prefers system clipboard.
*/ */
export const parseClipboard = async ( export const parseClipboard = async (
event: ClipboardEvent | null, event: ClipboardEvent,
isPlainPaste = false, isPlainPaste = false,
): Promise<ClipboardData> => { ): Promise<ClipboardData> => {
const systemClipboard = await getSystemClipboard(event); const parsedEventData = await parseClipboardEvent(event, isPlainPaste);
// if system clipboard empty, couldn't be resolved, or contains previously if (parsedEventData.type === "mixedContent") {
// copied excalidraw scene as SVG, fall back to previously copied excalidraw return {
// elements mixedContent: parsedEventData.value,
if ( };
!systemClipboard ||
(!isPlainPaste && systemClipboard.includes(SVG_EXPORT_TAG))
) {
return getAppClipboard();
} }
// if system clipboard contains spreadsheet, use it even though it's
// technically possible it's staler than in-app clipboard
const spreadsheetResult =
!isPlainPaste && parsePotentialSpreadsheet(systemClipboard);
if (spreadsheetResult) {
return spreadsheetResult;
}
const appClipboardData = getAppClipboard();
try { try {
const systemClipboardData = JSON.parse(systemClipboard); // if system clipboard contains spreadsheet, use it even though it's
// technically possible it's staler than in-app clipboard
const spreadsheetResult =
!isPlainPaste && parsePotentialSpreadsheet(parsedEventData.value);
if (spreadsheetResult) {
return spreadsheetResult;
}
} catch (error: any) {
console.error(error);
}
try {
const systemClipboardData = JSON.parse(parsedEventData.value);
const programmaticAPI = const programmaticAPI =
systemClipboardData.type === EXPORT_DATA_TYPES.excalidrawClipboardWithAPI; systemClipboardData.type === EXPORT_DATA_TYPES.excalidrawClipboardWithAPI;
if (clipboardContainsElements(systemClipboardData)) { if (clipboardContainsElements(systemClipboardData)) {
@@ -205,18 +365,9 @@ export const parseClipboard = async (
programmaticAPI, programmaticAPI,
}; };
} }
} catch (e) {} } catch {}
// system clipboard doesn't contain excalidraw elements → return plaintext
// unless we set a flag to prefer in-app clipboard because browser didn't return { text: parsedEventData.value };
// support storing to system clipboard on copy
return PREFER_APP_CLIPBOARD && appClipboardData.elements
? {
...appClipboardData,
text: isPlainPaste
? JSON.stringify(appClipboardData.elements, null, 2)
: undefined,
}
: { text: systemClipboard };
}; };
export const copyBlobToClipboardAsPng = async (blob: Blob | Promise<Blob>) => { export const copyBlobToClipboardAsPng = async (blob: Blob | Promise<Blob>) => {
@@ -249,28 +400,49 @@ export const copyBlobToClipboardAsPng = async (blob: Blob | Promise<Blob>) => {
} }
}; };
export const copyTextToSystemClipboard = async (text: string | null) => { export const copyTextToSystemClipboard = async (
let copied = false; text: string | null,
clipboardEvent?: ClipboardEvent | null,
) => {
// (1) first try using Async Clipboard API
if (probablySupportsClipboardWriteText) { if (probablySupportsClipboardWriteText) {
try { try {
// NOTE: doesn't work on FF on non-HTTPS domains, or when document // NOTE: doesn't work on FF on non-HTTPS domains, or when document
// not focused // not focused
await navigator.clipboard.writeText(text || ""); await navigator.clipboard.writeText(text || "");
copied = true; return;
} catch (error: any) { } catch (error: any) {
console.error(error); console.error(error);
} }
} }
// Note that execCommand doesn't allow copying empty strings, so if we're // (2) if fails and we have access to ClipboardEvent, use plain old setData()
// clearing clipboard using this API, we must copy at least an empty char try {
if (!copied && !copyTextViaExecCommand(text || " ")) { if (clipboardEvent) {
throw new Error("couldn't copy"); clipboardEvent.clipboardData?.setData("text/plain", text || "");
if (clipboardEvent.clipboardData?.getData("text/plain") !== text) {
throw new Error("Failed to setData on clipboardEvent");
}
return;
}
} catch (error: any) {
console.error(error);
}
// (3) if that fails, use document.execCommand
if (!copyTextViaExecCommand(text)) {
throw new Error(t("errors.copyToSystemClipboardFailed"));
} }
}; };
// adapted from https://github.com/zenorocha/clipboard.js/blob/ce79f170aa655c408b6aab33c9472e8e4fa52e19/src/clipboard-action.js#L48 // adapted from https://github.com/zenorocha/clipboard.js/blob/ce79f170aa655c408b6aab33c9472e8e4fa52e19/src/clipboard-action.js#L48
const copyTextViaExecCommand = (text: string) => { const copyTextViaExecCommand = (text: string | null) => {
// execCommand doesn't allow copying empty strings, so if we're
// clearing clipboard using this API, we must copy at least an empty char
if (!text) {
text = " ";
}
const isRTL = document.documentElement.getAttribute("dir") === "rtl"; const isRTL = document.documentElement.getAttribute("dir") === "rtl";
const textarea = document.createElement("textarea"); const textarea = document.createElement("textarea");
+68 -115
View File
@@ -1,7 +1,7 @@
import React, { useState } from "react"; import React, { useState } from "react";
import { ActionManager } from "../actions/manager"; import { ActionManager } from "../actions/manager";
import { getNonDeletedElements } from "../element"; import { getNonDeletedElements } from "../element";
import { ExcalidrawElement, PointerType } from "../element/types"; import { ExcalidrawElement } from "../element/types";
import { t } from "../i18n"; import { t } from "../i18n";
import { useDevice } from "../components/App"; import { useDevice } from "../components/App";
import { import {
@@ -11,7 +11,6 @@ import {
hasBackground, hasBackground,
hasStrokeStyle, hasStrokeStyle,
hasStrokeWidth, hasStrokeWidth,
hasText,
} from "../scene"; } from "../scene";
import { SHAPES } from "../shapes"; import { SHAPES } from "../shapes";
import { AppClassProperties, UIAppState, Zoom } from "../types"; import { AppClassProperties, UIAppState, Zoom } from "../types";
@@ -20,7 +19,7 @@ import Stack from "./Stack";
import { ToolButton } from "./ToolButton"; import { ToolButton } from "./ToolButton";
import { hasStrokeColor } from "../scene/comparisons"; import { hasStrokeColor } from "../scene/comparisons";
import { trackEvent } from "../analytics"; import { trackEvent } from "../analytics";
import { hasBoundTextElement } from "../element/typeChecks"; import { hasBoundTextElement, isTextElement } from "../element/typeChecks";
import clsx from "clsx"; import clsx from "clsx";
import { actionToggleZenMode } from "../actions"; import { actionToggleZenMode } from "../actions";
import { Tooltip } from "./Tooltip"; import { Tooltip } from "./Tooltip";
@@ -35,6 +34,7 @@ import {
EmbedIcon, EmbedIcon,
extraToolsIcon, extraToolsIcon,
frameToolIcon, frameToolIcon,
mermaidLogoIcon,
laserPointerToolIcon, laserPointerToolIcon,
} from "./icons"; } from "./icons";
import { KEYS } from "../keys"; import { KEYS } from "../keys";
@@ -66,7 +66,8 @@ export const SelectedShapeActions = ({
const isRTL = document.documentElement.getAttribute("dir") === "rtl"; const isRTL = document.documentElement.getAttribute("dir") === "rtl";
const showFillIcons = const showFillIcons =
hasBackground(appState.activeTool.type) || (hasBackground(appState.activeTool.type) &&
!isTransparent(appState.currentItemBackgroundColor)) ||
targetElements.some( targetElements.some(
(element) => (element) =>
hasBackground(element.type) && !isTransparent(element.backgroundColor), hasBackground(element.type) && !isTransparent(element.backgroundColor),
@@ -123,14 +124,15 @@ export const SelectedShapeActions = ({
<>{renderAction("changeRoundness")}</> <>{renderAction("changeRoundness")}</>
)} )}
{(hasText(appState.activeTool.type) || {(appState.activeTool.type === "text" ||
targetElements.some((element) => hasText(element.type))) && ( targetElements.some(isTextElement)) && (
<> <>
{renderAction("changeFontSize")} {renderAction("changeFontSize")}
{renderAction("changeFontFamily")} {renderAction("changeFontFamily")}
{suppportsHorizontalAlign(targetElements) && {(appState.activeTool.type === "text" ||
suppportsHorizontalAlign(targetElements)) &&
renderAction("changeTextAlign")} renderAction("changeTextAlign")}
</> </>
)} )}
@@ -213,20 +215,15 @@ export const SelectedShapeActions = ({
}; };
export const ShapesSwitcher = ({ export const ShapesSwitcher = ({
interactiveCanvas,
activeTool, activeTool,
onImageAction,
appState, appState,
app, app,
}: { }: {
interactiveCanvas: HTMLCanvasElement | null;
activeTool: UIAppState["activeTool"]; activeTool: UIAppState["activeTool"];
onImageAction: (data: { pointerType: PointerType | null }) => void;
appState: UIAppState; appState: UIAppState;
app: AppClassProperties; app: AppClassProperties;
}) => { }) => {
const [isExtraToolsMenuOpen, setIsExtraToolsMenuOpen] = useState(false); const [isExtraToolsMenuOpen, setIsExtraToolsMenuOpen] = useState(false);
const device = useDevice();
const frameToolSelected = activeTool.type === "frame"; const frameToolSelected = activeTool.type === "frame";
const laserToolSelected = activeTool.type === "laser"; const laserToolSelected = activeTool.type === "laser";
@@ -263,120 +260,76 @@ export const ShapesSwitcher = ({
if (appState.activeTool.type !== value) { if (appState.activeTool.type !== value) {
trackEvent("toolbar", value, "ui"); trackEvent("toolbar", value, "ui");
} }
app.setActiveTool({ type: value });
if (value === "image") { if (value === "image") {
onImageAction({ pointerType }); app.setActiveTool({
type: value,
insertOnCanvasDirectly: pointerType !== "mouse",
});
} else {
app.setActiveTool({ type: value });
} }
}} }}
/> />
); );
})} })}
<div className="App-toolbar__divider" /> <div className="App-toolbar__divider" />
{/* TEMP HACK because dropdown doesn't work well inside mobile toolbar */}
{device.isMobile ? ( <DropdownMenu open={isExtraToolsMenuOpen}>
<> <DropdownMenu.Trigger
<ToolButton className={clsx("App-toolbar__extra-tools-trigger", {
className={clsx("Shape", { fillable: false })} "App-toolbar__extra-tools-trigger--selected":
type="radio" frameToolSelected ||
embeddableToolSelected ||
// in collab we're already highlighting the laser button
// outside toolbar, so let's not highlight extra-tools button
// on top of it
(laserToolSelected && !app.props.isCollaborating),
})}
onToggle={() => setIsExtraToolsMenuOpen(!isExtraToolsMenuOpen)}
title={t("toolBar.extraTools")}
>
{extraToolsIcon}
</DropdownMenu.Trigger>
<DropdownMenu.Content
onClickOutside={() => setIsExtraToolsMenuOpen(false)}
onSelect={() => setIsExtraToolsMenuOpen(false)}
className="App-toolbar__extra-tools-dropdown"
>
<DropdownMenu.Item
onSelect={() => app.setActiveTool({ type: "frame" })}
icon={frameToolIcon} icon={frameToolIcon}
checked={activeTool.type === "frame"} shortcut={KEYS.F.toLocaleUpperCase()}
name="editor-current-shape" data-testid="toolbar-frame"
title={`${capitalizeString( selected={frameToolSelected}
t("toolBar.frame"), >
)}${KEYS.F.toLocaleUpperCase()}`} {t("toolBar.frame")}
keyBindingLabel={KEYS.F.toLocaleUpperCase()} </DropdownMenu.Item>
aria-label={capitalizeString(t("toolBar.frame"))} <DropdownMenu.Item
aria-keyshortcuts={KEYS.F.toLocaleUpperCase()} onSelect={() => app.setActiveTool({ type: "embeddable" })}
data-testid={`toolbar-frame`}
onPointerDown={({ pointerType }) => {
if (!appState.penDetected && pointerType === "pen") {
app.togglePenMode(true);
}
}}
onChange={({ pointerType }) => {
trackEvent("toolbar", "frame", "ui");
app.setActiveTool({ type: "frame" });
}}
selected={activeTool.type === "frame"}
/>
<ToolButton
className={clsx("Shape", { fillable: false })}
type="radio"
icon={EmbedIcon} icon={EmbedIcon}
checked={activeTool.type === "embeddable"} data-testid="toolbar-embeddable"
name="editor-current-shape" selected={embeddableToolSelected}
title={capitalizeString(t("toolBar.embeddable"))}
aria-label={capitalizeString(t("toolBar.embeddable"))}
data-testid={`toolbar-embeddable`}
onPointerDown={({ pointerType }) => {
if (!appState.penDetected && pointerType === "pen") {
app.togglePenMode(true);
}
}}
onChange={({ pointerType }) => {
trackEvent("toolbar", "embeddable", "ui");
app.setActiveTool({ type: "embeddable" });
}}
selected={activeTool.type === "embeddable"}
/>
</>
) : (
<DropdownMenu open={isExtraToolsMenuOpen}>
<DropdownMenu.Trigger
className={clsx("App-toolbar__extra-tools-trigger", {
"App-toolbar__extra-tools-trigger--selected":
frameToolSelected ||
embeddableToolSelected ||
// in collab we're already highlighting the laser button
// outside toolbar, so let's not highlight extra-tools button
// on top of it
(laserToolSelected && !app.props.isCollaborating),
})}
onToggle={() => setIsExtraToolsMenuOpen(!isExtraToolsMenuOpen)}
title={t("toolBar.extraTools")}
> >
{extraToolsIcon} {t("toolBar.embeddable")}
</DropdownMenu.Trigger> </DropdownMenu.Item>
<DropdownMenu.Content <DropdownMenu.Item
onClickOutside={() => setIsExtraToolsMenuOpen(false)} onSelect={() => app.setActiveTool({ type: "laser" })}
onSelect={() => setIsExtraToolsMenuOpen(false)} icon={laserPointerToolIcon}
className="App-toolbar__extra-tools-dropdown" data-testid="toolbar-laser"
selected={laserToolSelected}
shortcut={KEYS.K.toLocaleUpperCase()}
> >
<DropdownMenu.Item {t("toolBar.laser")}
onSelect={() => { </DropdownMenu.Item>
app.setActiveTool({ type: "frame" }); <DropdownMenu.Item
}} onSelect={() => app.setOpenDialog("mermaid")}
icon={frameToolIcon} icon={mermaidLogoIcon}
shortcut={KEYS.F.toLocaleUpperCase()} data-testid="toolbar-embeddable"
data-testid="toolbar-frame" >
selected={frameToolSelected} {t("toolBar.mermaidToExcalidraw")}
> </DropdownMenu.Item>
{t("toolBar.frame")} </DropdownMenu.Content>
</DropdownMenu.Item> </DropdownMenu>
<DropdownMenu.Item
onSelect={() => {
app.setActiveTool({ type: "embeddable" });
}}
icon={EmbedIcon}
data-testid="toolbar-embeddable"
selected={embeddableToolSelected}
>
{t("toolBar.embeddable")}
</DropdownMenu.Item>
<DropdownMenu.Item
onSelect={() => {
app.setActiveTool({ type: "laser" });
}}
icon={laserPointerToolIcon}
data-testid="toolbar-laser"
selected={laserToolSelected}
shortcut={KEYS.K.toLocaleUpperCase()}
>
{t("toolBar.laser")}
</DropdownMenu.Item>
</DropdownMenu.Content>
</DropdownMenu>
)}
</> </>
); );
}; };
+497 -369
View File
File diff suppressed because it is too large Load Diff
+1
View File
@@ -55,6 +55,7 @@ export const TopPicks = ({
type="button" type="button"
title={color} title={color}
onClick={() => onChange(color)} onClick={() => onChange(color)}
data-testid={`color-top-pick-${color}`}
> >
<div className="color-picker__button-outline" /> <div className="color-picker__button-outline" />
</button> </button>
+7 -9
View File
@@ -9,11 +9,7 @@ import {
} from "../actions/shortcuts"; } from "../actions/shortcuts";
import { Action } from "../actions/types"; import { Action } from "../actions/types";
import { ActionManager } from "../actions/manager"; import { ActionManager } from "../actions/manager";
import { import { useExcalidrawAppState, useExcalidrawElements } from "./App";
useExcalidrawAppState,
useExcalidrawElements,
useExcalidrawSetAppState,
} from "./App";
import React from "react"; import React from "react";
export type ContextMenuItem = typeof CONTEXT_MENU_SEPARATOR | Action; export type ContextMenuItem = typeof CONTEXT_MENU_SEPARATOR | Action;
@@ -25,14 +21,14 @@ type ContextMenuProps = {
items: ContextMenuItems; items: ContextMenuItems;
top: number; top: number;
left: number; left: number;
onClose: (callback?: () => void) => void;
}; };
export const CONTEXT_MENU_SEPARATOR = "separator"; export const CONTEXT_MENU_SEPARATOR = "separator";
export const ContextMenu = React.memo( export const ContextMenu = React.memo(
({ actionManager, items, top, left }: ContextMenuProps) => { ({ actionManager, items, top, left, onClose }: ContextMenuProps) => {
const appState = useExcalidrawAppState(); const appState = useExcalidrawAppState();
const setAppState = useExcalidrawSetAppState();
const elements = useExcalidrawElements(); const elements = useExcalidrawElements();
const filteredItems = items.reduce((acc: ContextMenuItem[], item) => { const filteredItems = items.reduce((acc: ContextMenuItem[], item) => {
@@ -54,7 +50,9 @@ export const ContextMenu = React.memo(
return ( return (
<Popover <Popover
onCloseRequest={() => setAppState({ contextMenu: null })} onCloseRequest={() => {
onClose();
}}
top={top} top={top}
left={left} left={left}
fitInViewport={true} fitInViewport={true}
@@ -102,7 +100,7 @@ export const ContextMenu = React.memo(
// we need update state before executing the action in case // we need update state before executing the action in case
// the action uses the appState it's being passed (that still // the action uses the appState it's being passed (that still
// contains a defined contextMenu) to return the next state. // contains a defined contextMenu) to return the next state.
setAppState({ contextMenu: null }, () => { onClose(() => {
actionManager.executeAction(item, "contextMenu"); actionManager.executeAction(item, "contextMenu");
}); });
}} }}
+1 -2
View File
@@ -82,9 +82,8 @@ const getHints = ({ appState, isMobile, device, app }: HintViewerProps) => {
if (activeTool.type === "selection") { if (activeTool.type === "selection") {
if ( if (
appState.selectionElement && appState.draggingElement?.type === "selection" &&
!selectedElements.length && !selectedElements.length &&
!appState.draggingElement &&
!appState.editingElement && !appState.editingElement &&
!appState.editingLinearElement !appState.editingLinearElement
) { ) {
+12 -3
View File
@@ -23,12 +23,15 @@ export type ExportCB = (
const JSONExportModal = ({ const JSONExportModal = ({
elements, elements,
appState, appState,
setAppState,
files, files,
actionManager, actionManager,
exportOpts, exportOpts,
canvas, canvas,
onCloseRequest,
}: { }: {
appState: UIAppState; appState: UIAppState;
setAppState: React.Component<any, UIAppState>["setState"];
files: BinaryFiles; files: BinaryFiles;
elements: readonly NonDeletedExcalidrawElement[]; elements: readonly NonDeletedExcalidrawElement[];
actionManager: ActionManager; actionManager: ActionManager;
@@ -72,9 +75,14 @@ const JSONExportModal = ({
title={t("exportDialog.link_button")} title={t("exportDialog.link_button")}
aria-label={t("exportDialog.link_button")} aria-label={t("exportDialog.link_button")}
showAriaLabel={true} showAriaLabel={true}
onClick={() => { onClick={async () => {
onExportToBackend(elements, appState, files, canvas); try {
trackEvent("export", "link", `ui (${getFrame()})`); trackEvent("export", "link", `ui (${getFrame()})`);
await onExportToBackend(elements, appState, files, canvas);
onCloseRequest();
} catch (error: any) {
setAppState({ errorMessage: error.message });
}
}} }}
/> />
</Card> </Card>
@@ -114,6 +122,7 @@ export const JSONExportDialog = ({
<JSONExportModal <JSONExportModal
elements={elements} elements={elements}
appState={appState} appState={appState}
setAppState={setAppState}
files={files} files={files}
actionManager={actionManager} actionManager={actionManager}
onCloseRequest={handleClose} onCloseRequest={handleClose}
+2 -24
View File
@@ -62,7 +62,6 @@ interface LayerUIProps {
appState: UIAppState; appState: UIAppState;
files: BinaryFiles; files: BinaryFiles;
canvas: HTMLCanvasElement; canvas: HTMLCanvasElement;
interactiveCanvas: HTMLCanvasElement | null;
setAppState: React.Component<any, AppState>["setState"]; setAppState: React.Component<any, AppState>["setState"];
elements: readonly NonDeletedExcalidrawElement[]; elements: readonly NonDeletedExcalidrawElement[];
onLockToggle: () => void; onLockToggle: () => void;
@@ -73,7 +72,6 @@ interface LayerUIProps {
renderTopRightUI?: ExcalidrawProps["renderTopRightUI"]; renderTopRightUI?: ExcalidrawProps["renderTopRightUI"];
renderCustomStats?: ExcalidrawProps["renderCustomStats"]; renderCustomStats?: ExcalidrawProps["renderCustomStats"];
UIOptions: AppProps["UIOptions"]; UIOptions: AppProps["UIOptions"];
onImageAction: (data: { insertOnCanvasDirectly: boolean }) => void;
onExportImage: AppClassProperties["onExportImage"]; onExportImage: AppClassProperties["onExportImage"];
renderWelcomeScreen: boolean; renderWelcomeScreen: boolean;
children?: React.ReactNode; children?: React.ReactNode;
@@ -123,7 +121,6 @@ const LayerUI = ({
setAppState, setAppState,
elements, elements,
canvas, canvas,
interactiveCanvas,
onLockToggle, onLockToggle,
onHandToolToggle, onHandToolToggle,
onPenModeToggle, onPenModeToggle,
@@ -131,7 +128,6 @@ const LayerUI = ({
renderTopRightUI, renderTopRightUI,
renderCustomStats, renderCustomStats,
UIOptions, UIOptions,
onImageAction,
onExportImage, onExportImage,
renderWelcomeScreen, renderWelcomeScreen,
children, children,
@@ -280,14 +276,8 @@ const LayerUI = ({
<ShapesSwitcher <ShapesSwitcher
appState={appState} appState={appState}
interactiveCanvas={interactiveCanvas}
activeTool={appState.activeTool} activeTool={appState.activeTool}
app={app} app={app}
onImageAction={({ pointerType }) => {
onImageAction({
insertOnCanvasDirectly: pointerType !== "mouse",
});
}}
/> />
</Stack.Row> </Stack.Row>
</Island> </Island>
@@ -472,8 +462,6 @@ const LayerUI = ({
onLockToggle={onLockToggle} onLockToggle={onLockToggle}
onHandToolToggle={onHandToolToggle} onHandToolToggle={onHandToolToggle}
onPenModeToggle={onPenModeToggle} onPenModeToggle={onPenModeToggle}
interactiveCanvas={interactiveCanvas}
onImageAction={onImageAction}
renderTopRightUI={renderTopRightUI} renderTopRightUI={renderTopRightUI}
renderCustomStats={renderCustomStats} renderCustomStats={renderCustomStats}
renderSidebars={renderSidebars} renderSidebars={renderSidebars}
@@ -560,18 +548,8 @@ const areEqual = (prevProps: LayerUIProps, nextProps: LayerUIProps) => {
return false; return false;
} }
const { const { canvas: _pC, appState: prevAppState, ...prev } = prevProps;
canvas: _pC, const { canvas: _nC, appState: nextAppState, ...next } = nextProps;
interactiveCanvas: _pIC,
appState: prevAppState,
...prev
} = prevProps;
const {
canvas: _nC,
interactiveCanvas: _nIC,
appState: nextAppState,
...next
} = nextProps;
return ( return (
isShallowEqual( isShallowEqual(
+221
View File
@@ -0,0 +1,221 @@
@import "../css/variables.module";
$verticalBreakpoint: 860px;
.excalidraw {
.dialog-mermaid {
&-title {
margin-bottom: 5px;
margin-top: 2px;
}
&-desc {
font-size: 15px;
font-style: italic;
font-weight: 500;
}
.Modal__content .Island {
box-shadow: none;
}
@at-root .excalidraw:not(.excalidraw--mobile)#{&} {
padding: 1.25rem;
.Modal__content {
height: 100%;
max-height: 750px;
@media screen and (max-width: $verticalBreakpoint) {
height: auto;
// When vertical, we want the height to span whole viewport.
// This is also important for the children not to overflow the
// modal/viewport (for some reason).
max-height: 100%;
}
.Island {
height: 100%;
display: flex;
flex-direction: column;
flex: 1 1 auto;
.Dialog__content {
display: flex;
flex: 1 1 auto;
}
}
}
}
}
.dialog-mermaid-body {
width: 100%;
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-rows: 1fr auto;
height: 100%;
column-gap: 4rem;
@media screen and (max-width: $verticalBreakpoint) {
flex-direction: column;
display: flex;
gap: 1rem;
}
}
.dialog-mermaid-panels {
display: grid;
width: 100%;
grid-template-columns: 1fr 1fr;
justify-content: space-between;
gap: 4rem;
grid-row: 1;
grid-column: 1 / 3;
@media screen and (max-width: $verticalBreakpoint) {
flex-direction: column;
display: flex;
gap: 1rem;
}
label {
font-size: 14px;
font-style: normal;
font-weight: 600;
margin-bottom: 4px;
margin-left: 4px;
@media screen and (max-width: $verticalBreakpoint) {
margin-top: 4px;
}
}
&-text {
display: flex;
flex-direction: column;
textarea {
width: 20rem;
height: 100%;
resize: none;
border-radius: var(--border-radius-lg);
border: 1px solid var(--dialog-border-color);
white-space: pre-wrap;
padding: 0.85rem;
box-sizing: border-box;
width: 100%;
font-family: monospace;
@media screen and (max-width: $verticalBreakpoint) {
width: auto;
height: 10rem;
}
}
}
&-preview-wrapper {
display: flex;
align-items: center;
justify-content: center;
padding: 0.85rem;
box-sizing: border-box;
width: 100%;
// acts as min-height
height: 200px;
flex-grow: 1;
position: relative;
background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAMUlEQVQ4T2NkYGAQYcAP3uCTZhw1gGGYhAGBZIA/nYDCgBDAm9BGDWAAJyRCgLaBCAAgXwixzAS0pgAAAABJRU5ErkJggg==")
left center;
border-radius: var(--border-radius-lg);
border: 1px solid var(--dialog-border-color);
@media screen and (max-width: $verticalBreakpoint) {
// acts as min-height
height: 400px;
width: auto;
}
canvas {
max-width: 100%;
max-height: 100%;
}
}
&-preview-canvas-container {
display: flex;
width: 100%;
height: 100%;
align-items: center;
justify-content: center;
flex-grow: 1;
}
&-preview {
display: flex;
flex-direction: column;
}
.mermaid-error {
color: red;
font-weight: 800;
font-size: 30px;
word-break: break-word;
overflow: auto;
max-height: 100%;
height: 100%;
width: 100%;
text-align: center;
position: absolute;
z-index: 10;
p {
font-weight: 500;
font-family: Cascadia;
text-align: left;
white-space: pre-wrap;
font-size: 0.875rem;
padding: 0 10px;
}
}
}
.dialog-mermaid-buttons {
grid-column: 2;
.dialog-mermaid-insert {
&.excalidraw-button {
font-family: "Assistant";
font-weight: 600;
height: 2.5rem;
margin-top: 1em;
margin-bottom: 0.3em;
width: 7.5rem;
font-size: 12px;
color: $oc-white;
background-color: var(--color-primary);
&:hover {
background-color: var(--color-primary-darker);
}
&:active {
background-color: var(--color-primary-darkest);
}
@media screen and (max-width: $verticalBreakpoint) {
width: 100%;
}
@at-root .excalidraw.theme--dark#{&} {
color: var(--color-gray-100);
}
}
span {
padding-left: 0.5rem;
display: flex;
}
}
}
}
+243
View File
@@ -0,0 +1,243 @@
import { useState, useRef, useEffect, useDeferredValue } from "react";
import { BinaryFiles } from "../types";
import { useApp } from "./App";
import { Button } from "./Button";
import { Dialog } from "./Dialog";
import { DEFAULT_EXPORT_PADDING, DEFAULT_FONT_SIZE } from "../constants";
import {
convertToExcalidrawElements,
exportToCanvas,
} from "../packages/excalidraw/index";
import { NonDeletedExcalidrawElement } from "../element/types";
import { canvasToBlob } from "../data/blob";
import { ArrowRightIcon } from "./icons";
import Spinner from "./Spinner";
import "./MermaidToExcalidraw.scss";
import { MermaidToExcalidrawResult } from "@excalidraw/mermaid-to-excalidraw/dist/interfaces";
import type { MermaidOptions } from "@excalidraw/mermaid-to-excalidraw";
import { t } from "../i18n";
import Trans from "./Trans";
const LOCAL_STORAGE_KEY_MERMAID_TO_EXCALIDRAW = "mermaid-to-excalidraw";
const MERMAID_EXAMPLE =
"flowchart TD\n A[Christmas] -->|Get money| B(Go shopping)\n B --> C{Let me think}\n C -->|One| D[Laptop]\n C -->|Two| E[iPhone]\n C -->|Three| F[Car]";
const saveMermaidDataToStorage = (data: string) => {
try {
localStorage.setItem(LOCAL_STORAGE_KEY_MERMAID_TO_EXCALIDRAW, data);
} catch (error: any) {
// Unable to access window.localStorage
console.error(error);
}
};
const importMermaidDataFromStorage = () => {
try {
const data = localStorage.getItem(LOCAL_STORAGE_KEY_MERMAID_TO_EXCALIDRAW);
if (data) {
return data;
}
} catch (error: any) {
// Unable to access localStorage
console.error(error);
}
return null;
};
const ErrorComp = ({ error }: { error: string }) => {
return (
<div data-testid="mermaid-error" className="mermaid-error">
Error! <p>{error}</p>
</div>
);
};
const MermaidToExcalidraw = () => {
const [mermaidToExcalidrawLib, setMermaidToExcalidrawLib] = useState<{
loaded: boolean;
api: {
parseMermaidToExcalidraw: (
defination: string,
options: MermaidOptions,
) => Promise<MermaidToExcalidrawResult>;
} | null;
}>({ loaded: false, api: null });
const [text, setText] = useState("");
const deferredText = useDeferredValue(text.trim());
const [error, setError] = useState(null);
const canvasRef = useRef<HTMLDivElement>(null);
const data = useRef<{
elements: readonly NonDeletedExcalidrawElement[];
files: BinaryFiles | null;
}>({ elements: [], files: null });
const app = useApp();
const resetPreview = () => {
const canvasNode = canvasRef.current;
if (!canvasNode) {
return;
}
const parent = canvasNode.parentElement;
if (!parent) {
return;
}
parent.style.background = "";
setError(null);
canvasNode.replaceChildren();
};
useEffect(() => {
const loadMermaidToExcalidrawLib = async () => {
const api = await import(
/* webpackChunkName:"mermaid-to-excalidraw" */ "@excalidraw/mermaid-to-excalidraw"
);
setMermaidToExcalidrawLib({ loaded: true, api });
};
loadMermaidToExcalidrawLib();
}, []);
useEffect(() => {
const data = importMermaidDataFromStorage() || MERMAID_EXAMPLE;
setText(data);
}, []);
useEffect(() => {
const renderExcalidrawPreview = async () => {
const canvasNode = canvasRef.current;
const parent = canvasNode?.parentElement;
if (
!mermaidToExcalidrawLib.loaded ||
!canvasNode ||
!parent ||
!mermaidToExcalidrawLib.api
) {
return;
}
if (!deferredText) {
resetPreview();
return;
}
try {
const { elements, files } =
await mermaidToExcalidrawLib.api.parseMermaidToExcalidraw(
deferredText,
{
fontSize: DEFAULT_FONT_SIZE,
},
);
setError(null);
data.current = {
elements: convertToExcalidrawElements(elements, {
regenerateIds: true,
}),
files,
};
const canvas = await exportToCanvas({
elements: data.current.elements,
files: data.current.files,
exportPadding: DEFAULT_EXPORT_PADDING,
maxWidthOrHeight:
Math.max(parent.offsetWidth, parent.offsetHeight) *
window.devicePixelRatio,
});
// if converting to blob fails, there's some problem that will
// likely prevent preview and export (e.g. canvas too big)
await canvasToBlob(canvas);
parent.style.background = "var(--default-bg-color)";
canvasNode.replaceChildren(canvas);
} catch (e: any) {
parent.style.background = "var(--default-bg-color)";
if (deferredText) {
setError(e.message);
}
}
};
renderExcalidrawPreview();
}, [deferredText, mermaidToExcalidrawLib]);
const onClose = () => {
app.setOpenDialog(null);
saveMermaidDataToStorage(text);
};
const onSelect = () => {
const { elements: newElements, files } = data.current;
app.addElementsFromPasteOrLibrary({
elements: newElements,
files,
position: "center",
fitToContent: true,
});
onClose();
};
return (
<Dialog
className="dialog-mermaid"
onCloseRequest={onClose}
size={1200}
title={
<>
<p className="dialog-mermaid-title">{t("mermaid.title")}</p>
<span className="dialog-mermaid-desc">
<Trans
i18nKey="mermaid.description"
flowchartLink={(el) => (
<a href="https://mermaid.js.org/syntax/flowchart.html">{el}</a>
)}
sequenceLink={(el) => (
<a href="https://mermaid.js.org/syntax/sequenceDiagram.html">
{el}
</a>
)}
/>
<br />
</span>
</>
}
>
<div className="dialog-mermaid-body">
<div className="dialog-mermaid-panels">
<div className="dialog-mermaid-panels-text">
<label>{t("mermaid.syntax")}</label>
<textarea
onChange={(event) => setText(event.target.value)}
value={text}
/>
</div>
<div className="dialog-mermaid-panels-preview">
<label>{t("mermaid.preview")}</label>
<div className="dialog-mermaid-panels-preview-wrapper">
{error && <ErrorComp error={error} />}
{mermaidToExcalidrawLib.loaded ? (
<div
ref={canvasRef}
style={{ opacity: error ? "0.15" : 1 }}
className="dialog-mermaid-panels-preview-canvas-container"
/>
) : (
<Spinner size="2rem" />
)}
</div>
</div>
</div>
<div className="dialog-mermaid-buttons">
<Button className="dialog-mermaid-insert" onSelect={onSelect}>
{t("mermaid.button")}
<span>{ArrowRightIcon}</span>
</Button>
</div>
</div>
</Dialog>
);
};
export default MermaidToExcalidraw;
+1 -10
View File
@@ -36,9 +36,7 @@ type MobileMenuProps = {
onLockToggle: () => void; onLockToggle: () => void;
onHandToolToggle: () => void; onHandToolToggle: () => void;
onPenModeToggle: () => void; onPenModeToggle: () => void;
interactiveCanvas: HTMLCanvasElement | null;
onImageAction: (data: { insertOnCanvasDirectly: boolean }) => void;
renderTopRightUI?: ( renderTopRightUI?: (
isMobile: boolean, isMobile: boolean,
appState: UIAppState, appState: UIAppState,
@@ -58,8 +56,7 @@ export const MobileMenu = ({
onLockToggle, onLockToggle,
onHandToolToggle, onHandToolToggle,
onPenModeToggle, onPenModeToggle,
interactiveCanvas,
onImageAction,
renderTopRightUI, renderTopRightUI,
renderCustomStats, renderCustomStats,
renderSidebars, renderSidebars,
@@ -85,14 +82,8 @@ export const MobileMenu = ({
<Stack.Row gap={1}> <Stack.Row gap={1}>
<ShapesSwitcher <ShapesSwitcher
appState={appState} appState={appState}
interactiveCanvas={interactiveCanvas}
activeTool={appState.activeTool} activeTool={appState.activeTool}
app={app} app={app}
onImageAction={({ pointerType }) => {
onImageAction({
insertOnCanvasDirectly: pointerType !== "mouse",
});
}}
/> />
</Stack.Row> </Stack.Row>
</Island> </Island>
+5 -5
View File
@@ -83,12 +83,12 @@ export const ToolButton = React.forwardRef((props: ToolButtonProps, ref) => {
} }
}; };
useEffect( useEffect(() => {
() => () => { isMountedRef.current = true;
return () => {
isMountedRef.current = false; isMountedRef.current = false;
}, };
[], }, []);
);
const lastPointerTypeRef = useRef<PointerType | null>(null); const lastPointerTypeRef = useRef<PointerType | null>(null);
+9
View File
@@ -160,6 +160,15 @@
width: var(--lg-button-size); width: var(--lg-button-size);
height: var(--lg-button-size); height: var(--lg-button-size);
@media screen and (max-width: 450px) {
width: 1.8rem;
height: 1.8rem;
}
@media screen and (max-width: 379px) {
width: 1.5rem;
height: 1.5rem;
}
svg { svg {
width: var(--lg-icon-size); width: var(--lg-icon-size);
height: var(--lg-icon-size); height: var(--lg-icon-size);
+5
View File
@@ -16,6 +16,10 @@
align-self: center; align-self: center;
background-color: var(--default-border-color); background-color: var(--default-border-color);
margin: 0 0.25rem; margin: 0 0.25rem;
@include isMobile {
margin: 0;
}
} }
} }
@@ -41,5 +45,6 @@
margin-top: 0.375rem; margin-top: 0.375rem;
right: 0; right: 0;
min-width: 11.875rem; min-width: 11.875rem;
z-index: 1;
} }
} }
@@ -7,8 +7,6 @@
margin-top: 0.25rem; margin-top: 0.25rem;
&--mobile { &--mobile {
bottom: 55px;
top: auto;
left: 0; left: 0;
width: 100%; width: 100%;
row-gap: 0.75rem; row-gap: 0.75rem;
+16
View File
@@ -1654,6 +1654,22 @@ export const frameToolIcon = createIcon(
tablerIconProps, tablerIconProps,
); );
export const mermaidLogoIcon = createIcon(
<path
fill="currentColor"
d="M407.48,111.18C335.587,108.103 269.573,152.338 245.08,220C220.587,152.338 154.573,108.103 82.68,111.18C80.285,168.229 107.577,222.632 154.74,254.82C178.908,271.419 193.35,298.951 193.27,328.27L193.27,379.13L296.9,379.13L296.9,328.27C296.816,298.953 311.255,271.42 335.42,254.82C382.596,222.644 409.892,168.233 407.48,111.18Z"
/>,
);
export const ArrowRightIcon = createIcon(
<g strokeWidth="1.25">
<path d="M4.16602 10H15.8327" />
<path d="M12.5 13.3333L15.8333 10" />
<path d="M12.5 6.66666L15.8333 9.99999" />
</g>,
modifiedTablerIconProps,
);
export const laserPointerToolIcon = createIcon( export const laserPointerToolIcon = createIcon(
<g <g
fill="none" fill="none"
+17 -3
View File
@@ -148,6 +148,8 @@ export const IMAGE_MIME_TYPES = {
jfif: "image/jfif", jfif: "image/jfif",
} as const; } as const;
export const ALLOWED_PASTE_MIME_TYPES = ["text/plain", "text/html"] as const;
export const MIME_TYPES = { export const MIME_TYPES = {
json: "application/json", json: "application/json",
// excalidraw data // excalidraw data
@@ -296,6 +298,18 @@ export const ROUNDNESS = {
* collaboration */ * collaboration */
export const PRECEDING_ELEMENT_KEY = "__precedingElement__"; export const PRECEDING_ELEMENT_KEY = "__precedingElement__";
export const ROUGHNESS = {
architect: 0,
artist: 1,
cartoonist: 2,
} as const;
export const STROKE_WIDTH = {
thin: 1,
bold: 2,
extraBold: 4,
} as const;
export const DEFAULT_ELEMENT_PROPS: { export const DEFAULT_ELEMENT_PROPS: {
strokeColor: ExcalidrawElement["strokeColor"]; strokeColor: ExcalidrawElement["strokeColor"];
backgroundColor: ExcalidrawElement["backgroundColor"]; backgroundColor: ExcalidrawElement["backgroundColor"];
@@ -308,10 +322,10 @@ export const DEFAULT_ELEMENT_PROPS: {
} = { } = {
strokeColor: COLOR_PALETTE.black, strokeColor: COLOR_PALETTE.black,
backgroundColor: COLOR_PALETTE.transparent, backgroundColor: COLOR_PALETTE.transparent,
fillStyle: "hachure", fillStyle: "solid",
strokeWidth: 1, strokeWidth: 2,
strokeStyle: "solid", strokeStyle: "solid",
roughness: 1, roughness: ROUGHNESS.artist,
opacity: 100, opacity: 100,
locked: false, locked: false,
}; };
+12 -5
View File
@@ -195,7 +195,7 @@
.buttonList label:focus-within, .buttonList label:focus-within,
input:focus-visible { input:focus-visible {
outline: transparent; outline: transparent;
box-shadow: 0 0 0 2px var(--focus-highlight-color); box-shadow: 0 0 0 1px var(--color-brand-hover);
} }
.buttonList { .buttonList {
@@ -280,6 +280,11 @@
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
padding: 8px; padding: 8px;
.dropdown-menu--mobile {
bottom: 55px;
top: auto;
}
} }
.App-mobile-menu { .App-mobile-menu {
@@ -537,13 +542,13 @@
&:not(:focus) { &:not(:focus) {
&:hover { &:hover {
background-color: var(--input-hover-bg-color); border-color: var(--color-brand-hover);
} }
} }
&:focus { &:focus {
outline: none; outline: none;
box-shadow: 0 0 0 2px var(--focus-highlight-color); border-color: var(--color-brand-hover);
} }
} }
@@ -592,6 +597,8 @@
background-color: var(--island-bg-color); background-color: var(--island-bg-color);
.ToolIcon__icon { .ToolIcon__icon {
width: 2rem;
height: 2rem;
border-radius: 0; border-radius: 0;
} }
@@ -601,8 +608,8 @@
} }
.App-toolbar--mobile { .App-toolbar--mobile {
overflow-x: auto; overflow: visible;
max-width: 90vw; max-width: 98vw;
.ToolIcon__keybinding { .ToolIcon__keybinding {
display: none; display: none;
+2
View File
@@ -99,5 +99,7 @@ export const setCursorForShape = (
interactiveCanvas.style.cursor = `url(${url}), auto`; interactiveCanvas.style.cursor = `url(${url}), auto`;
} else if (!["image", "custom"].includes(appState.activeTool.type)) { } else if (!["image", "custom"].includes(appState.activeTool.type)) {
interactiveCanvas.style.cursor = CURSOR_TYPE.CROSSHAIR; interactiveCanvas.style.cursor = CURSOR_TYPE.CROSSHAIR;
} else {
interactiveCanvas.style.cursor = CURSOR_TYPE.AUTO;
} }
}; };
File diff suppressed because it is too large Load Diff
+31 -3
View File
@@ -8,7 +8,7 @@ import { t } from "../i18n";
import { calculateScrollCenter } from "../scene"; import { calculateScrollCenter } from "../scene";
import { AppState, DataURL, LibraryItem } from "../types"; import { AppState, DataURL, LibraryItem } from "../types";
import { ValueOf } from "../utility-types"; import { ValueOf } from "../utility-types";
import { bytesToHexString } from "../utils"; import { bytesToHexString, isPromiseLike } from "../utils";
import { FileSystemHandle, nativeFileSystemSupported } from "./filesystem"; import { FileSystemHandle, nativeFileSystemSupported } from "./filesystem";
import { isValidExcalidrawData, isValidLibrary } from "./json"; import { isValidExcalidrawData, isValidLibrary } from "./json";
import { restore, restoreLibraryItems } from "./restore"; import { restore, restoreLibraryItems } from "./restore";
@@ -207,10 +207,13 @@ export const loadLibraryFromBlob = async (
}; };
export const canvasToBlob = async ( export const canvasToBlob = async (
canvas: HTMLCanvasElement, canvas: HTMLCanvasElement | Promise<HTMLCanvasElement>,
): Promise<Blob> => { ): Promise<Blob> => {
return new Promise((resolve, reject) => { return new Promise(async (resolve, reject) => {
try { try {
if (isPromiseLike(canvas)) {
canvas = await canvas;
}
canvas.toBlob((blob) => { canvas.toBlob((blob) => {
if (!blob) { if (!blob) {
return reject( return reject(
@@ -324,6 +327,31 @@ export const SVGStringToFile = (SVGString: string, filename: string = "") => {
}) as File & { type: typeof MIME_TYPES.svg }; }) as File & { type: typeof MIME_TYPES.svg };
}; };
export const ImageURLToFile = async (
imageUrl: string,
filename: string = "",
): Promise<File | undefined> => {
let response;
try {
response = await fetch(imageUrl);
} catch (error: any) {
throw new Error(t("errors.failedToFetchImage"));
}
if (!response.ok) {
throw new Error(t("errors.failedToFetchImage"));
}
const blob = await response.blob();
if (blob.type && isSupportedImageFile(blob)) {
const name = filename || blob.name || "";
return new File([blob], name, { type: blob.type });
}
throw new Error(t("errors.unsupportedFileType"));
};
export const getFileFromEvent = async ( export const getFileFromEvent = async (
event: React.DragEvent<HTMLDivElement>, event: React.DragEvent<HTMLDivElement>,
) => { ) => {
+1 -7
View File
@@ -66,17 +66,14 @@ export const exportCanvas = async (
} }
} }
const tempCanvas = await exportToCanvas(elements, appState, files, { const tempCanvas = exportToCanvas(elements, appState, files, {
exportBackground, exportBackground,
viewBackgroundColor, viewBackgroundColor,
exportPadding, exportPadding,
}); });
tempCanvas.style.display = "none";
document.body.appendChild(tempCanvas);
if (type === "png") { if (type === "png") {
let blob = await canvasToBlob(tempCanvas); let blob = await canvasToBlob(tempCanvas);
tempCanvas.remove();
if (appState.exportEmbedScene) { if (appState.exportEmbedScene) {
blob = await ( blob = await (
await import(/* webpackChunkName: "image" */ "./image") await import(/* webpackChunkName: "image" */ "./image")
@@ -114,11 +111,8 @@ export const exportCanvas = async (
} else { } else {
throw new Error(t("alerts.couldNotCopyToClipboard")); throw new Error(t("alerts.couldNotCopyToClipboard"));
} }
} finally {
tempCanvas.remove();
} }
} else { } else {
tempCanvas.remove();
// shouldn't happen // shouldn't happen
throw new Error("Unsupported export type"); throw new Error("Unsupported export type");
} }
+128 -9
View File
@@ -5,7 +5,31 @@ import {
} from "./transform"; } from "./transform";
import { ExcalidrawArrowElement } from "../element/types"; import { ExcalidrawArrowElement } from "../element/types";
const opts = { regenerateIds: false };
describe("Test Transform", () => { describe("Test Transform", () => {
it("should generate id unless opts.regenerateIds is set to false explicitly", () => {
const elements = [
{
type: "rectangle",
x: 100,
y: 100,
id: "rect-1",
},
];
let data = convertToExcalidrawElements(
elements as ExcalidrawElementSkeleton[],
);
expect(data.length).toBe(1);
expect(data[0].id).toBe("id0");
data = convertToExcalidrawElements(
elements as ExcalidrawElementSkeleton[],
opts,
);
expect(data[0].id).toBe("rect-1");
});
it("should transform regular shapes", () => { it("should transform regular shapes", () => {
const elements = [ const elements = [
{ {
@@ -59,6 +83,7 @@ describe("Test Transform", () => {
convertToExcalidrawElements( convertToExcalidrawElements(
elements as ExcalidrawElementSkeleton[], elements as ExcalidrawElementSkeleton[],
opts,
).forEach((ele) => { ).forEach((ele) => {
expect(ele).toMatchSnapshot({ expect(ele).toMatchSnapshot({
seed: expect.any(Number), seed: expect.any(Number),
@@ -87,6 +112,7 @@ describe("Test Transform", () => {
]; ];
convertToExcalidrawElements( convertToExcalidrawElements(
elements as ExcalidrawElementSkeleton[], elements as ExcalidrawElementSkeleton[],
opts,
).forEach((ele) => { ).forEach((ele) => {
expect(ele).toMatchSnapshot({ expect(ele).toMatchSnapshot({
seed: expect.any(Number), seed: expect.any(Number),
@@ -128,6 +154,7 @@ describe("Test Transform", () => {
]; ];
const excaldrawElements = convertToExcalidrawElements( const excaldrawElements = convertToExcalidrawElements(
elements as ExcalidrawElementSkeleton[], elements as ExcalidrawElementSkeleton[],
opts,
); );
expect(excaldrawElements.length).toBe(4); expect(excaldrawElements.length).toBe(4);
@@ -210,6 +237,7 @@ describe("Test Transform", () => {
]; ];
const excaldrawElements = convertToExcalidrawElements( const excaldrawElements = convertToExcalidrawElements(
elements as ExcalidrawElementSkeleton[], elements as ExcalidrawElementSkeleton[],
opts,
); );
expect(excaldrawElements.length).toBe(12); expect(excaldrawElements.length).toBe(12);
@@ -267,6 +295,7 @@ describe("Test Transform", () => {
]; ];
const excaldrawElements = convertToExcalidrawElements( const excaldrawElements = convertToExcalidrawElements(
elements as ExcalidrawElementSkeleton[], elements as ExcalidrawElementSkeleton[],
opts,
); );
expect(excaldrawElements.length).toBe(8); expect(excaldrawElements.length).toBe(8);
@@ -280,6 +309,90 @@ describe("Test Transform", () => {
}); });
}); });
describe("Test Frames", () => {
it("should transform frames and update frame ids when regenerated", () => {
const elementsSkeleton: ExcalidrawElementSkeleton[] = [
{
type: "rectangle",
x: 10,
y: 10,
strokeWidth: 2,
id: "1",
},
{
type: "diamond",
x: 120,
y: 20,
backgroundColor: "#fff3bf",
strokeWidth: 2,
label: {
text: "HELLO EXCALIDRAW",
strokeColor: "#099268",
fontSize: 30,
},
id: "2",
},
{
type: "frame",
children: ["1", "2"],
name: "My frame",
},
];
const excaldrawElements = convertToExcalidrawElements(
elementsSkeleton,
opts,
);
expect(excaldrawElements.length).toBe(4);
excaldrawElements.forEach((ele) => {
expect(ele).toMatchObject({
seed: expect.any(Number),
versionNonce: expect.any(Number),
id: expect.any(String),
});
});
});
it("should consider max of calculated and frame dimensions when provided", () => {
const elementsSkeleton: ExcalidrawElementSkeleton[] = [
{
type: "rectangle",
x: 10,
y: 10,
strokeWidth: 2,
id: "1",
},
{
type: "diamond",
x: 120,
y: 20,
backgroundColor: "#fff3bf",
strokeWidth: 2,
label: {
text: "HELLO EXCALIDRAW",
strokeColor: "#099268",
fontSize: 30,
},
id: "2",
},
{
type: "frame",
children: ["1", "2"],
name: "My frame",
width: 800,
height: 100,
},
];
const excaldrawElements = convertToExcalidrawElements(
elementsSkeleton,
opts,
);
const frame = excaldrawElements.find((ele) => ele.type === "frame")!;
expect(frame.width).toBe(800);
expect(frame.height).toBe(126);
});
});
describe("Test arrow bindings", () => { describe("Test arrow bindings", () => {
it("should bind arrows to shapes when start / end provided without ids", () => { it("should bind arrows to shapes when start / end provided without ids", () => {
const elements = [ const elements = [
@@ -300,6 +413,7 @@ describe("Test Transform", () => {
]; ];
const excaldrawElements = convertToExcalidrawElements( const excaldrawElements = convertToExcalidrawElements(
elements as ExcalidrawElementSkeleton[], elements as ExcalidrawElementSkeleton[],
opts,
); );
expect(excaldrawElements.length).toBe(4); expect(excaldrawElements.length).toBe(4);
@@ -321,7 +435,7 @@ describe("Test Transform", () => {
}); });
expect(text).toMatchObject({ expect(text).toMatchObject({
x: 340, x: 240,
y: 226.5, y: 226.5,
type: "text", type: "text",
text: "HELLO WORLD!!", text: "HELLO WORLD!!",
@@ -341,7 +455,7 @@ describe("Test Transform", () => {
}); });
expect(ellipse).toMatchObject({ expect(ellipse).toMatchObject({
x: 555, x: 355,
y: 189, y: 189,
type: "ellipse", type: "ellipse",
boundElements: [ boundElements: [
@@ -383,10 +497,10 @@ describe("Test Transform", () => {
const excaldrawElements = convertToExcalidrawElements( const excaldrawElements = convertToExcalidrawElements(
elements as ExcalidrawElementSkeleton[], elements as ExcalidrawElementSkeleton[],
opts,
); );
expect(excaldrawElements.length).toBe(4); expect(excaldrawElements.length).toBe(4);
const [arrow, text1, text2, text3] = excaldrawElements; const [arrow, text1, text2, text3] = excaldrawElements;
expect(arrow).toMatchObject({ expect(arrow).toMatchObject({
@@ -406,7 +520,7 @@ describe("Test Transform", () => {
}); });
expect(text1).toMatchObject({ expect(text1).toMatchObject({
x: 340, x: 240,
y: 226.5, y: 226.5,
type: "text", type: "text",
text: "HELLO WORLD!!", text: "HELLO WORLD!!",
@@ -426,7 +540,7 @@ describe("Test Transform", () => {
}); });
expect(text3).toMatchObject({ expect(text3).toMatchObject({
x: 555, x: 355,
y: 226.5, y: 226.5,
type: "text", type: "text",
boundElements: [ boundElements: [
@@ -499,6 +613,7 @@ describe("Test Transform", () => {
const excaldrawElements = convertToExcalidrawElements( const excaldrawElements = convertToExcalidrawElements(
elements as ExcalidrawElementSkeleton[], elements as ExcalidrawElementSkeleton[],
opts,
); );
expect(excaldrawElements.length).toBe(5); expect(excaldrawElements.length).toBe(5);
@@ -547,6 +662,7 @@ describe("Test Transform", () => {
const excaldrawElements = convertToExcalidrawElements( const excaldrawElements = convertToExcalidrawElements(
elements as ExcalidrawElementSkeleton[], elements as ExcalidrawElementSkeleton[],
opts,
); );
expect(excaldrawElements.length).toBe(4); expect(excaldrawElements.length).toBe(4);
@@ -600,17 +716,18 @@ describe("Test Transform", () => {
const excaldrawElements = convertToExcalidrawElements( const excaldrawElements = convertToExcalidrawElements(
elements as ExcalidrawElementSkeleton[], elements as ExcalidrawElementSkeleton[],
opts,
); );
expect(excaldrawElements.length).toBe(4); expect(excaldrawElements.length).toBe(4);
const [, , arrow] = excaldrawElements; const [, , arrow, text] = excaldrawElements;
expect(arrow).toMatchObject({ expect(arrow).toMatchObject({
type: "arrow", type: "arrow",
x: 255, x: 255,
y: 239, y: 239,
boundElements: [ boundElements: [
{ {
id: "id46", id: text.id,
type: "text", type: "text",
}, },
], ],
@@ -650,17 +767,18 @@ describe("Test Transform", () => {
]; ];
const excaldrawElements = convertToExcalidrawElements( const excaldrawElements = convertToExcalidrawElements(
elements as ExcalidrawElementSkeleton[], elements as ExcalidrawElementSkeleton[],
opts,
); );
expect(excaldrawElements.length).toBe(2); expect(excaldrawElements.length).toBe(2);
const [arrow, rect] = excaldrawElements; const [arrow, rect] = excaldrawElements;
expect((arrow as ExcalidrawArrowElement).endBinding).toStrictEqual({ expect((arrow as ExcalidrawArrowElement).endBinding).toStrictEqual({
elementId: "rect-1", elementId: "rect-1",
focus: 0, focus: 0,
gap: 5, gap: 205,
}); });
expect(rect.boundElements).toStrictEqual([ expect(rect.boundElements).toStrictEqual([
{ {
id: "id47", id: arrow.id,
type: "arrow", type: "arrow",
}, },
]); ]);
@@ -692,6 +810,7 @@ describe("Test Transform", () => {
]; ];
const excaldrawElements = convertToExcalidrawElements( const excaldrawElements = convertToExcalidrawElements(
elements as ExcalidrawElementSkeleton[], elements as ExcalidrawElementSkeleton[],
opts,
); );
expect(excaldrawElements.length).toBe(1); expect(excaldrawElements.length).toBe(1);
+161 -11
View File
@@ -5,6 +5,7 @@ import {
VERTICAL_ALIGN, VERTICAL_ALIGN,
} from "../constants"; } from "../constants";
import { import {
getCommonBounds,
newElement, newElement,
newLinearElement, newLinearElement,
redrawTextBoundingBox, redrawTextBoundingBox,
@@ -12,6 +13,7 @@ import {
import { bindLinearElement } from "../element/binding"; import { bindLinearElement } from "../element/binding";
import { import {
ElementConstructorOpts, ElementConstructorOpts,
newFrameElement,
newImageElement, newImageElement,
newTextElement, newTextElement,
} from "../element/newElement"; } from "../element/newElement";
@@ -39,6 +41,8 @@ import {
} from "../element/types"; } from "../element/types";
import { MarkOptional } from "../utility-types"; import { MarkOptional } from "../utility-types";
import { assertNever, getFontString } from "../utils"; import { assertNever, getFontString } from "../utils";
import { getSizeFromPoints } from "../points";
import { randomId } from "../random";
export type ValidLinearElement = { export type ValidLinearElement = {
type: "arrow" | "line"; type: "arrow" | "line";
@@ -133,9 +137,7 @@ export type ValidContainer =
export type ExcalidrawElementSkeleton = export type ExcalidrawElementSkeleton =
| Extract< | Extract<
Exclude<ExcalidrawElement, ExcalidrawSelectionElement>, Exclude<ExcalidrawElement, ExcalidrawSelectionElement>,
| ExcalidrawEmbeddableElement ExcalidrawEmbeddableElement | ExcalidrawFreeDrawElement
| ExcalidrawFreeDrawElement
| ExcalidrawFrameElement
> >
| ({ | ({
type: Extract<ExcalidrawLinearElement["type"], "line">; type: Extract<ExcalidrawLinearElement["type"], "line">;
@@ -156,10 +158,15 @@ export type ExcalidrawElementSkeleton =
x: number; x: number;
y: number; y: number;
fileId: FileId; fileId: FileId;
} & Partial<ExcalidrawImageElement>); } & Partial<ExcalidrawImageElement>)
| ({
type: "frame";
children: readonly ExcalidrawElement["id"][];
name?: string;
} & Partial<ExcalidrawFrameElement>);
const DEFAULT_LINEAR_ELEMENT_PROPS = { const DEFAULT_LINEAR_ELEMENT_PROPS = {
width: 300, width: 100,
height: 0, height: 0,
}; };
@@ -357,6 +364,48 @@ const bindLinearElementToElement = (
); );
} }
} }
// Update start/end points by 0.5 so bindings don't overlap with start/end bound element coordinates.
const endPointIndex = linearElement.points.length - 1;
const delta = 0.5;
const newPoints = JSON.parse(JSON.stringify(linearElement.points));
// left to right so shift the arrow towards right
if (
linearElement.points[endPointIndex][0] >
linearElement.points[endPointIndex - 1][0]
) {
newPoints[0][0] = delta;
newPoints[endPointIndex][0] -= delta;
}
// right to left so shift the arrow towards left
if (
linearElement.points[endPointIndex][0] <
linearElement.points[endPointIndex - 1][0]
) {
newPoints[0][0] = -delta;
newPoints[endPointIndex][0] += delta;
}
// top to bottom so shift the arrow towards top
if (
linearElement.points[endPointIndex][1] >
linearElement.points[endPointIndex - 1][1]
) {
newPoints[0][1] = delta;
newPoints[endPointIndex][1] -= delta;
}
// bottom to top so shift the arrow towards bottom
if (
linearElement.points[endPointIndex][1] <
linearElement.points[endPointIndex - 1][1]
) {
newPoints[0][1] = -delta;
newPoints[endPointIndex][1] += delta;
}
Object.assign(linearElement, { points: newPoints });
return { return {
linearElement, linearElement,
startBoundElement, startBoundElement,
@@ -384,18 +433,27 @@ class ElementStore {
} }
export const convertToExcalidrawElements = ( export const convertToExcalidrawElements = (
elements: ExcalidrawElementSkeleton[] | null, elementsSkeleton: ExcalidrawElementSkeleton[] | null,
opts?: { regenerateIds: boolean },
) => { ) => {
if (!elements) { if (!elementsSkeleton) {
return []; return [];
} }
const elements: ExcalidrawElementSkeleton[] = JSON.parse(
JSON.stringify(elementsSkeleton),
);
const elementStore = new ElementStore(); const elementStore = new ElementStore();
const elementsWithIds = new Map<string, ExcalidrawElementSkeleton>(); const elementsWithIds = new Map<string, ExcalidrawElementSkeleton>();
const oldToNewElementIdMap = new Map<string, string>();
// Create individual elements // Create individual elements
for (const element of elements) { for (const element of elements) {
let excalidrawElement: ExcalidrawElement; let excalidrawElement: ExcalidrawElement;
const originalId = element.id;
if (opts?.regenerateIds !== false) {
Object.assign(element, { id: randomId() });
}
switch (element.type) { switch (element.type) {
case "rectangle": case "rectangle":
case "ellipse": case "ellipse":
@@ -444,6 +502,11 @@ export const convertToExcalidrawElements = (
], ],
...element, ...element,
}); });
Object.assign(
excalidrawElement,
getSizeFromPoints(excalidrawElement.points),
);
break; break;
} }
case "text": { case "text": {
@@ -477,8 +540,15 @@ export const convertToExcalidrawElements = (
break; break;
} }
case "frame": {
excalidrawElement = newFrameElement({
x: 0,
y: 0,
...element,
});
break;
}
case "freedraw": case "freedraw":
case "frame":
case "embeddable": { case "embeddable": {
excalidrawElement = element; excalidrawElement = element;
break; break;
@@ -499,6 +569,9 @@ export const convertToExcalidrawElements = (
} else { } else {
elementStore.add(excalidrawElement); elementStore.add(excalidrawElement);
elementsWithIds.set(excalidrawElement.id, element); elementsWithIds.set(excalidrawElement.id, element);
if (originalId) {
oldToNewElementIdMap.set(originalId, excalidrawElement.id);
}
} }
} }
@@ -524,6 +597,18 @@ export const convertToExcalidrawElements = (
element.type === "arrow" ? element?.start : undefined; element.type === "arrow" ? element?.start : undefined;
const originalEnd = const originalEnd =
element.type === "arrow" ? element?.end : undefined; element.type === "arrow" ? element?.end : undefined;
if (originalStart && originalStart.id) {
const newStartId = oldToNewElementIdMap.get(originalStart.id);
if (newStartId) {
Object.assign(originalStart, { id: newStartId });
}
}
if (originalEnd && originalEnd.id) {
const newEndId = oldToNewElementIdMap.get(originalEnd.id);
if (newEndId) {
Object.assign(originalEnd, { id: newEndId });
}
}
const { linearElement, startBoundElement, endBoundElement } = const { linearElement, startBoundElement, endBoundElement } =
bindLinearElementToElement( bindLinearElementToElement(
container as ExcalidrawArrowElement, container as ExcalidrawArrowElement,
@@ -539,13 +624,23 @@ export const convertToExcalidrawElements = (
} else { } else {
switch (element.type) { switch (element.type) {
case "arrow": { case "arrow": {
const { start, end } = element;
if (start && start.id) {
const newStartId = oldToNewElementIdMap.get(start.id);
Object.assign(start, { id: newStartId });
}
if (end && end.id) {
const newEndId = oldToNewElementIdMap.get(end.id);
Object.assign(end, { id: newEndId });
}
const { linearElement, startBoundElement, endBoundElement } = const { linearElement, startBoundElement, endBoundElement } =
bindLinearElementToElement( bindLinearElementToElement(
excalidrawElement as ExcalidrawArrowElement, excalidrawElement as ExcalidrawArrowElement,
element.start, start,
element.end, end,
elementStore, elementStore,
); );
elementStore.add(linearElement); elementStore.add(linearElement);
elementStore.add(startBoundElement); elementStore.add(startBoundElement);
elementStore.add(endBoundElement); elementStore.add(endBoundElement);
@@ -557,5 +652,60 @@ export const convertToExcalidrawElements = (
} }
} }
} }
// Once all the excalidraw elements are created, we can add frames since we
// need to calculate coordinates and dimensions of frame which is possibe after all
// frame children are processed.
for (const [id, element] of elementsWithIds) {
if (element.type !== "frame") {
continue;
}
const frame = elementStore.getElement(id);
if (!frame) {
throw new Error(`Excalidraw element with id ${id} doesn't exist`);
}
const childrenElements: ExcalidrawElement[] = [];
element.children.forEach((id) => {
const newElementId = oldToNewElementIdMap.get(id);
if (!newElementId) {
throw new Error(`Element with ${id} wasn't mapped correctly`);
}
const elementInFrame = elementStore.getElement(newElementId);
if (!elementInFrame) {
throw new Error(`Frame element with id ${newElementId} doesn't exist`);
}
Object.assign(elementInFrame, { frameId: frame.id });
elementInFrame?.boundElements?.forEach((boundElement) => {
const ele = elementStore.getElement(boundElement.id);
if (!ele) {
throw new Error(
`Bound element with id ${boundElement.id} doesn't exist`,
);
}
Object.assign(ele, { frameId: frame.id });
childrenElements.push(ele);
});
childrenElements.push(elementInFrame);
});
let [minX, minY, maxX, maxY] = getCommonBounds(childrenElements);
const PADDING = 10;
minX = minX - PADDING;
minY = minY - PADDING;
maxX = maxX + PADDING;
maxY = maxY + PADDING;
// Take the max of calculated and provided frame dimensions, whichever is higher
const width = Math.max(frame?.width, maxX - minX);
const height = Math.max(frame?.height, maxY - minY);
Object.assign(frame, { x: minX, y: minY, width, height });
}
return elementStore.getElements(); return elementStore.getElements();
}; };
+1 -2
View File
@@ -210,7 +210,6 @@ export const Hyperlink = ({
}; };
const { x, y } = getCoordsForPopover(element, appState); const { x, y } = getCoordsForPopover(element, appState);
if ( if (
appState.selectionElement ||
appState.draggingElement || appState.draggingElement ||
appState.resizingElement || appState.resizingElement ||
appState.isRotating || appState.isRotating ||
@@ -393,7 +392,7 @@ export const getLinkHandleFromCoords = (
[x1, y1, x2, y2]: Bounds, [x1, y1, x2, y2]: Bounds,
angle: number, angle: number,
appState: Pick<UIAppState, "zoom">, appState: Pick<UIAppState, "zoom">,
): [x: number, y: number, width: number, height: number] => { ): Bounds => {
const size = DEFAULT_LINK_SIZE; const size = DEFAULT_LINK_SIZE;
const linkWidth = size / appState.zoom.value; const linkWidth = size / appState.zoom.value;
const linkHeight = size / appState.zoom.value; const linkHeight = size / appState.zoom.value;
+16 -16
View File
@@ -34,7 +34,12 @@ export type RectangleBox = {
type MaybeQuadraticSolution = [number | null, number | null] | false; type MaybeQuadraticSolution = [number | null, number | null] | false;
// x and y position of top left corner, x and y position of bottom right corner // x and y position of top left corner, x and y position of bottom right corner
export type Bounds = readonly [x1: number, y1: number, x2: number, y2: number]; export type Bounds = readonly [
minX: number,
minY: number,
maxX: number,
maxY: number,
];
export class ElementBounds { export class ElementBounds {
private static boundsCache = new WeakMap< private static boundsCache = new WeakMap<
@@ -63,7 +68,7 @@ export class ElementBounds {
} }
private static calculateBounds(element: ExcalidrawElement): Bounds { private static calculateBounds(element: ExcalidrawElement): Bounds {
let bounds: [number, number, number, number]; let bounds: Bounds;
const [x1, y1, x2, y2, cx, cy] = getElementAbsoluteCoords(element); const [x1, y1, x2, y2, cx, cy] = getElementAbsoluteCoords(element);
@@ -387,7 +392,7 @@ const getCubicBezierCurveBound = (
export const getMinMaxXYFromCurvePathOps = ( export const getMinMaxXYFromCurvePathOps = (
ops: Op[], ops: Op[],
transformXY?: (x: number, y: number) => [number, number], transformXY?: (x: number, y: number) => [number, number],
): [number, number, number, number] => { ): Bounds => {
let currentP: Point = [0, 0]; let currentP: Point = [0, 0];
const { minX, minY, maxX, maxY } = ops.reduce( const { minX, minY, maxX, maxY } = ops.reduce(
@@ -435,9 +440,9 @@ export const getMinMaxXYFromCurvePathOps = (
return [minX, minY, maxX, maxY]; return [minX, minY, maxX, maxY];
}; };
const getBoundsFromPoints = ( export const getBoundsFromPoints = (
points: ExcalidrawFreeDrawElement["points"], points: ExcalidrawFreeDrawElement["points"],
): [number, number, number, number] => { ): Bounds => {
let minX = Infinity; let minX = Infinity;
let minY = Infinity; let minY = Infinity;
let maxX = -Infinity; let maxX = -Infinity;
@@ -589,7 +594,7 @@ const getLinearElementRotatedBounds = (
element: ExcalidrawLinearElement, element: ExcalidrawLinearElement,
cx: number, cx: number,
cy: number, cy: number,
): [number, number, number, number] => { ): Bounds => {
if (element.points.length < 2) { if (element.points.length < 2) {
const [pointX, pointY] = element.points[0]; const [pointX, pointY] = element.points[0];
const [x, y] = rotate( const [x, y] = rotate(
@@ -600,7 +605,7 @@ const getLinearElementRotatedBounds = (
element.angle, element.angle,
); );
let coords: [number, number, number, number] = [x, y, x, y]; let coords: Bounds = [x, y, x, y];
const boundTextElement = getBoundTextElement(element); const boundTextElement = getBoundTextElement(element);
if (boundTextElement) { if (boundTextElement) {
const coordsWithBoundText = LinearElementEditor.getMinMaxXYWithBoundText( const coordsWithBoundText = LinearElementEditor.getMinMaxXYWithBoundText(
@@ -625,12 +630,7 @@ const getLinearElementRotatedBounds = (
const transformXY = (x: number, y: number) => const transformXY = (x: number, y: number) =>
rotate(element.x + x, element.y + y, cx, cy, element.angle); rotate(element.x + x, element.y + y, cx, cy, element.angle);
const res = getMinMaxXYFromCurvePathOps(ops, transformXY); const res = getMinMaxXYFromCurvePathOps(ops, transformXY);
let coords: [number, number, number, number] = [ let coords: Bounds = [res[0], res[1], res[2], res[3]];
res[0],
res[1],
res[2],
res[3],
];
const boundTextElement = getBoundTextElement(element); const boundTextElement = getBoundTextElement(element);
if (boundTextElement) { if (boundTextElement) {
const coordsWithBoundText = LinearElementEditor.getMinMaxXYWithBoundText( const coordsWithBoundText = LinearElementEditor.getMinMaxXYWithBoundText(
@@ -692,7 +692,7 @@ export const getResizedElementAbsoluteCoords = (
nextWidth: number, nextWidth: number,
nextHeight: number, nextHeight: number,
normalizePoints: boolean, normalizePoints: boolean,
): [number, number, number, number] => { ): Bounds => {
if (!(isLinearElement(element) || isFreeDrawElement(element))) { if (!(isLinearElement(element) || isFreeDrawElement(element))) {
return [ return [
element.x, element.x,
@@ -709,7 +709,7 @@ export const getResizedElementAbsoluteCoords = (
normalizePoints, normalizePoints,
); );
let bounds: [number, number, number, number]; let bounds: Bounds;
if (isFreeDrawElement(element)) { if (isFreeDrawElement(element)) {
// Free Draw // Free Draw
@@ -740,7 +740,7 @@ export const getResizedElementAbsoluteCoords = (
export const getElementPointsCoords = ( export const getElementPointsCoords = (
element: ExcalidrawLinearElement, element: ExcalidrawLinearElement,
points: readonly (readonly [number, number])[], points: readonly (readonly [number, number])[],
): [number, number, number, number] => { ): Bounds => {
// This might be computationally heavey // This might be computationally heavey
const gen = rough.generator(); const gen = rough.generator();
const curve = const curve =
+3 -1
View File
@@ -494,7 +494,9 @@ const hitTestFreeDrawElement = (
// for filled freedraw shapes, support // for filled freedraw shapes, support
// selecting from inside // selecting from inside
if (shape && shape.sets.length) { if (shape && shape.sets.length) {
return hitTestRoughShape(shape, x, y, threshold); return element.fillStyle === "solid"
? hitTestCurveInside(shape, x, y, "round")
: hitTestRoughShape(shape, x, y, threshold);
} }
return false; return false;
+51 -37
View File
@@ -1,5 +1,5 @@
import { updateBoundElements } from "./binding"; import { updateBoundElements } from "./binding";
import { getCommonBounds } from "./bounds"; import { Bounds, getCommonBounds } from "./bounds";
import { mutateElement } from "./mutateElement"; import { mutateElement } from "./mutateElement";
import { getPerfectElementSize } from "./sizeHelpers"; import { getPerfectElementSize } from "./sizeHelpers";
import { NonDeletedExcalidrawElement } from "./types"; import { NonDeletedExcalidrawElement } from "./types";
@@ -8,7 +8,11 @@ import { getBoundTextElement } from "./textElement";
import { isSelectedViaGroup } from "../groups"; import { isSelectedViaGroup } from "../groups";
import { getGridPoint } from "../math"; import { getGridPoint } from "../math";
import Scene from "../scene/Scene"; import Scene from "../scene/Scene";
import { isFrameElement } from "./typeChecks"; import {
isArrowElement,
isBoundToContainer,
isFrameElement,
} from "./typeChecks";
export const dragSelectedElements = ( export const dragSelectedElements = (
pointerDownState: PointerDownState, pointerDownState: PointerDownState,
@@ -35,44 +39,41 @@ export const dragSelectedElements = (
if (frames.length > 0) { if (frames.length > 0) {
const elementsInFrames = scene const elementsInFrames = scene
.getNonDeletedElements() .getNonDeletedElements()
.filter((e) => !isBoundToContainer(e))
.filter((e) => e.frameId !== null) .filter((e) => e.frameId !== null)
.filter((e) => frames.includes(e.frameId!)); .filter((e) => frames.includes(e.frameId!));
elementsInFrames.forEach((element) => elementsToUpdate.add(element)); elementsInFrames.forEach((element) => elementsToUpdate.add(element));
} }
const commonBounds = getCommonBounds(
Array.from(elementsToUpdate).map(
(el) => pointerDownState.originalElements.get(el.id) ?? el,
),
);
const adjustedOffset = calculateOffset(
commonBounds,
offset,
snapOffset,
gridSize,
);
elementsToUpdate.forEach((element) => { elementsToUpdate.forEach((element) => {
updateElementCoords( updateElementCoords(pointerDownState, element, adjustedOffset);
pointerDownState,
element,
offset,
snapOffset,
gridSize,
);
// update coords of bound text only if we're dragging the container directly // update coords of bound text only if we're dragging the container directly
// (we don't drag the group that it's part of) // (we don't drag the group that it's part of)
if ( if (
// Don't update coords of arrow label since we calculate its position during render
!isArrowElement(element) &&
// container isn't part of any group // container isn't part of any group
// (perf optim so we don't check `isSelectedViaGroup()` in every case) // (perf optim so we don't check `isSelectedViaGroup()` in every case)
!element.groupIds.length || (!element.groupIds.length ||
// container is part of a group, but we're dragging the container directly // container is part of a group, but we're dragging the container directly
(appState.editingGroupId && !isSelectedViaGroup(appState, element)) (appState.editingGroupId && !isSelectedViaGroup(appState, element)))
) { ) {
const textElement = getBoundTextElement(element); const textElement = getBoundTextElement(element);
if ( if (textElement) {
textElement && updateElementCoords(pointerDownState, textElement, adjustedOffset);
// when container is added to a frame, so will its bound text
// so the text is already in `elementsToUpdate` and we should avoid
// updating its coords again
(!textElement.frameId || !frames.includes(textElement.frameId))
) {
updateElementCoords(
pointerDownState,
textElement,
offset,
snapOffset,
gridSize,
);
} }
} }
updateBoundElements(element, { updateBoundElements(element, {
@@ -81,23 +82,20 @@ export const dragSelectedElements = (
}); });
}; };
const updateElementCoords = ( const calculateOffset = (
pointerDownState: PointerDownState, commonBounds: Bounds,
element: NonDeletedExcalidrawElement,
dragOffset: { x: number; y: number }, dragOffset: { x: number; y: number },
snapOffset: { x: number; y: number }, snapOffset: { x: number; y: number },
gridSize: AppState["gridSize"], gridSize: AppState["gridSize"],
) => { ): { x: number; y: number } => {
const originalElement = const [x, y] = commonBounds;
pointerDownState.originalElements.get(element.id) ?? element; let nextX = x + dragOffset.x + snapOffset.x;
let nextY = y + dragOffset.y + snapOffset.y;
let nextX = originalElement.x + dragOffset.x + snapOffset.x;
let nextY = originalElement.y + dragOffset.y + snapOffset.y;
if (snapOffset.x === 0 || snapOffset.y === 0) { if (snapOffset.x === 0 || snapOffset.y === 0) {
const [nextGridX, nextGridY] = getGridPoint( const [nextGridX, nextGridY] = getGridPoint(
originalElement.x + dragOffset.x, x + dragOffset.x,
originalElement.y + dragOffset.y, y + dragOffset.y,
gridSize, gridSize,
); );
@@ -109,6 +107,22 @@ const updateElementCoords = (
nextY = nextGridY; nextY = nextGridY;
} }
} }
return {
x: nextX - x,
y: nextY - y,
};
};
const updateElementCoords = (
pointerDownState: PointerDownState,
element: NonDeletedExcalidrawElement,
dragOffset: { x: number; y: number },
) => {
const originalElement =
pointerDownState.originalElements.get(element.id) ?? element;
const nextX = originalElement.x + dragOffset.x;
const nextY = originalElement.y + dragOffset.y;
mutateElement(element, { mutateElement(element, {
x: nextX, x: nextX,
+9
View File
@@ -28,6 +28,7 @@ const embeddedLinkCache = new Map<string, EmbeddedLink>();
const RE_YOUTUBE = const RE_YOUTUBE =
/^(?:http(?:s)?:\/\/)?(?:www\.)?youtu(?:be\.com|\.be)\/(embed\/|watch\?v=|shorts\/|playlist\?list=|embed\/videoseries\?list=)?([a-zA-Z0-9_-]+)(?:\?t=|&t=|\?start=|&start=)?([a-zA-Z0-9_-]+)?[^\s]*$/; /^(?:http(?:s)?:\/\/)?(?:www\.)?youtu(?:be\.com|\.be)\/(embed\/|watch\?v=|shorts\/|playlist\?list=|embed\/videoseries\?list=)?([a-zA-Z0-9_-]+)(?:\?t=|&t=|\?start=|&start=)?([a-zA-Z0-9_-]+)?[^\s]*$/;
const RE_VIMEO = const RE_VIMEO =
/^(?:http(?:s)?:\/\/)?(?:(?:w){3}.)?(?:player\.)?vimeo\.com\/(?:video\/)?([^?\s]+)(?:\?.*)?$/; /^(?:http(?:s)?:\/\/)?(?:(?:w){3}.)?(?:player\.)?vimeo\.com\/(?:video\/)?([^?\s]+)(?:\?.*)?$/;
const RE_FIGMA = /^https:\/\/(?:www\.)?figma\.com/; const RE_FIGMA = /^https:\/\/(?:www\.)?figma\.com/;
@@ -47,6 +48,9 @@ const RE_VALTOWN =
const RE_GENERIC_EMBED = const RE_GENERIC_EMBED =
/^<(?:iframe|blockquote)[\s\S]*?\s(?:src|href)=["']([^"']*)["'][\s\S]*?>$/i; /^<(?:iframe|blockquote)[\s\S]*?\s(?:src|href)=["']([^"']*)["'][\s\S]*?>$/i;
const RE_GIPHY =
/giphy.com\/(?:clips|embed|gifs)\/[a-zA-Z0-9]*?-?([a-zA-Z0-9]+)(?:[^a-zA-Z0-9]|$)/;
const ALLOWED_DOMAINS = new Set([ const ALLOWED_DOMAINS = new Set([
"youtube.com", "youtube.com",
"youtu.be", "youtu.be",
@@ -59,6 +63,7 @@ const ALLOWED_DOMAINS = new Set([
"*.simplepdf.eu", "*.simplepdf.eu",
"stackblitz.com", "stackblitz.com",
"val.town", "val.town",
"giphy.com",
]); ]);
const createSrcDoc = (body: string) => { const createSrcDoc = (body: string) => {
@@ -308,6 +313,10 @@ export const extractSrc = (htmlString: string): string => {
return gistMatch[1]; return gistMatch[1];
} }
if (RE_GIPHY.test(htmlString)) {
return `https://giphy.com/embed/${RE_GIPHY.exec(htmlString)![1]}`;
}
const match = htmlString.match(RE_GENERIC_EMBED); const match = htmlString.match(RE_GENERIC_EMBED);
if (match && match.length === 2) { if (match && match.length === 2) {
return match[1]; return match[1];
+7 -3
View File
@@ -21,6 +21,7 @@ import {
} from "../math"; } from "../math";
import { getElementAbsoluteCoords, getLockedLinearCursorAlignSize } from "."; import { getElementAbsoluteCoords, getLockedLinearCursorAlignSize } from ".";
import { import {
Bounds,
getCurvePathOps, getCurvePathOps,
getElementPointsCoords, getElementPointsCoords,
getMinMaxXYFromCurvePathOps, getMinMaxXYFromCurvePathOps,
@@ -134,7 +135,10 @@ export class LinearElementEditor {
appState: AppState, appState: AppState,
setState: React.Component<any, AppState>["setState"], setState: React.Component<any, AppState>["setState"],
) { ) {
if (!appState.editingLinearElement || !appState.selectionElement) { if (
!appState.editingLinearElement ||
appState.draggingElement?.type !== "selection"
) {
return false; return false;
} }
const { editingLinearElement } = appState; const { editingLinearElement } = appState;
@@ -146,7 +150,7 @@ export class LinearElementEditor {
} }
const [selectionX1, selectionY1, selectionX2, selectionY2] = const [selectionX1, selectionY1, selectionX2, selectionY2] =
getElementAbsoluteCoords(appState.selectionElement); getElementAbsoluteCoords(appState.draggingElement);
const pointsSceneCoords = const pointsSceneCoords =
LinearElementEditor.getPointsGlobalCoordinates(element); LinearElementEditor.getPointsGlobalCoordinates(element);
@@ -1313,7 +1317,7 @@ export class LinearElementEditor {
static getMinMaxXYWithBoundText = ( static getMinMaxXYWithBoundText = (
element: ExcalidrawLinearElement, element: ExcalidrawLinearElement,
elementBounds: [number, number, number, number], elementBounds: Bounds,
boundTextElement: ExcalidrawTextElementWithContainer, boundTextElement: ExcalidrawTextElementWithContainer,
): [number, number, number, number, number, number] => { ): [number, number, number, number, number, number] => {
let [x1, y1, x2, y2] = elementBounds; let [x1, y1, x2, y2] = elementBounds;
+4 -2
View File
@@ -144,13 +144,15 @@ export const newEmbeddableElement = (
}; };
export const newFrameElement = ( export const newFrameElement = (
opts: ElementConstructorOpts, opts: {
name?: string;
} & ElementConstructorOpts,
): NonDeleted<ExcalidrawFrameElement> => { ): NonDeleted<ExcalidrawFrameElement> => {
const frameElement = newElementWith( const frameElement = newElementWith(
{ {
..._newElementBase<ExcalidrawFrameElement>("frame", opts), ..._newElementBase<ExcalidrawFrameElement>("frame", opts),
type: "frame", type: "frame",
name: null, name: opts?.name || null,
}, },
{}, {},
); );
+2 -1
View File
@@ -13,6 +13,7 @@ import {
MaybeTransformHandleType, MaybeTransformHandleType,
} from "./transformHandles"; } from "./transformHandles";
import { AppState, Zoom } from "../types"; import { AppState, Zoom } from "../types";
import { Bounds } from "./bounds";
const isInsideTransformHandle = ( const isInsideTransformHandle = (
transformHandle: TransformHandle, transformHandle: TransformHandle,
@@ -87,7 +88,7 @@ export const getElementWithTransformHandleType = (
}; };
export const getTransformHandleTypeFromCoords = ( export const getTransformHandleTypeFromCoords = (
[x1, y1, x2, y2]: readonly [number, number, number, number], [x1, y1, x2, y2]: Bounds,
scenePointerX: number, scenePointerX: number,
scenePointerY: number, scenePointerY: number,
zoom: Zoom, zoom: Zoom,
+1 -1
View File
@@ -91,7 +91,7 @@ export const redrawTextBoundingBox = (
); );
const maxContainerWidth = getBoundTextMaxWidth(container); const maxContainerWidth = getBoundTextMaxWidth(container);
if (metrics.height > maxContainerHeight) { if (!isArrowElement(container) && metrics.height > maxContainerHeight) {
const nextHeight = computeContainerDimensionForBoundText( const nextHeight = computeContainerDimensionForBoundText(
metrics.height, metrics.height,
container.type, container.type,
+57 -65
View File
@@ -18,6 +18,7 @@ import {
import { API } from "../tests/helpers/api"; import { API } from "../tests/helpers/api";
import { mutateElement } from "./mutateElement"; import { mutateElement } from "./mutateElement";
import { getOriginalContainerHeightFromCache } from "./textWysiwyg"; import { getOriginalContainerHeightFromCache } from "./textWysiwyg";
import { getTextEditor, updateTextEditor } from "../tests/queries/dom";
// Unmount ReactDOM from root // Unmount ReactDOM from root
ReactDOM.unmountComponentAtNode(document.getElementById("root")!); ReactDOM.unmountComponentAtNode(document.getElementById("root")!);
@@ -25,16 +26,7 @@ ReactDOM.unmountComponentAtNode(document.getElementById("root")!);
const tab = " "; const tab = " ";
const mouse = new Pointer("mouse"); const mouse = new Pointer("mouse");
const getTextEditor = () => { const textEditorSelector = ".excalidraw-textEditorContainer > textarea";
return document.querySelector(
".excalidraw-textEditorContainer > textarea",
) as HTMLTextAreaElement;
};
const updateTextEditor = (editor: HTMLTextAreaElement, value: string) => {
fireEvent.change(editor, { target: { value } });
editor.dispatchEvent(new Event("input"));
};
describe("textWysiwyg", () => { describe("textWysiwyg", () => {
describe("start text editing", () => { describe("start text editing", () => {
@@ -185,7 +177,7 @@ describe("textWysiwyg", () => {
expect(h.state.editingElement?.id).toBe(boundText.id); expect(h.state.editingElement?.id).toBe(boundText.id);
}); });
it("should edit text under cursor when clicked with text tool", () => { it("should edit text under cursor when clicked with text tool", async () => {
const text = API.createElement({ const text = API.createElement({
type: "text", type: "text",
text: "ola", text: "ola",
@@ -200,14 +192,14 @@ describe("textWysiwyg", () => {
mouse.clickAt(text.x + 50, text.y + 50); mouse.clickAt(text.x + 50, text.y + 50);
const editor = getTextEditor(); const editor = await getTextEditor(textEditorSelector, false);
expect(editor).not.toBe(null); expect(editor).not.toBe(null);
expect(h.state.editingElement?.id).toBe(text.id); expect(h.state.editingElement?.id).toBe(text.id);
expect(h.elements.length).toBe(1); expect(h.elements.length).toBe(1);
}); });
it("should edit text under cursor when double-clicked with selection tool", () => { it("should edit text under cursor when double-clicked with selection tool", async () => {
const text = API.createElement({ const text = API.createElement({
type: "text", type: "text",
text: "ola", text: "ola",
@@ -222,12 +214,26 @@ describe("textWysiwyg", () => {
mouse.doubleClickAt(text.x + 50, text.y + 50); mouse.doubleClickAt(text.x + 50, text.y + 50);
const editor = getTextEditor(); const editor = await getTextEditor(textEditorSelector, false);
expect(editor).not.toBe(null); expect(editor).not.toBe(null);
expect(h.state.editingElement?.id).toBe(text.id); expect(h.state.editingElement?.id).toBe(text.id);
expect(h.elements.length).toBe(1); expect(h.elements.length).toBe(1);
}); });
// FIXME too flaky. No one knows why.
it.skip("should bump the version of a labeled arrow when the label is updated", async () => {
const arrow = UI.createElement("arrow", {
width: 300,
height: 0,
});
await UI.editText(arrow, "Hello");
const { version } = arrow;
await UI.editText(arrow, "Hello\nworld!");
expect(arrow.version).toEqual(version + 1);
});
}); });
describe("Test container-unbound text", () => { describe("Test container-unbound text", () => {
@@ -249,7 +255,7 @@ describe("textWysiwyg", () => {
textElement = UI.createElement("text"); textElement = UI.createElement("text");
mouse.clickOn(textElement); mouse.clickOn(textElement);
textarea = getTextEditor(); textarea = await getTextEditor(textEditorSelector, true);
}); });
afterAll(() => { afterAll(() => {
@@ -459,7 +465,7 @@ describe("textWysiwyg", () => {
UI.clickTool("text"); UI.clickTool("text");
mouse.clickAt(750, 300); mouse.clickAt(750, 300);
textarea = getTextEditor(); textarea = await getTextEditor(textEditorSelector, true);
updateTextEditor( updateTextEditor(
textarea, textarea,
"Excalidraw is an opensource virtual collaborative whiteboard for sketching hand-drawn like diagrams!", "Excalidraw is an opensource virtual collaborative whiteboard for sketching hand-drawn like diagrams!",
@@ -511,7 +517,7 @@ describe("textWysiwyg", () => {
{ id: text.id, type: "text" }, { id: text.id, type: "text" },
]); ]);
mouse.down(); mouse.down();
const editor = getTextEditor(); const editor = await getTextEditor(textEditorSelector, true);
updateTextEditor(editor, "Hello World!"); updateTextEditor(editor, "Hello World!");
@@ -539,7 +545,7 @@ describe("textWysiwyg", () => {
]); ]);
expect(text.angle).toBe(rectangle.angle); expect(text.angle).toBe(rectangle.angle);
mouse.down(); mouse.down();
const editor = getTextEditor(); const editor = await getTextEditor(textEditorSelector, true);
updateTextEditor(editor, "Hello World!"); updateTextEditor(editor, "Hello World!");
@@ -566,7 +572,7 @@ describe("textWysiwyg", () => {
API.setSelectedElements([diamond]); API.setSelectedElements([diamond]);
Keyboard.keyPress(KEYS.ENTER); Keyboard.keyPress(KEYS.ENTER);
const editor = getTextEditor(); const editor = await getTextEditor(textEditorSelector, true);
await new Promise((r) => setTimeout(r, 0)); await new Promise((r) => setTimeout(r, 0));
const value = new Array(1000).fill("1").join("\n"); const value = new Array(1000).fill("1").join("\n");
@@ -601,7 +607,7 @@ describe("textWysiwyg", () => {
expect(text.type).toBe("text"); expect(text.type).toBe("text");
expect(text.containerId).toBe(null); expect(text.containerId).toBe(null);
mouse.down(); mouse.down();
let editor = getTextEditor(); let editor = await getTextEditor(textEditorSelector, true);
await new Promise((r) => setTimeout(r, 0)); await new Promise((r) => setTimeout(r, 0));
editor.blur(); editor.blur();
@@ -616,7 +622,7 @@ describe("textWysiwyg", () => {
expect(text.containerId).toBe(rectangle.id); expect(text.containerId).toBe(rectangle.id);
mouse.down(); mouse.down();
editor = getTextEditor(); editor = await getTextEditor(textEditorSelector, true);
updateTextEditor(editor, "Hello World!"); updateTextEditor(editor, "Hello World!");
await new Promise((r) => setTimeout(r, 0)); await new Promise((r) => setTimeout(r, 0));
@@ -638,7 +644,7 @@ describe("textWysiwyg", () => {
const text = h.elements[1] as ExcalidrawTextElementWithContainer; const text = h.elements[1] as ExcalidrawTextElementWithContainer;
expect(text.type).toBe("text"); expect(text.type).toBe("text");
expect(text.containerId).toBe(rectangle.id); expect(text.containerId).toBe(rectangle.id);
const editor = getTextEditor(); const editor = await getTextEditor(textEditorSelector, true);
await new Promise((r) => setTimeout(r, 0)); await new Promise((r) => setTimeout(r, 0));
@@ -673,7 +679,7 @@ describe("textWysiwyg", () => {
{ id: text.id, type: "text" }, { id: text.id, type: "text" },
]); ]);
mouse.down(); mouse.down();
const editor = getTextEditor(); const editor = await getTextEditor(textEditorSelector, true);
updateTextEditor(editor, "Hello World!"); updateTextEditor(editor, "Hello World!");
await new Promise((r) => setTimeout(r, 0)); await new Promise((r) => setTimeout(r, 0));
@@ -698,7 +704,7 @@ describe("textWysiwyg", () => {
freedraw.y + freedraw.height / 2, freedraw.y + freedraw.height / 2,
); );
const editor = getTextEditor(); const editor = await getTextEditor(textEditorSelector, true);
updateTextEditor(editor, "Hello World!"); updateTextEditor(editor, "Hello World!");
fireEvent.keyDown(editor, { key: KEYS.ESCAPE }); fireEvent.keyDown(editor, { key: KEYS.ESCAPE });
@@ -732,7 +738,7 @@ describe("textWysiwyg", () => {
expect(text.type).toBe("text"); expect(text.type).toBe("text");
expect(text.containerId).toBe(null); expect(text.containerId).toBe(null);
mouse.down(); mouse.down();
const editor = getTextEditor(); const editor = await getTextEditor(textEditorSelector, true);
updateTextEditor(editor, "Hello World!"); updateTextEditor(editor, "Hello World!");
@@ -747,7 +753,7 @@ describe("textWysiwyg", () => {
UI.clickTool("text"); UI.clickTool("text");
mouse.clickAt(20, 30); mouse.clickAt(20, 30);
const editor = getTextEditor(); const editor = await getTextEditor(textEditorSelector, true);
updateTextEditor( updateTextEditor(
editor, editor,
@@ -792,7 +798,7 @@ describe("textWysiwyg", () => {
mouse.down(); mouse.down();
const text = h.elements[1] as ExcalidrawTextElementWithContainer; const text = h.elements[1] as ExcalidrawTextElementWithContainer;
let editor = getTextEditor(); let editor = await getTextEditor(textEditorSelector, true);
await new Promise((r) => setTimeout(r, 0)); await new Promise((r) => setTimeout(r, 0));
updateTextEditor(editor, "Hello World!"); updateTextEditor(editor, "Hello World!");
@@ -805,7 +811,7 @@ describe("textWysiwyg", () => {
rectangle.y + rectangle.height / 2, rectangle.y + rectangle.height / 2,
); );
mouse.down(); mouse.down();
editor = getTextEditor(); editor = await getTextEditor(textEditorSelector, true);
editor.select(); editor.select();
fireEvent.click(screen.getByTitle(/code/i)); fireEvent.click(screen.getByTitle(/code/i));
@@ -838,7 +844,7 @@ describe("textWysiwyg", () => {
Keyboard.keyDown(KEYS.ENTER); Keyboard.keyDown(KEYS.ENTER);
let text = h.elements[1] as ExcalidrawTextElementWithContainer; let text = h.elements[1] as ExcalidrawTextElementWithContainer;
let editor = getTextEditor(); let editor = await getTextEditor(textEditorSelector, true);
updateTextEditor(editor, "Hello World!"); updateTextEditor(editor, "Hello World!");
@@ -859,7 +865,7 @@ describe("textWysiwyg", () => {
mouse.select(rectangle); mouse.select(rectangle);
Keyboard.keyPress(KEYS.ENTER); Keyboard.keyPress(KEYS.ENTER);
editor = getTextEditor(); editor = await getTextEditor(textEditorSelector, true);
updateTextEditor(editor, "Hello"); updateTextEditor(editor, "Hello");
await new Promise((r) => setTimeout(r, 0)); await new Promise((r) => setTimeout(r, 0));
@@ -888,7 +894,7 @@ describe("textWysiwyg", () => {
const text = h.elements[1] as ExcalidrawTextElementWithContainer; const text = h.elements[1] as ExcalidrawTextElementWithContainer;
expect(text.containerId).toBe(rectangle.id); expect(text.containerId).toBe(rectangle.id);
const editor = getTextEditor(); const editor = await getTextEditor(textEditorSelector, true);
await new Promise((r) => setTimeout(r, 0)); await new Promise((r) => setTimeout(r, 0));
@@ -925,7 +931,7 @@ describe("textWysiwyg", () => {
// Bind first text // Bind first text
const text = h.elements[1] as ExcalidrawTextElementWithContainer; const text = h.elements[1] as ExcalidrawTextElementWithContainer;
expect(text.containerId).toBe(rectangle.id); expect(text.containerId).toBe(rectangle.id);
const editor = getTextEditor(); const editor = await getTextEditor(textEditorSelector, true);
await new Promise((r) => setTimeout(r, 0)); await new Promise((r) => setTimeout(r, 0));
updateTextEditor(editor, "Hello World!"); updateTextEditor(editor, "Hello World!");
editor.blur(); editor.blur();
@@ -946,7 +952,7 @@ describe("textWysiwyg", () => {
it("should respect text alignment when resizing", async () => { it("should respect text alignment when resizing", async () => {
Keyboard.keyPress(KEYS.ENTER); Keyboard.keyPress(KEYS.ENTER);
let editor = getTextEditor(); let editor = await getTextEditor(textEditorSelector, true);
await new Promise((r) => setTimeout(r, 0)); await new Promise((r) => setTimeout(r, 0));
updateTextEditor(editor, "Hello"); updateTextEditor(editor, "Hello");
editor.blur(); editor.blur();
@@ -963,7 +969,7 @@ describe("textWysiwyg", () => {
mouse.select(rectangle); mouse.select(rectangle);
Keyboard.keyPress(KEYS.ENTER); Keyboard.keyPress(KEYS.ENTER);
editor = getTextEditor(); editor = await getTextEditor(textEditorSelector, true);
editor.select(); editor.select();
@@ -986,7 +992,7 @@ describe("textWysiwyg", () => {
mouse.select(rectangle); mouse.select(rectangle);
Keyboard.keyPress(KEYS.ENTER); Keyboard.keyPress(KEYS.ENTER);
editor = getTextEditor(); editor = await getTextEditor(textEditorSelector, true);
editor.select(); editor.select();
@@ -1024,7 +1030,7 @@ describe("textWysiwyg", () => {
expect(text.type).toBe("text"); expect(text.type).toBe("text");
expect(text.containerId).toBe(rectangle.id); expect(text.containerId).toBe(rectangle.id);
mouse.down(); mouse.down();
const editor = getTextEditor(); const editor = await getTextEditor(textEditorSelector, true);
updateTextEditor(editor, "Hello World!"); updateTextEditor(editor, "Hello World!");
@@ -1039,7 +1045,7 @@ describe("textWysiwyg", () => {
it("should scale font size correctly when resizing using shift", async () => { it("should scale font size correctly when resizing using shift", async () => {
Keyboard.keyPress(KEYS.ENTER); Keyboard.keyPress(KEYS.ENTER);
const editor = getTextEditor(); const editor = await getTextEditor(textEditorSelector, true);
await new Promise((r) => setTimeout(r, 0)); await new Promise((r) => setTimeout(r, 0));
updateTextEditor(editor, "Hello"); updateTextEditor(editor, "Hello");
editor.blur(); editor.blur();
@@ -1059,7 +1065,7 @@ describe("textWysiwyg", () => {
it("should bind text correctly when container duplicated with alt-drag", async () => { it("should bind text correctly when container duplicated with alt-drag", async () => {
Keyboard.keyPress(KEYS.ENTER); Keyboard.keyPress(KEYS.ENTER);
const editor = getTextEditor(); const editor = await getTextEditor(textEditorSelector, true);
await new Promise((r) => setTimeout(r, 0)); await new Promise((r) => setTimeout(r, 0));
updateTextEditor(editor, "Hello"); updateTextEditor(editor, "Hello");
editor.blur(); editor.blur();
@@ -1091,7 +1097,7 @@ describe("textWysiwyg", () => {
it("undo should work", async () => { it("undo should work", async () => {
Keyboard.keyPress(KEYS.ENTER); Keyboard.keyPress(KEYS.ENTER);
const editor = getTextEditor(); const editor = await getTextEditor(textEditorSelector, true);
await new Promise((r) => setTimeout(r, 0)); await new Promise((r) => setTimeout(r, 0));
updateTextEditor(editor, "Hello"); updateTextEditor(editor, "Hello");
editor.blur(); editor.blur();
@@ -1128,7 +1134,7 @@ describe("textWysiwyg", () => {
it("should not allow bound text with only whitespaces", async () => { it("should not allow bound text with only whitespaces", async () => {
Keyboard.keyPress(KEYS.ENTER); Keyboard.keyPress(KEYS.ENTER);
const editor = getTextEditor(); const editor = await getTextEditor(textEditorSelector, true);
await new Promise((r) => setTimeout(r, 0)); await new Promise((r) => setTimeout(r, 0));
updateTextEditor(editor, " "); updateTextEditor(editor, " ");
@@ -1183,7 +1189,7 @@ describe("textWysiwyg", () => {
it("should reset the container height cache when resizing", async () => { it("should reset the container height cache when resizing", async () => {
Keyboard.keyPress(KEYS.ENTER); Keyboard.keyPress(KEYS.ENTER);
expect(getOriginalContainerHeightFromCache(rectangle.id)).toBe(75); expect(getOriginalContainerHeightFromCache(rectangle.id)).toBe(75);
let editor = getTextEditor(); let editor = await getTextEditor(textEditorSelector, true);
await new Promise((r) => setTimeout(r, 0)); await new Promise((r) => setTimeout(r, 0));
updateTextEditor(editor, "Hello"); updateTextEditor(editor, "Hello");
editor.blur(); editor.blur();
@@ -1195,7 +1201,7 @@ describe("textWysiwyg", () => {
mouse.select(rectangle); mouse.select(rectangle);
Keyboard.keyPress(KEYS.ENTER); Keyboard.keyPress(KEYS.ENTER);
editor = getTextEditor(); editor = await getTextEditor(textEditorSelector, true);
await new Promise((r) => setTimeout(r, 0)); await new Promise((r) => setTimeout(r, 0));
editor.blur(); editor.blur();
@@ -1211,7 +1217,7 @@ describe("textWysiwyg", () => {
Keyboard.keyPress(KEYS.ENTER); Keyboard.keyPress(KEYS.ENTER);
expect(getOriginalContainerHeightFromCache(rectangle.id)).toBe(75); expect(getOriginalContainerHeightFromCache(rectangle.id)).toBe(75);
const editor = getTextEditor(); const editor = await getTextEditor(textEditorSelector, true);
updateTextEditor(editor, "Hello World!"); updateTextEditor(editor, "Hello World!");
editor.blur(); editor.blur();
@@ -1236,7 +1242,7 @@ describe("textWysiwyg", () => {
Keyboard.keyPress(KEYS.ENTER); Keyboard.keyPress(KEYS.ENTER);
expect(getOriginalContainerHeightFromCache(rectangle.id)).toBe(75); expect(getOriginalContainerHeightFromCache(rectangle.id)).toBe(75);
const editor = getTextEditor(); const editor = await getTextEditor(textEditorSelector, true);
updateTextEditor(editor, "Hello World!"); updateTextEditor(editor, "Hello World!");
editor.blur(); editor.blur();
expect( expect(
@@ -1268,12 +1274,12 @@ describe("textWysiwyg", () => {
beforeEach(async () => { beforeEach(async () => {
Keyboard.keyPress(KEYS.ENTER); Keyboard.keyPress(KEYS.ENTER);
editor = getTextEditor(); editor = await getTextEditor(textEditorSelector, true);
updateTextEditor(editor, "Hello"); updateTextEditor(editor, "Hello");
editor.blur(); editor.blur();
mouse.select(rectangle); mouse.select(rectangle);
Keyboard.keyPress(KEYS.ENTER); Keyboard.keyPress(KEYS.ENTER);
editor = getTextEditor(); editor = await getTextEditor(textEditorSelector, true);
editor.select(); editor.select();
}); });
@@ -1384,7 +1390,7 @@ describe("textWysiwyg", () => {
it("should wrap text in a container when wrap text in container triggered from context menu", async () => { it("should wrap text in a container when wrap text in container triggered from context menu", async () => {
UI.clickTool("text"); UI.clickTool("text");
mouse.clickAt(20, 30); mouse.clickAt(20, 30);
const editor = getTextEditor(); const editor = await getTextEditor(textEditorSelector, true);
updateTextEditor( updateTextEditor(
editor, editor,
@@ -1430,7 +1436,7 @@ describe("textWysiwyg", () => {
type: "text", type: "text",
}, },
], ],
fillStyle: "hachure", fillStyle: "solid",
groupIds: [], groupIds: [],
height: 35, height: 35,
isDeleted: false, isDeleted: false,
@@ -1443,7 +1449,7 @@ describe("textWysiwyg", () => {
}, },
strokeColor: "#1e1e1e", strokeColor: "#1e1e1e",
strokeStyle: "solid", strokeStyle: "solid",
strokeWidth: 1, strokeWidth: 2,
type: "rectangle", type: "rectangle",
updated: 1, updated: 1,
version: 1, version: 1,
@@ -1472,7 +1478,7 @@ describe("textWysiwyg", () => {
// Bind first text // Bind first text
let text = h.elements[1] as ExcalidrawTextElementWithContainer; let text = h.elements[1] as ExcalidrawTextElementWithContainer;
expect(text.containerId).toBe(rectangle.id); expect(text.containerId).toBe(rectangle.id);
let editor = getTextEditor(); let editor = await getTextEditor(textEditorSelector, true);
await new Promise((r) => setTimeout(r, 0)); await new Promise((r) => setTimeout(r, 0));
updateTextEditor(editor, "Hello!"); updateTextEditor(editor, "Hello!");
expect( expect(
@@ -1497,7 +1503,7 @@ describe("textWysiwyg", () => {
rectangle.x + rectangle.width / 2, rectangle.x + rectangle.width / 2,
rectangle.y + rectangle.height / 2, rectangle.y + rectangle.height / 2,
); );
editor = getTextEditor(); editor = await getTextEditor(textEditorSelector, true);
await new Promise((r) => setTimeout(r, 0)); await new Promise((r) => setTimeout(r, 0));
updateTextEditor(editor, "Excalidraw"); updateTextEditor(editor, "Excalidraw");
editor.blur(); editor.blur();
@@ -1511,18 +1517,4 @@ describe("textWysiwyg", () => {
expect(text.text).toBe("Excalidraw"); expect(text.text).toBe("Excalidraw");
}); });
}); });
it("should bump the version of a labeled arrow when the label is updated", async () => {
await render(<Excalidraw handleKeyboardGlobally={true} />);
const arrow = UI.createElement("arrow", {
width: 300,
height: 0,
});
await UI.editText(arrow, "Hello");
const { version } = arrow;
await UI.editText(arrow, "Hello\nworld!");
expect(arrow.version).toEqual(version + 1);
});
}); });
+2 -2
View File
@@ -4,7 +4,7 @@ import {
PointerType, PointerType,
} from "./types"; } from "./types";
import { getElementAbsoluteCoords } from "./bounds"; import { Bounds, getElementAbsoluteCoords } from "./bounds";
import { rotate } from "../math"; import { rotate } from "../math";
import { InteractiveCanvasAppState, Zoom } from "../types"; import { InteractiveCanvasAppState, Zoom } from "../types";
import { isTextElement } from "."; import { isTextElement } from ".";
@@ -23,7 +23,7 @@ export type TransformHandleDirection =
export type TransformHandleType = TransformHandleDirection | "rotation"; export type TransformHandleType = TransformHandleDirection | "rotation";
export type TransformHandle = [number, number, number, number]; export type TransformHandle = Bounds;
export type TransformHandles = Partial<{ export type TransformHandles = Partial<{
[T in TransformHandleType]: TransformHandle; [T in TransformHandleType]: TransformHandle;
}>; }>;
+47
View File
@@ -0,0 +1,47 @@
type Subscriber<T extends any[]> = (...payload: T) => void;
export class Emitter<T extends any[] = []> {
public subscribers: Subscriber<T>[] = [];
public value: T | undefined;
private updateOnChangeOnly: boolean;
constructor(opts?: { initialState?: T; updateOnChangeOnly?: boolean }) {
this.updateOnChangeOnly = opts?.updateOnChangeOnly ?? false;
this.value = opts?.initialState;
}
/**
* Attaches subscriber
*
* @returns unsubscribe function
*/
on(...handlers: Subscriber<T>[] | Subscriber<T>[][]) {
const _handlers = handlers
.flat()
.filter((item) => typeof item === "function");
this.subscribers.push(..._handlers);
return () => this.off(_handlers);
}
off(...handlers: Subscriber<T>[] | Subscriber<T>[][]) {
const _handlers = handlers.flat();
this.subscribers = this.subscribers.filter(
(handler) => !_handlers.includes(handler),
);
}
trigger(...payload: T): any[] {
if (this.updateOnChangeOnly && this.value === payload) {
return [];
}
this.value = payload;
return this.subscribers.map((handler) => handler(...payload));
}
destroy() {
this.subscribers = [];
this.value = undefined;
}
}
+13 -13
View File
@@ -123,7 +123,7 @@ describe("adding elements to frames", () => {
const commonTestCases = async ( const commonTestCases = async (
func: typeof resizeFrameOverElement | typeof dragElementIntoFrame, func: typeof resizeFrameOverElement | typeof dragElementIntoFrame,
) => { ) => {
describe("when frame is in a layer below", async () => { describe.skip("when frame is in a layer below", async () => {
it("should add an element", async () => { it("should add an element", async () => {
h.elements = [frame, rect2]; h.elements = [frame, rect2];
@@ -167,7 +167,7 @@ describe("adding elements to frames", () => {
}); });
}); });
describe("when frame is in a layer above", async () => { describe.skip("when frame is in a layer above", async () => {
it("should add an element", async () => { it("should add an element", async () => {
h.elements = [rect2, frame]; h.elements = [rect2, frame];
@@ -212,7 +212,7 @@ describe("adding elements to frames", () => {
}); });
describe("when frame is in an inner layer", async () => { describe("when frame is in an inner layer", async () => {
it("should add elements", async () => { it.skip("should add elements", async () => {
h.elements = [rect2, frame, rect3]; h.elements = [rect2, frame, rect3];
func(frame, rect2); func(frame, rect2);
@@ -223,7 +223,7 @@ describe("adding elements to frames", () => {
expectEqualIds([rect2, rect3, frame]); expectEqualIds([rect2, rect3, frame]);
}); });
it("should add elements when there are other other elements in between", async () => { it.skip("should add elements when there are other other elements in between", async () => {
h.elements = [rect2, rect1, frame, rect4, rect3]; h.elements = [rect2, rect1, frame, rect4, rect3];
func(frame, rect2); func(frame, rect2);
@@ -234,7 +234,7 @@ describe("adding elements to frames", () => {
expectEqualIds([rect1, rect2, rect3, frame, rect4]); expectEqualIds([rect1, rect2, rect3, frame, rect4]);
}); });
it("should add elements when there are other elements in between and the order is reversed", async () => { it.skip("should add elements when there are other elements in between and the order is reversed", async () => {
h.elements = [rect3, rect4, frame, rect2, rect1]; h.elements = [rect3, rect4, frame, rect2, rect1];
func(frame, rect2); func(frame, rect2);
@@ -289,7 +289,7 @@ describe("adding elements to frames", () => {
describe("resizing frame over elements", async () => { describe("resizing frame over elements", async () => {
await commonTestCases(resizeFrameOverElement); await commonTestCases(resizeFrameOverElement);
it("resizing over text containers and labelled arrows", async () => { it.skip("resizing over text containers and labelled arrows", async () => {
await resizingTest( await resizingTest(
"rectangle", "rectangle",
["frame", "rectangle", "text"], ["frame", "rectangle", "text"],
@@ -339,7 +339,7 @@ describe("adding elements to frames", () => {
// ); // );
}); });
it("should add arrow bound with text when frame is in a layer below", async () => { it.skip("should add arrow bound with text when frame is in a layer below", async () => {
h.elements = [frame, arrow, text]; h.elements = [frame, arrow, text];
resizeFrameOverElement(frame, arrow); resizeFrameOverElement(frame, arrow);
@@ -359,7 +359,7 @@ describe("adding elements to frames", () => {
expectEqualIds([arrow, text, frame]); expectEqualIds([arrow, text, frame]);
}); });
it("should add arrow bound with text when frame is in an inner layer", async () => { it.skip("should add arrow bound with text when frame is in an inner layer", async () => {
h.elements = [arrow, frame, text]; h.elements = [arrow, frame, text];
resizeFrameOverElement(frame, arrow); resizeFrameOverElement(frame, arrow);
@@ -371,7 +371,7 @@ describe("adding elements to frames", () => {
}); });
describe("resizing frame over elements but downwards", async () => { describe("resizing frame over elements but downwards", async () => {
it("should add elements when frame is in a layer below", async () => { it.skip("should add elements when frame is in a layer below", async () => {
h.elements = [frame, rect1, rect2, rect3, rect4]; h.elements = [frame, rect1, rect2, rect3, rect4];
resizeFrameOverElement(frame, rect4); resizeFrameOverElement(frame, rect4);
@@ -382,7 +382,7 @@ describe("adding elements to frames", () => {
expectEqualIds([rect2, rect3, frame, rect4, rect1]); expectEqualIds([rect2, rect3, frame, rect4, rect1]);
}); });
it("should add elements when frame is in a layer above", async () => { it.skip("should add elements when frame is in a layer above", async () => {
h.elements = [rect1, rect2, rect3, rect4, frame]; h.elements = [rect1, rect2, rect3, rect4, frame];
resizeFrameOverElement(frame, rect4); resizeFrameOverElement(frame, rect4);
@@ -393,7 +393,7 @@ describe("adding elements to frames", () => {
expectEqualIds([rect1, rect2, rect3, frame, rect4]); expectEqualIds([rect1, rect2, rect3, frame, rect4]);
}); });
it("should add elements when frame is in an inner layer", async () => { it.skip("should add elements when frame is in an inner layer", async () => {
h.elements = [rect1, rect2, frame, rect3, rect4]; h.elements = [rect1, rect2, frame, rect3, rect4];
resizeFrameOverElement(frame, rect4); resizeFrameOverElement(frame, rect4);
@@ -408,7 +408,7 @@ describe("adding elements to frames", () => {
describe("dragging elements into the frame", async () => { describe("dragging elements into the frame", async () => {
await commonTestCases(dragElementIntoFrame); await commonTestCases(dragElementIntoFrame);
it("should drag element inside, duplicate it and keep it in frame", () => { it.skip("should drag element inside, duplicate it and keep it in frame", () => {
h.elements = [frame, rect2]; h.elements = [frame, rect2];
dragElementIntoFrame(frame, rect2); dragElementIntoFrame(frame, rect2);
@@ -422,7 +422,7 @@ describe("adding elements to frames", () => {
expectEqualIds([rect2_copy, rect2, frame]); expectEqualIds([rect2_copy, rect2, frame]);
}); });
it("should drag element inside, duplicate it and remove it from frame", () => { it.skip("should drag element inside, duplicate it and remove it from frame", () => {
h.elements = [frame, rect2]; h.elements = [frame, rect2];
dragElementIntoFrame(frame, rect2); dragElementIntoFrame(frame, rect2);
+49 -217
View File
@@ -19,10 +19,10 @@ import { mutateElement } from "./element/mutateElement";
import { AppClassProperties, AppState, StaticCanvasAppState } from "./types"; import { AppClassProperties, AppState, StaticCanvasAppState } from "./types";
import { getElementsWithinSelection, getSelectedElements } from "./scene"; import { getElementsWithinSelection, getSelectedElements } from "./scene";
import { isFrameElement } from "./element"; import { isFrameElement } from "./element";
import { moveOneRight } from "./zindex";
import { getElementsInGroup, selectGroupsFromGivenElements } from "./groups"; import { getElementsInGroup, selectGroupsFromGivenElements } from "./groups";
import Scene, { ExcalidrawElementsIncludingDeleted } from "./scene/Scene"; import Scene, { ExcalidrawElementsIncludingDeleted } from "./scene/Scene";
import { getElementLineSegments } from "./element/bounds"; import { getElementLineSegments } from "./element/bounds";
import { doLineSegmentsIntersect } from "./packages/utils";
// --------------------------- Frame State ------------------------------------ // --------------------------- Frame State ------------------------------------
export const bindElementsToFramesAfterDuplication = ( export const bindElementsToFramesAfterDuplication = (
@@ -56,130 +56,21 @@ export const bindElementsToFramesAfterDuplication = (
} }
}; };
// --------------------------- Frame Geometry --------------------------------- export function isElementIntersectingFrame(
class Point { element: ExcalidrawElement,
x: number; frame: ExcalidrawFrameElement,
y: number; ) {
const frameLineSegments = getElementLineSegments(frame);
constructor(x: number, y: number) { const elementLineSegments = getElementLineSegments(element);
this.x = x;
this.y = y;
}
}
class LineSegment { const intersecting = frameLineSegments.some((frameLineSegment) =>
first: Point; elementLineSegments.some((elementLineSegment) =>
second: Point; doLineSegmentsIntersect(frameLineSegment, elementLineSegment),
),
);
constructor(pointA: Point, pointB: Point) { return intersecting;
this.first = pointA;
this.second = pointB;
}
public getBoundingBox(): [Point, Point] {
return [
new Point(
Math.min(this.first.x, this.second.x),
Math.min(this.first.y, this.second.y),
),
new Point(
Math.max(this.first.x, this.second.x),
Math.max(this.first.y, this.second.y),
),
];
}
}
// https://martin-thoma.com/how-to-check-if-two-line-segments-intersect/
class FrameGeometry {
private static EPSILON = 0.000001;
private static crossProduct(a: Point, b: Point) {
return a.x * b.y - b.x * a.y;
}
private static doBoundingBoxesIntersect(
a: [Point, Point],
b: [Point, Point],
) {
return (
a[0].x <= b[1].x &&
a[1].x >= b[0].x &&
a[0].y <= b[1].y &&
a[1].y >= b[0].y
);
}
private static isPointOnLine(a: LineSegment, b: Point) {
const aTmp = new LineSegment(
new Point(0, 0),
new Point(a.second.x - a.first.x, a.second.y - a.first.y),
);
const bTmp = new Point(b.x - a.first.x, b.y - a.first.y);
const r = this.crossProduct(aTmp.second, bTmp);
return Math.abs(r) < this.EPSILON;
}
private static isPointRightOfLine(a: LineSegment, b: Point) {
const aTmp = new LineSegment(
new Point(0, 0),
new Point(a.second.x - a.first.x, a.second.y - a.first.y),
);
const bTmp = new Point(b.x - a.first.x, b.y - a.first.y);
return this.crossProduct(aTmp.second, bTmp) < 0;
}
private static lineSegmentTouchesOrCrossesLine(
a: LineSegment,
b: LineSegment,
) {
return (
this.isPointOnLine(a, b.first) ||
this.isPointOnLine(a, b.second) ||
(this.isPointRightOfLine(a, b.first)
? !this.isPointRightOfLine(a, b.second)
: this.isPointRightOfLine(a, b.second))
);
}
private static doLineSegmentsIntersect(
a: [readonly [number, number], readonly [number, number]],
b: [readonly [number, number], readonly [number, number]],
) {
const aSegment = new LineSegment(
new Point(a[0][0], a[0][1]),
new Point(a[1][0], a[1][1]),
);
const bSegment = new LineSegment(
new Point(b[0][0], b[0][1]),
new Point(b[1][0], b[1][1]),
);
const box1 = aSegment.getBoundingBox();
const box2 = bSegment.getBoundingBox();
return (
this.doBoundingBoxesIntersect(box1, box2) &&
this.lineSegmentTouchesOrCrossesLine(aSegment, bSegment) &&
this.lineSegmentTouchesOrCrossesLine(bSegment, aSegment)
);
}
public static isElementIntersectingFrame(
element: ExcalidrawElement,
frame: ExcalidrawFrameElement,
) {
const frameLineSegments = getElementLineSegments(frame);
const elementLineSegments = getElementLineSegments(element);
const intersecting = frameLineSegments.some((frameLineSegment) =>
elementLineSegments.some((elementLineSegment) =>
this.doLineSegmentsIntersect(frameLineSegment, elementLineSegment),
),
);
return intersecting;
}
} }
export const getElementsCompletelyInFrame = ( export const getElementsCompletelyInFrame = (
@@ -207,10 +98,7 @@ export const isElementContainingFrame = (
export const getElementsIntersectingFrame = ( export const getElementsIntersectingFrame = (
elements: readonly ExcalidrawElement[], elements: readonly ExcalidrawElement[],
frame: ExcalidrawFrameElement, frame: ExcalidrawFrameElement,
) => ) => elements.filter((element) => isElementIntersectingFrame(element, frame));
elements.filter((element) =>
FrameGeometry.isElementIntersectingFrame(element, frame),
);
export const elementsAreInFrameBounds = ( export const elementsAreInFrameBounds = (
elements: readonly ExcalidrawElement[], elements: readonly ExcalidrawElement[],
@@ -236,7 +124,7 @@ export const elementOverlapsWithFrame = (
) => { ) => {
return ( return (
elementsAreInFrameBounds([element], frame) || elementsAreInFrameBounds([element], frame) ||
FrameGeometry.isElementIntersectingFrame(element, frame) || isElementIntersectingFrame(element, frame) ||
isElementContainingFrame([frame], element, frame) isElementContainingFrame([frame], element, frame)
); );
}; };
@@ -273,7 +161,7 @@ export const groupsAreAtLeastIntersectingTheFrame = (
return !!elementsInGroup.find( return !!elementsInGroup.find(
(element) => (element) =>
elementsAreInFrameBounds([element], frame) || elementsAreInFrameBounds([element], frame) ||
FrameGeometry.isElementIntersectingFrame(element, frame), isElementIntersectingFrame(element, frame),
); );
}; };
@@ -294,7 +182,7 @@ export const groupsAreCompletelyOutOfFrame = (
elementsInGroup.find( elementsInGroup.find(
(element) => (element) =>
elementsAreInFrameBounds([element], frame) || elementsAreInFrameBounds([element], frame) ||
FrameGeometry.isElementIntersectingFrame(element, frame), isElementIntersectingFrame(element, frame),
) === undefined ) === undefined
); );
}; };
@@ -354,7 +242,7 @@ export const getElementsInResizingFrame = (
); );
for (const element of elementsNotCompletelyInFrame) { for (const element of elementsNotCompletelyInFrame) {
if (!FrameGeometry.isElementIntersectingFrame(element, frame)) { if (!isElementIntersectingFrame(element, frame)) {
if (element.groupIds.length === 0) { if (element.groupIds.length === 0) {
nextElementsInFrame.delete(element); nextElementsInFrame.delete(element);
} }
@@ -463,20 +351,17 @@ export const addElementsToFrame = (
elementsToAdd: NonDeletedExcalidrawElement[], elementsToAdd: NonDeletedExcalidrawElement[],
frame: ExcalidrawFrameElement, frame: ExcalidrawFrameElement,
) => { ) => {
const { allElementsIndexMap, currTargetFrameChildrenMap } = const { currTargetFrameChildrenMap } = allElements.reduce(
allElements.reduce( (acc, element, index) => {
(acc, element, index) => { if (element.frameId === frame.id) {
acc.allElementsIndexMap.set(element.id, index); acc.currTargetFrameChildrenMap.set(element.id, true);
if (element.frameId === frame.id) { }
acc.currTargetFrameChildrenMap.set(element.id, true); return acc;
} },
return acc; {
}, currTargetFrameChildrenMap: new Map<ExcalidrawElement["id"], true>(),
{ },
allElementsIndexMap: new Map<ExcalidrawElement["id"], number>(), );
currTargetFrameChildrenMap: new Map<ExcalidrawElement["id"], true>(),
},
);
const suppliedElementsToAddSet = new Set(elementsToAdd.map((el) => el.id)); const suppliedElementsToAddSet = new Set(elementsToAdd.map((el) => el.id));
@@ -502,66 +387,6 @@ export const addElementsToFrame = (
} }
} }
const finalElementsToAddSet = new Set(finalElementsToAdd.map((el) => el.id));
const nextElements: ExcalidrawElement[] = [];
const processedElements = new Set<ExcalidrawElement["id"]>();
for (const element of allElements) {
if (processedElements.has(element.id)) {
continue;
}
processedElements.add(element.id);
if (
finalElementsToAddSet.has(element.id) ||
(element.frameId && element.frameId === frame.id)
) {
// will be added in bulk once we process target frame
continue;
}
// target frame
if (element.id === frame.id) {
const currFrameChildren = getFrameElements(allElements, frame.id);
currFrameChildren.forEach((child) => {
processedElements.add(child.id);
});
// if not found, add all children on top by assigning the lowest index
const targetFrameIndex = allElementsIndexMap.get(frame.id) ?? -1;
const { newChildren_left, newChildren_right } = finalElementsToAdd.reduce(
(acc, element) => {
// if index not found, add on top of current frame children
const elementIndex = allElementsIndexMap.get(element.id) ?? Infinity;
if (elementIndex < targetFrameIndex) {
acc.newChildren_left.push(element);
} else {
acc.newChildren_right.push(element);
}
return acc;
},
{
newChildren_left: [] as ExcalidrawElement[],
newChildren_right: [] as ExcalidrawElement[],
},
);
nextElements.push(
...newChildren_left,
...currFrameChildren,
...newChildren_right,
element,
);
continue;
}
nextElements.push(element);
}
for (const element of finalElementsToAdd) { for (const element of finalElementsToAdd) {
mutateElement( mutateElement(
element, element,
@@ -571,8 +396,7 @@ export const addElementsToFrame = (
false, false,
); );
} }
return allElements.slice();
return nextElements;
}; };
export const removeElementsFromFrame = ( export const removeElementsFromFrame = (
@@ -580,20 +404,34 @@ export const removeElementsFromFrame = (
elementsToRemove: NonDeletedExcalidrawElement[], elementsToRemove: NonDeletedExcalidrawElement[],
appState: AppState, appState: AppState,
) => { ) => {
const _elementsToRemove: ExcalidrawElement[] = []; const _elementsToRemove = new Map<
ExcalidrawElement["id"],
ExcalidrawElement
>();
const toRemoveElementsByFrame = new Map<
ExcalidrawFrameElement["id"],
ExcalidrawElement[]
>();
for (const element of elementsToRemove) { for (const element of elementsToRemove) {
if (element.frameId) { if (element.frameId) {
_elementsToRemove.push(element); _elementsToRemove.set(element.id, element);
const arr = toRemoveElementsByFrame.get(element.frameId) || [];
arr.push(element);
const boundTextElement = getBoundTextElement(element); const boundTextElement = getBoundTextElement(element);
if (boundTextElement) { if (boundTextElement) {
_elementsToRemove.push(boundTextElement); _elementsToRemove.set(boundTextElement.id, boundTextElement);
arr.push(boundTextElement);
} }
toRemoveElementsByFrame.set(element.frameId, arr);
} }
} }
for (const element of _elementsToRemove) { for (const [, element] of _elementsToRemove) {
mutateElement( mutateElement(
element, element,
{ {
@@ -603,13 +441,7 @@ export const removeElementsFromFrame = (
); );
} }
const nextElements = moveOneRight( return allElements.slice();
allElements,
appState,
Array.from(_elementsToRemove),
);
return nextElements;
}; };
export const removeAllElementsFromFrame = ( export const removeAllElementsFromFrame = (
+6 -6
View File
@@ -17,9 +17,13 @@ export const useCreatePortalContainer = (opts?: {
useLayoutEffect(() => { useLayoutEffect(() => {
if (div) { if (div) {
div.className = "";
div.classList.add("excalidraw", ...(opts?.className?.split(/\s+/) || []));
div.classList.toggle("excalidraw--mobile", device.isMobile); div.classList.toggle("excalidraw--mobile", device.isMobile);
div.classList.toggle("excalidraw--mobile", isMobileRef.current);
div.classList.toggle("theme--dark", theme === "dark");
} }
}, [div, device.isMobile]); }, [div, theme, device.isMobile, opts?.className]);
useLayoutEffect(() => { useLayoutEffect(() => {
const container = opts?.parentSelector const container = opts?.parentSelector
@@ -32,10 +36,6 @@ export const useCreatePortalContainer = (opts?: {
const div = document.createElement("div"); const div = document.createElement("div");
div.classList.add("excalidraw", ...(opts?.className?.split(/\s+/) || []));
div.classList.toggle("excalidraw--mobile", isMobileRef.current);
div.classList.toggle("theme--dark", theme === "dark");
container.appendChild(div); container.appendChild(div);
setDiv(div); setDiv(div);
@@ -43,7 +43,7 @@ export const useCreatePortalContainer = (opts?: {
return () => { return () => {
container.removeChild(div); container.removeChild(div);
}; };
}, [excalidrawContainer, theme, opts?.className, opts?.parentSelector]); }, [excalidrawContainer, opts?.parentSelector]);
return div; return div;
}; };
+129 -80
View File
@@ -50,7 +50,7 @@
"veryLarge": "كبير جدا", "veryLarge": "كبير جدا",
"solid": "كامل", "solid": "كامل",
"hachure": "خطوط", "hachure": "خطوط",
"zigzag": "", "zigzag": "متعرج",
"crossHatch": "خطوط متقطعة", "crossHatch": "خطوط متقطعة",
"thin": "نحيف", "thin": "نحيف",
"bold": "داكن", "bold": "داكن",
@@ -106,11 +106,15 @@
"increaseFontSize": "تكبير حجم الخط", "increaseFontSize": "تكبير حجم الخط",
"unbindText": "فك ربط النص", "unbindText": "فك ربط النص",
"bindText": "ربط النص بالحاوية", "bindText": "ربط النص بالحاوية",
"createContainerFromText": "", "createContainerFromText": "نص مغلف في حاوية",
"link": { "link": {
"edit": "تعديل الرابط", "edit": "تعديل الرابط",
"editEmbed": "تحرير الرابط وإدراجه",
"create": "إنشاء رابط", "create": "إنشاء رابط",
"label": "رابط" "createEmbed": "إنشاء رابط و إدراجه",
"label": "رابط",
"labelEmbed": "رابط و إدراج",
"empty": "لم يتم تعيين رابط"
}, },
"lineEditor": { "lineEditor": {
"edit": "تحرير السطر", "edit": "تحرير السطر",
@@ -124,9 +128,9 @@
}, },
"statusPublished": "نُشر", "statusPublished": "نُشر",
"sidebarLock": "إبقاء الشريط الجانبي مفتوح", "sidebarLock": "إبقاء الشريط الجانبي مفتوح",
"selectAllElementsInFrame": "", "selectAllElementsInFrame": "تحديد جميع العناصر في الإطار",
"removeAllElementsFromFrame": "", "removeAllElementsFromFrame": "إزالة جميع العناصر من الإطار",
"eyeDropper": "" "eyeDropper": "اختيار اللون من القماش"
}, },
"library": { "library": {
"noItems": "لا توجد عناصر أضيفت بعد...", "noItems": "لا توجد عناصر أضيفت بعد...",
@@ -160,13 +164,16 @@
"darkMode": "الوضع المظلم", "darkMode": "الوضع المظلم",
"lightMode": "الوضع المضيء", "lightMode": "الوضع المضيء",
"zenMode": "وضع التأمل", "zenMode": "وضع التأمل",
"objectsSnapMode": "التقط إلى العناصر",
"exitZenMode": "إلغاء الوضع الليلى", "exitZenMode": "إلغاء الوضع الليلى",
"cancel": "إلغاء", "cancel": "إلغاء",
"clear": "مسح", "clear": "مسح",
"remove": "إزالة", "remove": "إزالة",
"embed": "تبديل الإدراج",
"publishLibrary": "انشر", "publishLibrary": "انشر",
"submit": "أرسل", "submit": "أرسل",
"confirm": "تأكيد" "confirm": "تأكيد",
"embeddableInteractionButton": "اضغط للتفاعل"
}, },
"alerts": { "alerts": {
"clearReset": "هذا سيُزيل كامل اللوحة. هل أنت متأكد؟", "clearReset": "هذا سيُزيل كامل اللوحة. هل أنت متأكد؟",
@@ -189,23 +196,28 @@
"resetLibrary": "هذا سوف يمسح مكتبتك. هل أنت متأكد؟", "resetLibrary": "هذا سوف يمسح مكتبتك. هل أنت متأكد؟",
"removeItemsFromsLibrary": "حذف {{count}} عنصر (عناصر) من المكتبة؟", "removeItemsFromsLibrary": "حذف {{count}} عنصر (عناصر) من المكتبة؟",
"invalidEncryptionKey": "مفتاح التشفير يجب أن يكون من 22 حرفاً. التعاون المباشر معطل.", "invalidEncryptionKey": "مفتاح التشفير يجب أن يكون من 22 حرفاً. التعاون المباشر معطل.",
"collabOfflineWarning": "" "collabOfflineWarning": "لا يوجد اتصال بالانترنت.\nلن يتم حفظ التغييرات التي قمت بها!"
}, },
"errors": { "errors": {
"unsupportedFileType": "نوع الملف غير مدعوم.", "unsupportedFileType": "نوع الملف غير مدعوم.",
"imageInsertError": "تعذر إدراج الصورة. حاول مرة أخرى لاحقاً...", "imageInsertError": "تعذر إدراج الصورة. حاول مرة أخرى لاحقاً...",
"fileTooBig": "الملف كبير جداً. الحد الأقصى المسموح به للحجم هو {{maxSize}}.", "fileTooBig": "الملف كبير جداً. الحد الأقصى المسموح به للحجم هو {{maxSize}}.",
"svgImageInsertError": "تعذر إدراج صورة SVG. يبدو أن ترميز SVG غير صحيح.", "svgImageInsertError": "تعذر إدراج صورة SVG. يبدو أن ترميز SVG غير صحيح.",
"failedToFetchImage": "",
"invalidSVGString": "SVG غير صالح.", "invalidSVGString": "SVG غير صالح.",
"cannotResolveCollabServer": "تعذر الاتصال بخادم التعاون. الرجاء إعادة تحميل الصفحة والمحاولة مرة أخرى.", "cannotResolveCollabServer": "تعذر الاتصال بخادم التعاون. الرجاء إعادة تحميل الصفحة والمحاولة مرة أخرى.",
"importLibraryError": "تعذر تحميل المكتبة", "importLibraryError": "تعذر تحميل المكتبة",
"collabSaveFailed": "تعذر الحفظ في قاعدة البيانات. إذا استمرت المشاكل، يفضل أن تحفظ ملفك محليا كي لا تفقد عملك.", "collabSaveFailed": "تعذر الحفظ في قاعدة البيانات. إذا استمرت المشاكل، يفضل أن تحفظ ملفك محليا كي لا تفقد عملك.",
"collabSaveFailed_sizeExceeded": "تعذر الحفظ في قاعدة البيانات، يبدو أن القماش كبير للغاية، يفضّل حفظ الملف محليا كي لا تفقد عملك.", "collabSaveFailed_sizeExceeded": "تعذر الحفظ في قاعدة البيانات، يبدو أن القماش كبير للغاية، يفضّل حفظ الملف محليا كي لا تفقد عملك.",
"brave_measure_text_error": { "brave_measure_text_error": {
"line1": "", "line1": "يبدو أنك تستخدم متصفح Brave مع إعداد <bold>حظر صارم لتتبع البصمة</bold>.",
"line2": "", "line2": "قد يؤدي هذا إلى كسر <bold>عناصر النص</bold> في الرسومات الخاصة بك.",
"line3": "", "line3": "من المستحسن إلغاء تفعيل هذا الإعداد. يمكنك اتباع <link>هذه الخطوات</link> لفعل ذلك.",
"line4": "" "line4": "إذا لم يصلح تعطيل هذا الإعداد طريقة عرض النصوص، الرجاء كتابة <issueLink>بلاغ</issueLink> على حسابنا في GitHub، أو راسلنا على <discordLink>Discord</discordLink>"
},
"libraryElementTypeError": {
"embeddable": "لا يمكن إضافة العناصر القابلة للتضمين في المكتبة.",
"image": "سوف يتم دعم إضافة صور إلى المكتبة قريباً!"
} }
}, },
"toolBar": { "toolBar": {
@@ -223,9 +235,11 @@
"penMode": "وضع القلم - امنع اللمس", "penMode": "وضع القلم - امنع اللمس",
"link": "إضافة/تحديث الرابط للشكل المحدد", "link": "إضافة/تحديث الرابط للشكل المحدد",
"eraser": "ممحاة", "eraser": "ممحاة",
"frame": "", "frame": "أداة الإطار",
"hand": "", "embeddable": "تضمين ويب",
"extraTools": "" "laser": "مؤشر ليزر",
"hand": "يد (أداة الإزاحة)",
"extraTools": "المزيد من أﻷدوات"
}, },
"headings": { "headings": {
"canvasActions": "إجراءات اللوحة", "canvasActions": "إجراءات اللوحة",
@@ -237,6 +251,7 @@
"linearElement": "انقر لبدء نقاط متعددة، اسحب لخط واحد", "linearElement": "انقر لبدء نقاط متعددة، اسحب لخط واحد",
"freeDraw": "انقر واسحب، افرج عند الانتهاء", "freeDraw": "انقر واسحب، افرج عند الانتهاء",
"text": "نصيحة: يمكنك أيضًا إضافة نص بالنقر المزدوج في أي مكان بأداة الاختيار", "text": "نصيحة: يمكنك أيضًا إضافة نص بالنقر المزدوج في أي مكان بأداة الاختيار",
"embeddable": "اضغط مع السحب لإنشاء موقع ويب مضمّن",
"text_selected": "انقر نقراً مزدوجاً أو اضغط ادخال لتعديل النص", "text_selected": "انقر نقراً مزدوجاً أو اضغط ادخال لتعديل النص",
"text_editing": "اضغط على Esc أو (Ctrl أو Cmd) + Enter لإنهاء التعديل", "text_editing": "اضغط على Esc أو (Ctrl أو Cmd) + Enter لإنهاء التعديل",
"linearElementMulti": "انقر فوق النقطة الأخيرة أو اضغط على Esc أو Enter للإنهاء", "linearElementMulti": "انقر فوق النقطة الأخيرة أو اضغط على Esc أو Enter للإنهاء",
@@ -245,14 +260,15 @@
"resizeImage": "يمكنك تغيير الحجم بحرية بالضغط بأستمرار على SHIFT،\nاضغط بأستمرار على ALT أيضا لتغيير الحجم من المركز", "resizeImage": "يمكنك تغيير الحجم بحرية بالضغط بأستمرار على SHIFT،\nاضغط بأستمرار على ALT أيضا لتغيير الحجم من المركز",
"rotate": "يمكنك تقييد الزوايا من خلال الضغط على SHIFT أثناء الدوران", "rotate": "يمكنك تقييد الزوايا من خلال الضغط على SHIFT أثناء الدوران",
"lineEditor_info": "اضغط على مفتاح (Ctrl أو Cmd) و انقر بشكل مزدوج، أو اضغط على مفتاحي (Ctrl أو Cmd) و (Enter) لتعديل النقاط", "lineEditor_info": "اضغط على مفتاح (Ctrl أو Cmd) و انقر بشكل مزدوج، أو اضغط على مفتاحي (Ctrl أو Cmd) و (Enter) لتعديل النقاط",
"lineEditor_pointSelected": "", "lineEditor_pointSelected": "اضغط على حذف لإزالة النقطة (النِّقَاط)، Ctrl/Cmd+D للتكرار، أو اسحب للانتقال",
"lineEditor_nothingSelected": "", "lineEditor_nothingSelected": "اختر نقطة لتعديلها (اضغط على SHIFT لتحديد عدة نِقَاط),\nأو اضغط على ALT و انقر بالفأرة لإضافة نِقَاط جديدة",
"placeImage": "", "placeImage": "انقر لوضع الصورة، أو انقر واسحب لتعيين حجمها يدوياً",
"publishLibrary": "نشر مكتبتك", "publishLibrary": "نشر مكتبتك",
"bindTextToElement": "", "bindTextToElement": "اضغط على إدخال لإضافة نص",
"deepBoxSelect": "", "deepBoxSelect": "اضغط على Ctrl\\Cmd للاختيار العميق، ولمنع السحب",
"eraserRevert": "", "eraserRevert": "اضغط على Alt لاستعادة العناصر المعلَّمة للحذف",
"firefox_clipboard_write": "" "firefox_clipboard_write": "يمكن على الأرجح تمكين هذه الميزة عن طريق تعيين علم \"dom.events.asyncClipboard.clipboardItem\" إلى \"true\". لتغيير أعلام المتصفح في Firefox، قم بزيارة صفحة \"about:config\".",
"disableSnapping": "اضغط على Ctrl أو Cmd لتعطيل الالتقاط"
}, },
"canvasError": { "canvasError": {
"cannotShowPreview": "تعذر عرض المعاينة", "cannotShowPreview": "تعذر عرض المعاينة",
@@ -260,11 +276,11 @@
"canvasTooBigTip": "نصيحة: حاول تحريك العناصر البعيدة بشكل أقرب قليلاً." "canvasTooBigTip": "نصيحة: حاول تحريك العناصر البعيدة بشكل أقرب قليلاً."
}, },
"errorSplash": { "errorSplash": {
"headingMain": "", "headingMain": "حدث خطأ. حاول <button>تحديث الصفحة</button>.",
"clearCanvasMessage": "إذا لم تعمل إعادة التحميل، حاول مرة أخرى ", "clearCanvasMessage": "إذا لم تعمل إعادة التحميل، حاول مرة أخرى ",
"clearCanvasCaveat": " هذا سيؤدي إلى فقدان العمل ", "clearCanvasCaveat": " هذا سيؤدي إلى فقدان العمل ",
"trackedToSentry": "", "trackedToSentry": "تم تتبع الخطأ في المعرف {{eventId}} على نظامنا.",
"openIssueMessage": "", "openIssueMessage": "حرصنا على عدم إضافة معلومات المشهد في بلاغ الخطأ. في حال كون مشهدك لا يحمل أي معلومات خاصة نرجو المتابعة على <button>نظام تتبع الأخطاء</button>. نرجو إضافة المعلومات أدناه بنسخها ولصقها في محتوى البلاغ على GitHub.",
"sceneContent": "محتوى المشهد:" "sceneContent": "محتوى المشهد:"
}, },
"roomDialog": { "roomDialog": {
@@ -294,16 +310,16 @@
"helpDialog": { "helpDialog": {
"blog": "اقرأ مدونتنا", "blog": "اقرأ مدونتنا",
"click": "انقر", "click": "انقر",
"deepSelect": "", "deepSelect": "تحديد عميق",
"deepBoxSelect": "", "deepBoxSelect": "تحديد عميق داخل المربع، ومنع السحب",
"curvedArrow": "سهم مائل", "curvedArrow": "سهم مائل",
"curvedLine": "خط مائل", "curvedLine": "خط مائل",
"documentation": "دليل الاستخدام", "documentation": "دليل الاستخدام",
"doubleClick": "انقر مرتين", "doubleClick": "انقر مرتين",
"drag": "اسحب", "drag": "اسحب",
"editor": "المحرر", "editor": "المحرر",
"editLineArrowPoints": "", "editLineArrowPoints": "تحرير سطر/نقاط سهم",
"editText": "", "editText": "تعديل النص / إضافة تسمية",
"github": "عثرت على مشكلة؟ إرسال", "github": "عثرت على مشكلة؟ إرسال",
"howto": "اتبع التعليمات", "howto": "اتبع التعليمات",
"or": "أو", "or": "أو",
@@ -316,9 +332,9 @@
"view": "عرض", "view": "عرض",
"zoomToFit": "تكبير للملائمة", "zoomToFit": "تكبير للملائمة",
"zoomToSelection": "تكبير للعنصر المحدد", "zoomToSelection": "تكبير للعنصر المحدد",
"toggleElementLock": "", "toggleElementLock": "إغلاق/فتح المحدد",
"movePageUpDown": "", "movePageUpDown": "نقل الصفحة أعلى/أسفل",
"movePageLeftRight": "" "movePageLeftRight": "نقل الصفحة يسار/يمين"
}, },
"clearCanvasDialog": { "clearCanvasDialog": {
"title": "مسح اللوحة" "title": "مسح اللوحة"
@@ -336,20 +352,20 @@
"authorName": "اسمك أو اسم المستخدم", "authorName": "اسمك أو اسم المستخدم",
"libraryName": "اسم مكتبتك", "libraryName": "اسم مكتبتك",
"libraryDesc": "وصف مكتبتك لمساعدة الناس على فهم استخدامها", "libraryDesc": "وصف مكتبتك لمساعدة الناس على فهم استخدامها",
"githubHandle": "", "githubHandle": "معالج GitHub (اختياري)، حتى تتمكن من تحرير المكتبة عند إرسالها للمراجعة",
"twitterHandle": "", "twitterHandle": "اسم مستخدم تويتر (اختياري)، حتى نعرف من الذي سيتم الإشارة إليه عند الترويج عبر تويتر",
"website": "" "website": "رابط إلى موقعك الشخصي أو في مكان آخر (اختياري)"
}, },
"errors": { "errors": {
"required": "مطلوب", "required": "مطلوب",
"website": "أدخل عنوان URL صالح" "website": "أدخل عنوان URL صالح"
}, },
"noteDescription": "", "noteDescription": "تقديم مكتبتك لتضمينها في مستودع المكتبة العامة <link></link> لأشخاص آخرين لاستخدامها في رسومهم.",
"noteGuidelines": "", "noteGuidelines": "تحتاج المكتبة إلى الموافقة أولا. يرجى قراءة <link>المعايير</link> قبل تقديمها. سوف تحتاج إلى حساب GitHub للتواصل وإجراء التغييرات عند الطلب، ولكن ليس مطلوبا بشكل صارم.",
"noteLicense": "", "noteLicense": "تقديمك يعني موافقتك على نشر المكتبة المقدمة تحت <link>MIT ترخيص</link>، ما يعني أن لأي أحد الحق في استخدامها دون قيود.",
"noteItems": "يجب أن يكون لكل عنصر مكتبة اسمه الخاص حتى يكون قابلاً للتصفية. سيتم تضمين عناصر المكتبة التالية:", "noteItems": "يجب أن يكون لكل عنصر مكتبة اسمه الخاص حتى يكون قابلاً للتصفية. سيتم تضمين عناصر المكتبة التالية:",
"atleastOneLibItem": "يرجى تحديد عنصر مكتبة واحد على الأقل للبدء", "atleastOneLibItem": "يرجى تحديد عنصر مكتبة واحد على الأقل للبدء",
"republishWarning": "" "republishWarning": "ملاحظة: بعض العناصر المحددة معينة على أنه نشرها أو تقديمها من قبل. يجب عليك فقط إعادة إرسال العناصر عند تحديث مكتبة موجودة أو إرسالها."
}, },
"publishSuccessDialog": { "publishSuccessDialog": {
"title": "تم إرسال المكتبة", "title": "تم إرسال المكتبة",
@@ -360,27 +376,27 @@
"removeItemsFromLib": "إزالة العناصر المحددة من المكتبة" "removeItemsFromLib": "إزالة العناصر المحددة من المكتبة"
}, },
"imageExportDialog": { "imageExportDialog": {
"header": "", "header": "تصدير الصورة",
"label": { "label": {
"withBackground": "", "withBackground": "الخلفية",
"onlySelected": "", "onlySelected": "المحدد فقط",
"darkMode": "", "darkMode": "الوضع الداكن",
"embedScene": "", "embedScene": "تضمين المشهد",
"scale": "", "scale": "الحجم",
"padding": "" "padding": "الهوامش"
}, },
"tooltip": { "tooltip": {
"embedScene": "" "embedScene": "سيتم حفظ بيانات المشهد في ملف PNG/SVG المصدّر بحيث يمكن استعادة المشهد منه.\nسيزيد حجم الملف المصدر."
}, },
"title": { "title": {
"exportToPng": "", "exportToPng": "تصدير بصيغة PNG",
"exportToSvg": "", "exportToSvg": "تصدير بصيغة SVG",
"copyPngToClipboard": "" "copyPngToClipboard": "نسخ الـ PNG إلى الحافظة"
}, },
"button": { "button": {
"exportToPng": "", "exportToPng": "PNG",
"exportToSvg": "", "exportToSvg": "SVG",
"copyPngToClipboard": "" "copyPngToClipboard": "نسخ إلى الحافظة"
} }
}, },
"encrypted": { "encrypted": {
@@ -411,43 +427,76 @@
"fileSavedToFilename": "حفظ باسم {filename}", "fileSavedToFilename": "حفظ باسم {filename}",
"canvas": "لوحة الرسم", "canvas": "لوحة الرسم",
"selection": "العنصر المحدد", "selection": "العنصر المحدد",
"pasteAsSingleElement": "" "pasteAsSingleElement": "استخدم {{shortcut}} للصق كعنصر واحد،\nأو لصق في محرر نص موجود",
"unableToEmbed": "تضمين هذا الرابط غير مسموح حاليًا. افتح بلاغاً على GitHub لطلب عنوان Url القائمة البيضاء",
"unrecognizedLinkFormat": "الرابط الذي ضمنته لا يتطابق مع التنسيق المتوقع. الرجاء محاولة لصق النص 'المضمن' المُزوَد من موقع المصدر"
}, },
"colors": { "colors": {
"transparent": "شفاف", "transparent": "شفاف",
"black": "", "black": "أسود",
"white": "", "white": "أبيض",
"red": "", "red": "أحمر",
"pink": "", "pink": "وردي",
"grape": "", "grape": "عنبي",
"violet": "", "violet": "بنفسجي",
"gray": "", "gray": "رمادي",
"blue": "", "blue": "أزرق",
"cyan": "", "cyan": "سماوي",
"teal": "", "teal": "أزرق مخضر",
"green": "", "green": "أخضر",
"yellow": "", "yellow": "أصفر",
"orange": "", "orange": "برتقالي",
"bronze": "" "bronze": "برونزي"
}, },
"welcomeScreen": { "welcomeScreen": {
"app": { "app": {
"center_heading": "", "center_heading": "جميع بياناتك محفوظة محليا في المتصفح الخاص بك.",
"center_heading_plus": "", "center_heading_plus": "هل تريد الذهاب إلى Excalidraw+ بدلاً من ذلك؟",
"menuHint": "" "menuHint": "التصدير والتفضيلات واللغات ..."
}, },
"defaults": { "defaults": {
"menuHint": "", "menuHint": "التصدير والتفضيلات وغيرها...",
"center_heading": "", "center_heading": "الرسم البياني التصويري. بشكل مبسط.",
"toolbarHint": "", "toolbarHint": "اختر أداة و ابدأ الرسم!",
"helpHint": "" "helpHint": "الاختصارات و المساعدة"
} }
}, },
"colorPicker": { "colorPicker": {
"mostUsedCustomColors": "", "mostUsedCustomColors": "الألوان المخصصة الأكثر استخداما",
"colors": "", "colors": "الألوان",
"shades": "", "shades": "الدرجات",
"hexCode": "", "hexCode": "رمز Hex",
"noShades": "" "noShades": "لا تتوفر درجات لهذا اللون"
},
"overwriteConfirm": {
"action": {
"exportToImage": {
"title": "تصدير كصورة",
"button": "تصدير كصورة",
"description": "تصدير بيانات المشهد إلى ملف يمكنك الاستيراد منه لاحقاً."
},
"saveToDisk": {
"title": "حفظ الملف للجهاز",
"button": "حفظ الملف للجهاز",
"description": "تصدير بيانات المشهد إلى ملف يمكنك الاستيراد منه لاحقاً."
},
"excalidrawPlus": {
"title": "Excalidraw+",
"button": "تصدير إلى Excalidraw+",
"description": "حفظ المشهد إلى مساحة العمل +Excalidraw الخاصة بك."
}
},
"modal": {
"loadFromFile": {
"title": "تحميل من ملف",
"button": "تحميل من ملف",
"description": "سيتم التحميل من الملف <bold>استبدال المحتوى الموجود</bold>.<br></br>يمكنك النسخ الاحتياطي لرسمك أولاً باستخدام أحد الخيارات أدناه."
},
"shareableLink": {
"title": "تحميل من رابط",
"button": "استبدال محتواي",
"description": "سيتسبب تحميل رسمة خارجية <bold>باستبدال محتواك الموجود حالياً</bold>.<br></br>بإمكانك إجراء النسخ الاحتياطي لرسمتك الحالية باستخدام أحد الخيارات أدناه."
}
}
} }
} }
+53 -4
View File
@@ -109,8 +109,12 @@
"createContainerFromText": "", "createContainerFromText": "",
"link": { "link": {
"edit": "", "edit": "",
"editEmbed": "",
"create": "", "create": "",
"label": "" "createEmbed": "",
"label": "",
"labelEmbed": "",
"empty": ""
}, },
"lineEditor": { "lineEditor": {
"edit": "", "edit": "",
@@ -160,13 +164,16 @@
"darkMode": "", "darkMode": "",
"lightMode": "", "lightMode": "",
"zenMode": "", "zenMode": "",
"objectsSnapMode": "",
"exitZenMode": "", "exitZenMode": "",
"cancel": "", "cancel": "",
"clear": "", "clear": "",
"remove": "", "remove": "",
"embed": "",
"publishLibrary": "", "publishLibrary": "",
"submit": "", "submit": "",
"confirm": "" "confirm": "",
"embeddableInteractionButton": ""
}, },
"alerts": { "alerts": {
"clearReset": "", "clearReset": "",
@@ -196,6 +203,7 @@
"imageInsertError": "", "imageInsertError": "",
"fileTooBig": "", "fileTooBig": "",
"svgImageInsertError": "", "svgImageInsertError": "",
"failedToFetchImage": "",
"invalidSVGString": "", "invalidSVGString": "",
"cannotResolveCollabServer": "", "cannotResolveCollabServer": "",
"importLibraryError": "", "importLibraryError": "",
@@ -206,6 +214,10 @@
"line2": "", "line2": "",
"line3": "", "line3": "",
"line4": "" "line4": ""
},
"libraryElementTypeError": {
"embeddable": "",
"image": ""
} }
}, },
"toolBar": { "toolBar": {
@@ -224,6 +236,8 @@
"link": "", "link": "",
"eraser": "", "eraser": "",
"frame": "", "frame": "",
"embeddable": "",
"laser": "",
"hand": "", "hand": "",
"extraTools": "" "extraTools": ""
}, },
@@ -237,6 +251,7 @@
"linearElement": "", "linearElement": "",
"freeDraw": "", "freeDraw": "",
"text": "", "text": "",
"embeddable": "",
"text_selected": "", "text_selected": "",
"text_editing": "", "text_editing": "",
"linearElementMulti": "", "linearElementMulti": "",
@@ -252,7 +267,8 @@
"bindTextToElement": "", "bindTextToElement": "",
"deepBoxSelect": "", "deepBoxSelect": "",
"eraserRevert": "", "eraserRevert": "",
"firefox_clipboard_write": "" "firefox_clipboard_write": "",
"disableSnapping": ""
}, },
"canvasError": { "canvasError": {
"cannotShowPreview": "", "cannotShowPreview": "",
@@ -411,7 +427,9 @@
"fileSavedToFilename": "", "fileSavedToFilename": "",
"canvas": "", "canvas": "",
"selection": "", "selection": "",
"pasteAsSingleElement": "" "pasteAsSingleElement": "",
"unableToEmbed": "",
"unrecognizedLinkFormat": ""
}, },
"colors": { "colors": {
"transparent": "", "transparent": "",
@@ -449,5 +467,36 @@
"shades": "", "shades": "",
"hexCode": "", "hexCode": "",
"noShades": "" "noShades": ""
},
"overwriteConfirm": {
"action": {
"exportToImage": {
"title": "",
"button": "",
"description": ""
},
"saveToDisk": {
"title": "",
"button": "",
"description": ""
},
"excalidrawPlus": {
"title": "",
"button": "",
"description": ""
}
},
"modal": {
"loadFromFile": {
"title": "",
"button": "",
"description": ""
},
"shareableLink": {
"title": "",
"button": "",
"description": ""
}
}
} }
} }
+145 -96
View File
@@ -1,7 +1,7 @@
{ {
"labels": { "labels": {
"paste": "Постави", "paste": "Постави",
"pasteAsPlaintext": "", "pasteAsPlaintext": "Постави като обикновен текст",
"pasteCharts": "Постави графики", "pasteCharts": "Постави графики",
"selectAll": "Маркирай всичко", "selectAll": "Маркирай всичко",
"multiSelect": "Добави елемент към селекция", "multiSelect": "Добави елемент към селекция",
@@ -50,7 +50,7 @@
"veryLarge": "Много голям", "veryLarge": "Много голям",
"solid": "Солиден", "solid": "Солиден",
"hachure": "Хералдика", "hachure": "Хералдика",
"zigzag": "", "zigzag": "Зигзаг",
"crossHatch": "Двойно-пресечено", "crossHatch": "Двойно-пресечено",
"thin": "Тънък", "thin": "Тънък",
"bold": "Ясно очертан", "bold": "Ясно очертан",
@@ -63,7 +63,7 @@
"cartoonist": "Карикатурист", "cartoonist": "Карикатурист",
"fileTitle": "Име на файл", "fileTitle": "Име на файл",
"colorPicker": "Избор на цвят", "colorPicker": "Избор на цвят",
"canvasColors": "", "canvasColors": "Използван на платно",
"canvasBackground": "Фон на платно", "canvasBackground": "Фон на платно",
"drawingCanvas": "Платно за рисуване", "drawingCanvas": "Платно за рисуване",
"layers": "Слоеве", "layers": "Слоеве",
@@ -99,37 +99,41 @@
"share": "Сподели", "share": "Сподели",
"showStroke": "", "showStroke": "",
"showBackground": "", "showBackground": "",
"toggleTheme": "", "toggleTheme": "Включи тема",
"personalLib": "", "personalLib": "Лична Библиотека",
"excalidrawLib": "", "excalidrawLib": "Excalidraw Библиотека",
"decreaseFontSize": "", "decreaseFontSize": "Намали размера на шрифта",
"increaseFontSize": "", "increaseFontSize": "Увеличи размера на шрифта",
"unbindText": "", "unbindText": "",
"bindText": "", "bindText": "",
"createContainerFromText": "", "createContainerFromText": "",
"link": { "link": {
"edit": "", "edit": "Редактирай линк",
"editEmbed": "",
"create": "", "create": "",
"label": "" "createEmbed": "",
"label": "Линк",
"labelEmbed": "",
"empty": ""
}, },
"lineEditor": { "lineEditor": {
"edit": "", "edit": "",
"exit": "" "exit": ""
}, },
"elementLock": { "elementLock": {
"lock": "", "lock": "Заключи",
"unlock": "", "unlock": "Отключи",
"lockAll": "", "lockAll": "Заключи всички",
"unlockAll": "" "unlockAll": "Отключи всички"
}, },
"statusPublished": "", "statusPublished": "Публикувани",
"sidebarLock": "", "sidebarLock": "",
"selectAllElementsInFrame": "", "selectAllElementsInFrame": "",
"removeAllElementsFromFrame": "", "removeAllElementsFromFrame": "",
"eyeDropper": "" "eyeDropper": "Избери цвят от платното"
}, },
"library": { "library": {
"noItems": "", "noItems": "Няма добавени неща все още...",
"hint_emptyLibrary": "", "hint_emptyLibrary": "",
"hint_emptyPrivateLibrary": "" "hint_emptyPrivateLibrary": ""
}, },
@@ -137,11 +141,11 @@
"clearReset": "Нулиране на платно", "clearReset": "Нулиране на платно",
"exportJSON": "", "exportJSON": "",
"exportImage": "", "exportImage": "",
"export": "", "export": "Запази на...",
"copyToClipboard": "Копиране в клипборда", "copyToClipboard": "Копиране в клипборда",
"save": "", "save": "Запази към текущ файл",
"saveAs": "Запиши като", "saveAs": "Запиши като",
"load": "", "load": "Отвори",
"getShareableLink": "Получаване на връзка за споделяне", "getShareableLink": "Получаване на връзка за споделяне",
"close": "Затвори", "close": "Затвори",
"selectLanguage": "Избор на език", "selectLanguage": "Избор на език",
@@ -160,13 +164,16 @@
"darkMode": "Тъмен режим", "darkMode": "Тъмен режим",
"lightMode": "Светъл режим", "lightMode": "Светъл режим",
"zenMode": "Режим Zen", "zenMode": "Режим Zen",
"objectsSnapMode": "",
"exitZenMode": "Спиране на Zen режим", "exitZenMode": "Спиране на Zen режим",
"cancel": "Отмени", "cancel": "Отмени",
"clear": "Изчисти", "clear": "Изчисти",
"remove": "Премахване", "remove": "Премахване",
"embed": "",
"publishLibrary": "Публикувай", "publishLibrary": "Публикувай",
"submit": "Изпрати", "submit": "Изпрати",
"confirm": "Потвърждаване" "confirm": "Потвърждаване",
"embeddableInteractionButton": ""
}, },
"alerts": { "alerts": {
"clearReset": "Това ще изчисти цялото платно. Сигурни ли сте?", "clearReset": "Това ще изчисти цялото платно. Сигурни ли сте?",
@@ -175,37 +182,42 @@
"couldNotLoadInvalidFile": "Невалиден файл не може да се зареди", "couldNotLoadInvalidFile": "Невалиден файл не може да се зареди",
"importBackendFailed": "Импортирането от бекенд не беше успешно.", "importBackendFailed": "Импортирането от бекенд не беше успешно.",
"cannotExportEmptyCanvas": "Не може да се експортира празно платно.", "cannotExportEmptyCanvas": "Не може да се експортира празно платно.",
"couldNotCopyToClipboard": "", "couldNotCopyToClipboard": "Не можем да копираме в клипбоарда.",
"decryptFailed": "Данните не можаха да се дешифрират.", "decryptFailed": "Данните не можаха да се дешифрират.",
"uploadedSecurly": "Качването е защитено с криптиране от край до край, което означава, че сървърът Excalidraw и трети страни не могат да четат съдържанието.", "uploadedSecurly": "Качването е защитено с криптиране от край до край, което означава, че сървърът Excalidraw и трети страни не могат да четат съдържанието.",
"loadSceneOverridePrompt": "Зареждането на външна рисунка ще презапише настоящото ви съдържание. Желаете ли да продължите?", "loadSceneOverridePrompt": "Зареждането на външна рисунка ще презапише настоящото ви съдържание. Желаете ли да продължите?",
"collabStopOverridePrompt": "Прекратяването на сесията ще презапише предишната, локално запазена, рисунка. Сигурни ли сте?\n\n(Ако искате да продължите с локалната рисунка, просто затворете таба на браузъра.)", "collabStopOverridePrompt": "Прекратяването на сесията ще презапише предишната, локално запазена, рисунка. Сигурни ли сте?\n\n(Ако искате да продължите с локалната рисунка, просто затворете таба на браузъра.)",
"errorAddingToLibrary": "", "errorAddingToLibrary": "Не можем да заредим от библиотеката",
"errorRemovingFromLibrary": "", "errorRemovingFromLibrary": "Не можем да премахнем елемент от библиотеката",
"confirmAddLibrary": "Ще се добавят {{numShapes}} фигура(и) във вашата библиотека. Сигурни ли сте?", "confirmAddLibrary": "Ще се добавят {{numShapes}} фигура(и) във вашата библиотека. Сигурни ли сте?",
"imageDoesNotContainScene": "", "imageDoesNotContainScene": "",
"cannotRestoreFromImage": "Не може да бъде възстановена сцена от този файл", "cannotRestoreFromImage": "Не може да бъде възстановена сцена от този файл",
"invalidSceneUrl": "", "invalidSceneUrl": "",
"resetLibrary": "", "resetLibrary": "",
"removeItemsFromsLibrary": "", "removeItemsFromsLibrary": "Изтрий {{count}} елемент(а) от библиотеката?",
"invalidEncryptionKey": "", "invalidEncryptionKey": "",
"collabOfflineWarning": "" "collabOfflineWarning": ""
}, },
"errors": { "errors": {
"unsupportedFileType": "Този файлов формат не се поддържа.", "unsupportedFileType": "Този файлов формат не се поддържа.",
"imageInsertError": "", "imageInsertError": "",
"fileTooBig": "", "fileTooBig": "Файлът е твърде голям. Максималния допустим размер е {{maxSize}}.",
"svgImageInsertError": "", "svgImageInsertError": "",
"invalidSVGString": "", "failedToFetchImage": "",
"invalidSVGString": "Невалиден SVG.",
"cannotResolveCollabServer": "", "cannotResolveCollabServer": "",
"importLibraryError": "", "importLibraryError": "Не можем да заредим библиотеката",
"collabSaveFailed": "", "collabSaveFailed": "",
"collabSaveFailed_sizeExceeded": "", "collabSaveFailed_sizeExceeded": "",
"brave_measure_text_error": { "brave_measure_text_error": {
"line1": "", "line1": "",
"line2": "", "line2": "",
"line3": "", "line3": "Силно препоръчваме да изключите тази настройка. Можете да следвате <link>тези стъпки</link> за това как да го направите.",
"line4": "" "line4": ""
},
"libraryElementTypeError": {
"embeddable": "",
"image": ""
} }
}, },
"toolBar": { "toolBar": {
@@ -222,10 +234,12 @@
"lock": "Поддържайте избрания инструмент активен след рисуване", "lock": "Поддържайте избрания инструмент активен след рисуване",
"penMode": "", "penMode": "",
"link": "", "link": "",
"eraser": "", "eraser": "Гума",
"frame": "", "frame": "",
"embeddable": "",
"laser": "",
"hand": "", "hand": "",
"extraTools": "" "extraTools": "Още инструменти"
}, },
"headings": { "headings": {
"canvasActions": "Действия по платното", "canvasActions": "Действия по платното",
@@ -237,6 +251,7 @@
"linearElement": "Кликнете, за да стартирате няколко точки, плъзнете за една линия", "linearElement": "Кликнете, за да стартирате няколко точки, плъзнете за една линия",
"freeDraw": "Натиснете и влачете, пуснете като сте готови", "freeDraw": "Натиснете и влачете, пуснете като сте готови",
"text": "Подсказка: Можете също да добавите текст като натиснете някъде два път с инструмента за селекция", "text": "Подсказка: Можете също да добавите текст като натиснете някъде два път с инструмента за селекция",
"embeddable": "",
"text_selected": "", "text_selected": "",
"text_editing": "", "text_editing": "",
"linearElementMulti": "Кликнете върху последната точка или натиснете Escape или Enter, за да завършите", "linearElementMulti": "Кликнете върху последната точка или натиснете Escape или Enter, за да завършите",
@@ -252,7 +267,8 @@
"bindTextToElement": "Натиснете Enter, за да добавите", "bindTextToElement": "Натиснете Enter, за да добавите",
"deepBoxSelect": "", "deepBoxSelect": "",
"eraserRevert": "", "eraserRevert": "",
"firefox_clipboard_write": "" "firefox_clipboard_write": "",
"disableSnapping": ""
}, },
"canvasError": { "canvasError": {
"cannotShowPreview": "Невъзможност за показване на preview", "cannotShowPreview": "Невъзможност за показване на preview",
@@ -288,7 +304,7 @@
"link_details": "", "link_details": "",
"link_button": "", "link_button": "",
"excalidrawplus_description": "", "excalidrawplus_description": "",
"excalidrawplus_button": "", "excalidrawplus_button": "Експорт",
"excalidrawplus_exportError": "" "excalidrawplus_exportError": ""
}, },
"helpDialog": { "helpDialog": {
@@ -299,7 +315,7 @@
"curvedArrow": "Извита стрелка", "curvedArrow": "Извита стрелка",
"curvedLine": "Извита линия", "curvedLine": "Извита линия",
"documentation": "Документация", "documentation": "Документация",
"doubleClick": "", "doubleClick": "двойно-щракване",
"drag": "плъзнете", "drag": "плъзнете",
"editor": "Редактор", "editor": "Редактор",
"editLineArrowPoints": "", "editLineArrowPoints": "",
@@ -308,41 +324,41 @@
"howto": "Следвайте нашите ръководства", "howto": "Следвайте нашите ръководства",
"or": "или", "or": "или",
"preventBinding": "Спри прилепяне на стрелките", "preventBinding": "Спри прилепяне на стрелките",
"tools": "", "tools": "Инструменти",
"shortcuts": "Клавиши за бърз достъп", "shortcuts": "Клавиши за бърз достъп",
"textFinish": "", "textFinish": "Завърши редактиране (текстов редактор)",
"textNewLine": "", "textNewLine": "Добави нова линия (текстов редактор)",
"title": "Помощ", "title": "Помощ",
"view": "Преглед", "view": "Преглед",
"zoomToFit": "Приближи докато се виждат всички елементи", "zoomToFit": "Приближи докато се виждат всички елементи",
"zoomToSelection": "Приближи селекцията", "zoomToSelection": "Приближи селекцията",
"toggleElementLock": "", "toggleElementLock": "Заключи/Отключи селекция",
"movePageUpDown": "", "movePageUpDown": "Премести страница нагоре/надолу",
"movePageLeftRight": "" "movePageLeftRight": "Премести страница наляво/надясно"
}, },
"clearCanvasDialog": { "clearCanvasDialog": {
"title": "" "title": "Изчисти платното"
}, },
"publishDialog": { "publishDialog": {
"title": "", "title": "Публикувай библиотека",
"itemName": "", "itemName": "Име",
"authorName": "", "authorName": "Авторско име",
"githubUsername": "", "githubUsername": "GitHub потребителско име",
"twitterUsername": "", "twitterUsername": "Twitter потребителско име",
"libraryName": "", "libraryName": "Име на библиотеката",
"libraryDesc": "", "libraryDesc": "Описание на библиотеката",
"website": "", "website": "Уебсайт",
"placeholder": { "placeholder": {
"authorName": "", "authorName": "Името или потребителското Ви име",
"libraryName": "", "libraryName": "Име на библиотеката Ви",
"libraryDesc": "", "libraryDesc": "Описание на библиотеката ви, за да помогнете на хората да разберат приложенията ѝ",
"githubHandle": "", "githubHandle": "",
"twitterHandle": "", "twitterHandle": "",
"website": "" "website": ""
}, },
"errors": { "errors": {
"required": "", "required": "Задължително",
"website": "" "website": "Въведете валиден URL адрес"
}, },
"noteDescription": "", "noteDescription": "",
"noteGuidelines": "", "noteGuidelines": "",
@@ -356,15 +372,15 @@
"content": "" "content": ""
}, },
"confirmDialog": { "confirmDialog": {
"resetLibrary": "", "resetLibrary": "Нулирай библиотека",
"removeItemsFromLib": "" "removeItemsFromLib": ""
}, },
"imageExportDialog": { "imageExportDialog": {
"header": "", "header": "",
"label": { "label": {
"withBackground": "", "withBackground": "Фон",
"onlySelected": "", "onlySelected": "Само избраното",
"darkMode": "", "darkMode": "Тъмен режим",
"embedScene": "", "embedScene": "",
"scale": "", "scale": "",
"padding": "" "padding": ""
@@ -373,14 +389,14 @@
"embedScene": "" "embedScene": ""
}, },
"title": { "title": {
"exportToPng": "", "exportToPng": "Изнасяне в PNG",
"exportToSvg": "", "exportToSvg": "Изнасяне в SVG",
"copyPngToClipboard": "" "copyPngToClipboard": "Копирай PNG в клипборда"
}, },
"button": { "button": {
"exportToPng": "", "exportToPng": "PNG",
"exportToSvg": "", "exportToSvg": "SVG",
"copyPngToClipboard": "" "copyPngToClipboard": "Копиране в клипборда"
} }
}, },
"encrypted": { "encrypted": {
@@ -403,51 +419,84 @@
"width": "Широчина" "width": "Широчина"
}, },
"toast": { "toast": {
"addedToLibrary": "", "addedToLibrary": "Добавена към библиотеката",
"copyStyles": "Копирани стилове.", "copyStyles": "Копирани стилове.",
"copyToClipboard": "Копирано в клипборда.", "copyToClipboard": "Копирано в клипборда.",
"copyToClipboardAsPng": "", "copyToClipboardAsPng": "Копира {{exportSelection}} в клипборда като PNG\n({{exportColorScheme}})",
"fileSaved": "", "fileSaved": "Файлът е запазен.",
"fileSavedToFilename": "", "fileSavedToFilename": "Запазен към {filename}",
"canvas": "", "canvas": "платно",
"selection": "", "selection": "селекция",
"pasteAsSingleElement": "" "pasteAsSingleElement": "",
"unableToEmbed": "",
"unrecognizedLinkFormat": ""
}, },
"colors": { "colors": {
"transparent": "", "transparent": "Прозрачен",
"black": "", "black": "Черен",
"white": "", "white": "Бял",
"red": "", "red": "Червен",
"pink": "", "pink": "Розов",
"grape": "", "grape": "Грозде",
"violet": "", "violet": "Виолетово",
"gray": "", "gray": "Сив",
"blue": "", "blue": "Син",
"cyan": "", "cyan": "Синьозелено",
"teal": "", "teal": "Тъмно синьо-зелено",
"green": "", "green": "Зелено",
"yellow": "", "yellow": "Жълто",
"orange": "", "orange": "Оранжево",
"bronze": "" "bronze": "Бронзово"
}, },
"welcomeScreen": { "welcomeScreen": {
"app": { "app": {
"center_heading": "", "center_heading": "Всичките Ви данни са запазени локално в браузъра Ви.",
"center_heading_plus": "", "center_heading_plus": "",
"menuHint": "" "menuHint": "Експорт, предпочитания, езици, ..."
}, },
"defaults": { "defaults": {
"menuHint": "", "menuHint": "Експорт, предпочитания, и още...",
"center_heading": "", "center_heading": "Диаграми. Направени. Просто.",
"toolbarHint": "", "toolbarHint": "Изберете инструмент & Започнете да рисувате!",
"helpHint": "" "helpHint": "Преки пътища & помощ"
} }
}, },
"colorPicker": { "colorPicker": {
"mostUsedCustomColors": "", "mostUsedCustomColors": "Най-често използвани цветове",
"colors": "", "colors": "Цветове",
"shades": "", "shades": "Нюанси",
"hexCode": "", "hexCode": "Шестнадесетичен код",
"noShades": "" "noShades": ""
},
"overwriteConfirm": {
"action": {
"exportToImage": {
"title": "Изнеси като изображение",
"button": "Изнеси като изображение",
"description": ""
},
"saveToDisk": {
"title": "Запази към диск",
"button": "Запази към диск",
"description": ""
},
"excalidrawPlus": {
"title": "Excalidraw+",
"button": "Експортирай към Excalidraw+",
"description": "Запази сцената към Excalidraw+ работното място."
}
},
"modal": {
"loadFromFile": {
"title": "Зареди от файл",
"button": "Зареди от файл",
"description": ""
},
"shareableLink": {
"title": "Зареди от линк",
"button": "Замени моето съдържание",
"description": ""
}
}
} }
} }
+53 -4
View File
@@ -109,8 +109,12 @@
"createContainerFromText": "", "createContainerFromText": "",
"link": { "link": {
"edit": "লিঙ্ক সংশোধন", "edit": "লিঙ্ক সংশোধন",
"editEmbed": "",
"create": "লিঙ্ক তৈরী", "create": "লিঙ্ক তৈরী",
"label": "লিঙ্ক নামকরণ" "createEmbed": "",
"label": "লিঙ্ক নামকরণ",
"labelEmbed": "",
"empty": ""
}, },
"lineEditor": { "lineEditor": {
"edit": "", "edit": "",
@@ -160,13 +164,16 @@
"darkMode": "ডার্ক মোড", "darkMode": "ডার্ক মোড",
"lightMode": "লাইট মোড", "lightMode": "লাইট মোড",
"zenMode": "জেন মোড", "zenMode": "জেন মোড",
"objectsSnapMode": "",
"exitZenMode": "জেন মোড বন্ধ করুন", "exitZenMode": "জেন মোড বন্ধ করুন",
"cancel": "বাতিল", "cancel": "বাতিল",
"clear": "সাফ", "clear": "সাফ",
"remove": "বিয়োগ", "remove": "বিয়োগ",
"embed": "",
"publishLibrary": "সংগ্রহ প্রকাশ করুন", "publishLibrary": "সংগ্রহ প্রকাশ করুন",
"submit": "জমা করুন", "submit": "জমা করুন",
"confirm": "নিশ্চিত করুন" "confirm": "নিশ্চিত করুন",
"embeddableInteractionButton": ""
}, },
"alerts": { "alerts": {
"clearReset": "এটি পুরো ক্যানভাস সাফ করবে। আপনি কি নিশ্চিত?", "clearReset": "এটি পুরো ক্যানভাস সাফ করবে। আপনি কি নিশ্চিত?",
@@ -196,6 +203,7 @@
"imageInsertError": "ছবি সন্নিবেশ করা যায়নি। পরে আবার চেষ্টা করুন...", "imageInsertError": "ছবি সন্নিবেশ করা যায়নি। পরে আবার চেষ্টা করুন...",
"fileTooBig": "ফাইলটি খুব বড়। সর্বাধিক অনুমোদিত আকার হল {{maxSize}}৷", "fileTooBig": "ফাইলটি খুব বড়। সর্বাধিক অনুমোদিত আকার হল {{maxSize}}৷",
"svgImageInsertError": "এসভীজী ছবি সন্নিবেশ করা যায়নি। এসভীজী মার্কআপটি অবৈধ মনে হচ্ছে৷", "svgImageInsertError": "এসভীজী ছবি সন্নিবেশ করা যায়নি। এসভীজী মার্কআপটি অবৈধ মনে হচ্ছে৷",
"failedToFetchImage": "",
"invalidSVGString": "এসভীজী মার্কআপটি অবৈধ মনে হচ্ছে৷", "invalidSVGString": "এসভীজী মার্কআপটি অবৈধ মনে হচ্ছে৷",
"cannotResolveCollabServer": "কোল্যাব সার্ভারের সাথে সংযোগ করা যায়নি। পৃষ্ঠাটি পুনরায় লোড করে আবার চেষ্টা করুন।", "cannotResolveCollabServer": "কোল্যাব সার্ভারের সাথে সংযোগ করা যায়নি। পৃষ্ঠাটি পুনরায় লোড করে আবার চেষ্টা করুন।",
"importLibraryError": "সংগ্রহ লোড করা যায়নি", "importLibraryError": "সংগ্রহ লোড করা যায়নি",
@@ -206,6 +214,10 @@
"line2": "", "line2": "",
"line3": "", "line3": "",
"line4": "" "line4": ""
},
"libraryElementTypeError": {
"embeddable": "",
"image": ""
} }
}, },
"toolBar": { "toolBar": {
@@ -224,6 +236,8 @@
"link": "একটি নির্বাচিত আকৃতির জন্য লিঙ্ক যোগ বা আপডেট করুন", "link": "একটি নির্বাচিত আকৃতির জন্য লিঙ্ক যোগ বা আপডেট করুন",
"eraser": "ঝাড়ন", "eraser": "ঝাড়ন",
"frame": "", "frame": "",
"embeddable": "",
"laser": "",
"hand": "", "hand": "",
"extraTools": "" "extraTools": ""
}, },
@@ -237,6 +251,7 @@
"linearElement": "একাধিক বিন্দু শুরু করতে ক্লিক করুন, একক লাইনের জন্য টেনে আনুন", "linearElement": "একাধিক বিন্দু শুরু করতে ক্লিক করুন, একক লাইনের জন্য টেনে আনুন",
"freeDraw": "ক্লিক করুন এবং টেনে আনুন, আপনার কাজ শেষ হলে ছেড়ে দিন", "freeDraw": "ক্লিক করুন এবং টেনে আনুন, আপনার কাজ শেষ হলে ছেড়ে দিন",
"text": "বিশেষ্য: আপনি নির্বাচন টুলের সাথে যে কোনো জায়গায় ডাবল-ক্লিক করে পাঠ্য যোগ করতে পারেন", "text": "বিশেষ্য: আপনি নির্বাচন টুলের সাথে যে কোনো জায়গায় ডাবল-ক্লিক করে পাঠ্য যোগ করতে পারেন",
"embeddable": "",
"text_selected": "লেখা সম্পাদনা করতে ডাবল-ক্লিক করুন বা এন্টার টিপুন", "text_selected": "লেখা সম্পাদনা করতে ডাবল-ক্লিক করুন বা এন্টার টিপুন",
"text_editing": "লেখা সম্পাদনা শেষ করতে এসকেপ বা কন্ট্রোল/কম্যান্ড যোগে এন্টার টিপুন", "text_editing": "লেখা সম্পাদনা শেষ করতে এসকেপ বা কন্ট্রোল/কম্যান্ড যোগে এন্টার টিপুন",
"linearElementMulti": "শেষ বিন্দুতে ক্লিক করুন অথবা শেষ করতে এসকেপ বা এন্টার টিপুন", "linearElementMulti": "শেষ বিন্দুতে ক্লিক করুন অথবা শেষ করতে এসকেপ বা এন্টার টিপুন",
@@ -252,7 +267,8 @@
"bindTextToElement": "লেখা যোগ করতে এন্টার টিপুন", "bindTextToElement": "লেখা যোগ করতে এন্টার টিপুন",
"deepBoxSelect": "", "deepBoxSelect": "",
"eraserRevert": "মুছে ফেলার জন্য চিহ্নিত উপাদানগুলিকে ফিরিয়ে আনতে অল্ট ধরে রাখুন", "eraserRevert": "মুছে ফেলার জন্য চিহ্নিত উপাদানগুলিকে ফিরিয়ে আনতে অল্ট ধরে রাখুন",
"firefox_clipboard_write": "" "firefox_clipboard_write": "",
"disableSnapping": ""
}, },
"canvasError": { "canvasError": {
"cannotShowPreview": "প্রিভিউ দেখাতে অপারগ", "cannotShowPreview": "প্রিভিউ দেখাতে অপারগ",
@@ -411,7 +427,9 @@
"fileSavedToFilename": "", "fileSavedToFilename": "",
"canvas": "", "canvas": "",
"selection": "বাছাই", "selection": "বাছাই",
"pasteAsSingleElement": "" "pasteAsSingleElement": "",
"unableToEmbed": "",
"unrecognizedLinkFormat": ""
}, },
"colors": { "colors": {
"transparent": "", "transparent": "",
@@ -449,5 +467,36 @@
"shades": "", "shades": "",
"hexCode": "", "hexCode": "",
"noShades": "" "noShades": ""
},
"overwriteConfirm": {
"action": {
"exportToImage": {
"title": "",
"button": "",
"description": ""
},
"saveToDisk": {
"title": "",
"button": "",
"description": ""
},
"excalidrawPlus": {
"title": "",
"button": "",
"description": ""
}
},
"modal": {
"loadFromFile": {
"title": "",
"button": "",
"description": ""
},
"shareableLink": {
"title": "",
"button": "",
"description": ""
}
}
} }
} }
+53 -4
View File
@@ -109,8 +109,12 @@
"createContainerFromText": "", "createContainerFromText": "",
"link": { "link": {
"edit": "Edita l'enllaç", "edit": "Edita l'enllaç",
"editEmbed": "",
"create": "Crea un enllaç", "create": "Crea un enllaç",
"label": "Enllaç" "createEmbed": "",
"label": "Enllaç",
"labelEmbed": "",
"empty": ""
}, },
"lineEditor": { "lineEditor": {
"edit": "Editar línia", "edit": "Editar línia",
@@ -160,13 +164,16 @@
"darkMode": "Mode fosc", "darkMode": "Mode fosc",
"lightMode": "Mode clar", "lightMode": "Mode clar",
"zenMode": "Mode zen", "zenMode": "Mode zen",
"objectsSnapMode": "",
"exitZenMode": "Surt de mode zen", "exitZenMode": "Surt de mode zen",
"cancel": "Cancel·la", "cancel": "Cancel·la",
"clear": "Neteja", "clear": "Neteja",
"remove": "Suprimeix", "remove": "Suprimeix",
"embed": "",
"publishLibrary": "Publica", "publishLibrary": "Publica",
"submit": "Envia", "submit": "Envia",
"confirm": "Confirma" "confirm": "Confirma",
"embeddableInteractionButton": ""
}, },
"alerts": { "alerts": {
"clearReset": "S'esborrarà tot el llenç. N'esteu segur?", "clearReset": "S'esborrarà tot el llenç. N'esteu segur?",
@@ -196,6 +203,7 @@
"imageInsertError": "No s'ha pogut insertar la imatge, torneu-ho a provar més tard...", "imageInsertError": "No s'ha pogut insertar la imatge, torneu-ho a provar més tard...",
"fileTooBig": "El fitxer és massa gros. La mida màxima permesa és {{maxSize}}.", "fileTooBig": "El fitxer és massa gros. La mida màxima permesa és {{maxSize}}.",
"svgImageInsertError": "No ha estat possible inserir la imatge SVG. Les marques SVG semblen invàlides.", "svgImageInsertError": "No ha estat possible inserir la imatge SVG. Les marques SVG semblen invàlides.",
"failedToFetchImage": "",
"invalidSVGString": "SVG no vàlid.", "invalidSVGString": "SVG no vàlid.",
"cannotResolveCollabServer": "No ha estat possible connectar amb el servidor collab. Si us plau recarregueu la pàgina i torneu a provar.", "cannotResolveCollabServer": "No ha estat possible connectar amb el servidor collab. Si us plau recarregueu la pàgina i torneu a provar.",
"importLibraryError": "No s'ha pogut carregar la biblioteca", "importLibraryError": "No s'ha pogut carregar la biblioteca",
@@ -206,6 +214,10 @@
"line2": "", "line2": "",
"line3": "", "line3": "",
"line4": "" "line4": ""
},
"libraryElementTypeError": {
"embeddable": "",
"image": ""
} }
}, },
"toolBar": { "toolBar": {
@@ -224,6 +236,8 @@
"link": "Afegeix / actualitza l'enllaç per a la forma seleccionada", "link": "Afegeix / actualitza l'enllaç per a la forma seleccionada",
"eraser": "Esborrador", "eraser": "Esborrador",
"frame": "", "frame": "",
"embeddable": "",
"laser": "",
"hand": "Mà (eina de desplaçament)", "hand": "Mà (eina de desplaçament)",
"extraTools": "" "extraTools": ""
}, },
@@ -237,6 +251,7 @@
"linearElement": "Feu clic per a dibuixar múltiples punts; arrossegueu per a una sola línia", "linearElement": "Feu clic per a dibuixar múltiples punts; arrossegueu per a una sola línia",
"freeDraw": "Feu clic i arrossegueu, deixeu anar per a finalitzar", "freeDraw": "Feu clic i arrossegueu, deixeu anar per a finalitzar",
"text": "Consell: també podeu afegir text fent doble clic en qualsevol lloc amb l'eina de selecció", "text": "Consell: també podeu afegir text fent doble clic en qualsevol lloc amb l'eina de selecció",
"embeddable": "",
"text_selected": "Feu doble clic o premeu Retorn per a editar el text", "text_selected": "Feu doble clic o premeu Retorn per a editar el text",
"text_editing": "Premeu Escapada o Ctrl+Retorn (o Ordre+Retorn) per a finalitzar l'edició", "text_editing": "Premeu Escapada o Ctrl+Retorn (o Ordre+Retorn) per a finalitzar l'edició",
"linearElementMulti": "Feu clic a l'ultim punt, o pitgeu Esc o Retorn per a finalitzar", "linearElementMulti": "Feu clic a l'ultim punt, o pitgeu Esc o Retorn per a finalitzar",
@@ -252,7 +267,8 @@
"bindTextToElement": "Premeu enter per a afegir-hi text", "bindTextToElement": "Premeu enter per a afegir-hi text",
"deepBoxSelect": "Manteniu CtrlOrCmd per a selecció profunda, i per a evitar l'arrossegament", "deepBoxSelect": "Manteniu CtrlOrCmd per a selecció profunda, i per a evitar l'arrossegament",
"eraserRevert": "Mantingueu premuda Alt per a revertir els elements seleccionats per a esborrar", "eraserRevert": "Mantingueu premuda Alt per a revertir els elements seleccionats per a esborrar",
"firefox_clipboard_write": "És probable que aquesta funció es pugui activar posant la marca \"dom.events.asyncClipboard.clipboardItem\" a \"true\". Per canviar les marques del navegador al Firefox, visiteu la pàgina \"about:config\"." "firefox_clipboard_write": "És probable que aquesta funció es pugui activar posant la marca \"dom.events.asyncClipboard.clipboardItem\" a \"true\". Per canviar les marques del navegador al Firefox, visiteu la pàgina \"about:config\".",
"disableSnapping": ""
}, },
"canvasError": { "canvasError": {
"cannotShowPreview": "No es pot mostrar la previsualització", "cannotShowPreview": "No es pot mostrar la previsualització",
@@ -411,7 +427,9 @@
"fileSavedToFilename": "S'ha desat a {filename}", "fileSavedToFilename": "S'ha desat a {filename}",
"canvas": "el llenç", "canvas": "el llenç",
"selection": "la selecció", "selection": "la selecció",
"pasteAsSingleElement": "Fer servir {{shortcut}} per enganxar com un sol element,\no enganxeu-lo en un editor de text existent" "pasteAsSingleElement": "Fer servir {{shortcut}} per enganxar com un sol element,\no enganxeu-lo en un editor de text existent",
"unableToEmbed": "",
"unrecognizedLinkFormat": ""
}, },
"colors": { "colors": {
"transparent": "Transparent", "transparent": "Transparent",
@@ -449,5 +467,36 @@
"shades": "", "shades": "",
"hexCode": "", "hexCode": "",
"noShades": "" "noShades": ""
},
"overwriteConfirm": {
"action": {
"exportToImage": {
"title": "",
"button": "",
"description": ""
},
"saveToDisk": {
"title": "",
"button": "",
"description": ""
},
"excalidrawPlus": {
"title": "",
"button": "",
"description": ""
}
},
"modal": {
"loadFromFile": {
"title": "",
"button": "",
"description": ""
},
"shareableLink": {
"title": "",
"button": "",
"description": ""
}
}
} }
} }
+53 -4
View File
@@ -109,8 +109,12 @@
"createContainerFromText": "Zabalit text do kontejneru", "createContainerFromText": "Zabalit text do kontejneru",
"link": { "link": {
"edit": "Upravit odkaz", "edit": "Upravit odkaz",
"editEmbed": "",
"create": "Vytvořit odkaz", "create": "Vytvořit odkaz",
"label": "Odkaz" "createEmbed": "",
"label": "Odkaz",
"labelEmbed": "",
"empty": ""
}, },
"lineEditor": { "lineEditor": {
"edit": "Upravit čáru", "edit": "Upravit čáru",
@@ -160,13 +164,16 @@
"darkMode": "Tmavý režim", "darkMode": "Tmavý režim",
"lightMode": "Světlý režim", "lightMode": "Světlý režim",
"zenMode": "Zen mód", "zenMode": "Zen mód",
"objectsSnapMode": "",
"exitZenMode": "Opustit zen mód", "exitZenMode": "Opustit zen mód",
"cancel": "Zrušit", "cancel": "Zrušit",
"clear": "Vyčistit", "clear": "Vyčistit",
"remove": "Odstranit", "remove": "Odstranit",
"embed": "",
"publishLibrary": "Zveřejnit", "publishLibrary": "Zveřejnit",
"submit": "Odeslat", "submit": "Odeslat",
"confirm": "Potvrdit" "confirm": "Potvrdit",
"embeddableInteractionButton": ""
}, },
"alerts": { "alerts": {
"clearReset": "Toto vymaže celé plátno. Jste si jisti?", "clearReset": "Toto vymaže celé plátno. Jste si jisti?",
@@ -196,6 +203,7 @@
"imageInsertError": "Nelze vložit obrázek. Zkuste to později...", "imageInsertError": "Nelze vložit obrázek. Zkuste to později...",
"fileTooBig": "Soubor je příliš velký. Maximální povolená velikost je {{maxSize}}.", "fileTooBig": "Soubor je příliš velký. Maximální povolená velikost je {{maxSize}}.",
"svgImageInsertError": "Nelze vložit SVG obrázek. Značení SVG je neplatné.", "svgImageInsertError": "Nelze vložit SVG obrázek. Značení SVG je neplatné.",
"failedToFetchImage": "",
"invalidSVGString": "Neplatný SVG.", "invalidSVGString": "Neplatný SVG.",
"cannotResolveCollabServer": "Nelze se připojit ke sdílenému serveru. Prosím obnovte stránku a zkuste to znovu.", "cannotResolveCollabServer": "Nelze se připojit ke sdílenému serveru. Prosím obnovte stránku a zkuste to znovu.",
"importLibraryError": "Nelze načíst knihovnu", "importLibraryError": "Nelze načíst knihovnu",
@@ -206,6 +214,10 @@
"line2": "To by mohlo vést k narušení <bold>Textových elementů</bold> ve vašich výkresech.", "line2": "To by mohlo vést k narušení <bold>Textových elementů</bold> ve vašich výkresech.",
"line3": "Důrazně doporučujeme zakázat toto nastavení. Můžete sledovat <link>tyto kroky</link> jak to udělat.", "line3": "Důrazně doporučujeme zakázat toto nastavení. Můžete sledovat <link>tyto kroky</link> jak to udělat.",
"line4": "Pokud vypnutí tohoto nastavení neopravuje zobrazení textových prvků, prosím, otevřete <issueLink>problém</issueLink> na našem GitHubu, nebo nám napište na <discordLink>Discord</discordLink>" "line4": "Pokud vypnutí tohoto nastavení neopravuje zobrazení textových prvků, prosím, otevřete <issueLink>problém</issueLink> na našem GitHubu, nebo nám napište na <discordLink>Discord</discordLink>"
},
"libraryElementTypeError": {
"embeddable": "",
"image": ""
} }
}, },
"toolBar": { "toolBar": {
@@ -224,6 +236,8 @@
"link": "Přidat/aktualizovat odkaz pro vybraný tvar", "link": "Přidat/aktualizovat odkaz pro vybraný tvar",
"eraser": "Guma", "eraser": "Guma",
"frame": "", "frame": "",
"embeddable": "",
"laser": "",
"hand": "Ruka (nástroj pro posouvání)", "hand": "Ruka (nástroj pro posouvání)",
"extraTools": "" "extraTools": ""
}, },
@@ -237,6 +251,7 @@
"linearElement": "Kliknutím pro více bodů, táhnutím pro jednu čáru", "linearElement": "Kliknutím pro více bodů, táhnutím pro jednu čáru",
"freeDraw": "Klikněte a táhněte, pro ukončení pusťte", "freeDraw": "Klikněte a táhněte, pro ukončení pusťte",
"text": "Tip: Text můžete také přidat dvojitým kliknutím kdekoli pomocí nástroje pro výběr", "text": "Tip: Text můžete také přidat dvojitým kliknutím kdekoli pomocí nástroje pro výběr",
"embeddable": "",
"text_selected": "Dvojklikem nebo stisknutím klávesy ENTER upravíte text", "text_selected": "Dvojklikem nebo stisknutím klávesy ENTER upravíte text",
"text_editing": "Stiskněte Escape nebo Ctrl/Cmd+ENTER pro dokončení úprav", "text_editing": "Stiskněte Escape nebo Ctrl/Cmd+ENTER pro dokončení úprav",
"linearElementMulti": "Klikněte na poslední bod nebo stiskněte Escape anebo Enter pro dokončení", "linearElementMulti": "Klikněte na poslední bod nebo stiskněte Escape anebo Enter pro dokončení",
@@ -252,7 +267,8 @@
"bindTextToElement": "Stiskněte Enter pro přidání textu", "bindTextToElement": "Stiskněte Enter pro přidání textu",
"deepBoxSelect": "Podržte Ctrl/Cmd pro hluboký výběr a pro zabránění táhnutí", "deepBoxSelect": "Podržte Ctrl/Cmd pro hluboký výběr a pro zabránění táhnutí",
"eraserRevert": "Podržením klávesy Alt vrátíte prvky označené pro smazání", "eraserRevert": "Podržením klávesy Alt vrátíte prvky označené pro smazání",
"firefox_clipboard_write": "Tato funkce může být povolena nastavením vlajky \"dom.events.asyncClipboard.clipboardItem\" na \"true\". Chcete-li změnit vlajky prohlížeče ve Firefoxu, navštivte stránku \"about:config\"." "firefox_clipboard_write": "Tato funkce může být povolena nastavením vlajky \"dom.events.asyncClipboard.clipboardItem\" na \"true\". Chcete-li změnit vlajky prohlížeče ve Firefoxu, navštivte stránku \"about:config\".",
"disableSnapping": ""
}, },
"canvasError": { "canvasError": {
"cannotShowPreview": "Náhled nelze zobrazit", "cannotShowPreview": "Náhled nelze zobrazit",
@@ -411,7 +427,9 @@
"fileSavedToFilename": "Uloženo do {filename}", "fileSavedToFilename": "Uloženo do {filename}",
"canvas": "plátno", "canvas": "plátno",
"selection": "výběr", "selection": "výběr",
"pasteAsSingleElement": "Pomocí {{shortcut}} vložte jako jeden prvek,\nnebo vložte do existujícího textového editoru" "pasteAsSingleElement": "Pomocí {{shortcut}} vložte jako jeden prvek,\nnebo vložte do existujícího textového editoru",
"unableToEmbed": "",
"unrecognizedLinkFormat": ""
}, },
"colors": { "colors": {
"transparent": "Průhledná", "transparent": "Průhledná",
@@ -449,5 +467,36 @@
"shades": "Stíny", "shades": "Stíny",
"hexCode": "Hex kód", "hexCode": "Hex kód",
"noShades": "Pro tuto barvu nejsou k dispozici žádné odstíny" "noShades": "Pro tuto barvu nejsou k dispozici žádné odstíny"
},
"overwriteConfirm": {
"action": {
"exportToImage": {
"title": "",
"button": "",
"description": ""
},
"saveToDisk": {
"title": "",
"button": "",
"description": ""
},
"excalidrawPlus": {
"title": "",
"button": "",
"description": ""
}
},
"modal": {
"loadFromFile": {
"title": "",
"button": "",
"description": ""
},
"shareableLink": {
"title": "",
"button": "",
"description": ""
}
}
} }
} }
+57 -8
View File
@@ -1,7 +1,7 @@
{ {
"labels": { "labels": {
"paste": "Indsæt", "paste": "Indsæt",
"pasteAsPlaintext": "", "pasteAsPlaintext": "Indsæt som klartekst",
"pasteCharts": "Indsæt diagrammer", "pasteCharts": "Indsæt diagrammer",
"selectAll": "Marker alle", "selectAll": "Marker alle",
"multiSelect": "Tilføj element til markering", "multiSelect": "Tilføj element til markering",
@@ -50,7 +50,7 @@
"veryLarge": "Meget stor", "veryLarge": "Meget stor",
"solid": "Solid", "solid": "Solid",
"hachure": "Skravering", "hachure": "Skravering",
"zigzag": "", "zigzag": "Zigzag",
"crossHatch": "Krydsskravering", "crossHatch": "Krydsskravering",
"thin": "Tynd", "thin": "Tynd",
"bold": "Fed", "bold": "Fed",
@@ -69,8 +69,8 @@
"layers": "Lag", "layers": "Lag",
"actions": "Handlinger", "actions": "Handlinger",
"language": "Sprog", "language": "Sprog",
"liveCollaboration": "", "liveCollaboration": "Live samarbejde...",
"duplicateSelection": "", "duplicateSelection": "Duplikér",
"untitled": "Unavngivet", "untitled": "Unavngivet",
"name": "Navn", "name": "Navn",
"yourName": "Dit navn", "yourName": "Dit navn",
@@ -109,8 +109,12 @@
"createContainerFromText": "", "createContainerFromText": "",
"link": { "link": {
"edit": "", "edit": "",
"editEmbed": "",
"create": "", "create": "",
"label": "" "createEmbed": "",
"label": "",
"labelEmbed": "",
"empty": ""
}, },
"lineEditor": { "lineEditor": {
"edit": "", "edit": "",
@@ -160,13 +164,16 @@
"darkMode": "Mørk tilstand", "darkMode": "Mørk tilstand",
"lightMode": "Lys baggrund", "lightMode": "Lys baggrund",
"zenMode": "Zentilstand", "zenMode": "Zentilstand",
"objectsSnapMode": "",
"exitZenMode": "Stop zentilstand", "exitZenMode": "Stop zentilstand",
"cancel": "Annuller", "cancel": "Annuller",
"clear": "Ryd", "clear": "Ryd",
"remove": "Fjern", "remove": "Fjern",
"embed": "",
"publishLibrary": "Publicér", "publishLibrary": "Publicér",
"submit": "Gem", "submit": "Gem",
"confirm": "Bekræft" "confirm": "Bekræft",
"embeddableInteractionButton": ""
}, },
"alerts": { "alerts": {
"clearReset": "Dette vil rydde hele lærredet. Er du sikker?", "clearReset": "Dette vil rydde hele lærredet. Er du sikker?",
@@ -196,6 +203,7 @@
"imageInsertError": "", "imageInsertError": "",
"fileTooBig": "", "fileTooBig": "",
"svgImageInsertError": "", "svgImageInsertError": "",
"failedToFetchImage": "",
"invalidSVGString": "", "invalidSVGString": "",
"cannotResolveCollabServer": "", "cannotResolveCollabServer": "",
"importLibraryError": "", "importLibraryError": "",
@@ -206,6 +214,10 @@
"line2": "", "line2": "",
"line3": "", "line3": "",
"line4": "" "line4": ""
},
"libraryElementTypeError": {
"embeddable": "",
"image": ""
} }
}, },
"toolBar": { "toolBar": {
@@ -224,6 +236,8 @@
"link": "", "link": "",
"eraser": "", "eraser": "",
"frame": "", "frame": "",
"embeddable": "",
"laser": "",
"hand": "", "hand": "",
"extraTools": "" "extraTools": ""
}, },
@@ -237,6 +251,7 @@
"linearElement": "", "linearElement": "",
"freeDraw": "Klik og træk, slip når du er færdig", "freeDraw": "Klik og træk, slip når du er færdig",
"text": "", "text": "",
"embeddable": "",
"text_selected": "", "text_selected": "",
"text_editing": "", "text_editing": "",
"linearElementMulti": "", "linearElementMulti": "",
@@ -252,7 +267,8 @@
"bindTextToElement": "", "bindTextToElement": "",
"deepBoxSelect": "", "deepBoxSelect": "",
"eraserRevert": "", "eraserRevert": "",
"firefox_clipboard_write": "" "firefox_clipboard_write": "",
"disableSnapping": ""
}, },
"canvasError": { "canvasError": {
"cannotShowPreview": "", "cannotShowPreview": "",
@@ -411,7 +427,9 @@
"fileSavedToFilename": "Gemt som {filename}", "fileSavedToFilename": "Gemt som {filename}",
"canvas": "canvas", "canvas": "canvas",
"selection": "markering", "selection": "markering",
"pasteAsSingleElement": "" "pasteAsSingleElement": "",
"unableToEmbed": "",
"unrecognizedLinkFormat": ""
}, },
"colors": { "colors": {
"transparent": "", "transparent": "",
@@ -449,5 +467,36 @@
"shades": "", "shades": "",
"hexCode": "", "hexCode": "",
"noShades": "" "noShades": ""
},
"overwriteConfirm": {
"action": {
"exportToImage": {
"title": "",
"button": "",
"description": ""
},
"saveToDisk": {
"title": "",
"button": "",
"description": ""
},
"excalidrawPlus": {
"title": "",
"button": "",
"description": ""
}
},
"modal": {
"loadFromFile": {
"title": "",
"button": "",
"description": ""
},
"shareableLink": {
"title": "",
"button": "",
"description": ""
}
}
} }
} }
+53 -4
View File
@@ -109,8 +109,12 @@
"createContainerFromText": "Text in Container einbetten", "createContainerFromText": "Text in Container einbetten",
"link": { "link": {
"edit": "Link bearbeiten", "edit": "Link bearbeiten",
"editEmbed": "Link bearbeiten & einbetten",
"create": "Link erstellen", "create": "Link erstellen",
"label": "Link" "createEmbed": "Link erstellen & einbetten",
"label": "Link",
"labelEmbed": "Verlinken & einbetten",
"empty": "Kein Link festgelegt"
}, },
"lineEditor": { "lineEditor": {
"edit": "Linie bearbeiten", "edit": "Linie bearbeiten",
@@ -160,13 +164,16 @@
"darkMode": "Dunkles Design", "darkMode": "Dunkles Design",
"lightMode": "Helles Design", "lightMode": "Helles Design",
"zenMode": "Zen-Modus", "zenMode": "Zen-Modus",
"objectsSnapMode": "Einrasten an Objekten",
"exitZenMode": "Zen-Modus verlassen", "exitZenMode": "Zen-Modus verlassen",
"cancel": "Abbrechen", "cancel": "Abbrechen",
"clear": "Löschen", "clear": "Löschen",
"remove": "Entfernen", "remove": "Entfernen",
"embed": "Einbettung umschalten",
"publishLibrary": "Veröffentlichen", "publishLibrary": "Veröffentlichen",
"submit": "Absenden", "submit": "Absenden",
"confirm": "Bestätigen" "confirm": "Bestätigen",
"embeddableInteractionButton": "Klicken, um zu interagieren"
}, },
"alerts": { "alerts": {
"clearReset": "Dies wird die ganze Zeichenfläche löschen. Bist du dir sicher?", "clearReset": "Dies wird die ganze Zeichenfläche löschen. Bist du dir sicher?",
@@ -196,6 +203,7 @@
"imageInsertError": "Das Bild konnte nicht eingefügt werden. Versuche es später erneut...", "imageInsertError": "Das Bild konnte nicht eingefügt werden. Versuche es später erneut...",
"fileTooBig": "Die Datei ist zu groß. Die maximal zulässige Größe ist {{maxSize}}.", "fileTooBig": "Die Datei ist zu groß. Die maximal zulässige Größe ist {{maxSize}}.",
"svgImageInsertError": "SVG-Bild konnte nicht eingefügt werden. Das SVG-Markup sieht ungültig aus.", "svgImageInsertError": "SVG-Bild konnte nicht eingefügt werden. Das SVG-Markup sieht ungültig aus.",
"failedToFetchImage": "Bild konnte nicht abgerufen werden.",
"invalidSVGString": "Ungültige SVG.", "invalidSVGString": "Ungültige SVG.",
"cannotResolveCollabServer": "Konnte keine Verbindung zum Collab-Server herstellen. Bitte lade die Seite neu und versuche es erneut.", "cannotResolveCollabServer": "Konnte keine Verbindung zum Collab-Server herstellen. Bitte lade die Seite neu und versuche es erneut.",
"importLibraryError": "Bibliothek konnte nicht geladen werden", "importLibraryError": "Bibliothek konnte nicht geladen werden",
@@ -206,6 +214,10 @@
"line2": "Dies könnte dazu führen, dass die <bold>Textelemente</bold> in Ihren Zeichnungen zerstört werden.", "line2": "Dies könnte dazu führen, dass die <bold>Textelemente</bold> in Ihren Zeichnungen zerstört werden.",
"line3": "Wir empfehlen dringend, diese Einstellung zu deaktivieren. Dazu kannst Du <link>diesen Schritten</link> folgen.", "line3": "Wir empfehlen dringend, diese Einstellung zu deaktivieren. Dazu kannst Du <link>diesen Schritten</link> folgen.",
"line4": "Wenn die Deaktivierung dieser Einstellung die fehlerhafte Anzeige von Textelementen nicht behebt, öffne bitte ein <issueLink>Ticket</issueLink> auf unserem GitHub oder schreibe uns auf <discordLink>Discord</discordLink>" "line4": "Wenn die Deaktivierung dieser Einstellung die fehlerhafte Anzeige von Textelementen nicht behebt, öffne bitte ein <issueLink>Ticket</issueLink> auf unserem GitHub oder schreibe uns auf <discordLink>Discord</discordLink>"
},
"libraryElementTypeError": {
"embeddable": "Einbettbare Elemente können der Bibliothek nicht hinzugefügt werden.",
"image": "Unterstützung für das Hinzufügen von Bildern in die Bibliothek kommt bald!"
} }
}, },
"toolBar": { "toolBar": {
@@ -224,6 +236,8 @@
"link": "Link für ausgewählte Form hinzufügen / aktualisieren", "link": "Link für ausgewählte Form hinzufügen / aktualisieren",
"eraser": "Radierer", "eraser": "Radierer",
"frame": "Rahmenwerkzeug", "frame": "Rahmenwerkzeug",
"embeddable": "Web-Einbettung",
"laser": "Laserpointer",
"hand": "Hand (Schwenkwerkzeug)", "hand": "Hand (Schwenkwerkzeug)",
"extraTools": "Weitere Werkzeuge" "extraTools": "Weitere Werkzeuge"
}, },
@@ -237,6 +251,7 @@
"linearElement": "Klicken für Linie mit mehreren Punkten, Ziehen für einzelne Linie", "linearElement": "Klicken für Linie mit mehreren Punkten, Ziehen für einzelne Linie",
"freeDraw": "Klicke und ziehe. Lass los, wenn du fertig bist", "freeDraw": "Klicke und ziehe. Lass los, wenn du fertig bist",
"text": "Tipp: Du kannst auch Text hinzufügen, indem du mit dem Auswahlwerkzeug auf eine beliebige Stelle doppelklickst", "text": "Tipp: Du kannst auch Text hinzufügen, indem du mit dem Auswahlwerkzeug auf eine beliebige Stelle doppelklickst",
"embeddable": "Klicken und ziehen, um eine Webseiten-Einbettung zu erstellen",
"text_selected": "Doppelklicken oder Eingabetaste drücken, um Text zu bearbeiten", "text_selected": "Doppelklicken oder Eingabetaste drücken, um Text zu bearbeiten",
"text_editing": "Drücke Escape oder CtrlOrCmd+Eingabetaste, um die Bearbeitung abzuschließen", "text_editing": "Drücke Escape oder CtrlOrCmd+Eingabetaste, um die Bearbeitung abzuschließen",
"linearElementMulti": "Zum Beenden auf den letzten Punkt klicken oder Escape oder Eingabe drücken", "linearElementMulti": "Zum Beenden auf den letzten Punkt klicken oder Escape oder Eingabe drücken",
@@ -252,7 +267,8 @@
"bindTextToElement": "Zum Hinzufügen Eingabetaste drücken", "bindTextToElement": "Zum Hinzufügen Eingabetaste drücken",
"deepBoxSelect": "Halte CtrlOrCmd gedrückt, um innerhalb der Gruppe auszuwählen, und um Ziehen zu vermeiden", "deepBoxSelect": "Halte CtrlOrCmd gedrückt, um innerhalb der Gruppe auszuwählen, und um Ziehen zu vermeiden",
"eraserRevert": "Halte Alt gedrückt, um die zum Löschen markierten Elemente zurückzusetzen", "eraserRevert": "Halte Alt gedrückt, um die zum Löschen markierten Elemente zurückzusetzen",
"firefox_clipboard_write": "Diese Funktion kann wahrscheinlich aktiviert werden, indem die Einstellung \"dom.events.asyncClipboard.clipboardItem\" auf \"true\" gesetzt wird. Um die Browsereinstellungen in Firefox zu ändern, besuche die Seite \"about:config\"." "firefox_clipboard_write": "Diese Funktion kann wahrscheinlich aktiviert werden, indem die Einstellung \"dom.events.asyncClipboard.clipboardItem\" auf \"true\" gesetzt wird. Um die Browsereinstellungen in Firefox zu ändern, besuche die Seite \"about:config\".",
"disableSnapping": "Halte CtrlOrCmd gedrückt, um das Einrasten zu deaktivieren"
}, },
"canvasError": { "canvasError": {
"cannotShowPreview": "Vorschau kann nicht angezeigt werden", "cannotShowPreview": "Vorschau kann nicht angezeigt werden",
@@ -411,7 +427,9 @@
"fileSavedToFilename": "Als {filename} gespeichert", "fileSavedToFilename": "Als {filename} gespeichert",
"canvas": "Zeichenfläche", "canvas": "Zeichenfläche",
"selection": "Auswahl", "selection": "Auswahl",
"pasteAsSingleElement": "Verwende {{shortcut}} , um als einzelnes Element\neinzufügen oder in einen existierenden Texteditor einzufügen" "pasteAsSingleElement": "Verwende {{shortcut}} , um als einzelnes Element\neinzufügen oder in einen existierenden Texteditor einzufügen",
"unableToEmbed": "Einbetten dieser URL ist derzeit nicht zulässig. Erstelle einen Issue auf GitHub, um die URL freigeben zu lassen",
"unrecognizedLinkFormat": "Der Link, den Du eingebettet hast, stimmt nicht mit dem erwarteten Format überein. Bitte versuche den 'embed' String einzufügen, der von der Quellseite zur Verfügung gestellt wird"
}, },
"colors": { "colors": {
"transparent": "Transparent", "transparent": "Transparent",
@@ -449,5 +467,36 @@
"shades": "Schattierungen", "shades": "Schattierungen",
"hexCode": "Hex-Code", "hexCode": "Hex-Code",
"noShades": "Keine Schattierungen für diese Farbe verfügbar" "noShades": "Keine Schattierungen für diese Farbe verfügbar"
},
"overwriteConfirm": {
"action": {
"exportToImage": {
"title": "Als Bild exportieren",
"button": "Als Bild exportieren",
"description": "Exportiere die Zeichnungsdaten als ein Bild, von dem Du später importieren kannst."
},
"saveToDisk": {
"title": "Auf Festplatte speichern",
"button": "Auf Festplatte speichern",
"description": "Exportiere die Zeichnungsdaten in eine Datei, von der Du später importieren kannst."
},
"excalidrawPlus": {
"title": "Excalidraw+",
"button": "Export nach Excalidraw+",
"description": "Speichere die Szene in deinem Excalidraw+-Arbeitsbereich."
}
},
"modal": {
"loadFromFile": {
"title": "Aus Datei laden",
"button": "Aus Datei laden",
"description": "Das Laden aus einer Datei wird <bold>Deinen vorhandenen Inhalt ersetzen</bold>.<br></br>Du kannst Deine Zeichnung zuerst mit einer der folgenden Optionen sichern."
},
"shareableLink": {
"title": "Aus Link laden",
"button": "Meinen Inhalt ersetzen",
"description": "Das Laden einer externen Zeichnung wird <bold>Deinen vorhandenen Inhalt ersetzen</bold>.<br></br>Du kannst Deine Zeichnung zuerst mit einer der folgenden Optionen sichern."
}
}
} }
} }
+53 -4
View File
@@ -109,8 +109,12 @@
"createContainerFromText": "", "createContainerFromText": "",
"link": { "link": {
"edit": "Επεξεργασία συνδέσμου", "edit": "Επεξεργασία συνδέσμου",
"editEmbed": "",
"create": "Δημιουργία συνδέσμου", "create": "Δημιουργία συνδέσμου",
"label": "Σύνδεσμος" "createEmbed": "",
"label": "Σύνδεσμος",
"labelEmbed": "",
"empty": ""
}, },
"lineEditor": { "lineEditor": {
"edit": "Επεξεργασία γραμμής", "edit": "Επεξεργασία γραμμής",
@@ -160,13 +164,16 @@
"darkMode": "Σκοτεινή λειτουργία", "darkMode": "Σκοτεινή λειτουργία",
"lightMode": "Φωτεινή λειτουργία", "lightMode": "Φωτεινή λειτουργία",
"zenMode": "Λειτουργία Zεν", "zenMode": "Λειτουργία Zεν",
"objectsSnapMode": "",
"exitZenMode": "Έξοδος από την λειτουργία Zen", "exitZenMode": "Έξοδος από την λειτουργία Zen",
"cancel": "Ακύρωση", "cancel": "Ακύρωση",
"clear": "Καθαρισμός", "clear": "Καθαρισμός",
"remove": "Κατάργηση", "remove": "Κατάργηση",
"embed": "",
"publishLibrary": "Δημοσίευση", "publishLibrary": "Δημοσίευση",
"submit": "Υποβολή", "submit": "Υποβολή",
"confirm": "Επιβεβαίωση" "confirm": "Επιβεβαίωση",
"embeddableInteractionButton": ""
}, },
"alerts": { "alerts": {
"clearReset": "Αυτό θα σβήσει ολόκληρο τον καμβά. Είσαι σίγουρος;", "clearReset": "Αυτό θα σβήσει ολόκληρο τον καμβά. Είσαι σίγουρος;",
@@ -196,6 +203,7 @@
"imageInsertError": "Αδυναμία εισαγωγής εικόνας. Προσπαθήστε ξανά αργότερα...", "imageInsertError": "Αδυναμία εισαγωγής εικόνας. Προσπαθήστε ξανά αργότερα...",
"fileTooBig": "Το αρχείο είναι πολύ μεγάλο. Το μέγιστο επιτρεπόμενο μέγεθος είναι {{maxSize}}.", "fileTooBig": "Το αρχείο είναι πολύ μεγάλο. Το μέγιστο επιτρεπόμενο μέγεθος είναι {{maxSize}}.",
"svgImageInsertError": "Αδυναμία εισαγωγής εικόνας SVG. Η σήμανση της SVG δεν φαίνεται έγκυρη.", "svgImageInsertError": "Αδυναμία εισαγωγής εικόνας SVG. Η σήμανση της SVG δεν φαίνεται έγκυρη.",
"failedToFetchImage": "",
"invalidSVGString": "Μη έγκυρο SVG.", "invalidSVGString": "Μη έγκυρο SVG.",
"cannotResolveCollabServer": "Αδυναμία σύνδεσης με τον διακομιστή συνεργασίας. Παρακαλώ ανανεώστε τη σελίδα και προσπαθήστε ξανά.", "cannotResolveCollabServer": "Αδυναμία σύνδεσης με τον διακομιστή συνεργασίας. Παρακαλώ ανανεώστε τη σελίδα και προσπαθήστε ξανά.",
"importLibraryError": "Αδυναμία φόρτωσης βιβλιοθήκης", "importLibraryError": "Αδυναμία φόρτωσης βιβλιοθήκης",
@@ -206,6 +214,10 @@
"line2": "", "line2": "",
"line3": "", "line3": "",
"line4": "" "line4": ""
},
"libraryElementTypeError": {
"embeddable": "",
"image": ""
} }
}, },
"toolBar": { "toolBar": {
@@ -224,6 +236,8 @@
"link": "Προσθήκη/ Ενημέρωση συνδέσμου για ένα επιλεγμένο σχήμα", "link": "Προσθήκη/ Ενημέρωση συνδέσμου για ένα επιλεγμένο σχήμα",
"eraser": "Γόμα", "eraser": "Γόμα",
"frame": "", "frame": "",
"embeddable": "",
"laser": "",
"hand": "", "hand": "",
"extraTools": "" "extraTools": ""
}, },
@@ -237,6 +251,7 @@
"linearElement": "Κάνε κλικ για να ξεκινήσεις πολλαπλά σημεία, σύρε για μια γραμμή", "linearElement": "Κάνε κλικ για να ξεκινήσεις πολλαπλά σημεία, σύρε για μια γραμμή",
"freeDraw": "Κάντε κλικ και σύρτε, απελευθερώσατε όταν έχετε τελειώσει", "freeDraw": "Κάντε κλικ και σύρτε, απελευθερώσατε όταν έχετε τελειώσει",
"text": "Tip: μπορείτε επίσης να προσθέστε κείμενο με διπλό-κλικ οπουδήποτε με το εργαλείο επιλογών", "text": "Tip: μπορείτε επίσης να προσθέστε κείμενο με διπλό-κλικ οπουδήποτε με το εργαλείο επιλογών",
"embeddable": "",
"text_selected": "Κάντε διπλό κλικ ή πατήστε ENTER για να επεξεργαστείτε το κείμενο", "text_selected": "Κάντε διπλό κλικ ή πατήστε ENTER για να επεξεργαστείτε το κείμενο",
"text_editing": "Πατήστε Escape ή CtrlOrCmd+ENTER για να ολοκληρώσετε την επεξεργασία", "text_editing": "Πατήστε Escape ή CtrlOrCmd+ENTER για να ολοκληρώσετε την επεξεργασία",
"linearElementMulti": "Κάνε κλικ στο τελευταίο σημείο ή πάτησε Escape ή Enter για να τελειώσεις", "linearElementMulti": "Κάνε κλικ στο τελευταίο σημείο ή πάτησε Escape ή Enter για να τελειώσεις",
@@ -252,7 +267,8 @@
"bindTextToElement": "Πατήστε Enter για προσθήκη κειμένου", "bindTextToElement": "Πατήστε Enter για προσθήκη κειμένου",
"deepBoxSelect": "Κρατήστε πατημένο το CtrlOrCmd για να επιλέξετε βαθιά, και να αποτρέψετε τη μεταφορά", "deepBoxSelect": "Κρατήστε πατημένο το CtrlOrCmd για να επιλέξετε βαθιά, και να αποτρέψετε τη μεταφορά",
"eraserRevert": "Κρατήστε πατημένο το Alt για να επαναφέρετε τα στοιχεία που σημειώθηκαν για διαγραφή", "eraserRevert": "Κρατήστε πατημένο το Alt για να επαναφέρετε τα στοιχεία που σημειώθηκαν για διαγραφή",
"firefox_clipboard_write": "Αυτή η επιλογή μπορεί πιθανώς να ενεργοποιηθεί αλλάζοντας την ρύθμιση \"dom.events.asyncClipboard.clipboardItem\" σε \"true\". Για να αλλάξετε τις ρυθμίσεις του προγράμματος περιήγησης στο Firefox, επισκεφθείτε τη σελίδα \"about:config\"." "firefox_clipboard_write": "Αυτή η επιλογή μπορεί πιθανώς να ενεργοποιηθεί αλλάζοντας την ρύθμιση \"dom.events.asyncClipboard.clipboardItem\" σε \"true\". Για να αλλάξετε τις ρυθμίσεις του προγράμματος περιήγησης στο Firefox, επισκεφθείτε τη σελίδα \"about:config\".",
"disableSnapping": ""
}, },
"canvasError": { "canvasError": {
"cannotShowPreview": "Αδυναμία εμφάνισης προεπισκόπησης", "cannotShowPreview": "Αδυναμία εμφάνισης προεπισκόπησης",
@@ -411,7 +427,9 @@
"fileSavedToFilename": "Αποθηκεύτηκε στο {filename}", "fileSavedToFilename": "Αποθηκεύτηκε στο {filename}",
"canvas": "καμβάς", "canvas": "καμβάς",
"selection": "επιλογή", "selection": "επιλογή",
"pasteAsSingleElement": "Χρησιμοποίησε το {{shortcut}} για να επικολλήσεις ως ένα μόνο στοιχείο,\nή να επικολλήσεις σε έναν υπάρχοντα επεξεργαστή κειμένου" "pasteAsSingleElement": "Χρησιμοποίησε το {{shortcut}} για να επικολλήσεις ως ένα μόνο στοιχείο,\nή να επικολλήσεις σε έναν υπάρχοντα επεξεργαστή κειμένου",
"unableToEmbed": "",
"unrecognizedLinkFormat": ""
}, },
"colors": { "colors": {
"transparent": "Διαφανές", "transparent": "Διαφανές",
@@ -449,5 +467,36 @@
"shades": "Αποχρώσεις", "shades": "Αποχρώσεις",
"hexCode": "Κωδικός Hex", "hexCode": "Κωδικός Hex",
"noShades": "Δεν υπάρχουν διαθέσιμες αποχρώσεις για αυτό το χρώμα" "noShades": "Δεν υπάρχουν διαθέσιμες αποχρώσεις για αυτό το χρώμα"
},
"overwriteConfirm": {
"action": {
"exportToImage": {
"title": "",
"button": "",
"description": ""
},
"saveToDisk": {
"title": "",
"button": "",
"description": ""
},
"excalidrawPlus": {
"title": "",
"button": "",
"description": ""
}
},
"modal": {
"loadFromFile": {
"title": "",
"button": "",
"description": ""
},
"shareableLink": {
"title": "",
"button": "",
"description": ""
}
}
} }
} }
+14 -2
View File
@@ -203,6 +203,7 @@
"imageInsertError": "Couldn't insert image. Try again later...", "imageInsertError": "Couldn't insert image. Try again later...",
"fileTooBig": "File is too big. Maximum allowed size is {{maxSize}}.", "fileTooBig": "File is too big. Maximum allowed size is {{maxSize}}.",
"svgImageInsertError": "Couldn't insert SVG image. The SVG markup looks invalid.", "svgImageInsertError": "Couldn't insert SVG image. The SVG markup looks invalid.",
"failedToFetchImage": "Failed to fetch image.",
"invalidSVGString": "Invalid SVG.", "invalidSVGString": "Invalid SVG.",
"cannotResolveCollabServer": "Couldn't connect to the collab server. Please reload the page and try again.", "cannotResolveCollabServer": "Couldn't connect to the collab server. Please reload the page and try again.",
"importLibraryError": "Couldn't load library", "importLibraryError": "Couldn't load library",
@@ -217,7 +218,10 @@
"libraryElementTypeError": { "libraryElementTypeError": {
"embeddable": "Embeddable elements cannot be added to the library.", "embeddable": "Embeddable elements cannot be added to the library.",
"image": "Support for adding images to the library coming soon!" "image": "Support for adding images to the library coming soon!"
} },
"asyncPasteFailedOnRead": "Couldn't paste (couldn't read from system clipboard).",
"asyncPasteFailedOnParse": "Couldn't paste.",
"copyToSystemClipboardFailed": "Couldn't copy to clipboard."
}, },
"toolBar": { "toolBar": {
"selection": "Selection", "selection": "Selection",
@@ -238,7 +242,8 @@
"embeddable": "Web Embed", "embeddable": "Web Embed",
"laser": "Laser pointer", "laser": "Laser pointer",
"hand": "Hand (panning tool)", "hand": "Hand (panning tool)",
"extraTools": "More tools" "extraTools": "More tools",
"mermaidToExcalidraw": "Mermaid to Excalidraw"
}, },
"headings": { "headings": {
"canvasActions": "Canvas actions", "canvasActions": "Canvas actions",
@@ -497,5 +502,12 @@
"description": "Loading external drawing will <bold>replace your existing content</bold>.<br></br>You can back up your drawing first by using one of the options below." "description": "Loading external drawing will <bold>replace your existing content</bold>.<br></br>You can back up your drawing first by using one of the options below."
} }
} }
},
"mermaid": {
"title": "Mermaid to Excalidraw",
"button": "Insert",
"description": "Currently only <flowchartLink>Flowcharts</flowchartLink> and <sequenceLink>Sequence Diagrams</sequenceLink> are supported. The other types will be rendered as image in Excalidraw.",
"syntax": "Mermaid Syntax",
"preview": "Preview"
} }
} }
+90 -41
View File
@@ -109,8 +109,12 @@
"createContainerFromText": "Envolver el texto en un contenedor", "createContainerFromText": "Envolver el texto en un contenedor",
"link": { "link": {
"edit": "Editar enlace", "edit": "Editar enlace",
"editEmbed": "Editar enlace e incrustar",
"create": "Crear enlace", "create": "Crear enlace",
"label": "Enlace" "createEmbed": "Crear enlace e incrustar",
"label": "Enlace",
"labelEmbed": "Enlazar e incrustar",
"empty": "No se ha establecido un enlace"
}, },
"lineEditor": { "lineEditor": {
"edit": "Editar línea", "edit": "Editar línea",
@@ -124,9 +128,9 @@
}, },
"statusPublished": "Publicado", "statusPublished": "Publicado",
"sidebarLock": "Mantener barra lateral abierta", "sidebarLock": "Mantener barra lateral abierta",
"selectAllElementsInFrame": "", "selectAllElementsInFrame": "Seleccionar todos los elementos en el marco",
"removeAllElementsFromFrame": "", "removeAllElementsFromFrame": "Eliminar todos los elementos del marco",
"eyeDropper": "" "eyeDropper": "Seleccionar un color del lienzo"
}, },
"library": { "library": {
"noItems": "No hay elementos añadidos todavía...", "noItems": "No hay elementos añadidos todavía...",
@@ -160,13 +164,16 @@
"darkMode": "Modo oscuro", "darkMode": "Modo oscuro",
"lightMode": "Modo claro", "lightMode": "Modo claro",
"zenMode": "Modo Zen", "zenMode": "Modo Zen",
"objectsSnapMode": "Ajustar a los objetos",
"exitZenMode": "Salir del modo Zen", "exitZenMode": "Salir del modo Zen",
"cancel": "Cancelar", "cancel": "Cancelar",
"clear": "Borrar", "clear": "Borrar",
"remove": "Eliminar", "remove": "Eliminar",
"embed": "",
"publishLibrary": "Publicar", "publishLibrary": "Publicar",
"submit": "Enviar", "submit": "Enviar",
"confirm": "Confirmar" "confirm": "Confirmar",
"embeddableInteractionButton": "Pulsa para interactuar"
}, },
"alerts": { "alerts": {
"clearReset": "Esto limpiará todo el lienzo. Estás seguro?", "clearReset": "Esto limpiará todo el lienzo. Estás seguro?",
@@ -196,16 +203,21 @@
"imageInsertError": "No se pudo insertar la imagen. Inténtelo de nuevo más tarde...", "imageInsertError": "No se pudo insertar la imagen. Inténtelo de nuevo más tarde...",
"fileTooBig": "Archivo demasiado grande. El tamaño máximo permitido es {{maxSize}}.", "fileTooBig": "Archivo demasiado grande. El tamaño máximo permitido es {{maxSize}}.",
"svgImageInsertError": "No se pudo insertar la imagen SVG. El código SVG parece inválido.", "svgImageInsertError": "No se pudo insertar la imagen SVG. El código SVG parece inválido.",
"failedToFetchImage": "",
"invalidSVGString": "SVG no válido.", "invalidSVGString": "SVG no válido.",
"cannotResolveCollabServer": "No se pudo conectar al servidor colaborador. Por favor, vuelva a cargar la página y vuelva a intentarlo.", "cannotResolveCollabServer": "No se pudo conectar al servidor colaborador. Por favor, vuelva a cargar la página y vuelva a intentarlo.",
"importLibraryError": "No se pudo cargar la librería", "importLibraryError": "No se pudo cargar la librería",
"collabSaveFailed": "No se pudo guardar en la base de datos del backend. Si los problemas persisten, debería guardar su archivo localmente para asegurarse de que no pierde su trabajo.", "collabSaveFailed": "No se pudo guardar en la base de datos del backend. Si los problemas persisten, debería guardar su archivo localmente para asegurarse de que no pierde su trabajo.",
"collabSaveFailed_sizeExceeded": "No se pudo guardar en la base de datos del backend, el lienzo parece ser demasiado grande. Debería guardar el archivo localmente para asegurarse de que no pierde su trabajo.", "collabSaveFailed_sizeExceeded": "No se pudo guardar en la base de datos del backend, el lienzo parece ser demasiado grande. Debería guardar el archivo localmente para asegurarse de que no pierde su trabajo.",
"brave_measure_text_error": { "brave_measure_text_error": {
"line1": "", "line1": "Parece que estás usando el navegador Brave con el ajuste <bold>Forzar el bloqueo de huellas digitales</bold> habilitado.",
"line2": "", "line2": "Esto podría resultar en errores en los <bold>Elementos de Texto</bold> en tus dibujos.",
"line3": "", "line3": "Recomendamos fuertemente deshabilitar esta configuración. Puedes seguir <link>estos pasos</link> sobre cómo hacerlo.",
"line4": "" "line4": ""
},
"libraryElementTypeError": {
"embeddable": "",
"image": ""
} }
}, },
"toolBar": { "toolBar": {
@@ -224,8 +236,10 @@
"link": "Añadir/Actualizar enlace para una forma seleccionada", "link": "Añadir/Actualizar enlace para una forma seleccionada",
"eraser": "Borrar", "eraser": "Borrar",
"frame": "", "frame": "",
"embeddable": "Incrustar Web",
"laser": "Puntero láser",
"hand": "Mano (herramienta de panoramización)", "hand": "Mano (herramienta de panoramización)",
"extraTools": "" "extraTools": "Más herramientas"
}, },
"headings": { "headings": {
"canvasActions": "Acciones del lienzo", "canvasActions": "Acciones del lienzo",
@@ -237,6 +251,7 @@
"linearElement": "Haz clic para dibujar múltiples puntos, arrastrar para solo una línea", "linearElement": "Haz clic para dibujar múltiples puntos, arrastrar para solo una línea",
"freeDraw": "Haz clic y arrastra, suelta al terminar", "freeDraw": "Haz clic y arrastra, suelta al terminar",
"text": "Consejo: también puedes añadir texto haciendo doble clic en cualquier lugar con la herramienta de selección", "text": "Consejo: también puedes añadir texto haciendo doble clic en cualquier lugar con la herramienta de selección",
"embeddable": "Haga clic y arrastre para crear un sitio web incrustado",
"text_selected": "Doble clic o pulse ENTER para editar el texto", "text_selected": "Doble clic o pulse ENTER para editar el texto",
"text_editing": "Pulse Escape o Ctrl/Cmd + ENTER para terminar de editar", "text_editing": "Pulse Escape o Ctrl/Cmd + ENTER para terminar de editar",
"linearElementMulti": "Haz clic en el último punto o presiona Escape o Enter para finalizar", "linearElementMulti": "Haz clic en el último punto o presiona Escape o Enter para finalizar",
@@ -252,7 +267,8 @@
"bindTextToElement": "Presione Entrar para agregar", "bindTextToElement": "Presione Entrar para agregar",
"deepBoxSelect": "Mantén CtrlOrCmd para seleccionar en profundidad, y para evitar arrastrar", "deepBoxSelect": "Mantén CtrlOrCmd para seleccionar en profundidad, y para evitar arrastrar",
"eraserRevert": "Mantenga pulsado Alt para revertir los elementos marcados para su eliminación", "eraserRevert": "Mantenga pulsado Alt para revertir los elementos marcados para su eliminación",
"firefox_clipboard_write": "Esta característica puede ser habilitada estableciendo la bandera \"dom.events.asyncClipboard.clipboardItem\" a \"true\". Para cambiar las banderas del navegador en Firefox, visite la página \"about:config\"." "firefox_clipboard_write": "Esta característica puede ser habilitada estableciendo la bandera \"dom.events.asyncClipboard.clipboardItem\" a \"true\". Para cambiar las banderas del navegador en Firefox, visite la página \"about:config\".",
"disableSnapping": "Mantén pulsado CtrlOrCmd para desactivar el ajuste"
}, },
"canvasError": { "canvasError": {
"cannotShowPreview": "No se puede mostrar la vista previa", "cannotShowPreview": "No se puede mostrar la vista previa",
@@ -360,27 +376,27 @@
"removeItemsFromLib": "Eliminar elementos seleccionados de la biblioteca" "removeItemsFromLib": "Eliminar elementos seleccionados de la biblioteca"
}, },
"imageExportDialog": { "imageExportDialog": {
"header": "", "header": "Exportar imagen",
"label": { "label": {
"withBackground": "", "withBackground": "Fondo",
"onlySelected": "", "onlySelected": "Sólo seleccionados",
"darkMode": "", "darkMode": "Modo oscuro",
"embedScene": "", "embedScene": "Incrustar escena",
"scale": "", "scale": "Escalar",
"padding": "" "padding": "Espaciado"
}, },
"tooltip": { "tooltip": {
"embedScene": "" "embedScene": ""
}, },
"title": { "title": {
"exportToPng": "", "exportToPng": "Exportar a PNG",
"exportToSvg": "", "exportToSvg": "Exportar a SVG",
"copyPngToClipboard": "" "copyPngToClipboard": "Copiar PNG al portapapeles"
}, },
"button": { "button": {
"exportToPng": "", "exportToPng": "PNG",
"exportToSvg": "", "exportToSvg": "SVG",
"copyPngToClipboard": "" "copyPngToClipboard": "Copiar al portapapeles"
} }
}, },
"encrypted": { "encrypted": {
@@ -411,24 +427,26 @@
"fileSavedToFilename": "Guardado en {filename}", "fileSavedToFilename": "Guardado en {filename}",
"canvas": "lienzo", "canvas": "lienzo",
"selection": "selección", "selection": "selección",
"pasteAsSingleElement": "Usa {{shortcut}} para pegar como un solo elemento,\no pegar en un editor de texto existente" "pasteAsSingleElement": "Usa {{shortcut}} para pegar como un solo elemento,\no pegar en un editor de texto existente",
"unableToEmbed": "",
"unrecognizedLinkFormat": ""
}, },
"colors": { "colors": {
"transparent": "Transparente", "transparent": "Transparente",
"black": "", "black": "Negro",
"white": "", "white": "Blanco",
"red": "", "red": "Rojo",
"pink": "", "pink": "Rosa",
"grape": "", "grape": "Uva",
"violet": "", "violet": "Violeta",
"gray": "", "gray": "Gris",
"blue": "", "blue": "Azul",
"cyan": "", "cyan": "Cian",
"teal": "", "teal": "Turquesa",
"green": "", "green": "Verde",
"yellow": "", "yellow": "Amarillo",
"orange": "", "orange": "Naranja",
"bronze": "" "bronze": "Bronce"
}, },
"welcomeScreen": { "welcomeScreen": {
"app": { "app": {
@@ -444,10 +462,41 @@
} }
}, },
"colorPicker": { "colorPicker": {
"mostUsedCustomColors": "", "mostUsedCustomColors": "Colores personalizados más utilizados",
"colors": "", "colors": "Colores",
"shades": "", "shades": "",
"hexCode": "", "hexCode": "Código Hexadecimal",
"noShades": "" "noShades": ""
},
"overwriteConfirm": {
"action": {
"exportToImage": {
"title": "Exportar como imagen",
"button": "Exportar como imagen",
"description": ""
},
"saveToDisk": {
"title": "Guardar en el disco",
"button": "Guardar en el disco",
"description": "Exporta los datos de la escena a un archivo desde el cual podrás importar más tarde."
},
"excalidrawPlus": {
"title": "",
"button": "Exportar a Excalidraw+",
"description": ""
}
},
"modal": {
"loadFromFile": {
"title": "Cargar desde un archivo",
"button": "Cargar desde un archivo",
"description": ""
},
"shareableLink": {
"title": "Cargar desde un enlace",
"button": "Reemplazar mi contenido",
"description": "Cargar un dibujo externo <bold>reemplazará tu contenido existente</bold>.<br></br>Puedes primero hacer una copia de seguridad de tu dibujo usando una de las opciones de abajo."
}
}
} }
} }
+53 -4
View File
@@ -109,8 +109,12 @@
"createContainerFromText": "Bilatu testua edukiontzi batean", "createContainerFromText": "Bilatu testua edukiontzi batean",
"link": { "link": {
"edit": "Editatu esteka", "edit": "Editatu esteka",
"editEmbed": "Editatu esteka eta kapsulatu",
"create": "Sortu esteka", "create": "Sortu esteka",
"label": "Esteka" "createEmbed": "Sortu esteka eta kapsulatu",
"label": "Esteka",
"labelEmbed": "Esteka eta kapsula",
"empty": "Ez da estekarik ezarri"
}, },
"lineEditor": { "lineEditor": {
"edit": "Editatu lerroa", "edit": "Editatu lerroa",
@@ -160,13 +164,16 @@
"darkMode": "Modu iluna", "darkMode": "Modu iluna",
"lightMode": "Modu argia", "lightMode": "Modu argia",
"zenMode": "Zen modua", "zenMode": "Zen modua",
"objectsSnapMode": "Atxiki objektuei",
"exitZenMode": "Irten Zen modutik", "exitZenMode": "Irten Zen modutik",
"cancel": "Utzi", "cancel": "Utzi",
"clear": "Garbitu", "clear": "Garbitu",
"remove": "Kendu", "remove": "Kendu",
"embed": "Aldatu kapsulatzea",
"publishLibrary": "Argitaratu", "publishLibrary": "Argitaratu",
"submit": "Bidali", "submit": "Bidali",
"confirm": "Bai" "confirm": "Bai",
"embeddableInteractionButton": "Egin klik elkar eragiteko"
}, },
"alerts": { "alerts": {
"clearReset": "Honek oihal osoa garbituko du. Ziur zaude?", "clearReset": "Honek oihal osoa garbituko du. Ziur zaude?",
@@ -196,6 +203,7 @@
"imageInsertError": "Ezin izan da irudia txertatu. Saiatu berriro geroago...", "imageInsertError": "Ezin izan da irudia txertatu. Saiatu berriro geroago...",
"fileTooBig": "Fitxategia handiegia da. Onartutako gehienezko tamaina {{maxSize}} da.", "fileTooBig": "Fitxategia handiegia da. Onartutako gehienezko tamaina {{maxSize}} da.",
"svgImageInsertError": "Ezin izan da SVG irudia txertatu. SVG markak baliogabea dirudi.", "svgImageInsertError": "Ezin izan da SVG irudia txertatu. SVG markak baliogabea dirudi.",
"failedToFetchImage": "",
"invalidSVGString": "SVG baliogabea.", "invalidSVGString": "SVG baliogabea.",
"cannotResolveCollabServer": "Ezin izan da elkarlaneko zerbitzarira konektatu. Mesedez, berriro kargatu orria eta saiatu berriro.", "cannotResolveCollabServer": "Ezin izan da elkarlaneko zerbitzarira konektatu. Mesedez, berriro kargatu orria eta saiatu berriro.",
"importLibraryError": "Ezin izan da liburutegia kargatu", "importLibraryError": "Ezin izan da liburutegia kargatu",
@@ -206,6 +214,10 @@
"line2": "Honek zure marrazkietako <bold>Testu-elementuak</bold> hautsi ditzake.", "line2": "Honek zure marrazkietako <bold>Testu-elementuak</bold> hautsi ditzake.",
"line3": "Ezarpen hau desgaitzea gomendatzen dugu. <link>urrats hauek</link> jarrai ditzakezu hori nola egin jakiteko.", "line3": "Ezarpen hau desgaitzea gomendatzen dugu. <link>urrats hauek</link> jarrai ditzakezu hori nola egin jakiteko.",
"line4": "Ezarpen hau desgaituz gero, testu-elementuen bistaratzea konpontzen ez bada, ireki <issueLink>arazo</issueLink> gure GitHub-en edo idatzi iezaguzu <discordLink>Discord</discordLink> helbidera" "line4": "Ezarpen hau desgaituz gero, testu-elementuen bistaratzea konpontzen ez bada, ireki <issueLink>arazo</issueLink> gure GitHub-en edo idatzi iezaguzu <discordLink>Discord</discordLink> helbidera"
},
"libraryElementTypeError": {
"embeddable": "Kapsulatutako elementuak ezin dira liburutegira gehitu.",
"image": "Laster egongo da irudiak liburutegian gehitzeko laguntza!"
} }
}, },
"toolBar": { "toolBar": {
@@ -224,6 +236,8 @@
"link": "Gehitu / Eguneratu esteka hautatutako forma baterako", "link": "Gehitu / Eguneratu esteka hautatutako forma baterako",
"eraser": "Borragoma", "eraser": "Borragoma",
"frame": "Marko tresna", "frame": "Marko tresna",
"embeddable": "Web kapsulatzea",
"laser": "Laser punteroa",
"hand": "Eskua (panoratze tresna)", "hand": "Eskua (panoratze tresna)",
"extraTools": "Tresna gehiago" "extraTools": "Tresna gehiago"
}, },
@@ -237,6 +251,7 @@
"linearElement": "Egin klik hainbat puntu hasteko, arrastatu lerro bakarrerako", "linearElement": "Egin klik hainbat puntu hasteko, arrastatu lerro bakarrerako",
"freeDraw": "Egin klik eta arrastatu, askatu amaitutakoan", "freeDraw": "Egin klik eta arrastatu, askatu amaitutakoan",
"text": "Aholkua: testua gehitu dezakezu edozein lekutan klik bikoitza eginez hautapen tresnarekin", "text": "Aholkua: testua gehitu dezakezu edozein lekutan klik bikoitza eginez hautapen tresnarekin",
"embeddable": "Egin klik eta arrastatu webgunea kapsulatzeko",
"text_selected": "Egin klik bikoitza edo sakatu SARTU testua editatzeko", "text_selected": "Egin klik bikoitza edo sakatu SARTU testua editatzeko",
"text_editing": "Sakatu Esc edo Ctrl+SARTU editatzen amaitzeko", "text_editing": "Sakatu Esc edo Ctrl+SARTU editatzen amaitzeko",
"linearElementMulti": "Egin klik azken puntuan edo sakatu Esc edo Sartu amaitzeko", "linearElementMulti": "Egin klik azken puntuan edo sakatu Esc edo Sartu amaitzeko",
@@ -252,7 +267,8 @@
"bindTextToElement": "Sakatu Sartu testua gehitzeko", "bindTextToElement": "Sakatu Sartu testua gehitzeko",
"deepBoxSelect": "Eutsi Ctrl edo Cmd sakatuta aukeraketa sakona egiteko eta arrastatzea saihesteko", "deepBoxSelect": "Eutsi Ctrl edo Cmd sakatuta aukeraketa sakona egiteko eta arrastatzea saihesteko",
"eraserRevert": "Eduki Alt sakatuta ezabatzeko markatutako elementuak leheneratzeko", "eraserRevert": "Eduki Alt sakatuta ezabatzeko markatutako elementuak leheneratzeko",
"firefox_clipboard_write": "Ezaugarri hau \"dom.events.asyncClipboard.clipboardItem\" marka \"true\" gisa ezarrita gaitu daiteke. Firefox-en arakatzailearen banderak aldatzeko, bisitatu \"about:config\" orrialdera." "firefox_clipboard_write": "Ezaugarri hau \"dom.events.asyncClipboard.clipboardItem\" marka \"true\" gisa ezarrita gaitu daiteke. Firefox-en arakatzailearen banderak aldatzeko, bisitatu \"about:config\" orrialdera.",
"disableSnapping": "Eduki sakatuta Ctrl edo Cmd tekla atxikipena desgaitzeko"
}, },
"canvasError": { "canvasError": {
"cannotShowPreview": "Ezin da oihala aurreikusi", "cannotShowPreview": "Ezin da oihala aurreikusi",
@@ -411,7 +427,9 @@
"fileSavedToFilename": "{filename}-n gorde da", "fileSavedToFilename": "{filename}-n gorde da",
"canvas": "oihala", "canvas": "oihala",
"selection": "hautapena", "selection": "hautapena",
"pasteAsSingleElement": "Erabili {{shortcut}} elementu bakar gisa itsasteko,\nedo itsatsi lehendik dagoen testu-editore batean" "pasteAsSingleElement": "Erabili {{shortcut}} elementu bakar gisa itsasteko,\nedo itsatsi lehendik dagoen testu-editore batean",
"unableToEmbed": "Url hau txertatzea ez da une honetan onartzen. Sortu issue bat GitHub-en Urla zerrenda zurian sartzea eskatzeko",
"unrecognizedLinkFormat": "Kapsulatu duzun esteka ez dator bat espero den formatuarekin. Mesedez, saiatu iturburu-guneak emandako 'kapsulatu' katea itsasten"
}, },
"colors": { "colors": {
"transparent": "Gardena", "transparent": "Gardena",
@@ -449,5 +467,36 @@
"shades": "Ñabardurak", "shades": "Ñabardurak",
"hexCode": "Hez kodea", "hexCode": "Hez kodea",
"noShades": "Kolore honetarako ez dago ñabardurarik eskuragarri" "noShades": "Kolore honetarako ez dago ñabardurarik eskuragarri"
},
"overwriteConfirm": {
"action": {
"exportToImage": {
"title": "Esportatu irudi gisa",
"button": "Esportatu irudi gisa",
"description": "Esportatu eszenaren datuak geroago inportatu ahal izango duzun irudi gisa."
},
"saveToDisk": {
"title": "Gorde diskoan",
"button": "Gorde diskoan",
"description": "Esportatu eszenaren datuak geroago inportatu ahal izango duzun fitxategi batan."
},
"excalidrawPlus": {
"title": "Excalidraw+",
"button": "Esportatu Excalidraw+ra",
"description": "Gorde eszena zure Excalidraw+ laneko areara."
}
},
"modal": {
"loadFromFile": {
"title": "Fitxategitik kargatu",
"button": "Fitxategitik kargatu",
"description": "Fitxategi batetik kargatzeak <bold>lehendik duzun edukia ordezkatuko du</bold>.<br></br>Lehenengo marrazkiaren babeskopia egin dezakezu beheko aukeretako bat erabiliz."
},
"shareableLink": {
"title": "Estekatik kargatu",
"button": "Ordeztu nire edukia",
"description": "Kanpoko irudi bat kargatzeak <bold>lehendik duzun edukia ordezkatuko du</bold>.<br></br>. Zure marrazkiaren babeskopia egin dezakezu lehenik beheko aukeretako bat erabiliz."
}
}
} }
} }
+73 -24
View File
@@ -109,8 +109,12 @@
"createContainerFromText": "متن را در یک جایگاه بپیچید", "createContainerFromText": "متن را در یک جایگاه بپیچید",
"link": { "link": {
"edit": "ویرایش لینک", "edit": "ویرایش لینک",
"editEmbed": "",
"create": "ایجاد پیوند", "create": "ایجاد پیوند",
"label": "لینک" "createEmbed": "",
"label": "لینک",
"labelEmbed": "",
"empty": ""
}, },
"lineEditor": { "lineEditor": {
"edit": "ویرایش لینک", "edit": "ویرایش لینک",
@@ -126,7 +130,7 @@
"sidebarLock": "باز نگه داشتن سایدبار", "sidebarLock": "باز نگه داشتن سایدبار",
"selectAllElementsInFrame": "", "selectAllElementsInFrame": "",
"removeAllElementsFromFrame": "", "removeAllElementsFromFrame": "",
"eyeDropper": "" "eyeDropper": "انتخاب رنگ از کرباس"
}, },
"library": { "library": {
"noItems": "آیتمی به اینجا اضافه نشده...", "noItems": "آیتمی به اینجا اضافه نشده...",
@@ -160,13 +164,16 @@
"darkMode": "حالت تیره", "darkMode": "حالت تیره",
"lightMode": "حالت روشن", "lightMode": "حالت روشن",
"zenMode": "حالت ذن", "zenMode": "حالت ذن",
"objectsSnapMode": "",
"exitZenMode": "خروج از حالت تمرکز", "exitZenMode": "خروج از حالت تمرکز",
"cancel": "لغو", "cancel": "لغو",
"clear": "پاک کردن", "clear": "پاک کردن",
"remove": "پاک کردن", "remove": "پاک کردن",
"embed": "",
"publishLibrary": "انتشار", "publishLibrary": "انتشار",
"submit": "ارسال", "submit": "ارسال",
"confirm": "تایید" "confirm": "تایید",
"embeddableInteractionButton": ""
}, },
"alerts": { "alerts": {
"clearReset": "این کار کل صفحه را پاک میکند. آیا مطمئنید؟", "clearReset": "این کار کل صفحه را پاک میکند. آیا مطمئنید؟",
@@ -196,6 +203,7 @@
"imageInsertError": "عکس ارسال نشد. بعداً دوباره تلاش کنید...", "imageInsertError": "عکس ارسال نشد. بعداً دوباره تلاش کنید...",
"fileTooBig": "فایل خیلی بزرگ است حداکثر اندازه مجاز {{maxSize}}.", "fileTooBig": "فایل خیلی بزرگ است حداکثر اندازه مجاز {{maxSize}}.",
"svgImageInsertError": "تصویر SVG وارد نشد. نشانه گذاری SVG نامعتبر به نظر می رسد.", "svgImageInsertError": "تصویر SVG وارد نشد. نشانه گذاری SVG نامعتبر به نظر می رسد.",
"failedToFetchImage": "",
"invalidSVGString": "SVG نادرست.", "invalidSVGString": "SVG نادرست.",
"cannotResolveCollabServer": "به سرور collab متصل نشد. لطفا صفحه را مجددا بارگذاری کنید و دوباره تلاش کنید.", "cannotResolveCollabServer": "به سرور collab متصل نشد. لطفا صفحه را مجددا بارگذاری کنید و دوباره تلاش کنید.",
"importLibraryError": "داده‌ها بارگذاری نشدند", "importLibraryError": "داده‌ها بارگذاری نشدند",
@@ -206,6 +214,10 @@
"line2": "این می تواند منجر به شکستن <bold>عناصر متن</bold> در نقاشی های شما شود.", "line2": "این می تواند منجر به شکستن <bold>عناصر متن</bold> در نقاشی های شما شود.",
"line3": "اکیداً توصیه می کنیم این تنظیم را غیرفعال کنید. برای نحوه انجام این کار می‌توانید <link>این مراحل</link> را دنبال کنید.", "line3": "اکیداً توصیه می کنیم این تنظیم را غیرفعال کنید. برای نحوه انجام این کار می‌توانید <link>این مراحل</link> را دنبال کنید.",
"line4": "اگر غیرفعال کردن این تنظیم نمایش عناصر متنی را برطرف نکرد، لطفاً یک <issueLink>مشکل</issueLink> را در GitHub ما باز کنید یا برای ما در <discordLink>Discord</discordLink> بنویسید." "line4": "اگر غیرفعال کردن این تنظیم نمایش عناصر متنی را برطرف نکرد، لطفاً یک <issueLink>مشکل</issueLink> را در GitHub ما باز کنید یا برای ما در <discordLink>Discord</discordLink> بنویسید."
},
"libraryElementTypeError": {
"embeddable": "",
"image": ""
} }
}, },
"toolBar": { "toolBar": {
@@ -224,8 +236,10 @@
"link": "افزودن/به‌روزرسانی پیوند برای شکل انتخابی", "link": "افزودن/به‌روزرسانی پیوند برای شکل انتخابی",
"eraser": "پاک کن", "eraser": "پاک کن",
"frame": "", "frame": "",
"embeddable": "",
"laser": "",
"hand": "دست (ابزار پانینگ)", "hand": "دست (ابزار پانینگ)",
"extraTools": "" "extraTools": "ابزارهای بیشتر"
}, },
"headings": { "headings": {
"canvasActions": "عملیات روی بوم", "canvasActions": "عملیات روی بوم",
@@ -237,6 +251,7 @@
"linearElement": "برای چند نقطه کلیک و برای یک خط بکشید", "linearElement": "برای چند نقطه کلیک و برای یک خط بکشید",
"freeDraw": "کلیک کنید و بکشید و وقتی کار تمام شد رها کنید", "freeDraw": "کلیک کنید و بکشید و وقتی کار تمام شد رها کنید",
"text": "نکته: با برنامه انتخاب شده شما میتوانید با دوبار کلیک کردن هرکجا میخواید متن اظاف کنید", "text": "نکته: با برنامه انتخاب شده شما میتوانید با دوبار کلیک کردن هرکجا میخواید متن اظاف کنید",
"embeddable": "",
"text_selected": "دوبار کلیک کنید یا Enter را فشار دهید تا نقاط را ویرایش کنید", "text_selected": "دوبار کلیک کنید یا Enter را فشار دهید تا نقاط را ویرایش کنید",
"text_editing": "Escape یا CtrlOrCmd+ENTER را فشار دهید تا ویرایش تمام شود", "text_editing": "Escape یا CtrlOrCmd+ENTER را فشار دهید تا ویرایش تمام شود",
"linearElementMulti": "روی آخرین نقطه کلیک کنید یا کلید ESC را بزنید یا کلید Enter را بزنید برای اتمام کار", "linearElementMulti": "روی آخرین نقطه کلیک کنید یا کلید ESC را بزنید یا کلید Enter را بزنید برای اتمام کار",
@@ -252,7 +267,8 @@
"bindTextToElement": "برای افزودن اینتر را بزنید", "bindTextToElement": "برای افزودن اینتر را بزنید",
"deepBoxSelect": "CtrlOrCmd را برای انتخاب عمیق و جلوگیری از کشیدن نگه دارید", "deepBoxSelect": "CtrlOrCmd را برای انتخاب عمیق و جلوگیری از کشیدن نگه دارید",
"eraserRevert": "Alt را نگه دارید تا عناصر علامت گذاری شده برای حذف برگردند", "eraserRevert": "Alt را نگه دارید تا عناصر علامت گذاری شده برای حذف برگردند",
"firefox_clipboard_write": "احتمالاً می‌توان این ویژگی را با تنظیم پرچم «dom.events.asyncClipboard.clipboardItem» روی «true» فعال کرد. برای تغییر پرچم های مرورگر در فایرفاکس، از صفحه \"about:config\" دیدن کنید." "firefox_clipboard_write": "احتمالاً می‌توان این ویژگی را با تنظیم پرچم «dom.events.asyncClipboard.clipboardItem» روی «true» فعال کرد. برای تغییر پرچم های مرورگر در فایرفاکس، از صفحه \"about:config\" دیدن کنید.",
"disableSnapping": ""
}, },
"canvasError": { "canvasError": {
"cannotShowPreview": "پیش نمایش نشان داده نمی شود", "cannotShowPreview": "پیش نمایش نشان داده نمی شود",
@@ -362,7 +378,7 @@
"imageExportDialog": { "imageExportDialog": {
"header": "", "header": "",
"label": { "label": {
"withBackground": "", "withBackground": "پس زمینه",
"onlySelected": "", "onlySelected": "",
"darkMode": "", "darkMode": "",
"embedScene": "", "embedScene": "",
@@ -411,24 +427,26 @@
"fileSavedToFilename": "ذخیره در {filename}", "fileSavedToFilename": "ذخیره در {filename}",
"canvas": "بوم", "canvas": "بوم",
"selection": "انتخاب", "selection": "انتخاب",
"pasteAsSingleElement": "از {{shortcut}} برای چسباندن به عنوان یک عنصر استفاده کنید،\nیا در یک ویرایشگر متن موجود جایگذاری کنید" "pasteAsSingleElement": "از {{shortcut}} برای چسباندن به عنوان یک عنصر استفاده کنید،\nیا در یک ویرایشگر متن موجود جایگذاری کنید",
"unableToEmbed": "",
"unrecognizedLinkFormat": ""
}, },
"colors": { "colors": {
"transparent": "شفاف", "transparent": "شفاف",
"black": "", "black": "سیاه",
"white": "", "white": "سفید",
"red": "", "red": "قرمز",
"pink": "", "pink": "صورتی",
"grape": "", "grape": "یاقوتی",
"violet": "", "violet": "بنفش",
"gray": "", "gray": "خاکستری",
"blue": "", "blue": "آبی",
"cyan": "", "cyan": "فیروزه‌ای",
"teal": "", "teal": "سبزآبی",
"green": "", "green": "سبز",
"yellow": "", "yellow": "زرد",
"orange": "", "orange": "نارنجی",
"bronze": "" "bronze": "برنزی"
}, },
"welcomeScreen": { "welcomeScreen": {
"app": { "app": {
@@ -445,9 +463,40 @@
}, },
"colorPicker": { "colorPicker": {
"mostUsedCustomColors": "", "mostUsedCustomColors": "",
"colors": "", "colors": "رنگ‌ها",
"shades": "", "shades": "جلوه‌ها",
"hexCode": "", "hexCode": "کدِ هگز",
"noShades": "" "noShades": ""
},
"overwriteConfirm": {
"action": {
"exportToImage": {
"title": "",
"button": "",
"description": ""
},
"saveToDisk": {
"title": "ذخیره در دیسک",
"button": "ذخیره در دیسک",
"description": ""
},
"excalidrawPlus": {
"title": "",
"button": "",
"description": ""
}
},
"modal": {
"loadFromFile": {
"title": "بارگذاری از فایل",
"button": "بارگذاری از فایل",
"description": ""
},
"shareableLink": {
"title": "",
"button": "",
"description": ""
}
}
} }
} }
+53 -4
View File
@@ -109,8 +109,12 @@
"createContainerFromText": "", "createContainerFromText": "",
"link": { "link": {
"edit": "Muokkaa linkkiä", "edit": "Muokkaa linkkiä",
"editEmbed": "",
"create": "Luo linkki", "create": "Luo linkki",
"label": "Linkki" "createEmbed": "",
"label": "Linkki",
"labelEmbed": "",
"empty": ""
}, },
"lineEditor": { "lineEditor": {
"edit": "Muokkaa riviä", "edit": "Muokkaa riviä",
@@ -160,13 +164,16 @@
"darkMode": "Tumma tila", "darkMode": "Tumma tila",
"lightMode": "Vaalea tila", "lightMode": "Vaalea tila",
"zenMode": "Zen-tila", "zenMode": "Zen-tila",
"objectsSnapMode": "",
"exitZenMode": "Poistu zen-tilasta", "exitZenMode": "Poistu zen-tilasta",
"cancel": "Peruuta", "cancel": "Peruuta",
"clear": "Pyyhi", "clear": "Pyyhi",
"remove": "Poista", "remove": "Poista",
"embed": "",
"publishLibrary": "Julkaise", "publishLibrary": "Julkaise",
"submit": "Lähetä", "submit": "Lähetä",
"confirm": "Vahvista" "confirm": "Vahvista",
"embeddableInteractionButton": ""
}, },
"alerts": { "alerts": {
"clearReset": "Tämä tyhjentää koko piirtoalueen. Jatketaanko?", "clearReset": "Tämä tyhjentää koko piirtoalueen. Jatketaanko?",
@@ -196,6 +203,7 @@
"imageInsertError": "Kuvan lisääminen epäonnistui. Yritä myöhemmin uudelleen...", "imageInsertError": "Kuvan lisääminen epäonnistui. Yritä myöhemmin uudelleen...",
"fileTooBig": "Tiedosto on liian suuri. Suurin sallittu koko on {{maxSize}}.", "fileTooBig": "Tiedosto on liian suuri. Suurin sallittu koko on {{maxSize}}.",
"svgImageInsertError": "SVG- kuvaa ei voitu lisätä. Tiedoston SVG-sisältö näyttää virheelliseltä.", "svgImageInsertError": "SVG- kuvaa ei voitu lisätä. Tiedoston SVG-sisältö näyttää virheelliseltä.",
"failedToFetchImage": "",
"invalidSVGString": "Virheellinen SVG.", "invalidSVGString": "Virheellinen SVG.",
"cannotResolveCollabServer": "Yhteyden muodostaminen collab-palvelimeen epäonnistui. Virkistä sivu ja yritä uudelleen.", "cannotResolveCollabServer": "Yhteyden muodostaminen collab-palvelimeen epäonnistui. Virkistä sivu ja yritä uudelleen.",
"importLibraryError": "Kokoelman lataaminen epäonnistui", "importLibraryError": "Kokoelman lataaminen epäonnistui",
@@ -206,6 +214,10 @@
"line2": "", "line2": "",
"line3": "", "line3": "",
"line4": "" "line4": ""
},
"libraryElementTypeError": {
"embeddable": "",
"image": ""
} }
}, },
"toolBar": { "toolBar": {
@@ -224,6 +236,8 @@
"link": "Lisää/päivitä linkki valitulle muodolle", "link": "Lisää/päivitä linkki valitulle muodolle",
"eraser": "Poistotyökalu", "eraser": "Poistotyökalu",
"frame": "", "frame": "",
"embeddable": "",
"laser": "",
"hand": "Käsi (panning-työkalu)", "hand": "Käsi (panning-työkalu)",
"extraTools": "" "extraTools": ""
}, },
@@ -237,6 +251,7 @@
"linearElement": "Klikkaa piirtääksesi useampi piste, raahaa piirtääksesi yksittäinen viiva", "linearElement": "Klikkaa piirtääksesi useampi piste, raahaa piirtääksesi yksittäinen viiva",
"freeDraw": "Paina ja raahaa, päästä irti kun olet valmis", "freeDraw": "Paina ja raahaa, päästä irti kun olet valmis",
"text": "Vinkki: voit myös lisätä tekstiä kaksoisnapsauttamalla mihin tahansa valintatyökalulla", "text": "Vinkki: voit myös lisätä tekstiä kaksoisnapsauttamalla mihin tahansa valintatyökalulla",
"embeddable": "",
"text_selected": "Kaksoisnapsauta tai paina ENTER muokataksesi tekstiä", "text_selected": "Kaksoisnapsauta tai paina ENTER muokataksesi tekstiä",
"text_editing": "Paina Escape tai CtrlOrCmd+ENTER lopettaaksesi muokkaamisen", "text_editing": "Paina Escape tai CtrlOrCmd+ENTER lopettaaksesi muokkaamisen",
"linearElementMulti": "Lopeta klikkaamalla viimeistä pistettä, painamalla Escape- tai Enter-näppäintä", "linearElementMulti": "Lopeta klikkaamalla viimeistä pistettä, painamalla Escape- tai Enter-näppäintä",
@@ -252,7 +267,8 @@
"bindTextToElement": "Lisää tekstiä painamalla enter", "bindTextToElement": "Lisää tekstiä painamalla enter",
"deepBoxSelect": "Käytä syvävalintaa ja estä raahaus painamalla CtrlOrCmd", "deepBoxSelect": "Käytä syvävalintaa ja estä raahaus painamalla CtrlOrCmd",
"eraserRevert": "Pidä Alt alaspainettuna, kumotaksesi merkittyjen elementtien poistamisen", "eraserRevert": "Pidä Alt alaspainettuna, kumotaksesi merkittyjen elementtien poistamisen",
"firefox_clipboard_write": "Tämä ominaisuus voidaan todennäköisesti ottaa käyttöön asettamalla \"dom.events.asyncClipboard.clipboardItem\" kohta \"true\":ksi. Vaihtaaksesi selaimen kohdan Firefoxissa, käy \"about:config\" sivulla." "firefox_clipboard_write": "Tämä ominaisuus voidaan todennäköisesti ottaa käyttöön asettamalla \"dom.events.asyncClipboard.clipboardItem\" kohta \"true\":ksi. Vaihtaaksesi selaimen kohdan Firefoxissa, käy \"about:config\" sivulla.",
"disableSnapping": ""
}, },
"canvasError": { "canvasError": {
"cannotShowPreview": "Esikatselua ei voitu näyttää", "cannotShowPreview": "Esikatselua ei voitu näyttää",
@@ -411,7 +427,9 @@
"fileSavedToFilename": "Tallennettiin kohteeseen {filename}", "fileSavedToFilename": "Tallennettiin kohteeseen {filename}",
"canvas": "piirtoalue", "canvas": "piirtoalue",
"selection": "valinta", "selection": "valinta",
"pasteAsSingleElement": "Käytä {{shortcut}} liittääksesi yhtenä elementtinä,\ntai liittääksesi olemassa olevaan tekstieditoriin" "pasteAsSingleElement": "Käytä {{shortcut}} liittääksesi yhtenä elementtinä,\ntai liittääksesi olemassa olevaan tekstieditoriin",
"unableToEmbed": "",
"unrecognizedLinkFormat": ""
}, },
"colors": { "colors": {
"transparent": "Läpinäkyvä", "transparent": "Läpinäkyvä",
@@ -449,5 +467,36 @@
"shades": "", "shades": "",
"hexCode": "", "hexCode": "",
"noShades": "" "noShades": ""
},
"overwriteConfirm": {
"action": {
"exportToImage": {
"title": "",
"button": "",
"description": ""
},
"saveToDisk": {
"title": "",
"button": "",
"description": ""
},
"excalidrawPlus": {
"title": "",
"button": "",
"description": ""
}
},
"modal": {
"loadFromFile": {
"title": "",
"button": "",
"description": ""
},
"shareableLink": {
"title": "",
"button": "",
"description": ""
}
}
} }
} }
+94 -45
View File
@@ -50,7 +50,7 @@
"veryLarge": "Très grande", "veryLarge": "Très grande",
"solid": "Solide", "solid": "Solide",
"hachure": "Hachures", "hachure": "Hachures",
"zigzag": "", "zigzag": "Zigzag",
"crossHatch": "Hachures croisées", "crossHatch": "Hachures croisées",
"thin": "Fine", "thin": "Fine",
"bold": "Épaisse", "bold": "Épaisse",
@@ -109,8 +109,12 @@
"createContainerFromText": "Encadrer le texte dans un conteneur", "createContainerFromText": "Encadrer le texte dans un conteneur",
"link": { "link": {
"edit": "Modifier le lien", "edit": "Modifier le lien",
"editEmbed": "Éditer le lien & intégrer",
"create": "Ajouter un lien", "create": "Ajouter un lien",
"label": "Lien" "createEmbed": "Créer un lien & intégrer",
"label": "Lien",
"labelEmbed": "",
"empty": "Aucun lien défini"
}, },
"lineEditor": { "lineEditor": {
"edit": "Modifier la ligne", "edit": "Modifier la ligne",
@@ -124,8 +128,8 @@
}, },
"statusPublished": "Publié", "statusPublished": "Publié",
"sidebarLock": "Maintenir la barre latérale ouverte", "sidebarLock": "Maintenir la barre latérale ouverte",
"selectAllElementsInFrame": "", "selectAllElementsInFrame": "Sélectionner tous les éléments du cadre",
"removeAllElementsFromFrame": "", "removeAllElementsFromFrame": "Supprimer tous les éléments du cadre",
"eyeDropper": "" "eyeDropper": ""
}, },
"library": { "library": {
@@ -160,13 +164,16 @@
"darkMode": "Mode sombre", "darkMode": "Mode sombre",
"lightMode": "Mode clair", "lightMode": "Mode clair",
"zenMode": "Mode zen", "zenMode": "Mode zen",
"objectsSnapMode": "Aimanter aux objets",
"exitZenMode": "Quitter le mode zen", "exitZenMode": "Quitter le mode zen",
"cancel": "Annuler", "cancel": "Annuler",
"clear": "Effacer", "clear": "Effacer",
"remove": "Supprimer", "remove": "Supprimer",
"embed": "Activer/Désactiver l'intégration",
"publishLibrary": "Publier", "publishLibrary": "Publier",
"submit": "Envoyer", "submit": "Envoyer",
"confirm": "Confirmer" "confirm": "Confirmer",
"embeddableInteractionButton": "Cliquez pour interagir"
}, },
"alerts": { "alerts": {
"clearReset": "L'intégralité du canevas va être effacée. Êtes-vous sûr ?", "clearReset": "L'intégralité du canevas va être effacée. Êtes-vous sûr ?",
@@ -196,16 +203,21 @@
"imageInsertError": "Impossible d'insérer l'image. Réessayez plus tard...", "imageInsertError": "Impossible d'insérer l'image. Réessayez plus tard...",
"fileTooBig": "Le fichier est trop volumineux. La taille maximale autorisée est de {{maxSize}}.", "fileTooBig": "Le fichier est trop volumineux. La taille maximale autorisée est de {{maxSize}}.",
"svgImageInsertError": "Impossible d'insérer l'image SVG. Le balisage SVG semble invalide.", "svgImageInsertError": "Impossible d'insérer l'image SVG. Le balisage SVG semble invalide.",
"failedToFetchImage": "",
"invalidSVGString": "SVG invalide.", "invalidSVGString": "SVG invalide.",
"cannotResolveCollabServer": "Impossible de se connecter au serveur collaboratif. Veuillez recharger la page et réessayer.", "cannotResolveCollabServer": "Impossible de se connecter au serveur collaboratif. Veuillez recharger la page et réessayer.",
"importLibraryError": "Impossible de charger la bibliothèque", "importLibraryError": "Impossible de charger la bibliothèque",
"collabSaveFailed": "Impossible d'enregistrer dans la base de données en arrière-plan. Si des problèmes persistent, vous devriez enregistrer votre fichier localement pour vous assurer de ne pas perdre votre travail.", "collabSaveFailed": "Impossible d'enregistrer dans la base de données en arrière-plan. Si des problèmes persistent, vous devriez enregistrer votre fichier localement pour vous assurer de ne pas perdre votre travail.",
"collabSaveFailed_sizeExceeded": "Impossible d'enregistrer dans la base de données en arrière-plan, le tableau semble trop grand. Vous devriez enregistrer le fichier localement pour vous assurer de ne pas perdre votre travail.", "collabSaveFailed_sizeExceeded": "Impossible d'enregistrer dans la base de données en arrière-plan, le tableau semble trop grand. Vous devriez enregistrer le fichier localement pour vous assurer de ne pas perdre votre travail.",
"brave_measure_text_error": { "brave_measure_text_error": {
"line1": "", "line1": "On dirait que vous utilisez le navigateur Brave avec l'option <bold>Bloquer agressivement le fichage</bold> activée.",
"line2": "", "line2": "Cela pourrait entraîner des problèmes avec les <bold>Éléments Textuels</bold> dans vos dessins.",
"line3": "", "line3": "Nous recommandons fortement de désactiver cette option. Vous pouvez suivre <link>ces instructions</link> pour savoir comment faire.",
"line4": "" "line4": "Si désactiver cette option de résout pas le problème d'affichage des éléments textuels, veuillez ouvrir un <issueLink>ticket</issueLink> sur notre GitHub, ou écrivez-nous sur notre <discordLink>Discord</discordLink>"
},
"libraryElementTypeError": {
"embeddable": "Les éléments intégrés ne peuvent pas être ajoutés à la librairie.",
"image": "Le support pour l'ajout d'images à la librairie arrive bientôt !"
} }
}, },
"toolBar": { "toolBar": {
@@ -223,9 +235,11 @@
"penMode": "Mode stylo - évite le toucher", "penMode": "Mode stylo - évite le toucher",
"link": "Ajouter/mettre à jour le lien pour une forme sélectionnée", "link": "Ajouter/mettre à jour le lien pour une forme sélectionnée",
"eraser": "Gomme", "eraser": "Gomme",
"frame": "", "frame": "Outil de cadre",
"embeddable": "Intégration Web",
"laser": "",
"hand": "Mains (outil de déplacement de la vue)", "hand": "Mains (outil de déplacement de la vue)",
"extraTools": "" "extraTools": "Plus d'outils"
}, },
"headings": { "headings": {
"canvasActions": "Actions du canevas", "canvasActions": "Actions du canevas",
@@ -237,6 +251,7 @@
"linearElement": "Cliquez pour démarrer plusieurs points, faites glisser pour une seule ligne", "linearElement": "Cliquez pour démarrer plusieurs points, faites glisser pour une seule ligne",
"freeDraw": "Cliquez et faites glissez, relâchez quand vous avez terminé", "freeDraw": "Cliquez et faites glissez, relâchez quand vous avez terminé",
"text": "Astuce : vous pouvez aussi ajouter du texte en double-cliquant n'importe où avec l'outil de sélection", "text": "Astuce : vous pouvez aussi ajouter du texte en double-cliquant n'importe où avec l'outil de sélection",
"embeddable": "Cliquez et glissez pour créer une intégration de site web",
"text_selected": "Double-cliquez ou appuyez sur ENTRÉE pour modifier le texte", "text_selected": "Double-cliquez ou appuyez sur ENTRÉE pour modifier le texte",
"text_editing": "Appuyez sur ÉCHAP ou Ctrl/Cmd+ENTRÉE pour terminer l'édition", "text_editing": "Appuyez sur ÉCHAP ou Ctrl/Cmd+ENTRÉE pour terminer l'édition",
"linearElementMulti": "Cliquez sur le dernier point ou appuyez sur Échap ou Entrée pour terminer", "linearElementMulti": "Cliquez sur le dernier point ou appuyez sur Échap ou Entrée pour terminer",
@@ -252,7 +267,8 @@
"bindTextToElement": "Appuyer sur Entrée pour ajouter du texte", "bindTextToElement": "Appuyer sur Entrée pour ajouter du texte",
"deepBoxSelect": "Maintenir Ctrl ou Cmd pour sélectionner dans les groupes et empêcher le déplacement", "deepBoxSelect": "Maintenir Ctrl ou Cmd pour sélectionner dans les groupes et empêcher le déplacement",
"eraserRevert": "Maintenez Alt enfoncé pour annuler les éléments marqués pour suppression", "eraserRevert": "Maintenez Alt enfoncé pour annuler les éléments marqués pour suppression",
"firefox_clipboard_write": "Cette fonctionnalité devrait pouvoir être activée en définissant l'option \"dom.events.asyncClipboard.clipboard.clipboardItem\" à \"true\". Pour modifier les paramètres du navigateur dans Firefox, visitez la page \"about:config\"." "firefox_clipboard_write": "Cette fonctionnalité devrait pouvoir être activée en définissant l'option \"dom.events.asyncClipboard.clipboard.clipboardItem\" à \"true\". Pour modifier les paramètres du navigateur dans Firefox, visitez la page \"about:config\".",
"disableSnapping": "Maintenez CtrlOuCmd pour désactiver l'aimantation"
}, },
"canvasError": { "canvasError": {
"cannotShowPreview": "Impossible dafficher laperçu", "cannotShowPreview": "Impossible dafficher laperçu",
@@ -360,27 +376,27 @@
"removeItemsFromLib": "Enlever les éléments sélectionnés de la bibliothèque" "removeItemsFromLib": "Enlever les éléments sélectionnés de la bibliothèque"
}, },
"imageExportDialog": { "imageExportDialog": {
"header": "", "header": "Exporter l'image",
"label": { "label": {
"withBackground": "", "withBackground": "Fond",
"onlySelected": "", "onlySelected": "Uniquement la sélection",
"darkMode": "", "darkMode": "Mode sombre",
"embedScene": "", "embedScene": "Intégrer la scène",
"scale": "", "scale": "Échelle",
"padding": "" "padding": ""
}, },
"tooltip": { "tooltip": {
"embedScene": "" "embedScene": "Les données de la scène seront sauvegardées dans le fichier PNG/SVG exporté afin que la scène puisse être restaurée depuis celui-ci.\nCela augmentera la taille du fichier exporté."
}, },
"title": { "title": {
"exportToPng": "", "exportToPng": "Exporter en PNG",
"exportToSvg": "", "exportToSvg": "Exporter en SVG",
"copyPngToClipboard": "" "copyPngToClipboard": "Copier le PNG dans le presse-papier"
}, },
"button": { "button": {
"exportToPng": "", "exportToPng": "PNG",
"exportToSvg": "", "exportToSvg": "SVG",
"copyPngToClipboard": "" "copyPngToClipboard": "Copier dans le presse-papier"
} }
}, },
"encrypted": { "encrypted": {
@@ -411,24 +427,26 @@
"fileSavedToFilename": "Enregistré sous {filename}", "fileSavedToFilename": "Enregistré sous {filename}",
"canvas": "canevas", "canvas": "canevas",
"selection": "sélection", "selection": "sélection",
"pasteAsSingleElement": "Utiliser {{shortcut}} pour coller comme un seul élément,\nou coller dans un éditeur de texte existant" "pasteAsSingleElement": "Utiliser {{shortcut}} pour coller comme un seul élément,\nou coller dans un éditeur de texte existant",
"unableToEmbed": "Intégrer cet URL n'est actuellement pas autorisé. Ouvrez un ticket sur GitHub pour demander son ajout à la liste blanche",
"unrecognizedLinkFormat": "Le lien que vous avez intégré ne correspond pas au format attendu. Veuillez essayer de coller la chaîne d'intégration fournie par le site source"
}, },
"colors": { "colors": {
"transparent": "Transparent", "transparent": "Transparent",
"black": "", "black": "Noir",
"white": "", "white": "Blanc",
"red": "", "red": "Rouge",
"pink": "", "pink": "Rose",
"grape": "", "grape": "Mauve",
"violet": "", "violet": "Violet",
"gray": "", "gray": "Gris",
"blue": "", "blue": "Bleu",
"cyan": "", "cyan": "Cyan",
"teal": "", "teal": "Turquoise",
"green": "", "green": "Vert",
"yellow": "", "yellow": "Jaune",
"orange": "", "orange": "Orange",
"bronze": "" "bronze": "Bronze"
}, },
"welcomeScreen": { "welcomeScreen": {
"app": { "app": {
@@ -444,10 +462,41 @@
} }
}, },
"colorPicker": { "colorPicker": {
"mostUsedCustomColors": "", "mostUsedCustomColors": "Couleurs personnalisées les plus fréquemment utilisées",
"colors": "", "colors": "Couleurs",
"shades": "", "shades": "Nuances",
"hexCode": "", "hexCode": "Code hex",
"noShades": "" "noShades": "Aucune nuance disponible pour cette couleur"
},
"overwriteConfirm": {
"action": {
"exportToImage": {
"title": "Exporter en image",
"button": "Exporter en image",
"description": "Exporter les données de la scène comme une image que vous pourrez importer ultérieurement."
},
"saveToDisk": {
"title": "Sauvegarder sur le disque",
"button": "Sauvegarder sur le disque",
"description": "Exporter les données de la scène comme un fichier que vous pourrez importer ultérieurement."
},
"excalidrawPlus": {
"title": "Excalidraw+",
"button": "Exporter vers Excalidraw+",
"description": "Enregistrer la scène dans votre espace de travail Excalidraw+."
}
},
"modal": {
"loadFromFile": {
"title": "Charger depuis un fichier",
"button": "Charger depuis un fichier",
"description": "Charger depuis un fichier va <bold>remplacer votre contenu existant</bold>.<br></br>Vous pouvez d'abord sauvegarder votre dessin en utilisant l'une des options ci-dessous."
},
"shareableLink": {
"title": "Charger depuis un lien",
"button": "Remplacer mon contenu",
"description": "Charger un dessin externe va <bold>remplacer votre contenu existant</bold>.<br></br>Vous pouvez d'abord sauvegarder votre dessin en utilisant l'une des options ci-dessous."
}
}
} }
} }
+77 -28
View File
@@ -50,7 +50,7 @@
"veryLarge": "Moi grande", "veryLarge": "Moi grande",
"solid": "Sólido", "solid": "Sólido",
"hachure": "Folleto", "hachure": "Folleto",
"zigzag": "", "zigzag": "Zigzag",
"crossHatch": "Raiado transversal", "crossHatch": "Raiado transversal",
"thin": "Estreito", "thin": "Estreito",
"bold": "Groso", "bold": "Groso",
@@ -109,8 +109,12 @@
"createContainerFromText": "Envolver o texto nun contedor", "createContainerFromText": "Envolver o texto nun contedor",
"link": { "link": {
"edit": "Editar ligazón", "edit": "Editar ligazón",
"editEmbed": "",
"create": "Crear ligazón", "create": "Crear ligazón",
"label": "Ligazón" "createEmbed": "",
"label": "Ligazón",
"labelEmbed": "",
"empty": ""
}, },
"lineEditor": { "lineEditor": {
"edit": "Editar liña", "edit": "Editar liña",
@@ -160,13 +164,16 @@
"darkMode": "Modo escuro", "darkMode": "Modo escuro",
"lightMode": "Modo claro", "lightMode": "Modo claro",
"zenMode": "Modo zen", "zenMode": "Modo zen",
"objectsSnapMode": "",
"exitZenMode": "Saír do modo zen", "exitZenMode": "Saír do modo zen",
"cancel": "Cancelar", "cancel": "Cancelar",
"clear": "Limpar", "clear": "Limpar",
"remove": "Eliminar", "remove": "Eliminar",
"embed": "",
"publishLibrary": "Publicar", "publishLibrary": "Publicar",
"submit": "Enviar", "submit": "Enviar",
"confirm": "Confirmar" "confirm": "Confirmar",
"embeddableInteractionButton": "Faga clic para interactuar"
}, },
"alerts": { "alerts": {
"clearReset": "Isto limpará todo o lenzo. Estás seguro?", "clearReset": "Isto limpará todo o lenzo. Estás seguro?",
@@ -196,6 +203,7 @@
"imageInsertError": "Non se puido inserir a imaxe. Probe de novo máis tarde...", "imageInsertError": "Non se puido inserir a imaxe. Probe de novo máis tarde...",
"fileTooBig": "O ficheiro é demasiado grande. O tamaño máximo permitido é {{maxSize}}.", "fileTooBig": "O ficheiro é demasiado grande. O tamaño máximo permitido é {{maxSize}}.",
"svgImageInsertError": "Non se puido inserir como imaxe SVG. O marcado SVG semella inválido.", "svgImageInsertError": "Non se puido inserir como imaxe SVG. O marcado SVG semella inválido.",
"failedToFetchImage": "",
"invalidSVGString": "SVG inválido.", "invalidSVGString": "SVG inválido.",
"cannotResolveCollabServer": "Non se puido conectar ao servidor de colaboración. Por favor recargue a páxina e probe de novo.", "cannotResolveCollabServer": "Non se puido conectar ao servidor de colaboración. Por favor recargue a páxina e probe de novo.",
"importLibraryError": "Non se puido cargar a biblioteca", "importLibraryError": "Non se puido cargar a biblioteca",
@@ -206,6 +214,10 @@
"line2": "", "line2": "",
"line3": "", "line3": "",
"line4": "" "line4": ""
},
"libraryElementTypeError": {
"embeddable": "",
"image": ""
} }
}, },
"toolBar": { "toolBar": {
@@ -224,8 +236,10 @@
"link": "Engadir/ Actualizar ligazón para a forma seleccionada", "link": "Engadir/ Actualizar ligazón para a forma seleccionada",
"eraser": "Goma de borrar", "eraser": "Goma de borrar",
"frame": "", "frame": "",
"embeddable": "Inserir na web",
"laser": "Punteiro láser",
"hand": "Man (ferramenta de desprazamento)", "hand": "Man (ferramenta de desprazamento)",
"extraTools": "" "extraTools": "Máis ferramentas"
}, },
"headings": { "headings": {
"canvasActions": "Accións do lenzo", "canvasActions": "Accións do lenzo",
@@ -237,6 +251,7 @@
"linearElement": "Faga clic para iniciar varios puntos, arrastre para unha sola liña", "linearElement": "Faga clic para iniciar varios puntos, arrastre para unha sola liña",
"freeDraw": "Fai clic e arrastra, solta cando acabes", "freeDraw": "Fai clic e arrastra, solta cando acabes",
"text": "Consello: tamén podes engadir texto facendo dobre-clic en calquera lugar coa ferramenta de selección", "text": "Consello: tamén podes engadir texto facendo dobre-clic en calquera lugar coa ferramenta de selección",
"embeddable": "Faga clic e arrastre para crear un sitio web embebido",
"text_selected": "Dobre-clic ou prema ENTER para editar o texto", "text_selected": "Dobre-clic ou prema ENTER para editar o texto",
"text_editing": "Prema Escape ou CtrlOrCmd+ENTER para finalizar a edición", "text_editing": "Prema Escape ou CtrlOrCmd+ENTER para finalizar a edición",
"linearElementMulti": "Faga clic no último punto ou prema Escape ou Enter para rematar", "linearElementMulti": "Faga clic no último punto ou prema Escape ou Enter para rematar",
@@ -252,7 +267,8 @@
"bindTextToElement": "Prema a tecla enter para engadir texto", "bindTextToElement": "Prema a tecla enter para engadir texto",
"deepBoxSelect": "Manteña pulsado CtrlOrCmd para seleccionar en profundidade e evitar o arrastre", "deepBoxSelect": "Manteña pulsado CtrlOrCmd para seleccionar en profundidade e evitar o arrastre",
"eraserRevert": "Manteña pulsado Alt para reverter os elementos marcados para a súa eliminación", "eraserRevert": "Manteña pulsado Alt para reverter os elementos marcados para a súa eliminación",
"firefox_clipboard_write": "Esta función pódese activar establecendo a opción \"dom.events.asyncClipboard.clipboardItem\" a \"true\". Para cambiar as opcións do navegador en Firefox, visita a páxina \"about:config\"." "firefox_clipboard_write": "Esta función pódese activar establecendo a opción \"dom.events.asyncClipboard.clipboardItem\" a \"true\". Para cambiar as opcións do navegador en Firefox, visita a páxina \"about:config\".",
"disableSnapping": ""
}, },
"canvasError": { "canvasError": {
"cannotShowPreview": "Non se pode mostrar a vista previa", "cannotShowPreview": "Non se pode mostrar a vista previa",
@@ -360,11 +376,11 @@
"removeItemsFromLib": "Eliminar os elementos seleccionados da biblioteca" "removeItemsFromLib": "Eliminar os elementos seleccionados da biblioteca"
}, },
"imageExportDialog": { "imageExportDialog": {
"header": "", "header": "Exportar imaxe",
"label": { "label": {
"withBackground": "", "withBackground": "Fondo",
"onlySelected": "", "onlySelected": "",
"darkMode": "", "darkMode": "Modo escuro",
"embedScene": "", "embedScene": "",
"scale": "", "scale": "",
"padding": "" "padding": ""
@@ -373,14 +389,14 @@
"embedScene": "" "embedScene": ""
}, },
"title": { "title": {
"exportToPng": "", "exportToPng": "Exportar a PNG",
"exportToSvg": "", "exportToSvg": "Exportar a SVG",
"copyPngToClipboard": "" "copyPngToClipboard": "Copiar PNG ao portapapeis"
}, },
"button": { "button": {
"exportToPng": "", "exportToPng": "PNG",
"exportToSvg": "", "exportToSvg": "SVG",
"copyPngToClipboard": "" "copyPngToClipboard": "Copiar ao portapapeis"
} }
}, },
"encrypted": { "encrypted": {
@@ -411,24 +427,26 @@
"fileSavedToFilename": "Gardado en {filename}", "fileSavedToFilename": "Gardado en {filename}",
"canvas": "lenzo", "canvas": "lenzo",
"selection": "selección", "selection": "selección",
"pasteAsSingleElement": "Usa {{shortcut}} para pegar como un único elemento\nou pega nun editor de texto existente" "pasteAsSingleElement": "Usa {{shortcut}} para pegar como un único elemento\nou pega nun editor de texto existente",
"unableToEmbed": "",
"unrecognizedLinkFormat": ""
}, },
"colors": { "colors": {
"transparent": "Transparente", "transparent": "Transparente",
"black": "", "black": "Negro",
"white": "", "white": "Branco",
"red": "", "red": "Vermello",
"pink": "", "pink": "Rosa",
"grape": "", "grape": "Uva",
"violet": "", "violet": "Violeta",
"gray": "", "gray": "Gris",
"blue": "", "blue": "Azul",
"cyan": "", "cyan": "",
"teal": "", "teal": "",
"green": "", "green": "Verde",
"yellow": "", "yellow": "Marelo",
"orange": "", "orange": "Laranxa",
"bronze": "" "bronze": "Bronce"
}, },
"welcomeScreen": { "welcomeScreen": {
"app": { "app": {
@@ -445,9 +463,40 @@
}, },
"colorPicker": { "colorPicker": {
"mostUsedCustomColors": "", "mostUsedCustomColors": "",
"colors": "", "colors": "Cores",
"shades": "", "shades": "",
"hexCode": "", "hexCode": "",
"noShades": "" "noShades": ""
},
"overwriteConfirm": {
"action": {
"exportToImage": {
"title": "Exportar como imaxe",
"button": "Exportar como imaxe",
"description": ""
},
"saveToDisk": {
"title": "Gardar no disco",
"button": "Gardar no disco",
"description": ""
},
"excalidrawPlus": {
"title": "Excalidraw+",
"button": "Exportar a Excalidraw+",
"description": ""
}
},
"modal": {
"loadFromFile": {
"title": "Cargar dende arquivo",
"button": "Cargar dende arquivo",
"description": ""
},
"shareableLink": {
"title": "Cargar dende un enlace",
"button": "Substituír o meu contido",
"description": ""
}
}
} }
} }
+56 -7
View File
@@ -50,7 +50,7 @@
"veryLarge": "גדול מאוד", "veryLarge": "גדול מאוד",
"solid": "מוצק", "solid": "מוצק",
"hachure": "קווים מקבילים קצרים להצגת כיוון וחדות שיפוע במפה", "hachure": "קווים מקבילים קצרים להצגת כיוון וחדות שיפוע במפה",
"zigzag": "", "zigzag": "זיגזג",
"crossHatch": "קווים מוצלבים שתי וערב", "crossHatch": "קווים מוצלבים שתי וערב",
"thin": "דק", "thin": "דק",
"bold": "מודגש", "bold": "מודגש",
@@ -109,8 +109,12 @@
"createContainerFromText": "ארוז טקסט במיכל", "createContainerFromText": "ארוז טקסט במיכל",
"link": { "link": {
"edit": "עריכת קישור", "edit": "עריכת קישור",
"editEmbed": "ערוך קישור ושבץ",
"create": "יצירת קישור", "create": "יצירת קישור",
"label": "קישור" "createEmbed": "צור קישור ושבץ",
"label": "קישור",
"labelEmbed": "קשר ושבץ",
"empty": "לא נקבע קישור"
}, },
"lineEditor": { "lineEditor": {
"edit": "ערוך קו", "edit": "ערוך קו",
@@ -124,8 +128,8 @@
}, },
"statusPublished": "פורסם", "statusPublished": "פורסם",
"sidebarLock": "שמור את סרגל הצד פתוח", "sidebarLock": "שמור את סרגל הצד פתוח",
"selectAllElementsInFrame": "", "selectAllElementsInFrame": "בחר את כל האלמנטים במסגרת",
"removeAllElementsFromFrame": "", "removeAllElementsFromFrame": "הסר את כל האלמנטים שבמסגרת",
"eyeDropper": "" "eyeDropper": ""
}, },
"library": { "library": {
@@ -160,13 +164,16 @@
"darkMode": "מצב כהה", "darkMode": "מצב כהה",
"lightMode": "מצב בהיר", "lightMode": "מצב בהיר",
"zenMode": "מצב זן", "zenMode": "מצב זן",
"objectsSnapMode": "",
"exitZenMode": "צא ממצב זן", "exitZenMode": "צא ממצב זן",
"cancel": "ביטול", "cancel": "ביטול",
"clear": "ניקוי", "clear": "ניקוי",
"remove": "הסר", "remove": "הסר",
"embed": "",
"publishLibrary": "פרסום", "publishLibrary": "פרסום",
"submit": "שליחה", "submit": "שליחה",
"confirm": "אשר" "confirm": "אשר",
"embeddableInteractionButton": ""
}, },
"alerts": { "alerts": {
"clearReset": "פעולה זו תנקה את כל הקנבס. אתה בטוח?", "clearReset": "פעולה זו תנקה את כל הקנבס. אתה בטוח?",
@@ -196,6 +203,7 @@
"imageInsertError": "לא ניתן היה להוסיף את התמונה. אנא נסה שוב מאוחר יותר...", "imageInsertError": "לא ניתן היה להוסיף את התמונה. אנא נסה שוב מאוחר יותר...",
"fileTooBig": "הקובץ גדול מדי. הגודל המירבי המותר הינו {{maxSize}}.", "fileTooBig": "הקובץ גדול מדי. הגודל המירבי המותר הינו {{maxSize}}.",
"svgImageInsertError": "לא ניתן היה להוסיף את תמונת ה-SVG. הסימונים בתוך קובץ ה-SVG עשויים להיות שגויים.", "svgImageInsertError": "לא ניתן היה להוסיף את תמונת ה-SVG. הסימונים בתוך קובץ ה-SVG עשויים להיות שגויים.",
"failedToFetchImage": "",
"invalidSVGString": "SVG שגוי.", "invalidSVGString": "SVG שגוי.",
"cannotResolveCollabServer": "לא הצלחתי להתחבר לשרת השיתוף. אנא רענן את הדף ונסה שוב.", "cannotResolveCollabServer": "לא הצלחתי להתחבר לשרת השיתוף. אנא רענן את הדף ונסה שוב.",
"importLibraryError": "לא ניתן היה לטעון את הספריה", "importLibraryError": "לא ניתן היה לטעון את הספריה",
@@ -206,6 +214,10 @@
"line2": "", "line2": "",
"line3": "", "line3": "",
"line4": "" "line4": ""
},
"libraryElementTypeError": {
"embeddable": "",
"image": ""
} }
}, },
"toolBar": { "toolBar": {
@@ -224,6 +236,8 @@
"link": "הוספה/עדכון קישור של הצורה שנבחרה", "link": "הוספה/עדכון קישור של הצורה שנבחרה",
"eraser": "מחק", "eraser": "מחק",
"frame": "", "frame": "",
"embeddable": "",
"laser": "",
"hand": "יד (כלי הזזה)", "hand": "יד (כלי הזזה)",
"extraTools": "" "extraTools": ""
}, },
@@ -237,6 +251,7 @@
"linearElement": "לחץ להתחלת מספר נקודות, גרור לקו יחיד", "linearElement": "לחץ להתחלת מספר נקודות, גרור לקו יחיד",
"freeDraw": "לחץ וגרור, שחרר כשסיימת", "freeDraw": "לחץ וגרור, שחרר כשסיימת",
"text": "טיפ: אפשר להוסיף טקסט על ידי לחיצה כפולה בכל מקום עם כלי הבחירה", "text": "טיפ: אפשר להוסיף טקסט על ידי לחיצה כפולה בכל מקום עם כלי הבחירה",
"embeddable": "",
"text_selected": "לחץ לחיצה כפולה או הקש על אנטר לעריכת הטקסט", "text_selected": "לחץ לחיצה כפולה או הקש על אנטר לעריכת הטקסט",
"text_editing": "כדי לסיים את העריכה לחץ על מקש Escape או על Ctrl (Cmd במחשבי אפל) ומקש Enter", "text_editing": "כדי לסיים את העריכה לחץ על מקש Escape או על Ctrl (Cmd במחשבי אפל) ומקש Enter",
"linearElementMulti": "הקלק על הנקודה האחרונה או הקש Escape או Enter לסיום", "linearElementMulti": "הקלק על הנקודה האחרונה או הקש Escape או Enter לסיום",
@@ -252,7 +267,8 @@
"bindTextToElement": "הקש Enter כדי להוספת טקסט", "bindTextToElement": "הקש Enter כדי להוספת טקסט",
"deepBoxSelect": "החזק Ctrl / Cmd לבחירה עמוקה ולמניעת גרירה", "deepBoxSelect": "החזק Ctrl / Cmd לבחירה עמוקה ולמניעת גרירה",
"eraserRevert": "החזק Alt להחזרת רכיבים מסומנים למחיקה", "eraserRevert": "החזק Alt להחזרת רכיבים מסומנים למחיקה",
"firefox_clipboard_write": "יכולות זה ניתנת להפעלה על ידי שינוי הדגל של \"dom.events.asyncClipboard.clipboardItem\" למצב \"true\". כדי לשנות את הדגל בדפדפן Firefox, בקר בעמוד ״about:config״." "firefox_clipboard_write": "יכולות זה ניתנת להפעלה על ידי שינוי הדגל של \"dom.events.asyncClipboard.clipboardItem\" למצב \"true\". כדי לשנות את הדגל בדפדפן Firefox, בקר בעמוד ״about:config״.",
"disableSnapping": ""
}, },
"canvasError": { "canvasError": {
"cannotShowPreview": "לא ניתן להראות תצוגה מקדימה", "cannotShowPreview": "לא ניתן להראות תצוגה מקדימה",
@@ -411,7 +427,9 @@
"fileSavedToFilename": "נשמר לקובץ {filename}", "fileSavedToFilename": "נשמר לקובץ {filename}",
"canvas": "קנבאס", "canvas": "קנבאס",
"selection": "בחירה", "selection": "בחירה",
"pasteAsSingleElement": "השתמש ב- {{shortcut}} כדי להדביק כפריט יחיד,\nאו הדבק לתוך עורך טקסט קיים" "pasteAsSingleElement": "השתמש ב- {{shortcut}} כדי להדביק כפריט יחיד,\nאו הדבק לתוך עורך טקסט קיים",
"unableToEmbed": "",
"unrecognizedLinkFormat": ""
}, },
"colors": { "colors": {
"transparent": "שקוף", "transparent": "שקוף",
@@ -449,5 +467,36 @@
"shades": "", "shades": "",
"hexCode": "", "hexCode": "",
"noShades": "" "noShades": ""
},
"overwriteConfirm": {
"action": {
"exportToImage": {
"title": "",
"button": "",
"description": ""
},
"saveToDisk": {
"title": "",
"button": "",
"description": ""
},
"excalidrawPlus": {
"title": "",
"button": "",
"description": ""
}
},
"modal": {
"loadFromFile": {
"title": "",
"button": "",
"description": ""
},
"shareableLink": {
"title": "",
"button": "",
"description": ""
}
}
} }
} }
+53 -4
View File
@@ -109,8 +109,12 @@
"createContainerFromText": "मूलपाठ कंटेनर में मोड के दिखाए", "createContainerFromText": "मूलपाठ कंटेनर में मोड के दिखाए",
"link": { "link": {
"edit": "", "edit": "",
"editEmbed": "",
"create": "", "create": "",
"label": "" "createEmbed": "",
"label": "",
"labelEmbed": "",
"empty": ""
}, },
"lineEditor": { "lineEditor": {
"edit": "रेखा संपादित करे", "edit": "रेखा संपादित करे",
@@ -160,13 +164,16 @@
"darkMode": "डार्क मोड", "darkMode": "डार्क मोड",
"lightMode": "लाइट मोड", "lightMode": "लाइट मोड",
"zenMode": "ज़ेन मोड", "zenMode": "ज़ेन मोड",
"objectsSnapMode": "वस्तुओं से पकड़े",
"exitZenMode": "जेन मोड से बाहर निकलें", "exitZenMode": "जेन मोड से बाहर निकलें",
"cancel": "", "cancel": "",
"clear": "साफ़ करे", "clear": "साफ़ करे",
"remove": "हटाएं", "remove": "हटाएं",
"embed": "",
"publishLibrary": "प्रकाशित करें", "publishLibrary": "प्रकाशित करें",
"submit": "प्रस्तुत करे", "submit": "प्रस्तुत करे",
"confirm": "पुष्टि करें" "confirm": "पुष्टि करें",
"embeddableInteractionButton": ""
}, },
"alerts": { "alerts": {
"clearReset": "इससे पूरा कैनवास साफ हो जाएगा। क्या आपको यकीन है?", "clearReset": "इससे पूरा कैनवास साफ हो जाएगा। क्या आपको यकीन है?",
@@ -196,6 +203,7 @@
"imageInsertError": "छवि सम्मिलित नहीं की जा सकी. पुनः प्रयत्न करे...", "imageInsertError": "छवि सम्मिलित नहीं की जा सकी. पुनः प्रयत्न करे...",
"fileTooBig": "फ़ाइल ज़रूरत से ज़्यादा बड़ी हैं. अधिकतम अनुमित परिमाण {{maxSize}} हैं", "fileTooBig": "फ़ाइल ज़रूरत से ज़्यादा बड़ी हैं. अधिकतम अनुमित परिमाण {{maxSize}} हैं",
"svgImageInsertError": "एसवीजी छवि सम्मिलित नहीं कर सके, एसवीजी रचना अनुचित हैं", "svgImageInsertError": "एसवीजी छवि सम्मिलित नहीं कर सके, एसवीजी रचना अनुचित हैं",
"failedToFetchImage": "",
"invalidSVGString": "अनुचित SVG", "invalidSVGString": "अनुचित SVG",
"cannotResolveCollabServer": "कॉलेब सर्वर से कनेक्शन नहीं हो पा रहा. कृपया पृष्ठ को पुनः लाने का प्रयास करे.", "cannotResolveCollabServer": "कॉलेब सर्वर से कनेक्शन नहीं हो पा रहा. कृपया पृष्ठ को पुनः लाने का प्रयास करे.",
"importLibraryError": "संग्रह प्रतिष्ठापित नहीं किया जा सका", "importLibraryError": "संग्रह प्रतिष्ठापित नहीं किया जा सका",
@@ -206,6 +214,10 @@
"line2": "यह आपके चित्रों के <bold>पाठ तत्वों</bold>को खंडित कर सकता हैं", "line2": "यह आपके चित्रों के <bold>पाठ तत्वों</bold>को खंडित कर सकता हैं",
"line3": "हमें आपसे ठोस आग्रह है की आप सेट्टिंग में इस विकल्प का चयन ना करे.<link> इस अनुक्रम </link> का पालन करके इसका पता लगा सकते हैं", "line3": "हमें आपसे ठोस आग्रह है की आप सेट्टिंग में इस विकल्प का चयन ना करे.<link> इस अनुक्रम </link> का पालन करके इसका पता लगा सकते हैं",
"line4": "यदि इस सेटिंग्स को अक्षम करने पर भी पृष्ठ ठीक नहीं दिखता हो तो, हमारे GitHub पर एक <issueLink>मुद्दा प्रस्तुत</issueLink> करे, या हमें <discordLink>डिस्कोर्ड</discordLink> पर लिखित सम्पर्क करें" "line4": "यदि इस सेटिंग्स को अक्षम करने पर भी पृष्ठ ठीक नहीं दिखता हो तो, हमारे GitHub पर एक <issueLink>मुद्दा प्रस्तुत</issueLink> करे, या हमें <discordLink>डिस्कोर्ड</discordLink> पर लिखित सम्पर्क करें"
},
"libraryElementTypeError": {
"embeddable": "",
"image": ""
} }
}, },
"toolBar": { "toolBar": {
@@ -224,6 +236,8 @@
"link": "", "link": "",
"eraser": "रबड़", "eraser": "रबड़",
"frame": "", "frame": "",
"embeddable": "",
"laser": "लेसर टॉर्च",
"hand": "हाथ ( खिसकाने का औज़ार)", "hand": "हाथ ( खिसकाने का औज़ार)",
"extraTools": "" "extraTools": ""
}, },
@@ -237,6 +251,7 @@
"linearElement": "कई बिंदुओं को शुरू करने के लिए क्लिक करें, सिंगल लाइन के लिए खींचें", "linearElement": "कई बिंदुओं को शुरू करने के लिए क्लिक करें, सिंगल लाइन के लिए खींचें",
"freeDraw": "क्लिक करें और खींचें। समाप्त करने के लिए, छोड़ो", "freeDraw": "क्लिक करें और खींचें। समाप्त करने के लिए, छोड़ो",
"text": "आप चयन टूल से कहीं भी डबल-क्लिक करके टेक्स्ट जोड़ सकते हैं", "text": "आप चयन टूल से कहीं भी डबल-क्लिक करके टेक्स्ट जोड़ सकते हैं",
"embeddable": "",
"text_selected": "", "text_selected": "",
"text_editing": "", "text_editing": "",
"linearElementMulti": "अंतिम बिंदु पर क्लिक करें या समाप्त होने के लिए एस्केप या एंटर दबाएं", "linearElementMulti": "अंतिम बिंदु पर क्लिक करें या समाप्त होने के लिए एस्केप या एंटर दबाएं",
@@ -252,7 +267,8 @@
"bindTextToElement": "", "bindTextToElement": "",
"deepBoxSelect": "", "deepBoxSelect": "",
"eraserRevert": "मिटाने के लिए चुने हुए चीजों को ना चुनने के लिए Alt साथ में दबाए", "eraserRevert": "मिटाने के लिए चुने हुए चीजों को ना चुनने के लिए Alt साथ में दबाए",
"firefox_clipboard_write": "\"dom.events.asyncClipboard.clipboardItem\" फ़्लैग को \"true\" पर सेट करके इस सुविधा को संभवतः सक्षम किया जा सकता है। Firefox में ब्राउज़र फ़्लैग बदलने के लिए, \"about:config\" पृष्ठ पर जाएँ।" "firefox_clipboard_write": "\"dom.events.asyncClipboard.clipboardItem\" फ़्लैग को \"true\" पर सेट करके इस सुविधा को संभवतः सक्षम किया जा सकता है। Firefox में ब्राउज़र फ़्लैग बदलने के लिए, \"about:config\" पृष्ठ पर जाएँ।",
"disableSnapping": "स्नैपिंग को निष्क्रिय करने के लिए CtrlOrCmd दबाए रखें"
}, },
"canvasError": { "canvasError": {
"cannotShowPreview": "पूर्वावलोकन नहीं दिखा सकते हैं", "cannotShowPreview": "पूर्वावलोकन नहीं दिखा सकते हैं",
@@ -411,7 +427,9 @@
"fileSavedToFilename": "", "fileSavedToFilename": "",
"canvas": "", "canvas": "",
"selection": "", "selection": "",
"pasteAsSingleElement": "एक अवयव के रूप में चिपकाने के लिए {{shortcut}} का उपयोग करें,\nया किसी मौजूदा पाठ संपादक में चिपकायें" "pasteAsSingleElement": "एक अवयव के रूप में चिपकाने के लिए {{shortcut}} का उपयोग करें,\nया किसी मौजूदा पाठ संपादक में चिपकायें",
"unableToEmbed": "",
"unrecognizedLinkFormat": ""
}, },
"colors": { "colors": {
"transparent": "", "transparent": "",
@@ -449,5 +467,36 @@
"shades": "छाया", "shades": "छाया",
"hexCode": "हेक्स कोड", "hexCode": "हेक्स कोड",
"noShades": "इस रंग की कोई छाया उपलब्ध नहीं हैं" "noShades": "इस रंग की कोई छाया उपलब्ध नहीं हैं"
},
"overwriteConfirm": {
"action": {
"exportToImage": {
"title": "छवि स्वरूप में निर्यात करे",
"button": "छवि स्वरूप निर्यात करे",
"description": "दृष्य डेटा छवि स्वरूप में निर्यात करे, उस स्वरूप से आप उसे पुनः आयात कर सकते हो"
},
"saveToDisk": {
"title": "डिस्क में सम्हाले",
"button": "डिस्क में सम्हाले",
"description": "दृष्य डेटा बाहरी फ़ाइल में निर्यात करे, जहाँसे आप उसे पुनः आयात कर सकते हो"
},
"excalidrawPlus": {
"title": "एक्षकालीड्रॉ+",
"button": "एक्षकालीड्रॉ+ में निर्यात करे",
"description": "दृष्य को आपके एक्षकालीड्रॉ+ के कर्यस्थल में सम्हाले"
}
},
"modal": {
"loadFromFile": {
"title": "फ़ाइल से लोड करें:",
"button": "फ़ाइल से लोड करें:",
"description": "फ़ाइल से लोड करने पर <bold>यह आपके कार्य की जगह लेलेगा </bold><br></br>आपकी ड्रॉइंग निम्न दर्शित विकल्पो में से एक चुनके और उपयोग करके सम्हाल सकते हैं"
},
"shareableLink": {
"title": "लिंक से लोड करें:",
"button": "इस जगह प्रतिस्थापित करे",
"description": "बाहर का चित्र लोड करने पर <bold>यह आपके कार्य की जगह लेलेगा </bold><br></br>आप आपकी ड्रॉइंग पहले निम्न दर्शित विकल्पो में से एक चुनके और उपयोग करके सम्हाल सकते हों."
}
}
} }
} }
+54 -5
View File
@@ -109,8 +109,12 @@
"createContainerFromText": "", "createContainerFromText": "",
"link": { "link": {
"edit": "Hivatkozás szerkesztése", "edit": "Hivatkozás szerkesztése",
"editEmbed": "",
"create": "Hivatkozás létrehozása", "create": "Hivatkozás létrehozása",
"label": "Hivatkozás" "createEmbed": "",
"label": "Hivatkozás",
"labelEmbed": "",
"empty": ""
}, },
"lineEditor": { "lineEditor": {
"edit": "", "edit": "",
@@ -160,13 +164,16 @@
"darkMode": "Sötét mód", "darkMode": "Sötét mód",
"lightMode": "Világos mód", "lightMode": "Világos mód",
"zenMode": "Letisztult mód", "zenMode": "Letisztult mód",
"objectsSnapMode": "",
"exitZenMode": "Kilépés a letisztult módból", "exitZenMode": "Kilépés a letisztult módból",
"cancel": "Mégsem", "cancel": "Mégsem",
"clear": "Kiűrítés", "clear": "Kiűrítés",
"remove": "Eltávolítás", "remove": "Eltávolítás",
"embed": "",
"publishLibrary": "Közzététel", "publishLibrary": "Közzététel",
"submit": "Elküldés", "submit": "Elküldés",
"confirm": "Megerősítés" "confirm": "Megerősítés",
"embeddableInteractionButton": ""
}, },
"alerts": { "alerts": {
"clearReset": "Ez a művelet törli a vászont. Biztos benne?", "clearReset": "Ez a művelet törli a vászont. Biztos benne?",
@@ -196,6 +203,7 @@
"imageInsertError": "Nem sikerült beszúrni a képet. Próbáld újra később...", "imageInsertError": "Nem sikerült beszúrni a képet. Próbáld újra később...",
"fileTooBig": "A fájl túl nagy. A megengedett maximális méret {{maxSize}}.", "fileTooBig": "A fájl túl nagy. A megengedett maximális méret {{maxSize}}.",
"svgImageInsertError": "Nem sikerült beszúrni az SVG-képet. Az SVG szintaktika érvénytelennek tűnik.", "svgImageInsertError": "Nem sikerült beszúrni az SVG-képet. Az SVG szintaktika érvénytelennek tűnik.",
"failedToFetchImage": "",
"invalidSVGString": "Érvénytelen SVG.", "invalidSVGString": "Érvénytelen SVG.",
"cannotResolveCollabServer": "", "cannotResolveCollabServer": "",
"importLibraryError": "", "importLibraryError": "",
@@ -206,6 +214,10 @@
"line2": "", "line2": "",
"line3": "", "line3": "",
"line4": "" "line4": ""
},
"libraryElementTypeError": {
"embeddable": "",
"image": ""
} }
}, },
"toolBar": { "toolBar": {
@@ -224,6 +236,8 @@
"link": "Hivatkozás hozzáadása/frissítése a kiválasztott alakzathoz", "link": "Hivatkozás hozzáadása/frissítése a kiválasztott alakzathoz",
"eraser": "", "eraser": "",
"frame": "", "frame": "",
"embeddable": "",
"laser": "",
"hand": "", "hand": "",
"extraTools": "" "extraTools": ""
}, },
@@ -237,6 +251,7 @@
"linearElement": "Kattintással görbe, az eger húzásával pedig egyenes nyilat rajzolhatsz", "linearElement": "Kattintással görbe, az eger húzásával pedig egyenes nyilat rajzolhatsz",
"freeDraw": "Kattints és húzd, majd engedd el, amikor végeztél", "freeDraw": "Kattints és húzd, majd engedd el, amikor végeztél",
"text": "Tipp: A kijelölés eszközzel a dupla kattintás új szöveget hoz létre", "text": "Tipp: A kijelölés eszközzel a dupla kattintás új szöveget hoz létre",
"embeddable": "",
"text_selected": "Kattints duplán, vagy nyomj entert a szöveg szerkesztéséhez", "text_selected": "Kattints duplán, vagy nyomj entert a szöveg szerkesztéséhez",
"text_editing": "Nyomjd meg az Escape vagy a Ctrl/Cmd+ENTER billentyűkombinációt a szerkesztés befejezéséhez", "text_editing": "Nyomjd meg az Escape vagy a Ctrl/Cmd+ENTER billentyűkombinációt a szerkesztés befejezéséhez",
"linearElementMulti": "Kattints a következő ív pozíciójára, vagy fejezd be a nyilat az Escape vagy Enter megnyomásával", "linearElementMulti": "Kattints a következő ív pozíciójára, vagy fejezd be a nyilat az Escape vagy Enter megnyomásával",
@@ -252,7 +267,8 @@
"bindTextToElement": "Nyomd meg az Entert szöveg hozzáadáshoz", "bindTextToElement": "Nyomd meg az Entert szöveg hozzáadáshoz",
"deepBoxSelect": "Tartsd lenyomva a Ctrl/Cmd billentyűt a mély kijelöléshez és a húzás megakadályozásához", "deepBoxSelect": "Tartsd lenyomva a Ctrl/Cmd billentyűt a mély kijelöléshez és a húzás megakadályozásához",
"eraserRevert": "", "eraserRevert": "",
"firefox_clipboard_write": "" "firefox_clipboard_write": "",
"disableSnapping": ""
}, },
"canvasError": { "canvasError": {
"cannotShowPreview": "Előnézet nem jeleníthető meg", "cannotShowPreview": "Előnézet nem jeleníthető meg",
@@ -360,7 +376,7 @@
"removeItemsFromLib": "A kiválasztott elemek eltávolítása a könyvtárból" "removeItemsFromLib": "A kiválasztott elemek eltávolítása a könyvtárból"
}, },
"imageExportDialog": { "imageExportDialog": {
"header": "", "header": "Kép exportálása",
"label": { "label": {
"withBackground": "", "withBackground": "",
"onlySelected": "", "onlySelected": "",
@@ -411,7 +427,9 @@
"fileSavedToFilename": "Mentve mint {filename}", "fileSavedToFilename": "Mentve mint {filename}",
"canvas": "rajzvászon", "canvas": "rajzvászon",
"selection": "kijelölés", "selection": "kijelölés",
"pasteAsSingleElement": "" "pasteAsSingleElement": "",
"unableToEmbed": "",
"unrecognizedLinkFormat": ""
}, },
"colors": { "colors": {
"transparent": "Átlátszó", "transparent": "Átlátszó",
@@ -449,5 +467,36 @@
"shades": "", "shades": "",
"hexCode": "", "hexCode": "",
"noShades": "" "noShades": ""
},
"overwriteConfirm": {
"action": {
"exportToImage": {
"title": "",
"button": "",
"description": ""
},
"saveToDisk": {
"title": "",
"button": "",
"description": ""
},
"excalidrawPlus": {
"title": "",
"button": "",
"description": ""
}
},
"modal": {
"loadFromFile": {
"title": "",
"button": "",
"description": ""
},
"shareableLink": {
"title": "",
"button": "",
"description": ""
}
}
} }
} }
+72 -23
View File
@@ -109,8 +109,12 @@
"createContainerFromText": "Bungkus teks dalam kontainer", "createContainerFromText": "Bungkus teks dalam kontainer",
"link": { "link": {
"edit": "Edit tautan", "edit": "Edit tautan",
"editEmbed": "",
"create": "Buat tautan", "create": "Buat tautan",
"label": "Tautan" "createEmbed": "",
"label": "Tautan",
"labelEmbed": "",
"empty": ""
}, },
"lineEditor": { "lineEditor": {
"edit": "Edit tautan", "edit": "Edit tautan",
@@ -124,9 +128,9 @@
}, },
"statusPublished": "Telah terbit", "statusPublished": "Telah terbit",
"sidebarLock": "Biarkan sidebar tetap terbuka", "sidebarLock": "Biarkan sidebar tetap terbuka",
"selectAllElementsInFrame": "", "selectAllElementsInFrame": "Pilih semua elemen di bingkai",
"removeAllElementsFromFrame": "", "removeAllElementsFromFrame": "Hapus semua elemen dari bingkai",
"eyeDropper": "" "eyeDropper": "Ambil warna dari kanvas"
}, },
"library": { "library": {
"noItems": "Belum ada item yang ditambahkan...", "noItems": "Belum ada item yang ditambahkan...",
@@ -160,13 +164,16 @@
"darkMode": "Mode gelap", "darkMode": "Mode gelap",
"lightMode": "Mode terang", "lightMode": "Mode terang",
"zenMode": "Mode zen", "zenMode": "Mode zen",
"objectsSnapMode": "",
"exitZenMode": "Keluar dari mode zen", "exitZenMode": "Keluar dari mode zen",
"cancel": "Batal", "cancel": "Batal",
"clear": "Hapus", "clear": "Hapus",
"remove": "Hapus", "remove": "Hapus",
"embed": "",
"publishLibrary": "Terbitkan", "publishLibrary": "Terbitkan",
"submit": "Kirimkan", "submit": "Kirimkan",
"confirm": "Konfirmasi" "confirm": "Konfirmasi",
"embeddableInteractionButton": ""
}, },
"alerts": { "alerts": {
"clearReset": "Ini akan menghapus semua yang ada dikanvas. Apakah kamu yakin ?", "clearReset": "Ini akan menghapus semua yang ada dikanvas. Apakah kamu yakin ?",
@@ -196,6 +203,7 @@
"imageInsertError": "Tidak dapat menyisipkan gambar. Coba lagi nanti...", "imageInsertError": "Tidak dapat menyisipkan gambar. Coba lagi nanti...",
"fileTooBig": "File terlalu besar. Ukuran maksimum yang dibolehkan {{maxSize}}.", "fileTooBig": "File terlalu besar. Ukuran maksimum yang dibolehkan {{maxSize}}.",
"svgImageInsertError": "Tidak dapat menyisipkan gambar SVG. Markup SVG sepertinya tidak valid.", "svgImageInsertError": "Tidak dapat menyisipkan gambar SVG. Markup SVG sepertinya tidak valid.",
"failedToFetchImage": "",
"invalidSVGString": "SVG tidak valid.", "invalidSVGString": "SVG tidak valid.",
"cannotResolveCollabServer": "Tidak dapat terhubung ke server kolab. Muat ulang laman dan coba lagi.", "cannotResolveCollabServer": "Tidak dapat terhubung ke server kolab. Muat ulang laman dan coba lagi.",
"importLibraryError": "Tidak dapat memuat pustaka", "importLibraryError": "Tidak dapat memuat pustaka",
@@ -206,6 +214,10 @@
"line2": "Ini dapat membuat <bold>Elemen Teks</bold> dalam gambar mu.", "line2": "Ini dapat membuat <bold>Elemen Teks</bold> dalam gambar mu.",
"line3": "Kami sangat menyarankan mematikan pengaturan ini. Anda dapat mengikuti <link>langkah-langkah ini</link> untuk melakukannya.", "line3": "Kami sangat menyarankan mematikan pengaturan ini. Anda dapat mengikuti <link>langkah-langkah ini</link> untuk melakukannya.",
"line4": "Jika mematikan pengaturan ini tidak membenarkan tampilan elemen teks, mohon buka\n<issueLink>isu</issueLink> di GitHub kami, atau chat kami di <discordLink>Discord</discordLink>" "line4": "Jika mematikan pengaturan ini tidak membenarkan tampilan elemen teks, mohon buka\n<issueLink>isu</issueLink> di GitHub kami, atau chat kami di <discordLink>Discord</discordLink>"
},
"libraryElementTypeError": {
"embeddable": "",
"image": ""
} }
}, },
"toolBar": { "toolBar": {
@@ -223,9 +235,11 @@
"penMode": "Mode pena - mencegah sentuhan", "penMode": "Mode pena - mencegah sentuhan",
"link": "Tambah/Perbarui tautan untuk bentuk yang dipilih", "link": "Tambah/Perbarui tautan untuk bentuk yang dipilih",
"eraser": "Penghapus", "eraser": "Penghapus",
"frame": "", "frame": "Alat bingkai",
"embeddable": "",
"laser": "",
"hand": "Tangan (alat panning)", "hand": "Tangan (alat panning)",
"extraTools": "" "extraTools": "Alat-alat lain"
}, },
"headings": { "headings": {
"canvasActions": "Opsi Kanvas", "canvasActions": "Opsi Kanvas",
@@ -237,6 +251,7 @@
"linearElement": "Klik untuk memulai banyak poin, seret untuk satu baris", "linearElement": "Klik untuk memulai banyak poin, seret untuk satu baris",
"freeDraw": "Klik dan seret, lepaskan jika Anda selesai", "freeDraw": "Klik dan seret, lepaskan jika Anda selesai",
"text": "Tip: Anda juga dapat menambahkan teks dengan klik ganda di mana saja dengan alat pemilihan", "text": "Tip: Anda juga dapat menambahkan teks dengan klik ganda di mana saja dengan alat pemilihan",
"embeddable": "",
"text_selected": "Klik ganda atau tekan ENTER untuk edit teks", "text_selected": "Klik ganda atau tekan ENTER untuk edit teks",
"text_editing": "Tekan Escape atau CtrlAtauCmd+ENTER untuk selesai mengedit", "text_editing": "Tekan Escape atau CtrlAtauCmd+ENTER untuk selesai mengedit",
"linearElementMulti": "Klik pada titik akhir atau tekan Escape atau Enter untuk menyelesaikan", "linearElementMulti": "Klik pada titik akhir atau tekan Escape atau Enter untuk menyelesaikan",
@@ -252,7 +267,8 @@
"bindTextToElement": "Tekan enter untuk tambahkan teks", "bindTextToElement": "Tekan enter untuk tambahkan teks",
"deepBoxSelect": "Tekan Ctrl atau Cmd untuk memilih yang di dalam, dan mencegah penggeseran", "deepBoxSelect": "Tekan Ctrl atau Cmd untuk memilih yang di dalam, dan mencegah penggeseran",
"eraserRevert": "Tahan Alt untuk mengembalikan elemen yang ditandai untuk dihapus", "eraserRevert": "Tahan Alt untuk mengembalikan elemen yang ditandai untuk dihapus",
"firefox_clipboard_write": "Fitur ini dapat diaktifkan melalui pengaturan flag \"dom.events.asyncClipboard.clipboardItem\" ke \"true\". Untuk mengganti flag di Firefox, pergi ke laman \"about:config\"." "firefox_clipboard_write": "Fitur ini dapat diaktifkan melalui pengaturan flag \"dom.events.asyncClipboard.clipboardItem\" ke \"true\". Untuk mengganti flag di Firefox, pergi ke laman \"about:config\".",
"disableSnapping": ""
}, },
"canvasError": { "canvasError": {
"cannotShowPreview": "Tidak dapat menampilkan pratinjau", "cannotShowPreview": "Tidak dapat menampilkan pratinjau",
@@ -360,27 +376,27 @@
"removeItemsFromLib": "Hapus item yang dipilih dari pustaka" "removeItemsFromLib": "Hapus item yang dipilih dari pustaka"
}, },
"imageExportDialog": { "imageExportDialog": {
"header": "", "header": "Ekspor gambar",
"label": { "label": {
"withBackground": "", "withBackground": "Latar",
"onlySelected": "", "onlySelected": "Hanya yang dipilih",
"darkMode": "", "darkMode": "Mode gelap",
"embedScene": "", "embedScene": "Sematkan pemandangan",
"scale": "", "scale": "Skala",
"padding": "" "padding": "Lapisan"
}, },
"tooltip": { "tooltip": {
"embedScene": "" "embedScene": "Data pemandangan akan disimpan dalam file PNG/SVG yang diekspor sehingga pemandangan itu dapat dipulihkan darinya.\nAkan membesarkan ukuran file yang diekspor."
}, },
"title": { "title": {
"exportToPng": "", "exportToPng": "Ekspor ke PNG",
"exportToSvg": "", "exportToSvg": "Ekspor ke SVG",
"copyPngToClipboard": "" "copyPngToClipboard": "Salin PNG ke papan klip"
}, },
"button": { "button": {
"exportToPng": "", "exportToPng": "PNG",
"exportToSvg": "", "exportToSvg": "SVG",
"copyPngToClipboard": "" "copyPngToClipboard": "Salin ke papan klip"
} }
}, },
"encrypted": { "encrypted": {
@@ -411,7 +427,9 @@
"fileSavedToFilename": "Disimpan ke {filename}", "fileSavedToFilename": "Disimpan ke {filename}",
"canvas": "kanvas", "canvas": "kanvas",
"selection": "pilihan", "selection": "pilihan",
"pasteAsSingleElement": "Gunakan {{shortcut}} untuk menempelkan sebagai satu elemen,\natau tempelkan ke teks editor yang ada" "pasteAsSingleElement": "Gunakan {{shortcut}} untuk menempelkan sebagai satu elemen,\natau tempelkan ke teks editor yang ada",
"unableToEmbed": "",
"unrecognizedLinkFormat": ""
}, },
"colors": { "colors": {
"transparent": "Transparan", "transparent": "Transparan",
@@ -449,5 +467,36 @@
"shades": "Nuansa", "shades": "Nuansa",
"hexCode": "Kode hexa", "hexCode": "Kode hexa",
"noShades": "Tidak ada nuansa untuk warna ini" "noShades": "Tidak ada nuansa untuk warna ini"
},
"overwriteConfirm": {
"action": {
"exportToImage": {
"title": "Ekspor sebagai gambar",
"button": "Ekspor sebagai gambar",
"description": "Ekspor data pemandangan sebagai gambar yang dapat anda impor nanti."
},
"saveToDisk": {
"title": "Simpan ke disk",
"button": "Simpan ke disk",
"description": "Ekspor data pemandangan ke file yang dapat Anda dapat impor nanti."
},
"excalidrawPlus": {
"title": "Excalidraw+",
"button": "Ekspor ke Excalidraw+",
"description": "Simpan pemandangan ke ruang kerja Excalidraw+ Anda."
}
},
"modal": {
"loadFromFile": {
"title": "Muat dari file",
"button": "Muat dari file",
"description": "Memuat dari file yang akan <bold>menggantikan konten Anda sekarang</bold>.<br></br>Anda dapat mencadangkan gambar anda dulu menggunakan opsi-opsi ini."
},
"shareableLink": {
"title": "Muat dari link",
"button": "Ganti konten saya",
"description": "Memuat dari file yang akan <bold>menggantikan konten Anda sekarang</bold>.<br></br>Anda dapat mencadangkan gambar anda dulu menggunakan opsi-opsi ini."
}
}
} }
} }
+58 -9
View File
@@ -109,8 +109,12 @@
"createContainerFromText": "Avvolgi il testo in un container", "createContainerFromText": "Avvolgi il testo in un container",
"link": { "link": {
"edit": "Modifica link", "edit": "Modifica link",
"editEmbed": "Modifica collegamento e incorpora",
"create": "Crea link", "create": "Crea link",
"label": "Link" "createEmbed": "Crea collegamento e incorpora",
"label": "Link",
"labelEmbed": "Collega & incorpora",
"empty": "Nessun collegamento impostato"
}, },
"lineEditor": { "lineEditor": {
"edit": "Modifica linea", "edit": "Modifica linea",
@@ -124,9 +128,9 @@
}, },
"statusPublished": "Pubblicato", "statusPublished": "Pubblicato",
"sidebarLock": "Mantieni aperta la barra laterale", "sidebarLock": "Mantieni aperta la barra laterale",
"selectAllElementsInFrame": "", "selectAllElementsInFrame": "Seleziona tutti gli elementi nel riquadro",
"removeAllElementsFromFrame": "", "removeAllElementsFromFrame": "Rimuovi tutti gli elementi dal riquadro",
"eyeDropper": "" "eyeDropper": "Scegli il colore della tela"
}, },
"library": { "library": {
"noItems": "Nessun elemento ancora aggiunto...", "noItems": "Nessun elemento ancora aggiunto...",
@@ -160,13 +164,16 @@
"darkMode": "Tema scuro", "darkMode": "Tema scuro",
"lightMode": "Tema chiaro", "lightMode": "Tema chiaro",
"zenMode": "Modalità Zen", "zenMode": "Modalità Zen",
"objectsSnapMode": "Aggancia agli oggetti",
"exitZenMode": "Uscire dalla modalità zen", "exitZenMode": "Uscire dalla modalità zen",
"cancel": "Annulla", "cancel": "Annulla",
"clear": "Cancella", "clear": "Cancella",
"remove": "Rimuovi", "remove": "Rimuovi",
"embed": "Attiva/disattiva incorporamento",
"publishLibrary": "Pubblica", "publishLibrary": "Pubblica",
"submit": "Invia", "submit": "Invia",
"confirm": "Conferma" "confirm": "Conferma",
"embeddableInteractionButton": "Clicca per interagire"
}, },
"alerts": { "alerts": {
"clearReset": "Questa azione cancellerà l'intera tela. Sei sicuro?", "clearReset": "Questa azione cancellerà l'intera tela. Sei sicuro?",
@@ -196,6 +203,7 @@
"imageInsertError": "Non è stato possibile inserire l'immagine. Riprova più tardi...", "imageInsertError": "Non è stato possibile inserire l'immagine. Riprova più tardi...",
"fileTooBig": "Il file è troppo grande. La dimensione massima consentita è {{maxSize}}.", "fileTooBig": "Il file è troppo grande. La dimensione massima consentita è {{maxSize}}.",
"svgImageInsertError": "Impossibile inserire l'immagine SVG. Il markup SVG non sembra corretto.", "svgImageInsertError": "Impossibile inserire l'immagine SVG. Il markup SVG non sembra corretto.",
"failedToFetchImage": "",
"invalidSVGString": "SVG non valido.", "invalidSVGString": "SVG non valido.",
"cannotResolveCollabServer": "Impossibile connettersi al server di collab. Ricarica la pagina e riprova.", "cannotResolveCollabServer": "Impossibile connettersi al server di collab. Ricarica la pagina e riprova.",
"importLibraryError": "Impossibile caricare la libreria", "importLibraryError": "Impossibile caricare la libreria",
@@ -206,6 +214,10 @@
"line2": "Ciò potrebbe causare la rottura degli <bold>Elementi di testo</bold> nei tuoi disegni.", "line2": "Ciò potrebbe causare la rottura degli <bold>Elementi di testo</bold> nei tuoi disegni.",
"line3": "Consigliamo vivamente di disabilitare questa impostazione. Puoi seguire <link>questi passaggi</link> su come farlo.", "line3": "Consigliamo vivamente di disabilitare questa impostazione. Puoi seguire <link>questi passaggi</link> su come farlo.",
"line4": "Se la disattivazione di questa impostazione non risolve la visualizzazione degli elementi di testo, apri un <issueLink>problema</issueLink> sul nostro GitHub o scrivici su <discordLink>Discord</discordLink>" "line4": "Se la disattivazione di questa impostazione non risolve la visualizzazione degli elementi di testo, apri un <issueLink>problema</issueLink> sul nostro GitHub o scrivici su <discordLink>Discord</discordLink>"
},
"libraryElementTypeError": {
"embeddable": "Gli elementi incorporabili non possono essere aggiunti alla libreria.",
"image": "Il supporto per l'aggiunta d'immagini alla libreria verrà aggiunto a breve!"
} }
}, },
"toolBar": { "toolBar": {
@@ -223,7 +235,9 @@
"penMode": "Modalità penna - previene il tocco", "penMode": "Modalità penna - previene il tocco",
"link": "Aggiungi/ aggiorna il link per una forma selezionata", "link": "Aggiungi/ aggiorna il link per una forma selezionata",
"eraser": "Gomma", "eraser": "Gomma",
"frame": "", "frame": "Strumento riquadro",
"embeddable": "Incorporamento Web",
"laser": "Puntatore laser",
"hand": "Mano (strumento di panoramica)", "hand": "Mano (strumento di panoramica)",
"extraTools": "Altri strumenti" "extraTools": "Altri strumenti"
}, },
@@ -237,6 +251,7 @@
"linearElement": "Clicca per iniziare una linea in più punti, trascina per singola linea", "linearElement": "Clicca per iniziare una linea in più punti, trascina per singola linea",
"freeDraw": "Clicca e trascina, rilascia quando avrai finito", "freeDraw": "Clicca e trascina, rilascia quando avrai finito",
"text": "Suggerimento: puoi anche aggiungere del testo facendo doppio clic ovunque con lo strumento di selezione", "text": "Suggerimento: puoi anche aggiungere del testo facendo doppio clic ovunque con lo strumento di selezione",
"embeddable": "Fare click e trascina per creare un incorporamento web",
"text_selected": "Fai doppio click o premi INVIO per modificare il testo", "text_selected": "Fai doppio click o premi INVIO per modificare il testo",
"text_editing": "Premi ESC o CtrlOCmd+INVIO per completare le modifiche", "text_editing": "Premi ESC o CtrlOCmd+INVIO per completare le modifiche",
"linearElementMulti": "Clicca sull'ultimo punto o premi Esc o Invio per finire", "linearElementMulti": "Clicca sull'ultimo punto o premi Esc o Invio per finire",
@@ -252,7 +267,8 @@
"bindTextToElement": "Premi invio per aggiungere il testo", "bindTextToElement": "Premi invio per aggiungere il testo",
"deepBoxSelect": "Tieni premuto CtrlOCmd per selezionare in profondità e per impedire il trascinamento", "deepBoxSelect": "Tieni premuto CtrlOCmd per selezionare in profondità e per impedire il trascinamento",
"eraserRevert": "Tieni premuto Alt per ripristinare gli elementi contrassegnati per l'eliminazione", "eraserRevert": "Tieni premuto Alt per ripristinare gli elementi contrassegnati per l'eliminazione",
"firefox_clipboard_write": "Questa funzione può essere abilitata impostando il flag \"dom.events.asyncClipboard.clipboardItem\" su \"true\". Per modificare i flag del browser in Firefox, visitare la pagina \"about:config\"." "firefox_clipboard_write": "Questa funzione può essere abilitata impostando il flag \"dom.events.asyncClipboard.clipboardItem\" su \"true\". Per modificare i flag del browser in Firefox, visitare la pagina \"about:config\".",
"disableSnapping": "Tieni premuto Ctrl o Cmd per disabilitare lo snap"
}, },
"canvasError": { "canvasError": {
"cannotShowPreview": "Impossibile visualizzare l'anteprima", "cannotShowPreview": "Impossibile visualizzare l'anteprima",
@@ -367,7 +383,7 @@
"darkMode": "Tema scuro", "darkMode": "Tema scuro",
"embedScene": "Includi scena", "embedScene": "Includi scena",
"scale": "Scala", "scale": "Scala",
"padding": "" "padding": "Rientro"
}, },
"tooltip": { "tooltip": {
"embedScene": "I dati della scena saranno salvati nel file PNG/SVG esportato in modo che la scena possa essere ripristinata da esso.\nQuesto aumenterà la dimensione del file esportato." "embedScene": "I dati della scena saranno salvati nel file PNG/SVG esportato in modo che la scena possa essere ripristinata da esso.\nQuesto aumenterà la dimensione del file esportato."
@@ -411,7 +427,9 @@
"fileSavedToFilename": "Salvato in {filename}", "fileSavedToFilename": "Salvato in {filename}",
"canvas": "tela", "canvas": "tela",
"selection": "selezione", "selection": "selezione",
"pasteAsSingleElement": "Usa {{shortcut}} per incollare come un singolo elemento,\no incollare in un editor di testo esistente" "pasteAsSingleElement": "Usa {{shortcut}} per incollare come un singolo elemento,\no incollare in un editor di testo esistente",
"unableToEmbed": "Incorporare questo url non è permesso. Crea una issue su GitHub per richiedere che l'url sia autorizzato",
"unrecognizedLinkFormat": "Il link che hai incorporato non corrisponde al formato previsto. Prova a incollare la stringa 'embed' fornita dal sito di origine"
}, },
"colors": { "colors": {
"transparent": "Trasparente", "transparent": "Trasparente",
@@ -449,5 +467,36 @@
"shades": "Sfumature", "shades": "Sfumature",
"hexCode": "Codice esadecimale", "hexCode": "Codice esadecimale",
"noShades": "Nessuna sfumatura disponibile per questo colore" "noShades": "Nessuna sfumatura disponibile per questo colore"
},
"overwriteConfirm": {
"action": {
"exportToImage": {
"title": "Esporta come immagine",
"button": "Esporta come immagine",
"description": "Esporta i dati della scena come immagine, che potrai importare in seguito."
},
"saveToDisk": {
"title": "Salva su disco",
"button": "Salva su disco",
"description": "Esporta i dati della scena su file, che potrai importare in seguito."
},
"excalidrawPlus": {
"title": "Excalidraw+",
"button": "Esporta su Excalidraw+",
"description": "Salva la scena sul tuo spazio di lavoro Excalidraw+."
}
},
"modal": {
"loadFromFile": {
"title": "Carica da file",
"button": "Carica da file",
"description": "Il caricamento da file sostituirà <bold>il contenuto esistente</bold>.<br></br>Puoi salvare il tuo disegno prima usando una delle opzioni qui sotto."
},
"shareableLink": {
"title": "Carica da link",
"button": "Sostituisci il mio contenuto",
"description": "Il caricamento da file sostituirà <bold>il contenuto esistente</bold>.<br></br>Puoi salvare il tuo disegno prima usando una delle opzioni qui sotto."
}
}
} }
} }
+93 -44
View File
@@ -50,7 +50,7 @@
"veryLarge": "特大", "veryLarge": "特大",
"solid": "ベタ塗り", "solid": "ベタ塗り",
"hachure": "斜線", "hachure": "斜線",
"zigzag": "", "zigzag": "ジグザグ",
"crossHatch": "網掛け", "crossHatch": "網掛け",
"thin": "細", "thin": "細",
"bold": "太字", "bold": "太字",
@@ -106,11 +106,15 @@
"increaseFontSize": "フォントサイズを拡大", "increaseFontSize": "フォントサイズを拡大",
"unbindText": "テキストのバインド解除", "unbindText": "テキストのバインド解除",
"bindText": "テキストをコンテナにバインド", "bindText": "テキストをコンテナにバインド",
"createContainerFromText": "", "createContainerFromText": "コンテナ内でテキストを折り返す",
"link": { "link": {
"edit": "リンクを編集", "edit": "リンクを編集",
"editEmbed": "リンクの編集と埋め込み",
"create": "リンクを作成", "create": "リンクを作成",
"label": "リンク" "createEmbed": "リンクの作成と埋め込み",
"label": "リンク",
"labelEmbed": "リンクと埋め込み",
"empty": "リンクが設定されていません"
}, },
"lineEditor": { "lineEditor": {
"edit": "行を編集", "edit": "行を編集",
@@ -124,9 +128,9 @@
}, },
"statusPublished": "公開済み", "statusPublished": "公開済み",
"sidebarLock": "サイドバーを開いたままにする", "sidebarLock": "サイドバーを開いたままにする",
"selectAllElementsInFrame": "", "selectAllElementsInFrame": "フレーム内のすべての要素を選択",
"removeAllElementsFromFrame": "", "removeAllElementsFromFrame": "フレーム内のすべての要素を削除",
"eyeDropper": "" "eyeDropper": "キャンバスから色を選択"
}, },
"library": { "library": {
"noItems": "まだアイテムが追加されていません…", "noItems": "まだアイテムが追加されていません…",
@@ -160,13 +164,16 @@
"darkMode": "ダークモード", "darkMode": "ダークモード",
"lightMode": "ライトモード", "lightMode": "ライトモード",
"zenMode": "Zenモード", "zenMode": "Zenモード",
"objectsSnapMode": "",
"exitZenMode": "集中モードをやめる", "exitZenMode": "集中モードをやめる",
"cancel": "キャンセル", "cancel": "キャンセル",
"clear": "消去", "clear": "消去",
"remove": "削除", "remove": "削除",
"embed": "埋め込みの切り替え",
"publishLibrary": "公開", "publishLibrary": "公開",
"submit": "送信", "submit": "送信",
"confirm": "確認" "confirm": "確認",
"embeddableInteractionButton": ""
}, },
"alerts": { "alerts": {
"clearReset": "この操作によってキャンバス全体が消えます。よろしいですか?", "clearReset": "この操作によってキャンバス全体が消えます。よろしいですか?",
@@ -196,16 +203,21 @@
"imageInsertError": "画像を挿入できませんでした。後でもう一度お試しください...", "imageInsertError": "画像を挿入できませんでした。後でもう一度お試しください...",
"fileTooBig": "ファイルが大きすぎます。許可される最大サイズは {{maxSize}} です。", "fileTooBig": "ファイルが大きすぎます。許可される最大サイズは {{maxSize}} です。",
"svgImageInsertError": "SVGイメージを挿入できませんでした。SVGマークアップは無効に見えます。", "svgImageInsertError": "SVGイメージを挿入できませんでした。SVGマークアップは無効に見えます。",
"failedToFetchImage": "",
"invalidSVGString": "無効なSVGです。", "invalidSVGString": "無効なSVGです。",
"cannotResolveCollabServer": "コラボレーションサーバに接続できませんでした。ページを再読み込みして、もう一度お試しください。", "cannotResolveCollabServer": "コラボレーションサーバに接続できませんでした。ページを再読み込みして、もう一度お試しください。",
"importLibraryError": "ライブラリを読み込めませんでした。", "importLibraryError": "ライブラリを読み込めませんでした。",
"collabSaveFailed": "バックエンドデータベースに保存できませんでした。問題が解決しない場合は、作業を失わないようにローカルにファイルを保存してください。", "collabSaveFailed": "バックエンドデータベースに保存できませんでした。問題が解決しない場合は、作業を失わないようにローカルにファイルを保存してください。",
"collabSaveFailed_sizeExceeded": "キャンバスが大きすぎるため、バックエンドデータベースに保存できませんでした。問題が解決しない場合は、作業を失わないようにローカルにファイルを保存してください。", "collabSaveFailed_sizeExceeded": "キャンバスが大きすぎるため、バックエンドデータベースに保存できませんでした。問題が解決しない場合は、作業を失わないようにローカルにファイルを保存してください。",
"brave_measure_text_error": { "brave_measure_text_error": {
"line1": "", "line1": "<bold>Aggressly Block Fingerprinting</bold> の設定が有効なBraveブラウザを使用しているようです。",
"line2": "", "line2": "これにより、図面の <bold>テキスト要素</bold> が壊れる可能性があります。",
"line3": "", "line3": "この設定を無効にすることを強く推奨します。 <link>設定手順</link> をこちらから確認できます。",
"line4": "" "line4": "この設定を無効にすると、テキスト要素の表示が修正されません。 GitHub で <issueLink>Issue</issueLink> を開くか、 <discordLink>Discord</discordLink> にご記入ください"
},
"libraryElementTypeError": {
"embeddable": "",
"image": ""
} }
}, },
"toolBar": { "toolBar": {
@@ -223,9 +235,11 @@
"penMode": "ペンモード - タッチ防止", "penMode": "ペンモード - タッチ防止",
"link": "選択した図形のリンクを追加/更新", "link": "選択した図形のリンクを追加/更新",
"eraser": "消しゴム", "eraser": "消しゴム",
"frame": "", "frame": "フレームツール",
"embeddable": "Web埋め込み",
"laser": "",
"hand": "手 (パンニングツール)", "hand": "手 (パンニングツール)",
"extraTools": "" "extraTools": "その他のツール"
}, },
"headings": { "headings": {
"canvasActions": "キャンバス操作", "canvasActions": "キャンバス操作",
@@ -237,6 +251,7 @@
"linearElement": "クリックすると複数の頂点からなる曲線を開始、ドラッグすると直線", "linearElement": "クリックすると複数の頂点からなる曲線を開始、ドラッグすると直線",
"freeDraw": "クリックしてドラッグします。離すと終了します", "freeDraw": "クリックしてドラッグします。離すと終了します",
"text": "ヒント: 選択ツールを使用して任意の場所をダブルクリックしてテキストを追加することもできます", "text": "ヒント: 選択ツールを使用して任意の場所をダブルクリックしてテキストを追加することもできます",
"embeddable": "",
"text_selected": "テキストを編集するには、ダブルクリックまたはEnterキーを押します", "text_selected": "テキストを編集するには、ダブルクリックまたはEnterキーを押します",
"text_editing": "Esc キーまたは CtrlOrCmd+ENTER キーを押して編集を終了します", "text_editing": "Esc キーまたは CtrlOrCmd+ENTER キーを押して編集を終了します",
"linearElementMulti": "最後のポイントをクリックするか、エスケープまたはEnterを押して終了します", "linearElementMulti": "最後のポイントをクリックするか、エスケープまたはEnterを押して終了します",
@@ -252,7 +267,8 @@
"bindTextToElement": "Enterを押してテキストを追加", "bindTextToElement": "Enterを押してテキストを追加",
"deepBoxSelect": "CtrlOrCmd を押し続けることでドラッグを抑止し、深い選択を行います", "deepBoxSelect": "CtrlOrCmd を押し続けることでドラッグを抑止し、深い選択を行います",
"eraserRevert": "Alt を押し続けることで削除マークされた要素を元に戻す", "eraserRevert": "Alt を押し続けることで削除マークされた要素を元に戻す",
"firefox_clipboard_write": "この機能は、\"dom.events.asyncClipboard.clipboardItem\" フラグを \"true\" に設定することで有効になる可能性があります。Firefox でブラウザーの設定を変更するには、\"about:config\" ページを参照してください。" "firefox_clipboard_write": "この機能は、\"dom.events.asyncClipboard.clipboardItem\" フラグを \"true\" に設定することで有効になる可能性があります。Firefox でブラウザーの設定を変更するには、\"about:config\" ページを参照してください。",
"disableSnapping": ""
}, },
"canvasError": { "canvasError": {
"cannotShowPreview": "プレビューを表示できません", "cannotShowPreview": "プレビューを表示できません",
@@ -360,27 +376,27 @@
"removeItemsFromLib": "選択したアイテムをライブラリから削除" "removeItemsFromLib": "選択したアイテムをライブラリから削除"
}, },
"imageExportDialog": { "imageExportDialog": {
"header": "", "header": "画像をエクスポート",
"label": { "label": {
"withBackground": "", "withBackground": "背景",
"onlySelected": "", "onlySelected": "",
"darkMode": "", "darkMode": "ダークモード",
"embedScene": "", "embedScene": "",
"scale": "", "scale": "スケール",
"padding": "" "padding": "余白"
}, },
"tooltip": { "tooltip": {
"embedScene": "" "embedScene": ""
}, },
"title": { "title": {
"exportToPng": "", "exportToPng": "PNG にエクスポート",
"exportToSvg": "", "exportToSvg": "SVG にエクスポート",
"copyPngToClipboard": "" "copyPngToClipboard": "クリップボードにPNGをコピー"
}, },
"button": { "button": {
"exportToPng": "", "exportToPng": "PNG",
"exportToSvg": "", "exportToSvg": "SVG",
"copyPngToClipboard": "" "copyPngToClipboard": "クリップボードにコピー"
} }
}, },
"encrypted": { "encrypted": {
@@ -411,24 +427,26 @@
"fileSavedToFilename": "{filename} に保存しました", "fileSavedToFilename": "{filename} に保存しました",
"canvas": "キャンバス", "canvas": "キャンバス",
"selection": "選択", "selection": "選択",
"pasteAsSingleElement": "{{shortcut}} を使用して単一の要素として貼り付けるか、\n既存のテキストエディタに貼り付け" "pasteAsSingleElement": "{{shortcut}} を使用して単一の要素として貼り付けるか、\n既存のテキストエディタに貼り付け",
"unableToEmbed": "",
"unrecognizedLinkFormat": ""
}, },
"colors": { "colors": {
"transparent": "透明", "transparent": "透明",
"black": "", "black": "",
"white": "", "white": "",
"red": "", "red": "",
"pink": "", "pink": "ピンク",
"grape": "", "grape": "グレープ",
"violet": "", "violet": "バイオレット",
"gray": "", "gray": "灰色",
"blue": "", "blue": "",
"cyan": "", "cyan": "シアン",
"teal": "", "teal": "ティール",
"green": "", "green": "",
"yellow": "", "yellow": "",
"orange": "", "orange": "オレンジ",
"bronze": "" "bronze": "ブロンズ"
}, },
"welcomeScreen": { "welcomeScreen": {
"app": { "app": {
@@ -444,10 +462,41 @@
} }
}, },
"colorPicker": { "colorPicker": {
"mostUsedCustomColors": "", "mostUsedCustomColors": "最も使用されているカスタム色",
"colors": "", "colors": "",
"shades": "", "shades": "",
"hexCode": "", "hexCode": "Hexコード",
"noShades": "" "noShades": ""
},
"overwriteConfirm": {
"action": {
"exportToImage": {
"title": "画像としてエクスポート",
"button": "画像としてエクスポート",
"description": ""
},
"saveToDisk": {
"title": "ディスクに保存",
"button": "ディスクに保存",
"description": ""
},
"excalidrawPlus": {
"title": "Excalidraw+",
"button": "Excalidraw+にエクスポート",
"description": "Excalidraw+ ワークスペースにシーンを保存します。"
}
},
"modal": {
"loadFromFile": {
"title": "ファイルからロード",
"button": "ファイルからロード",
"description": ""
},
"shareableLink": {
"title": "リンクからロード",
"button": "",
"description": ""
}
}
} }
} }
+116 -67
View File
@@ -1,14 +1,14 @@
{ {
"labels": { "labels": {
"paste": "", "paste": "Qoyıw",
"pasteAsPlaintext": "", "pasteAsPlaintext": "Ápiwayı tekst retinde qoyıw",
"pasteCharts": "", "pasteCharts": "Diagrammalardı qoyıw",
"selectAll": "Barlıǵın tańlaw", "selectAll": "Barlıǵın tańlaw",
"multiSelect": "", "multiSelect": "",
"moveCanvas": "", "moveCanvas": "",
"cut": "", "cut": "Qıyıw",
"copy": "Kóshirip alıw", "copy": "Kóshirip alıw",
"copyAsPng": "", "copyAsPng": "Almasıw buferine PNG retinde kóshirip alıw",
"copyAsSvg": "", "copyAsSvg": "",
"copyText": "", "copyText": "",
"bringForward": "", "bringForward": "",
@@ -18,8 +18,8 @@
"delete": "Óshiriw", "delete": "Óshiriw",
"copyStyles": "", "copyStyles": "",
"pasteStyles": "", "pasteStyles": "",
"stroke": "", "stroke": "Jiyek",
"background": "", "background": "Fon",
"fill": "", "fill": "",
"strokeWidth": "", "strokeWidth": "",
"strokeStyle": "", "strokeStyle": "",
@@ -29,31 +29,31 @@
"sloppiness": "", "sloppiness": "",
"opacity": "", "opacity": "",
"textAlign": "", "textAlign": "",
"edges": "", "edges": "Qırlar",
"sharp": "", "sharp": "",
"round": "", "round": "",
"arrowheads": "", "arrowheads": "",
"arrowhead_none": "", "arrowhead_none": "",
"arrowhead_arrow": "", "arrowhead_arrow": "Jebe",
"arrowhead_bar": "", "arrowhead_bar": "",
"arrowhead_dot": "", "arrowhead_dot": "Noqat",
"arrowhead_triangle": "", "arrowhead_triangle": "",
"fontSize": "Shrift ólshemi", "fontSize": "Shrift ólshemi",
"fontFamily": "", "fontFamily": "",
"addWatermark": "", "addWatermark": "",
"handDrawn": "", "handDrawn": "",
"normal": "", "normal": "",
"code": "", "code": "Kod",
"small": "", "small": "",
"medium": "", "medium": "",
"large": "", "large": "Úlken",
"veryLarge": "", "veryLarge": "Júdá úlken",
"solid": "", "solid": "",
"hachure": "", "hachure": "",
"zigzag": "", "zigzag": "Zigzag",
"crossHatch": "", "crossHatch": "",
"thin": "", "thin": "Jińishke",
"bold": "", "bold": "Qalıń",
"left": "", "left": "",
"center": "", "center": "",
"right": "", "right": "",
@@ -71,19 +71,19 @@
"language": "Til", "language": "Til",
"liveCollaboration": "", "liveCollaboration": "",
"duplicateSelection": "Nusqa", "duplicateSelection": "Nusqa",
"untitled": "", "untitled": "Atamasız",
"name": "Ataması", "name": "Ataması",
"yourName": "Atıńız", "yourName": "Atıńız",
"madeWithExcalidraw": "", "madeWithExcalidraw": "Excalidraw járdeminde islengen",
"group": "", "group": "",
"ungroup": "", "ungroup": "",
"collaborators": "", "collaborators": "Qatnasıwshılar",
"showGrid": "", "showGrid": "",
"addToLibrary": "Kitapxanaǵa qosıw", "addToLibrary": "Kitapxanaǵa qosıw",
"removeFromLibrary": "Kitapxanadan alıp taslaw", "removeFromLibrary": "Kitapxanadan alıp taslaw",
"libraryLoadingMessage": "Kitapxana júklenbekte…", "libraryLoadingMessage": "Kitapxana júklenbekte…",
"libraries": "Kitapxanalardı kóriw", "libraries": "Kitapxanalardı kóriw",
"loadingScene": "", "loadingScene": "Saxna júklenbekte…",
"align": "", "align": "",
"alignTop": "", "alignTop": "",
"alignBottom": "", "alignBottom": "",
@@ -99,22 +99,26 @@
"share": "Bólisiw", "share": "Bólisiw",
"showStroke": "", "showStroke": "",
"showBackground": "", "showBackground": "",
"toggleTheme": "", "toggleTheme": "Temanı ózgertiw",
"personalLib": "", "personalLib": "Jeke kitapxana",
"excalidrawLib": "", "excalidrawLib": "Excalidraw kitapxanası",
"decreaseFontSize": "", "decreaseFontSize": "Shrift ólshemin kishireytiw",
"increaseFontSize": "", "increaseFontSize": "Shrift ólshemin úlkeytiw",
"unbindText": "", "unbindText": "",
"bindText": "", "bindText": "",
"createContainerFromText": "", "createContainerFromText": "",
"link": { "link": {
"edit": "Siltemeni ózgertiw", "edit": "Siltemeni ózgertiw",
"editEmbed": "",
"create": "Siltemeni jaratıw", "create": "Siltemeni jaratıw",
"label": "Silteme" "createEmbed": "",
"label": "Silteme",
"labelEmbed": "",
"empty": ""
}, },
"lineEditor": { "lineEditor": {
"edit": "", "edit": "Qatardı ózgertiw",
"exit": "" "exit": "Qatardı ózgertiw redaktorınan shıǵıw"
}, },
"elementLock": { "elementLock": {
"lock": "Qulıplaw", "lock": "Qulıplaw",
@@ -136,11 +140,11 @@
"buttons": { "buttons": {
"clearReset": "", "clearReset": "",
"exportJSON": "", "exportJSON": "",
"exportImage": "", "exportImage": "Súwretti eksportlaw...",
"export": "", "export": "Retinde saqlaw...",
"copyToClipboard": "Almasıw buferine kóshirip alındı", "copyToClipboard": "Almasıw buferine kóshirip alındı",
"save": "", "save": "Ámeldegi faylǵa saqlaw",
"saveAs": "", "saveAs": "Retinde saqlaw",
"load": "Ashıw", "load": "Ashıw",
"getShareableLink": "", "getShareableLink": "",
"close": "Jabıw", "close": "Jabıw",
@@ -160,13 +164,16 @@
"darkMode": "Qarańǵı tema", "darkMode": "Qarańǵı tema",
"lightMode": "Jaqtı tema", "lightMode": "Jaqtı tema",
"zenMode": "", "zenMode": "",
"objectsSnapMode": "",
"exitZenMode": "", "exitZenMode": "",
"cancel": "Biykarlaw", "cancel": "Biykarlaw",
"clear": "Tazalaw", "clear": "Tazalaw",
"remove": "Óshiriw", "remove": "Óshiriw",
"embed": "",
"publishLibrary": "", "publishLibrary": "",
"submit": "Jiberiw", "submit": "Jiberiw",
"confirm": "Tastıyıqlaw" "confirm": "Tastıyıqlaw",
"embeddableInteractionButton": ""
}, },
"alerts": { "alerts": {
"clearReset": "", "clearReset": "",
@@ -196,6 +203,7 @@
"imageInsertError": "", "imageInsertError": "",
"fileTooBig": "", "fileTooBig": "",
"svgImageInsertError": "", "svgImageInsertError": "",
"failedToFetchImage": "",
"invalidSVGString": "Jaramsız SVG.", "invalidSVGString": "Jaramsız SVG.",
"cannotResolveCollabServer": "", "cannotResolveCollabServer": "",
"importLibraryError": "Kitapxananı júklew ámelge aspadı", "importLibraryError": "Kitapxananı júklew ámelge aspadı",
@@ -206,12 +214,16 @@
"line2": "", "line2": "",
"line3": "", "line3": "",
"line4": "" "line4": ""
},
"libraryElementTypeError": {
"embeddable": "",
"image": ""
} }
}, },
"toolBar": { "toolBar": {
"selection": "", "selection": "",
"image": "Súwret qoyıw", "image": "Súwret qoyıw",
"rectangle": "", "rectangle": "Tórt múyeshlik",
"diamond": "", "diamond": "",
"ellipse": "", "ellipse": "",
"arrow": "", "arrow": "",
@@ -224,19 +236,22 @@
"link": "", "link": "",
"eraser": "Óshirgish", "eraser": "Óshirgish",
"frame": "", "frame": "",
"embeddable": "",
"laser": "",
"hand": "", "hand": "",
"extraTools": "" "extraTools": ""
}, },
"headings": { "headings": {
"canvasActions": "", "canvasActions": "",
"selectedShapeActions": "", "selectedShapeActions": "",
"shapes": "" "shapes": "Figuralar"
}, },
"hints": { "hints": {
"canvasPanning": "", "canvasPanning": "",
"linearElement": "", "linearElement": "",
"freeDraw": "", "freeDraw": "",
"text": "", "text": "",
"embeddable": "",
"text_selected": "", "text_selected": "",
"text_editing": "", "text_editing": "",
"linearElementMulti": "", "linearElementMulti": "",
@@ -249,10 +264,11 @@
"lineEditor_nothingSelected": "", "lineEditor_nothingSelected": "",
"placeImage": "", "placeImage": "",
"publishLibrary": "", "publishLibrary": "",
"bindTextToElement": "", "bindTextToElement": "Tekst qosıw ushın Enter túymesin basıń",
"deepBoxSelect": "", "deepBoxSelect": "",
"eraserRevert": "", "eraserRevert": "",
"firefox_clipboard_write": "" "firefox_clipboard_write": "",
"disableSnapping": ""
}, },
"canvasError": { "canvasError": {
"cannotShowPreview": "", "cannotShowPreview": "",
@@ -281,18 +297,18 @@
"title": "Qátelik" "title": "Qátelik"
}, },
"exportDialog": { "exportDialog": {
"disk_title": "", "disk_title": "Diskke saqlaw",
"disk_details": "", "disk_details": "",
"disk_button": "", "disk_button": "Faylǵa saqlaw",
"link_title": "", "link_title": "",
"link_details": "", "link_details": "",
"link_button": "", "link_button": "Siltemege eksportlaw",
"excalidrawplus_description": "", "excalidrawplus_description": "",
"excalidrawplus_button": "Eksportlaw", "excalidrawplus_button": "Eksportlaw",
"excalidrawplus_exportError": "" "excalidrawplus_exportError": ""
}, },
"helpDialog": { "helpDialog": {
"blog": "", "blog": "Biziń blogtı oqıń",
"click": "basıw", "click": "basıw",
"deepSelect": "", "deepSelect": "",
"deepBoxSelect": "", "deepBoxSelect": "",
@@ -301,7 +317,7 @@
"documentation": "Hújjetshilik", "documentation": "Hújjetshilik",
"doubleClick": "", "doubleClick": "",
"drag": "", "drag": "",
"editor": "", "editor": "Redaktor",
"editLineArrowPoints": "", "editLineArrowPoints": "",
"editText": "", "editText": "",
"github": "", "github": "",
@@ -333,7 +349,7 @@
"libraryDesc": "", "libraryDesc": "",
"website": "Veb-sayt", "website": "Veb-sayt",
"placeholder": { "placeholder": {
"authorName": "", "authorName": "Atıńız yamasa paydalanıwshı atı",
"libraryName": "", "libraryName": "",
"libraryDesc": "", "libraryDesc": "",
"githubHandle": "", "githubHandle": "",
@@ -356,15 +372,15 @@
"content": "" "content": ""
}, },
"confirmDialog": { "confirmDialog": {
"resetLibrary": "", "resetLibrary": "Kitapxananı qayta ornatıw",
"removeItemsFromLib": "" "removeItemsFromLib": ""
}, },
"imageExportDialog": { "imageExportDialog": {
"header": "", "header": "Súwretti eksportlaw",
"label": { "label": {
"withBackground": "", "withBackground": "Fon",
"onlySelected": "", "onlySelected": "",
"darkMode": "", "darkMode": "Qarańǵı tema",
"embedScene": "", "embedScene": "",
"scale": "", "scale": "",
"padding": "" "padding": ""
@@ -378,9 +394,9 @@
"copyPngToClipboard": "" "copyPngToClipboard": ""
}, },
"button": { "button": {
"exportToPng": "", "exportToPng": "PNG",
"exportToSvg": "", "exportToSvg": "SVG",
"copyPngToClipboard": "" "copyPngToClipboard": "Almasıw buferine kóshirip alıw"
} }
}, },
"encrypted": { "encrypted": {
@@ -389,8 +405,8 @@
}, },
"stats": { "stats": {
"angle": "", "angle": "",
"element": "", "element": "Element",
"elements": "", "elements": "Elementler",
"height": "", "height": "",
"scene": "Saxna", "scene": "Saxna",
"selected": "Tańlandı", "selected": "Tańlandı",
@@ -403,31 +419,33 @@
"width": "" "width": ""
}, },
"toast": { "toast": {
"addedToLibrary": "", "addedToLibrary": "Kitapxanaǵa qosıldı",
"copyStyles": "", "copyStyles": "",
"copyToClipboard": "", "copyToClipboard": "Almasıw buferine kóshirip alındı.",
"copyToClipboardAsPng": "", "copyToClipboardAsPng": "",
"fileSaved": "Fayl saqlandı.", "fileSaved": "Fayl saqlandı.",
"fileSavedToFilename": "{filename} saqlandı", "fileSavedToFilename": "{filename} saqlandı",
"canvas": "", "canvas": "",
"selection": "", "selection": "",
"pasteAsSingleElement": "" "pasteAsSingleElement": "",
"unableToEmbed": "",
"unrecognizedLinkFormat": ""
}, },
"colors": { "colors": {
"transparent": "", "transparent": "",
"black": "", "black": "Qara",
"white": "", "white": "Aq",
"red": "", "red": "Qızıl",
"pink": "", "pink": "Qızǵılt",
"grape": "", "grape": "",
"violet": "", "violet": "Qızǵılt kók",
"gray": "", "gray": "",
"blue": "", "blue": "Kók",
"cyan": "", "cyan": "Kók aspan",
"teal": "", "teal": "Piruza",
"green": "", "green": "Jasıl",
"yellow": "", "yellow": "Sarı",
"orange": "", "orange": "Qızǵılt sarı",
"bronze": "" "bronze": ""
}, },
"welcomeScreen": { "welcomeScreen": {
@@ -445,9 +463,40 @@
}, },
"colorPicker": { "colorPicker": {
"mostUsedCustomColors": "", "mostUsedCustomColors": "",
"colors": "", "colors": "Reńler",
"shades": "", "shades": "",
"hexCode": "", "hexCode": "",
"noShades": "" "noShades": ""
},
"overwriteConfirm": {
"action": {
"exportToImage": {
"title": "Súwret retinde eksportlaw",
"button": "Súwret retinde eksportlaw",
"description": ""
},
"saveToDisk": {
"title": "Diskke saqlaw",
"button": "Diskke saqlaw",
"description": ""
},
"excalidrawPlus": {
"title": "Excalidraw+",
"button": "",
"description": ""
}
},
"modal": {
"loadFromFile": {
"title": "Fayldan júklew",
"button": "Fayldan júklew",
"description": ""
},
"shareableLink": {
"title": "Siltemeden júklew",
"button": "",
"description": ""
}
}
} }
} }
+53 -4
View File
@@ -109,8 +109,12 @@
"createContainerFromText": "", "createContainerFromText": "",
"link": { "link": {
"edit": "Ẓreg aseɣwen", "edit": "Ẓreg aseɣwen",
"editEmbed": "",
"create": "Snulfu-d aseɣwen", "create": "Snulfu-d aseɣwen",
"label": "Aseɣwen" "createEmbed": "",
"label": "Aseɣwen",
"labelEmbed": "",
"empty": ""
}, },
"lineEditor": { "lineEditor": {
"edit": "Ẓreg izirig", "edit": "Ẓreg izirig",
@@ -160,13 +164,16 @@
"darkMode": "Askar imsulles", "darkMode": "Askar imsulles",
"lightMode": "Askar afaw", "lightMode": "Askar afaw",
"zenMode": "Askar Zen", "zenMode": "Askar Zen",
"objectsSnapMode": "",
"exitZenMode": "Ffeɣ seg uskar Zen", "exitZenMode": "Ffeɣ seg uskar Zen",
"cancel": "Sefsex", "cancel": "Sefsex",
"clear": "Sfeḍ", "clear": "Sfeḍ",
"remove": "Kkes", "remove": "Kkes",
"embed": "",
"publishLibrary": "Ẓreg", "publishLibrary": "Ẓreg",
"submit": "Azen", "submit": "Azen",
"confirm": "Sentem" "confirm": "Sentem",
"embeddableInteractionButton": ""
}, },
"alerts": { "alerts": {
"clearReset": "Ayagi ad isfeḍ akk taɣzut n usuneɣ. Tetḥeqqeḍ?", "clearReset": "Ayagi ad isfeḍ akk taɣzut n usuneɣ. Tetḥeqqeḍ?",
@@ -196,6 +203,7 @@
"imageInsertError": "D awezɣi tugra n tugna. Eɛreḍ tikkelt-nniḍen ardeqqal...", "imageInsertError": "D awezɣi tugra n tugna. Eɛreḍ tikkelt-nniḍen ardeqqal...",
"fileTooBig": "Afaylu meqqer aṭas. Tiddi tafellayt yurgen d {{maxSize}}.", "fileTooBig": "Afaylu meqqer aṭas. Tiddi tafellayt yurgen d {{maxSize}}.",
"svgImageInsertError": "D awezɣi tugra n tugna SVG. Acraḍ SVG yettban-d d armeɣtu.", "svgImageInsertError": "D awezɣi tugra n tugna SVG. Acraḍ SVG yettban-d d armeɣtu.",
"failedToFetchImage": "",
"invalidSVGString": "SVG armeɣtu.", "invalidSVGString": "SVG armeɣtu.",
"cannotResolveCollabServer": "Ulamek tuqqna s aqeddac n umyalel. Ma ulac uɣilif ales asali n usebter sakin eɛreḍ tikkelt-nniḍen.", "cannotResolveCollabServer": "Ulamek tuqqna s aqeddac n umyalel. Ma ulac uɣilif ales asali n usebter sakin eɛreḍ tikkelt-nniḍen.",
"importLibraryError": "Ur d-ssalay ara tamkarḍit", "importLibraryError": "Ur d-ssalay ara tamkarḍit",
@@ -206,6 +214,10 @@
"line2": "Ayagi yezmer ad d-iglu s truẓi n<bold>Iferdisen n uḍris</bold>deg wunuɣen-inek.", "line2": "Ayagi yezmer ad d-iglu s truẓi n<bold>Iferdisen n uḍris</bold>deg wunuɣen-inek.",
"line3": "Ad k-nsemter ad tsexsiḍ aɣewwar-agi. Tzemreḍ ad tḍefreḍ<link>isurifen-agi</link> ɣef wamek ara txedmeḍ.", "line3": "Ad k-nsemter ad tsexsiḍ aɣewwar-agi. Tzemreḍ ad tḍefreḍ<link>isurifen-agi</link> ɣef wamek ara txedmeḍ.",
"line4": "" "line4": ""
},
"libraryElementTypeError": {
"embeddable": "",
"image": ""
} }
}, },
"toolBar": { "toolBar": {
@@ -224,6 +236,8 @@
"link": "Rnu/leqqem aseɣwen i talɣa yettwafernen", "link": "Rnu/leqqem aseɣwen i talɣa yettwafernen",
"eraser": "Sfeḍ", "eraser": "Sfeḍ",
"frame": "", "frame": "",
"embeddable": "",
"laser": "",
"hand": "Afus (afecku n usmutti n tmuɣli)", "hand": "Afus (afecku n usmutti n tmuɣli)",
"extraTools": "" "extraTools": ""
}, },
@@ -237,6 +251,7 @@
"linearElement": "Ssit akken ad tebduḍ aṭas n tenqiḍin, zuɣer i yiwen n yizirig", "linearElement": "Ssit akken ad tebduḍ aṭas n tenqiḍin, zuɣer i yiwen n yizirig",
"freeDraw": "Ssit yerna zuɣer, serreḥ ticki tfukeḍ", "freeDraw": "Ssit yerna zuɣer, serreḥ ticki tfukeḍ",
"text": "Tixidest: tzemreḍ daɣen ad ternuḍ aḍris s usiti snat n tikkal anida tebɣiḍ s ufecku n tefrayt", "text": "Tixidest: tzemreḍ daɣen ad ternuḍ aḍris s usiti snat n tikkal anida tebɣiḍ s ufecku n tefrayt",
"embeddable": "",
"text_selected": "Ssit snat n tikkal neɣ ssed taqeffalt Kcem akken ad tẓergeḍ aḍris", "text_selected": "Ssit snat n tikkal neɣ ssed taqeffalt Kcem akken ad tẓergeḍ aḍris",
"text_editing": "Ssit Escape neɣ CtrlOrCmd+ENTER akken ad tfakkeḍ asiẓreg", "text_editing": "Ssit Escape neɣ CtrlOrCmd+ENTER akken ad tfakkeḍ asiẓreg",
"linearElementMulti": "Ssit ɣef tenqiḍt taneggarut neɣ ssed taqeffalt Escape neɣ taqeffalt Kcem akken ad tfakkeḍ", "linearElementMulti": "Ssit ɣef tenqiḍt taneggarut neɣ ssed taqeffalt Escape neɣ taqeffalt Kcem akken ad tfakkeḍ",
@@ -252,7 +267,8 @@
"bindTextToElement": "Ssed ɣef kcem akken ad ternuḍ aḍris", "bindTextToElement": "Ssed ɣef kcem akken ad ternuḍ aḍris",
"deepBoxSelect": "Ṭṭef CtrlOrCmd akken ad tferneḍ s telqey, yerna ad trewleḍ i uzuɣer", "deepBoxSelect": "Ṭṭef CtrlOrCmd akken ad tferneḍ s telqey, yerna ad trewleḍ i uzuɣer",
"eraserRevert": "Ssed Alt akken ad tsefsxeḍ iferdisen yettwacerḍen i tukksa", "eraserRevert": "Ssed Alt akken ad tsefsxeḍ iferdisen yettwacerḍen i tukksa",
"firefox_clipboard_write": "" "firefox_clipboard_write": "",
"disableSnapping": ""
}, },
"canvasError": { "canvasError": {
"cannotShowPreview": "Ulamek abeqqeḍ n teskant", "cannotShowPreview": "Ulamek abeqqeḍ n teskant",
@@ -411,7 +427,9 @@
"fileSavedToFilename": "Yettwasekles di {filename}", "fileSavedToFilename": "Yettwasekles di {filename}",
"canvas": "taɣzut n usuneɣ", "canvas": "taɣzut n usuneɣ",
"selection": "tafrayt", "selection": "tafrayt",
"pasteAsSingleElement": "" "pasteAsSingleElement": "",
"unableToEmbed": "",
"unrecognizedLinkFormat": ""
}, },
"colors": { "colors": {
"transparent": "Afrawan", "transparent": "Afrawan",
@@ -449,5 +467,36 @@
"shades": "", "shades": "",
"hexCode": "", "hexCode": "",
"noShades": "" "noShades": ""
},
"overwriteConfirm": {
"action": {
"exportToImage": {
"title": "",
"button": "",
"description": ""
},
"saveToDisk": {
"title": "",
"button": "",
"description": ""
},
"excalidrawPlus": {
"title": "",
"button": "",
"description": ""
}
},
"modal": {
"loadFromFile": {
"title": "",
"button": "",
"description": ""
},
"shareableLink": {
"title": "",
"button": "",
"description": ""
}
}
} }
} }
+53 -4
View File
@@ -109,8 +109,12 @@
"createContainerFromText": "", "createContainerFromText": "",
"link": { "link": {
"edit": "", "edit": "",
"editEmbed": "",
"create": "", "create": "",
"label": "" "createEmbed": "",
"label": "",
"labelEmbed": "",
"empty": ""
}, },
"lineEditor": { "lineEditor": {
"edit": "", "edit": "",
@@ -160,13 +164,16 @@
"darkMode": "", "darkMode": "",
"lightMode": "", "lightMode": "",
"zenMode": "", "zenMode": "",
"objectsSnapMode": "",
"exitZenMode": "", "exitZenMode": "",
"cancel": "", "cancel": "",
"clear": "", "clear": "",
"remove": "", "remove": "",
"embed": "",
"publishLibrary": "", "publishLibrary": "",
"submit": "", "submit": "",
"confirm": "" "confirm": "",
"embeddableInteractionButton": ""
}, },
"alerts": { "alerts": {
"clearReset": "", "clearReset": "",
@@ -196,6 +203,7 @@
"imageInsertError": "Суретті жүктеу мүмкін болмады. Кейінірек қайталап көріңіз...", "imageInsertError": "Суретті жүктеу мүмкін болмады. Кейінірек қайталап көріңіз...",
"fileTooBig": "Файл өте үлкен. Максималды рұқсат етілген көлем {{maxSize}}.", "fileTooBig": "Файл өте үлкен. Максималды рұқсат етілген көлем {{maxSize}}.",
"svgImageInsertError": "", "svgImageInsertError": "",
"failedToFetchImage": "",
"invalidSVGString": "", "invalidSVGString": "",
"cannotResolveCollabServer": "", "cannotResolveCollabServer": "",
"importLibraryError": "", "importLibraryError": "",
@@ -206,6 +214,10 @@
"line2": "", "line2": "",
"line3": "", "line3": "",
"line4": "" "line4": ""
},
"libraryElementTypeError": {
"embeddable": "",
"image": ""
} }
}, },
"toolBar": { "toolBar": {
@@ -224,6 +236,8 @@
"link": "", "link": "",
"eraser": "", "eraser": "",
"frame": "", "frame": "",
"embeddable": "",
"laser": "",
"hand": "", "hand": "",
"extraTools": "" "extraTools": ""
}, },
@@ -237,6 +251,7 @@
"linearElement": "", "linearElement": "",
"freeDraw": "", "freeDraw": "",
"text": "", "text": "",
"embeddable": "",
"text_selected": "", "text_selected": "",
"text_editing": "", "text_editing": "",
"linearElementMulti": "", "linearElementMulti": "",
@@ -252,7 +267,8 @@
"bindTextToElement": "", "bindTextToElement": "",
"deepBoxSelect": "", "deepBoxSelect": "",
"eraserRevert": "", "eraserRevert": "",
"firefox_clipboard_write": "" "firefox_clipboard_write": "",
"disableSnapping": ""
}, },
"canvasError": { "canvasError": {
"cannotShowPreview": "", "cannotShowPreview": "",
@@ -411,7 +427,9 @@
"fileSavedToFilename": "{filename} сақталды", "fileSavedToFilename": "{filename} сақталды",
"canvas": "", "canvas": "",
"selection": "таңдау", "selection": "таңдау",
"pasteAsSingleElement": "" "pasteAsSingleElement": "",
"unableToEmbed": "",
"unrecognizedLinkFormat": ""
}, },
"colors": { "colors": {
"transparent": "", "transparent": "",
@@ -449,5 +467,36 @@
"shades": "", "shades": "",
"hexCode": "", "hexCode": "",
"noShades": "" "noShades": ""
},
"overwriteConfirm": {
"action": {
"exportToImage": {
"title": "",
"button": "",
"description": ""
},
"saveToDisk": {
"title": "",
"button": "",
"description": ""
},
"excalidrawPlus": {
"title": "",
"button": "",
"description": ""
}
},
"modal": {
"loadFromFile": {
"title": "",
"button": "",
"description": ""
},
"shareableLink": {
"title": "",
"button": "",
"description": ""
}
}
} }
} }
+53 -4
View File
@@ -109,8 +109,12 @@
"createContainerFromText": "រុំអត្ថបទក្នុងប្រអប់មួយ", "createContainerFromText": "រុំអត្ថបទក្នុងប្រអប់មួយ",
"link": { "link": {
"edit": "កែតំណភ្ជាប់", "edit": "កែតំណភ្ជាប់",
"editEmbed": "",
"create": "បង្កើតតំណភ្ជាប់", "create": "បង្កើតតំណភ្ជាប់",
"label": "តំណ" "createEmbed": "",
"label": "តំណ",
"labelEmbed": "",
"empty": ""
}, },
"lineEditor": { "lineEditor": {
"edit": "កែសម្រួលបន្ទាត់", "edit": "កែសម្រួលបន្ទាត់",
@@ -160,13 +164,16 @@
"darkMode": "ម៉ូដងងឹត", "darkMode": "ម៉ូដងងឹត",
"lightMode": "ម៉ូដភ្លឺ", "lightMode": "ម៉ូដភ្លឺ",
"zenMode": "ម៉ូត Zen", "zenMode": "ម៉ូត Zen",
"objectsSnapMode": "",
"exitZenMode": "ចេញពី zen ម៉ូត", "exitZenMode": "ចេញពី zen ម៉ូត",
"cancel": "បោះបង់", "cancel": "បោះបង់",
"clear": "សម្អាត", "clear": "សម្អាត",
"remove": "ដកចេញ", "remove": "ដកចេញ",
"embed": "",
"publishLibrary": "បោះពុម្ពផ្សាយ", "publishLibrary": "បោះពុម្ពផ្សាយ",
"submit": "ដាក់​ស្នើ", "submit": "ដាក់​ស្នើ",
"confirm": "បញ្ជាក់" "confirm": "បញ្ជាក់",
"embeddableInteractionButton": ""
}, },
"alerts": { "alerts": {
"clearReset": "វានឹងសម្អាតបាវទាំងមូល។ តើ​អ្នក​ប្រាកដ​ឬ​អត់?", "clearReset": "វានឹងសម្អាតបាវទាំងមូល។ តើ​អ្នក​ប្រាកដ​ឬ​អត់?",
@@ -196,6 +203,7 @@
"imageInsertError": "មិនអាចបញ្ចូលរូបភាពបានទេ។ សូម​ព្យាយាម​ម្តង​ទៀត​នៅ​ពេល​ក្រោយ……", "imageInsertError": "មិនអាចបញ្ចូលរូបភាពបានទេ។ សូម​ព្យាយាម​ម្តង​ទៀត​នៅ​ពេល​ក្រោយ……",
"fileTooBig": "ឯកសារធំពេក។ ទំហំអតិបរមាដែលអនុញ្ញាតគឺ {{maxSize}}។", "fileTooBig": "ឯកសារធំពេក។ ទំហំអតិបរមាដែលអនុញ្ញាតគឺ {{maxSize}}។",
"svgImageInsertError": "មិនអាចបញ្ចូលរូបភាព SVG បានទេ។ ស្លាក SVG ហាក់ដូចជាមិនត្រឹមត្រូវ។", "svgImageInsertError": "មិនអាចបញ្ចូលរូបភាព SVG បានទេ។ ស្លាក SVG ហាក់ដូចជាមិនត្រឹមត្រូវ។",
"failedToFetchImage": "",
"invalidSVGString": "SVG មិន​ត្រឹមត្រូវ។", "invalidSVGString": "SVG មិន​ត្រឹមត្រូវ។",
"cannotResolveCollabServer": "មិនអាចភ្ជាប់ទៅម៉ាស៊ីនមេសហការផ្ទាល់បានទេ។ សូមផ្ទុកទំព័រឡើងវិញ ហើយព្យាយាមម្តងទៀត។", "cannotResolveCollabServer": "មិនអាចភ្ជាប់ទៅម៉ាស៊ីនមេសហការផ្ទាល់បានទេ។ សូមផ្ទុកទំព័រឡើងវិញ ហើយព្យាយាមម្តងទៀត។",
"importLibraryError": "មិនអាចផ្ទុកបណ្ណាល័យបានទេ។", "importLibraryError": "មិនអាចផ្ទុកបណ្ណាល័យបានទេ។",
@@ -206,6 +214,10 @@
"line2": "វាអាចបណ្តាលឱ្យមានការបំបែក <bold>ធាតុអត្ថបទ</bold> នៅក្នុងគំនូររបស់អ្នក។", "line2": "វាអាចបណ្តាលឱ្យមានការបំបែក <bold>ធាតុអត្ថបទ</bold> នៅក្នុងគំនូររបស់អ្នក។",
"line3": "យើងណែនាំយ៉ាងមុតមាំឱ្យបិទការកំណត់នេះ។ អ្នកអាចអនុវត្តតាម <link>ជំហានទាំងនេះ</link> ដើម្បីបិទការកំណត់នេះ។", "line3": "យើងណែនាំយ៉ាងមុតមាំឱ្យបិទការកំណត់នេះ។ អ្នកអាចអនុវត្តតាម <link>ជំហានទាំងនេះ</link> ដើម្បីបិទការកំណត់នេះ។",
"line4": "ប្រសិនបើការបិទការកំណត់នេះមិនបានជួសជុលការបង្ហាញធាតុអត្ថបទទេ សូមដាក់ <issueLink>issue</issueLink> នៅលើ GitHub ឬរាយការណ៍នៅលើ <discordLink>Discord</discordLink> របស់យើង" "line4": "ប្រសិនបើការបិទការកំណត់នេះមិនបានជួសជុលការបង្ហាញធាតុអត្ថបទទេ សូមដាក់ <issueLink>issue</issueLink> នៅលើ GitHub ឬរាយការណ៍នៅលើ <discordLink>Discord</discordLink> របស់យើង"
},
"libraryElementTypeError": {
"embeddable": "",
"image": ""
} }
}, },
"toolBar": { "toolBar": {
@@ -224,6 +236,8 @@
"link": "បន្ថែម/ធ្វើបច្ចុប្បន្នភាពតំណភ្ជាប់សម្រាប់រូបរាងដែលបានជ្រើសរើស", "link": "បន្ថែម/ធ្វើបច្ចុប្បន្នភាពតំណភ្ជាប់សម្រាប់រូបរាងដែលបានជ្រើសរើស",
"eraser": "ជ័រលុប", "eraser": "ជ័រលុប",
"frame": "", "frame": "",
"embeddable": "",
"laser": "",
"hand": "ដៃ (panning tool)", "hand": "ដៃ (panning tool)",
"extraTools": "" "extraTools": ""
}, },
@@ -237,6 +251,7 @@
"linearElement": "ចុចដើម្បីបង្កើតចំណុចច្រើន អូសដើម្បីបង្កើតបន្ទាត់មួយ", "linearElement": "ចុចដើម្បីបង្កើតចំណុចច្រើន អូសដើម្បីបង្កើតបន្ទាត់មួយ",
"freeDraw": "ចុច​ហើយ​អូស លែង​ពេល​រួចរាល់", "freeDraw": "ចុច​ហើយ​អូស លែង​ពេល​រួចរាល់",
"text": "គន្លឹះ៖ អ្នកក៏អាចបន្ថែមអត្ថបទដោយចុចពីរដងនៅកន្លែងណាមួយដោយប្រើឧបករណ៍ជ្រើសរើស", "text": "គន្លឹះ៖ អ្នកក៏អាចបន្ថែមអត្ថបទដោយចុចពីរដងនៅកន្លែងណាមួយដោយប្រើឧបករណ៍ជ្រើសរើស",
"embeddable": "",
"text_selected": "ចុចពីរដង ឬចុច ENTER ដើម្បីកែសម្រួលអត្ថបទ", "text_selected": "ចុចពីរដង ឬចុច ENTER ដើម្បីកែសម្រួលអត្ថបទ",
"text_editing": "ចុច Escape ឬ CtrlOrCmd +ENTER ដើម្បីបញ្ចប់ការកែសម្រួល", "text_editing": "ចុច Escape ឬ CtrlOrCmd +ENTER ដើម្បីបញ្ចប់ការកែសម្រួល",
"linearElementMulti": "ចុចលើចំណុចចុងក្រោយ ឬចុច Esc/Enter ដើម្បីបញ្ចប់", "linearElementMulti": "ចុចលើចំណុចចុងក្រោយ ឬចុច Esc/Enter ដើម្បីបញ្ចប់",
@@ -252,7 +267,8 @@
"bindTextToElement": "ចុច Enter ដើម្បីបន្ថែមអត្ថបទ", "bindTextToElement": "ចុច Enter ដើម្បីបន្ថែមអត្ថបទ",
"deepBoxSelect": "សង្កត់ CtrlOrCmd ដើម្បីជ្រើសរើសយ៉ាងជ្រៅ និងជៀសវាងការអូស", "deepBoxSelect": "សង្កត់ CtrlOrCmd ដើម្បីជ្រើសរើសយ៉ាងជ្រៅ និងជៀសវាងការអូស",
"eraserRevert": "សង្កត់ Alt ដើម្បីដកការជ្រើសរើសធាតុដែលត្រូវបានសម្គាល់សម្រាប់ការលុប", "eraserRevert": "សង្កត់ Alt ដើម្បីដកការជ្រើសរើសធាតុដែលត្រូវបានសម្គាល់សម្រាប់ការលុប",
"firefox_clipboard_write": "បើកមុខងារនេះដោយកំណត់ទង់ \"dom.events.asyncClipboard.clipboardItem\" ទៅ \"true\" \nដើម្បីផ្លាស់ប្តូរទង់កម្មវិធីរុករកនៅក្នុង Firefox សូមចូលទៅកាន់ទំព័រ \"about:config\"។" "firefox_clipboard_write": "បើកមុខងារនេះដោយកំណត់ទង់ \"dom.events.asyncClipboard.clipboardItem\" ទៅ \"true\" \nដើម្បីផ្លាស់ប្តូរទង់កម្មវិធីរុករកនៅក្នុង Firefox សូមចូលទៅកាន់ទំព័រ \"about:config\"។",
"disableSnapping": ""
}, },
"canvasError": { "canvasError": {
"cannotShowPreview": "មិនអាចបង្ហាញការមើលជាមុនបាន", "cannotShowPreview": "មិនអាចបង្ហាញការមើលជាមុនបាន",
@@ -411,7 +427,9 @@
"fileSavedToFilename": "បានរក្សាទុកនៅក្នុង {filename}", "fileSavedToFilename": "បានរក្សាទុកនៅក្នុង {filename}",
"canvas": "តំបន់គំនូរ", "canvas": "តំបន់គំនូរ",
"selection": "ការជ្រើសរើស", "selection": "ការជ្រើសរើស",
"pasteAsSingleElement": "ប្រើ {{shortcut}} ដើម្បីបិទភ្ជាប់ជាធាតុតែមួយ,\nឬបិទភ្ជាប់ទៅក្នុងកម្មវិធីនិពន្ធអត្ថបទដែលមានស្រាប់" "pasteAsSingleElement": "ប្រើ {{shortcut}} ដើម្បីបិទភ្ជាប់ជាធាតុតែមួយ,\nឬបិទភ្ជាប់ទៅក្នុងកម្មវិធីនិពន្ធអត្ថបទដែលមានស្រាប់",
"unableToEmbed": "",
"unrecognizedLinkFormat": ""
}, },
"colors": { "colors": {
"transparent": "ថ្លាមើលធ្លុះ", "transparent": "ថ្លាមើលធ្លុះ",
@@ -449,5 +467,36 @@
"shades": "ស្រមោល", "shades": "ស្រមោល",
"hexCode": "លេខកូដ hex", "hexCode": "លេខកូដ hex",
"noShades": "មិនមានស្រមោលសម្រាប់ពណ៌នេះទេ" "noShades": "មិនមានស្រមោលសម្រាប់ពណ៌នេះទេ"
},
"overwriteConfirm": {
"action": {
"exportToImage": {
"title": "",
"button": "",
"description": ""
},
"saveToDisk": {
"title": "",
"button": "",
"description": ""
},
"excalidrawPlus": {
"title": "",
"button": "",
"description": ""
}
},
"modal": {
"loadFromFile": {
"title": "",
"button": "",
"description": ""
},
"shareableLink": {
"title": "",
"button": "",
"description": ""
}
}
} }
} }
+54 -5
View File
@@ -109,8 +109,12 @@
"createContainerFromText": "텍스트를 컨테이너에 담기", "createContainerFromText": "텍스트를 컨테이너에 담기",
"link": { "link": {
"edit": "링크 수정하기", "edit": "링크 수정하기",
"editEmbed": "링크 & 임베드 수정하기",
"create": "링크 만들기", "create": "링크 만들기",
"label": "링크" "createEmbed": "링크 & 임베드 만들기",
"label": "링크",
"labelEmbed": "링크 & 임베드",
"empty": "링크를 지정하지 않았습니다"
}, },
"lineEditor": { "lineEditor": {
"edit": "선 수정하기", "edit": "선 수정하기",
@@ -160,13 +164,16 @@
"darkMode": "다크 모드", "darkMode": "다크 모드",
"lightMode": "밝은 모드", "lightMode": "밝은 모드",
"zenMode": "젠 모드", "zenMode": "젠 모드",
"objectsSnapMode": "다른 요소들에 정렬시키기",
"exitZenMode": "젠 모드 종료하기", "exitZenMode": "젠 모드 종료하기",
"cancel": "취소", "cancel": "취소",
"clear": "지우기", "clear": "지우기",
"remove": "삭제", "remove": "삭제",
"embed": "임베딩 토글",
"publishLibrary": "게시하기", "publishLibrary": "게시하기",
"submit": "제출", "submit": "제출",
"confirm": "확인" "confirm": "확인",
"embeddableInteractionButton": "클릭하여 상호작용"
}, },
"alerts": { "alerts": {
"clearReset": "모든 작업 내용이 초기화됩니다. 계속하시겠습니까?", "clearReset": "모든 작업 내용이 초기화됩니다. 계속하시겠습니까?",
@@ -196,6 +203,7 @@
"imageInsertError": "이미지를 삽입할 수 없습니다. 나중에 다시 시도 하십시오", "imageInsertError": "이미지를 삽입할 수 없습니다. 나중에 다시 시도 하십시오",
"fileTooBig": "파일이 너무 큽니다. 최대 크기는 {{maxSize}} 입니다.", "fileTooBig": "파일이 너무 큽니다. 최대 크기는 {{maxSize}} 입니다.",
"svgImageInsertError": "SVG 이미지를 삽입하지 못했습니다. SVG 문법이 유효하지 않은 것 같습니다.", "svgImageInsertError": "SVG 이미지를 삽입하지 못했습니다. SVG 문법이 유효하지 않은 것 같습니다.",
"failedToFetchImage": "이미지를 가져오는데 실패했습니다.",
"invalidSVGString": "유효하지 않은 SVG입니다.", "invalidSVGString": "유효하지 않은 SVG입니다.",
"cannotResolveCollabServer": "협업 서버에 접속하는데 실패했습니다. 페이지를 새로고침하고 다시 시도해보세요.", "cannotResolveCollabServer": "협업 서버에 접속하는데 실패했습니다. 페이지를 새로고침하고 다시 시도해보세요.",
"importLibraryError": "라이브러리를 불러오지 못했습니다.", "importLibraryError": "라이브러리를 불러오지 못했습니다.",
@@ -206,6 +214,10 @@
"line2": "이 기능으로 인해 화이트보드의 <bold>텍스트 요소들</bold>이 손상될 수 있습니다.", "line2": "이 기능으로 인해 화이트보드의 <bold>텍스트 요소들</bold>이 손상될 수 있습니다.",
"line3": "저희는 해당 기능을 비활성화하는 것을 강력히 권장 드립니다. 비활성화 방법에 대해서는 <link>이 게시글</link>을 참고해주세요.", "line3": "저희는 해당 기능을 비활성화하는 것을 강력히 권장 드립니다. 비활성화 방법에 대해서는 <link>이 게시글</link>을 참고해주세요.",
"line4": "만약 이 설정을 껐음에도 텍스트 요소들이 올바르게 표시되지 않는다면, 저희 Github에 <issueLink>이슈</issueLink>를 올려주시거나 <discordLink>Discord</discordLink>로 알려주세요." "line4": "만약 이 설정을 껐음에도 텍스트 요소들이 올바르게 표시되지 않는다면, 저희 Github에 <issueLink>이슈</issueLink>를 올려주시거나 <discordLink>Discord</discordLink>로 알려주세요."
},
"libraryElementTypeError": {
"embeddable": "임베드 요소들은 라이브러리에 추가할 수 없습니다.",
"image": "라이브러리에 이미지 삽입 기능은 곧 지원될 예정입니다!"
} }
}, },
"toolBar": { "toolBar": {
@@ -224,6 +236,8 @@
"link": "선택한 도형에 대해서 링크를 추가/업데이트", "link": "선택한 도형에 대해서 링크를 추가/업데이트",
"eraser": "지우개", "eraser": "지우개",
"frame": "프레임 도구", "frame": "프레임 도구",
"embeddable": "웹 임베드",
"laser": "레이저 포인터",
"hand": "손 (패닝 도구)", "hand": "손 (패닝 도구)",
"extraTools": "다른 도구" "extraTools": "다른 도구"
}, },
@@ -237,6 +251,7 @@
"linearElement": "여러 점을 연결하려면 클릭하고, 직선을 그리려면 바로 드래그하세요.", "linearElement": "여러 점을 연결하려면 클릭하고, 직선을 그리려면 바로 드래그하세요.",
"freeDraw": "클릭 후 드래그하세요. 완료되면 놓으세요.", "freeDraw": "클릭 후 드래그하세요. 완료되면 놓으세요.",
"text": "팁: 선택 툴로 아무 곳이나 더블 클릭해 텍스트를 추가할 수도 있습니다.", "text": "팁: 선택 툴로 아무 곳이나 더블 클릭해 텍스트를 추가할 수도 있습니다.",
"embeddable": "클릭 및 드래그하여 웹사이트 임베드 만들기",
"text_selected": "더블 클릭 또는 ENTER를 눌러서 텍스트 수정", "text_selected": "더블 클릭 또는 ENTER를 눌러서 텍스트 수정",
"text_editing": "ESC나 CtrlOrCmd+ENTER를 눌러서 수정을 종료하기", "text_editing": "ESC나 CtrlOrCmd+ENTER를 눌러서 수정을 종료하기",
"linearElementMulti": "마지막 지점을 클릭하거나 Esc 또는 Enter 키를 눌러 완료하세요.", "linearElementMulti": "마지막 지점을 클릭하거나 Esc 또는 Enter 키를 눌러 완료하세요.",
@@ -252,7 +267,8 @@
"bindTextToElement": "Enter 키를 눌러서 텍스트 추가하기", "bindTextToElement": "Enter 키를 눌러서 텍스트 추가하기",
"deepBoxSelect": "CtrlOrCmd 키를 눌러서 깊게 선택하고, 드래그하지 않도록 하기", "deepBoxSelect": "CtrlOrCmd 키를 눌러서 깊게 선택하고, 드래그하지 않도록 하기",
"eraserRevert": "Alt를 눌러서 삭제하도록 지정된 요소를 되돌리기", "eraserRevert": "Alt를 눌러서 삭제하도록 지정된 요소를 되돌리기",
"firefox_clipboard_write": "이 기능은 설정에서 \"dom.events.asyncClipboard.clipboardItem\" 플래그를 \"true\"로 설정하여 활성화할 수 있습니다. Firefox에서 브라우저 플래그를 수정하려면, \"about:config\" 페이지에 접속하세요." "firefox_clipboard_write": "이 기능은 설정에서 \"dom.events.asyncClipboard.clipboardItem\" 플래그를 \"true\"로 설정하여 활성화할 수 있습니다. Firefox에서 브라우저 플래그를 수정하려면, \"about:config\" 페이지에 접속하세요.",
"disableSnapping": "CtrlOrCmd 키를 눌러서 다른 요소와의 정렬 무시하기"
}, },
"canvasError": { "canvasError": {
"cannotShowPreview": "미리보기를 볼 수 없습니다", "cannotShowPreview": "미리보기를 볼 수 없습니다",
@@ -411,7 +427,9 @@
"fileSavedToFilename": "{filename} 로 저장되었습니다", "fileSavedToFilename": "{filename} 로 저장되었습니다",
"canvas": "캔버스", "canvas": "캔버스",
"selection": "선택한 요소", "selection": "선택한 요소",
"pasteAsSingleElement": "단일 요소로 붙여넣거나, 기존 텍스트 에디터에 붙여넣으려면 {{shortcut}} 을 사용하세요." "pasteAsSingleElement": "단일 요소로 붙여넣거나, 기존 텍스트 에디터에 붙여넣으려면 {{shortcut}} 을 사용하세요.",
"unableToEmbed": "이 URL의 임베딩이 허용되지 않았습니다. GitHub에 이슈를 남겨서 이 URL이 화이트리스트에 등재될 수 있도록 요청하세요",
"unrecognizedLinkFormat": "임베딩하려는 링크의 형식이 잘못된 것 같습니다. 원본 사이트에서 제공하는 \"임베딩\" 텍스트를 그대로 붙여 넣어 주세요"
}, },
"colors": { "colors": {
"transparent": "투명", "transparent": "투명",
@@ -444,10 +462,41 @@
} }
}, },
"colorPicker": { "colorPicker": {
"mostUsedCustomColors": "많이 쓰이는 사용 색상들", "mostUsedCustomColors": "가장 많이 사용 색상들",
"colors": "색상", "colors": "색상",
"shades": "색조", "shades": "색조",
"hexCode": "Hex 코드", "hexCode": "Hex 코드",
"noShades": "사용할 수 있는 색조가 없음" "noShades": "사용할 수 있는 색조가 없음"
},
"overwriteConfirm": {
"action": {
"exportToImage": {
"title": "이미지로 내보내기",
"button": "이미지로 내보내기",
"description": "나중에 다시 불러올 수 있도록 화면 데이터를 이미지로 내보냅니다."
},
"saveToDisk": {
"title": "디스크에 저장",
"button": "디스크에 저장",
"description": "나중에 다시 불러올 수 있도록 화면 데이터를 내보냅니다."
},
"excalidrawPlus": {
"title": "Excalidraw+",
"button": "Excalidraw+로 내보내기",
"description": "화면을 당신의 Excalidraw+ 작업 공간으로 저장합니다."
}
},
"modal": {
"loadFromFile": {
"title": "파일에서 불러오기",
"button": "파일에서 불러오기",
"description": "파일을 불러오면 <bold>현재 작성된 데이터를 덮어쓰게 됩니다</bold>.<br></br>다음 옵션 중 하나를 선택하여 작업물을 백업해 둘 수 있습니다."
},
"shareableLink": {
"title": "주소에서 불러오기",
"button": "컨텐츠를 덮어쓰기",
"description": "외부 작업물을 불러오면 <bold>현재 작성된 데이터를 덮어쓰게 됩니다</bold>.<br></br>다음 옵션 중 하나를 선택하여 작업물을 백업해 둘 수 있습니다."
}
}
} }
} }
+53 -4
View File
@@ -109,8 +109,12 @@
"createContainerFromText": "دەق لە چوارچێوەیەکدا بپێچە", "createContainerFromText": "دەق لە چوارچێوەیەکدا بپێچە",
"link": { "link": {
"edit": "دەستکاریکردنی بەستەر", "edit": "دەستکاریکردنی بەستەر",
"editEmbed": "",
"create": "دروستکردنی بەستەر", "create": "دروستکردنی بەستەر",
"label": "بەستەر" "createEmbed": "",
"label": "بەستەر",
"labelEmbed": "",
"empty": ""
}, },
"lineEditor": { "lineEditor": {
"edit": "دەستکاری کردنی دێڕ", "edit": "دەستکاری کردنی دێڕ",
@@ -160,13 +164,16 @@
"darkMode": "دۆخی تاریک", "darkMode": "دۆخی تاریک",
"lightMode": "دۆخی ڕووناک", "lightMode": "دۆخی ڕووناک",
"zenMode": "دۆخی زێن", "zenMode": "دۆخی زێن",
"objectsSnapMode": "",
"exitZenMode": "بەجێهێشتنی دۆخی زێن", "exitZenMode": "بەجێهێشتنی دۆخی زێن",
"cancel": "هەڵوەشاندنەوە", "cancel": "هەڵوەشاندنەوە",
"clear": "خاوێنکردنەوە", "clear": "خاوێنکردنەوە",
"remove": "لابردن", "remove": "لابردن",
"embed": "",
"publishLibrary": "بڵاوکردنەوە", "publishLibrary": "بڵاوکردنەوە",
"submit": "پێشکەشکردن", "submit": "پێشکەشکردن",
"confirm": "دوپاتکردنەوە" "confirm": "دوپاتکردنەوە",
"embeddableInteractionButton": ""
}, },
"alerts": { "alerts": {
"clearReset": "ئەمە هەموو تابلۆکە خاوێن دەکاتەوە، دڵنیایت؟", "clearReset": "ئەمە هەموو تابلۆکە خاوێن دەکاتەوە، دڵنیایت؟",
@@ -196,6 +203,7 @@
"imageInsertError": "نەیتوانی وێنە داخڵ بکات. دواتر هەوڵ بدە", "imageInsertError": "نەیتوانی وێنە داخڵ بکات. دواتر هەوڵ بدە",
"fileTooBig": "فایلەکە زۆر گەورەیە. زۆرترین قەبارەی ڕێگەپێدراو {{maxSize}}}.", "fileTooBig": "فایلەکە زۆر گەورەیە. زۆرترین قەبارەی ڕێگەپێدراو {{maxSize}}}.",
"svgImageInsertError": "نەیتوانی وێنەی SVG داخڵ بکات. نیشانەی ئێس ڤی جی نادروست دیارە.", "svgImageInsertError": "نەیتوانی وێنەی SVG داخڵ بکات. نیشانەی ئێس ڤی جی نادروست دیارە.",
"failedToFetchImage": "",
"invalidSVGString": "ئێس ڤی جی نادروستە.", "invalidSVGString": "ئێس ڤی جی نادروستە.",
"cannotResolveCollabServer": "ناتوانێت پەیوەندی بکات بە سێرڤەری کۆلاب. تکایە لاپەڕەکە دووبارە باربکەوە و دووبارە هەوڵ بدەوە.", "cannotResolveCollabServer": "ناتوانێت پەیوەندی بکات بە سێرڤەری کۆلاب. تکایە لاپەڕەکە دووبارە باربکەوە و دووبارە هەوڵ بدەوە.",
"importLibraryError": "نەیتوانی کتێبخانە بار بکات", "importLibraryError": "نەیتوانی کتێبخانە بار بکات",
@@ -206,6 +214,10 @@
"line2": "ئەمە ئەکرێ ببێتە هۆی تێکدانی <bold>دانە دەقییەکان</bold> لە وێنەکێشانەکانتدا.", "line2": "ئەمە ئەکرێ ببێتە هۆی تێکدانی <bold>دانە دەقییەکان</bold> لە وێنەکێشانەکانتدا.",
"line3": "ئێمە بە توندی پێشنیاری لەکارخستنی ئەم ڕێکخستنە دەکەین. بۆ لە کارخستنی دەتوانیت بەم <link>هەنگاوانە</link>دا بڕۆیت.", "line3": "ئێمە بە توندی پێشنیاری لەکارخستنی ئەم ڕێکخستنە دەکەین. بۆ لە کارخستنی دەتوانیت بەم <link>هەنگاوانە</link>دا بڕۆیت.",
"line4": "ئەگەر لەکارخستنی ئەم ڕێکخستنە نەبوە هۆی چاککردنەوەی پێشاندانی دانە دەقییەکان، تکایە <issueLink>کێشە</issueLink>یەک بکەرەوە لەسەر گیتهەبەکەمان، یان بۆمان بنوسە لەسەر <discordLink>دیسکۆرد</discordLink>" "line4": "ئەگەر لەکارخستنی ئەم ڕێکخستنە نەبوە هۆی چاککردنەوەی پێشاندانی دانە دەقییەکان، تکایە <issueLink>کێشە</issueLink>یەک بکەرەوە لەسەر گیتهەبەکەمان، یان بۆمان بنوسە لەسەر <discordLink>دیسکۆرد</discordLink>"
},
"libraryElementTypeError": {
"embeddable": "",
"image": ""
} }
}, },
"toolBar": { "toolBar": {
@@ -224,6 +236,8 @@
"link": "زیادکردن/ نوێکردنەوەی لینک بۆ شێوەی دیاریکراو", "link": "زیادکردن/ نوێکردنەوەی لینک بۆ شێوەی دیاریکراو",
"eraser": "سڕەر", "eraser": "سڕەر",
"frame": "ئامرازی چوارچێوە", "frame": "ئامرازی چوارچێوە",
"embeddable": "",
"laser": "",
"hand": "دەست (ئامرازی پانکردن)", "hand": "دەست (ئامرازی پانکردن)",
"extraTools": "ئامرازی زیاتر" "extraTools": "ئامرازی زیاتر"
}, },
@@ -237,6 +251,7 @@
"linearElement": "کرتە بکە بۆ دەستپێکردنی چەند خاڵێک، ڕایبکێشە بۆ یەک هێڵ", "linearElement": "کرتە بکە بۆ دەستپێکردنی چەند خاڵێک، ڕایبکێشە بۆ یەک هێڵ",
"freeDraw": "کرتە بکە و ڕایبکێشە، کاتێک تەواو بوویت دەست هەڵگرە", "freeDraw": "کرتە بکە و ڕایبکێشە، کاتێک تەواو بوویت دەست هەڵگرە",
"text": "زانیاری: هەروەها دەتوانیت دەق زیادبکەیت بە دوو کرتەکردن لە هەر شوێنێک لەگەڵ ئامڕازی دەستنیشانکردن", "text": "زانیاری: هەروەها دەتوانیت دەق زیادبکەیت بە دوو کرتەکردن لە هەر شوێنێک لەگەڵ ئامڕازی دەستنیشانکردن",
"embeddable": "",
"text_selected": "دووجار کلیک بکە یان ENTER بکە بۆ دەستکاریکردنی دەق", "text_selected": "دووجار کلیک بکە یان ENTER بکە بۆ دەستکاریکردنی دەق",
"text_editing": "بۆ تەواوکردنی دەستکاریکردنەکە Escape یان Ctrl/Cmd+ENTER بکە", "text_editing": "بۆ تەواوکردنی دەستکاریکردنەکە Escape یان Ctrl/Cmd+ENTER بکە",
"linearElementMulti": "کلیک لەسەر کۆتا خاڵ بکە یان Escape یان Enter بکە بۆ تەواوکردن", "linearElementMulti": "کلیک لەسەر کۆتا خاڵ بکە یان Escape یان Enter بکە بۆ تەواوکردن",
@@ -252,7 +267,8 @@
"bindTextToElement": "بۆ زیادکردنی دەق enter بکە", "bindTextToElement": "بۆ زیادکردنی دەق enter بکە",
"deepBoxSelect": "CtrlOrCmd ڕابگرە بۆ هەڵبژاردنی قووڵ، و بۆ ڕێگریکردن لە ڕاکێشان", "deepBoxSelect": "CtrlOrCmd ڕابگرە بۆ هەڵبژاردنی قووڵ، و بۆ ڕێگریکردن لە ڕاکێشان",
"eraserRevert": "بۆ گەڕاندنەوەی ئەو توخمانەی کە بۆ سڕینەوە نیشانە کراون، Alt ڕابگرە", "eraserRevert": "بۆ گەڕاندنەوەی ئەو توخمانەی کە بۆ سڕینەوە نیشانە کراون، Alt ڕابگرە",
"firefox_clipboard_write": "ئەم تایبەتمەندییە بە ئەگەرێکی زۆرەوە دەتوانرێت چالاک بکرێت بە ڕێکخستنی ئاڵای \"dom.events.asyncClipboard.clipboardItem\" بۆ \"true\". بۆ گۆڕینی ئاڵاکانی وێبگەڕ لە فایەرفۆکسدا، سەردانی لاپەڕەی \"about:config\" بکە." "firefox_clipboard_write": "ئەم تایبەتمەندییە بە ئەگەرێکی زۆرەوە دەتوانرێت چالاک بکرێت بە ڕێکخستنی ئاڵای \"dom.events.asyncClipboard.clipboardItem\" بۆ \"true\". بۆ گۆڕینی ئاڵاکانی وێبگەڕ لە فایەرفۆکسدا، سەردانی لاپەڕەی \"about:config\" بکە.",
"disableSnapping": ""
}, },
"canvasError": { "canvasError": {
"cannotShowPreview": "ناتوانرێ پێشبینین پیشان بدرێت", "cannotShowPreview": "ناتوانرێ پێشبینین پیشان بدرێت",
@@ -411,7 +427,9 @@
"fileSavedToFilename": "هەڵگیراوە بۆ {filename}", "fileSavedToFilename": "هەڵگیراوە بۆ {filename}",
"canvas": "تابلۆ", "canvas": "تابلۆ",
"selection": "دەستنیشانکراوەکان", "selection": "دەستنیشانکراوەکان",
"pasteAsSingleElement": "بۆ دانانەوە وەکو یەک توخم یان دانانەوە بۆ نێو دەسکاریکەرێکی دەق کە بوونی هەیە {{shortcut}} بەکاربهێنە" "pasteAsSingleElement": "بۆ دانانەوە وەکو یەک توخم یان دانانەوە بۆ نێو دەسکاریکەرێکی دەق کە بوونی هەیە {{shortcut}} بەکاربهێنە",
"unableToEmbed": "",
"unrecognizedLinkFormat": ""
}, },
"colors": { "colors": {
"transparent": "ڕوون", "transparent": "ڕوون",
@@ -449,5 +467,36 @@
"shades": "سێبەرەکان", "shades": "سێبەرەکان",
"hexCode": "کۆدی هێکس", "hexCode": "کۆدی هێکس",
"noShades": "هیچ سێبەرێک بۆ ئەم ڕەنگە بەردەست نییە" "noShades": "هیچ سێبەرێک بۆ ئەم ڕەنگە بەردەست نییە"
},
"overwriteConfirm": {
"action": {
"exportToImage": {
"title": "",
"button": "",
"description": ""
},
"saveToDisk": {
"title": "",
"button": "",
"description": ""
},
"excalidrawPlus": {
"title": "",
"button": "",
"description": ""
}
},
"modal": {
"loadFromFile": {
"title": "",
"button": "",
"description": ""
},
"shareableLink": {
"title": "",
"button": "",
"description": ""
}
}
} }
} }
+53 -4
View File
@@ -109,8 +109,12 @@
"createContainerFromText": "", "createContainerFromText": "",
"link": { "link": {
"edit": "Redeguoti nuorodą", "edit": "Redeguoti nuorodą",
"editEmbed": "",
"create": "Sukurti nuorodą", "create": "Sukurti nuorodą",
"label": "Nuoroda" "createEmbed": "",
"label": "Nuoroda",
"labelEmbed": "",
"empty": ""
}, },
"lineEditor": { "lineEditor": {
"edit": "", "edit": "",
@@ -160,13 +164,16 @@
"darkMode": "Tamsus režimas", "darkMode": "Tamsus režimas",
"lightMode": "Šviesus režimas", "lightMode": "Šviesus režimas",
"zenMode": "„Zen“ režimas", "zenMode": "„Zen“ režimas",
"objectsSnapMode": "",
"exitZenMode": "Išeiti iš „Zen“ režimo", "exitZenMode": "Išeiti iš „Zen“ režimo",
"cancel": "Atšaukti", "cancel": "Atšaukti",
"clear": "Išvalyti", "clear": "Išvalyti",
"remove": "Pašalinti", "remove": "Pašalinti",
"embed": "",
"publishLibrary": "Paskelbti", "publishLibrary": "Paskelbti",
"submit": "Pateikti", "submit": "Pateikti",
"confirm": "Patvirtinti" "confirm": "Patvirtinti",
"embeddableInteractionButton": ""
}, },
"alerts": { "alerts": {
"clearReset": "", "clearReset": "",
@@ -196,6 +203,7 @@
"imageInsertError": "Nepyko įkelti paveiksliuko. Pabandyk vėliau...", "imageInsertError": "Nepyko įkelti paveiksliuko. Pabandyk vėliau...",
"fileTooBig": "Per didelis failas. Didžiausias leidžiamas dydis yra {{maxSize}}.", "fileTooBig": "Per didelis failas. Didžiausias leidžiamas dydis yra {{maxSize}}.",
"svgImageInsertError": "Nepavyko įtraukti SVG paveiksliuko. Panašu, jog SVG yra nevalidus.", "svgImageInsertError": "Nepavyko įtraukti SVG paveiksliuko. Panašu, jog SVG yra nevalidus.",
"failedToFetchImage": "",
"invalidSVGString": "Nevalidus SVG.", "invalidSVGString": "Nevalidus SVG.",
"cannotResolveCollabServer": "Nepavyko prisijungti prie serverio bendradarbiavimui. Perkrauk puslapį ir pabandyk prisijungti dar kartą.", "cannotResolveCollabServer": "Nepavyko prisijungti prie serverio bendradarbiavimui. Perkrauk puslapį ir pabandyk prisijungti dar kartą.",
"importLibraryError": "Nepavyko įkelti bibliotekos", "importLibraryError": "Nepavyko įkelti bibliotekos",
@@ -206,6 +214,10 @@
"line2": "", "line2": "",
"line3": "", "line3": "",
"line4": "" "line4": ""
},
"libraryElementTypeError": {
"embeddable": "",
"image": ""
} }
}, },
"toolBar": { "toolBar": {
@@ -224,6 +236,8 @@
"link": "Pridėti / Atnaujinti pasirinktos figūros nuorodą", "link": "Pridėti / Atnaujinti pasirinktos figūros nuorodą",
"eraser": "Trintukas", "eraser": "Trintukas",
"frame": "", "frame": "",
"embeddable": "",
"laser": "",
"hand": "", "hand": "",
"extraTools": "" "extraTools": ""
}, },
@@ -237,6 +251,7 @@
"linearElement": "Paspaudimai sukurs papildomus taškus, nepertraukiamas tempimas sukurs liniją", "linearElement": "Paspaudimai sukurs papildomus taškus, nepertraukiamas tempimas sukurs liniją",
"freeDraw": "Spausk ir tempk, paleisk kai norėsi pabaigti", "freeDraw": "Spausk ir tempk, paleisk kai norėsi pabaigti",
"text": "Užuomina: tekstą taip pat galima pridėti bet kur su dvigubu pelės paspaudimu, kol parinkas žymėjimo įrankis", "text": "Užuomina: tekstą taip pat galima pridėti bet kur su dvigubu pelės paspaudimu, kol parinkas žymėjimo įrankis",
"embeddable": "",
"text_selected": "", "text_selected": "",
"text_editing": "", "text_editing": "",
"linearElementMulti": "", "linearElementMulti": "",
@@ -252,7 +267,8 @@
"bindTextToElement": "", "bindTextToElement": "",
"deepBoxSelect": "", "deepBoxSelect": "",
"eraserRevert": "", "eraserRevert": "",
"firefox_clipboard_write": "" "firefox_clipboard_write": "",
"disableSnapping": ""
}, },
"canvasError": { "canvasError": {
"cannotShowPreview": "", "cannotShowPreview": "",
@@ -411,7 +427,9 @@
"fileSavedToFilename": "Išsaugota į {filename}", "fileSavedToFilename": "Išsaugota į {filename}",
"canvas": "drobė", "canvas": "drobė",
"selection": "", "selection": "",
"pasteAsSingleElement": "" "pasteAsSingleElement": "",
"unableToEmbed": "",
"unrecognizedLinkFormat": ""
}, },
"colors": { "colors": {
"transparent": "Permatoma", "transparent": "Permatoma",
@@ -449,5 +467,36 @@
"shades": "", "shades": "",
"hexCode": "", "hexCode": "",
"noShades": "" "noShades": ""
},
"overwriteConfirm": {
"action": {
"exportToImage": {
"title": "",
"button": "",
"description": ""
},
"saveToDisk": {
"title": "",
"button": "",
"description": ""
},
"excalidrawPlus": {
"title": "",
"button": "",
"description": ""
}
},
"modal": {
"loadFromFile": {
"title": "",
"button": "",
"description": ""
},
"shareableLink": {
"title": "",
"button": "",
"description": ""
}
}
} }
} }
+53 -4
View File
@@ -109,8 +109,12 @@
"createContainerFromText": "Ietilpināt tekstu figurā", "createContainerFromText": "Ietilpināt tekstu figurā",
"link": { "link": {
"edit": "Rediģēt saiti", "edit": "Rediģēt saiti",
"editEmbed": "",
"create": "Izveidot saiti", "create": "Izveidot saiti",
"label": "Saite" "createEmbed": "",
"label": "Saite",
"labelEmbed": "",
"empty": ""
}, },
"lineEditor": { "lineEditor": {
"edit": "Rediģēt līniju", "edit": "Rediģēt līniju",
@@ -160,13 +164,16 @@
"darkMode": "Tumšais režīms", "darkMode": "Tumšais režīms",
"lightMode": "Gaišais režīms", "lightMode": "Gaišais režīms",
"zenMode": "Zen režīms", "zenMode": "Zen režīms",
"objectsSnapMode": "",
"exitZenMode": "Pamest Zen režīmu", "exitZenMode": "Pamest Zen režīmu",
"cancel": "Atcelt", "cancel": "Atcelt",
"clear": "Notīrīt", "clear": "Notīrīt",
"remove": "Noņemt", "remove": "Noņemt",
"embed": "",
"publishLibrary": "Publicēt", "publishLibrary": "Publicēt",
"submit": "Iesniegt", "submit": "Iesniegt",
"confirm": "Apstiprināt" "confirm": "Apstiprināt",
"embeddableInteractionButton": ""
}, },
"alerts": { "alerts": {
"clearReset": "Šī funkcija notīrīs visu tāfeli. Vai turpināt?", "clearReset": "Šī funkcija notīrīs visu tāfeli. Vai turpināt?",
@@ -196,6 +203,7 @@
"imageInsertError": "Nevarēja ievietot attēlu. Mēģiniet vēlāk...", "imageInsertError": "Nevarēja ievietot attēlu. Mēģiniet vēlāk...",
"fileTooBig": "Datne ir par lielu. Lielākais atļautais izmērs ir {{maxSize}}.", "fileTooBig": "Datne ir par lielu. Lielākais atļautais izmērs ir {{maxSize}}.",
"svgImageInsertError": "Nevarēja ievietot SVG attēlu. Šķiet, ka SVG marķējums nav derīgs.", "svgImageInsertError": "Nevarēja ievietot SVG attēlu. Šķiet, ka SVG marķējums nav derīgs.",
"failedToFetchImage": "",
"invalidSVGString": "Nederīgs SVG.", "invalidSVGString": "Nederīgs SVG.",
"cannotResolveCollabServer": "Nevarēja savienoties ar sadarbošanās serveri. Lūdzu, pārlādējiet lapu un mēģiniet vēlreiz.", "cannotResolveCollabServer": "Nevarēja savienoties ar sadarbošanās serveri. Lūdzu, pārlādējiet lapu un mēģiniet vēlreiz.",
"importLibraryError": "Nevarēja ielādēt bibliotēku", "importLibraryError": "Nevarēja ielādēt bibliotēku",
@@ -206,6 +214,10 @@
"line2": "", "line2": "",
"line3": "", "line3": "",
"line4": "" "line4": ""
},
"libraryElementTypeError": {
"embeddable": "",
"image": ""
} }
}, },
"toolBar": { "toolBar": {
@@ -224,6 +236,8 @@
"link": "Pievienot/rediģēt atlasītās figūras saiti", "link": "Pievienot/rediģēt atlasītās figūras saiti",
"eraser": "Dzēšgumija", "eraser": "Dzēšgumija",
"frame": "", "frame": "",
"embeddable": "",
"laser": "",
"hand": "Roka (panoramēšanas rīks)", "hand": "Roka (panoramēšanas rīks)",
"extraTools": "" "extraTools": ""
}, },
@@ -237,6 +251,7 @@
"linearElement": "Klikšķiniet, lai sāktu zīmēt vairākus punktus; velciet, lai zīmētu līniju", "linearElement": "Klikšķiniet, lai sāktu zīmēt vairākus punktus; velciet, lai zīmētu līniju",
"freeDraw": "Spiediet un velciet; atlaidiet, kad pabeidzat", "freeDraw": "Spiediet un velciet; atlaidiet, kad pabeidzat",
"text": "Ieteikums: lai pievienotu tekstu, varat arī jebkur dubultklikšķināt ar atlases rīku", "text": "Ieteikums: lai pievienotu tekstu, varat arī jebkur dubultklikšķināt ar atlases rīku",
"embeddable": "",
"text_selected": "Dubultklikšķiniet vai spiediet ievades taustiņu, lai rediģētu tekstu", "text_selected": "Dubultklikšķiniet vai spiediet ievades taustiņu, lai rediģētu tekstu",
"text_editing": "Spiediet iziešanas taustiņu vai CtrlOrCmd+ENTER, lai beigtu rediģēt", "text_editing": "Spiediet iziešanas taustiņu vai CtrlOrCmd+ENTER, lai beigtu rediģēt",
"linearElementMulti": "Klikšķiniet uz pēdējā punkta vai spiediet izejas vai ievades taustiņu, lai pabeigtu", "linearElementMulti": "Klikšķiniet uz pēdējā punkta vai spiediet izejas vai ievades taustiņu, lai pabeigtu",
@@ -252,7 +267,8 @@
"bindTextToElement": "Spiediet ievades taustiņu, lai pievienotu tekstu", "bindTextToElement": "Spiediet ievades taustiņu, lai pievienotu tekstu",
"deepBoxSelect": "Turient nospiestu Ctrl vai Cmd, lai atlasītu dziļumā un lai nepieļautu objektu pavilkšanu", "deepBoxSelect": "Turient nospiestu Ctrl vai Cmd, lai atlasītu dziļumā un lai nepieļautu objektu pavilkšanu",
"eraserRevert": "Turiet Alt, lai noņemtu elementus no dzēsšanas atlases", "eraserRevert": "Turiet Alt, lai noņemtu elementus no dzēsšanas atlases",
"firefox_clipboard_write": "Šis iestatījums var tikt ieslēgts ar \"dom.events.asyncClipboard.clipboardItem\" marķieri pārslēgtu uz \"true\". Lai mainītu pārlūka marķierus Firefox, apmeklē \"about:config\" lapu." "firefox_clipboard_write": "Šis iestatījums var tikt ieslēgts ar \"dom.events.asyncClipboard.clipboardItem\" marķieri pārslēgtu uz \"true\". Lai mainītu pārlūka marķierus Firefox, apmeklē \"about:config\" lapu.",
"disableSnapping": ""
}, },
"canvasError": { "canvasError": {
"cannotShowPreview": "Nevar rādīt priekšskatījumu", "cannotShowPreview": "Nevar rādīt priekšskatījumu",
@@ -411,7 +427,9 @@
"fileSavedToFilename": "Saglabāts kā {filename}", "fileSavedToFilename": "Saglabāts kā {filename}",
"canvas": "tāfeli", "canvas": "tāfeli",
"selection": "atlasi", "selection": "atlasi",
"pasteAsSingleElement": "Izmantojiet {{shortcut}}, lai ielīmētu kā jaunu elementu, vai ielīmētu esošā teksta lauciņā" "pasteAsSingleElement": "Izmantojiet {{shortcut}}, lai ielīmētu kā jaunu elementu, vai ielīmētu esošā teksta lauciņā",
"unableToEmbed": "",
"unrecognizedLinkFormat": ""
}, },
"colors": { "colors": {
"transparent": "Caurspīdīgs", "transparent": "Caurspīdīgs",
@@ -449,5 +467,36 @@
"shades": "", "shades": "",
"hexCode": "", "hexCode": "",
"noShades": "" "noShades": ""
},
"overwriteConfirm": {
"action": {
"exportToImage": {
"title": "",
"button": "",
"description": ""
},
"saveToDisk": {
"title": "",
"button": "",
"description": ""
},
"excalidrawPlus": {
"title": "",
"button": "",
"description": ""
}
},
"modal": {
"loadFromFile": {
"title": "",
"button": "",
"description": ""
},
"shareableLink": {
"title": "",
"button": "",
"description": ""
}
}
} }
} }
+53 -4
View File
@@ -109,8 +109,12 @@
"createContainerFromText": "मजकूर कंटेनर मधे मोडून दाखवा", "createContainerFromText": "मजकूर कंटेनर मधे मोडून दाखवा",
"link": { "link": {
"edit": "दुवा संपादन", "edit": "दुवा संपादन",
"editEmbed": "",
"create": "दुवा तयार करा", "create": "दुवा तयार करा",
"label": "दुवा" "createEmbed": "",
"label": "दुवा",
"labelEmbed": "",
"empty": ""
}, },
"lineEditor": { "lineEditor": {
"edit": "रेघ संपादन", "edit": "रेघ संपादन",
@@ -160,13 +164,16 @@
"darkMode": "अंधार स्थिथि", "darkMode": "अंधार स्थिथि",
"lightMode": "उजेड स्थिति", "lightMode": "उजेड स्थिति",
"zenMode": "ध्यानग्र स्थिति", "zenMode": "ध्यानग्र स्थिति",
"objectsSnapMode": "वस्तूंपासून पकड़ा",
"exitZenMode": "ध्यानग्र स्थितितून बाहेर", "exitZenMode": "ध्यानग्र स्थितितून बाहेर",
"cancel": "रद्द", "cancel": "रद्द",
"clear": "स्वछ", "clear": "स्वछ",
"remove": "हटवा", "remove": "हटवा",
"embed": "",
"publishLibrary": "प्रकाशित करा", "publishLibrary": "प्रकाशित करा",
"submit": "जमा करा", "submit": "जमा करा",
"confirm": "पुष्टि करा" "confirm": "पुष्टि करा",
"embeddableInteractionButton": ""
}, },
"alerts": { "alerts": {
"clearReset": "पटल स्वच्छ होणार, तुम्हाला खात्री आहे का?", "clearReset": "पटल स्वच्छ होणार, तुम्हाला खात्री आहे का?",
@@ -196,6 +203,7 @@
"imageInsertError": "प्रतिमा आत घालता येत नाही. नंतर पुन्हा प्रयत्न करा...", "imageInsertError": "प्रतिमा आत घालता येत नाही. नंतर पुन्हा प्रयत्न करा...",
"fileTooBig": "फाइल फार मोठी आहे. आकाराची कमाल परवानगी {{maxSize}} आहे.", "fileTooBig": "फाइल फार मोठी आहे. आकाराची कमाल परवानगी {{maxSize}} आहे.",
"svgImageInsertError": "एस-वी-जी प्रतिमा आत घालवू शकलो नाही. एस-वी-जी-मार्क-अप यंत्र अयोग्य आहे.", "svgImageInsertError": "एस-वी-जी प्रतिमा आत घालवू शकलो नाही. एस-वी-जी-मार्क-अप यंत्र अयोग्य आहे.",
"failedToFetchImage": "",
"invalidSVGString": "अयोग्य एस-वी-जी.", "invalidSVGString": "अयोग्य एस-वी-जी.",
"cannotResolveCollabServer": "कॉलेब-सर्वर हे पोहोचत नाही आहे. पान परत लोड करायचा प्रयत्न करावे.", "cannotResolveCollabServer": "कॉलेब-सर्वर हे पोहोचत नाही आहे. पान परत लोड करायचा प्रयत्न करावे.",
"importLibraryError": "संग्रह प्रतिस्थापित नाही करता आला", "importLibraryError": "संग्रह प्रतिस्थापित नाही करता आला",
@@ -206,6 +214,10 @@
"line2": "हे तुमच्या चित्रांच्या <bold>पाठ तत्वांनां </bold> खंडित करू शकतात.", "line2": "हे तुमच्या चित्रांच्या <bold>पाठ तत्वांनां </bold> खंडित करू शकतात.",
"line3": "तुम्हाला आमच्या कड़ून खूप आग्रह आहे की हे सेटिंग्स मधले चयन नका करु. <link>हे अनुक्रम </link> हे कसे करावे हे दाखवु शकते.", "line3": "तुम्हाला आमच्या कड़ून खूप आग्रह आहे की हे सेटिंग्स मधले चयन नका करु. <link>हे अनुक्रम </link> हे कसे करावे हे दाखवु शकते.",
"line4": "ही सेटिंग अक्षम करूनही पृष्ठ योग्यरित्या प्रदर्शित होत नसल्यास, आमच्या GitHub वर <issueLink>समस्या</issueLink> सबमिट करा, किव्हा <discordLink>डिस्कॉर्ड</discordLink> वर आम्हाला लिहा" "line4": "ही सेटिंग अक्षम करूनही पृष्ठ योग्यरित्या प्रदर्शित होत नसल्यास, आमच्या GitHub वर <issueLink>समस्या</issueLink> सबमिट करा, किव्हा <discordLink>डिस्कॉर्ड</discordLink> वर आम्हाला लिहा"
},
"libraryElementTypeError": {
"embeddable": "",
"image": ""
} }
}, },
"toolBar": { "toolBar": {
@@ -224,6 +236,8 @@
"link": "निवडलेल्या आकारासाठी दुवा जोडा/बदल करा", "link": "निवडलेल्या आकारासाठी दुवा जोडा/बदल करा",
"eraser": "खोड रबर", "eraser": "खोड रबर",
"frame": "", "frame": "",
"embeddable": "",
"laser": "लेसर टॉर्च",
"hand": "हात ( सरकवण्या चे उपकरण)", "hand": "हात ( सरकवण्या चे उपकरण)",
"extraTools": "" "extraTools": ""
}, },
@@ -237,6 +251,7 @@
"linearElement": "अनेक बिंदु साठी क्लिक करा, रेघे साठी ड्रैग करा", "linearElement": "अनेक बिंदु साठी क्लिक करा, रेघे साठी ड्रैग करा",
"freeDraw": "क्लिक आणि ड्रैग करा, झालं तेव्हा सोडा", "freeDraw": "क्लिक आणि ड्रैग करा, झालं तेव्हा सोडा",
"text": "टीप: तुम्हीं निवड यंत्रानी कोठेही दुहेरी क्लिक करून टेक्स्ट जोडू शकता", "text": "टीप: तुम्हीं निवड यंत्रानी कोठेही दुहेरी क्लिक करून टेक्स्ट जोडू शकता",
"embeddable": "",
"text_selected": "लेखन संपादन साठी दुहेरी क्लिक करा किव्हा एंटर दाबा", "text_selected": "लेखन संपादन साठी दुहेरी क्लिक करा किव्हा एंटर दाबा",
"text_editing": "संपादन संपवायचं असल्यास एस्केप दाबा किव्हा कंट्रोल या कम्मांड बरोबार एंटर दाबा", "text_editing": "संपादन संपवायचं असल्यास एस्केप दाबा किव्हा कंट्रोल या कम्मांड बरोबार एंटर दाबा",
"linearElementMulti": "शेवटच्या बिंदु वर क्लिक करा किव्हा एस्केप या एंटर दाबा", "linearElementMulti": "शेवटच्या बिंदु वर क्लिक करा किव्हा एस्केप या एंटर दाबा",
@@ -252,7 +267,8 @@
"bindTextToElement": "मजकूर जोडण्यासाठी एंटर की दाबा", "bindTextToElement": "मजकूर जोडण्यासाठी एंटर की दाबा",
"deepBoxSelect": "खोल निवड ह्या साठी कंट्रोल किव्हा कमांड दाबून ठेवा, आणि बाहेर खेचणे वाचवण्या साठी पण", "deepBoxSelect": "खोल निवड ह्या साठी कंट्रोल किव्हा कमांड दाबून ठेवा, आणि बाहेर खेचणे वाचवण्या साठी पण",
"eraserRevert": "खोडण्या साठी घेतलेल्या वस्तु ना घेण्या साठी Alt दाबून ठेवावे", "eraserRevert": "खोडण्या साठी घेतलेल्या वस्तु ना घेण्या साठी Alt दाबून ठेवावे",
"firefox_clipboard_write": "हे वैशिष्ट्य \"dom.events.asyncClipboard.clipboardItem\" फ्लॅग \"सत्य\" वर सेट करून शक्यतो सक्षम केले जाऊ शकते. Firefox मध्ये ब्राउझर फ्लॅग बदलण्यासाठी, \"about:config\" पृष्ठावर जा." "firefox_clipboard_write": "हे वैशिष्ट्य \"dom.events.asyncClipboard.clipboardItem\" फ्लॅग \"सत्य\" वर सेट करून शक्यतो सक्षम केले जाऊ शकते. Firefox मध्ये ब्राउझर फ्लॅग बदलण्यासाठी, \"about:config\" पृष्ठावर जा.",
"disableSnapping": "स्नैपिंग अक्षम करण्या साठी CtrlOrCmd दाबून ठेवा"
}, },
"canvasError": { "canvasError": {
"cannotShowPreview": "पूर्वावलोकन दाखवू शकत नाही", "cannotShowPreview": "पूर्वावलोकन दाखवू शकत नाही",
@@ -411,7 +427,9 @@
"fileSavedToFilename": "{filename} मधे जतन झाली", "fileSavedToFilename": "{filename} मधे जतन झाली",
"canvas": "पटल", "canvas": "पटल",
"selection": "निवड", "selection": "निवड",
"pasteAsSingleElement": "एक घटक म्हणून चिपकावण्या साठी {{shortcut}} वापरा,\nकिंवा विद्यमान मजकूर संपादकात चिपकवा" "pasteAsSingleElement": "एक घटक म्हणून चिपकावण्या साठी {{shortcut}} वापरा,\nकिंवा विद्यमान मजकूर संपादकात चिपकवा",
"unableToEmbed": "",
"unrecognizedLinkFormat": ""
}, },
"colors": { "colors": {
"transparent": "पारदर्शक", "transparent": "पारदर्शक",
@@ -449,5 +467,36 @@
"shades": "रंगछटा", "shades": "रंगछटा",
"hexCode": "हेक्स कोड", "hexCode": "हेक्स कोड",
"noShades": "ह्या रंगाच्या छटा उपलब्ध नाहित" "noShades": "ह्या रंगाच्या छटा उपलब्ध नाहित"
},
"overwriteConfirm": {
"action": {
"exportToImage": {
"title": "छवि स्वरूपे निर्यात करा",
"button": "छवि स्वरूपे निर्यात करा",
"description": "सीन डेटा बाहेर एक फ़ाइल मधे जतन करा, त्या फ़ाइल मधुन तो डेटा नंतर परत आणु शकता."
},
"saveToDisk": {
"title": "डिस्क मधे जतन करा",
"button": "डिस्क मधे जतन करा",
"description": "सीन डेटा बाहेर एक फ़ाइल मधे जतन करा, त्या फ़ाइल मधुन तो डेटा नंतर परत आणु शकता."
},
"excalidrawPlus": {
"title": "एक्षकालीड्रॉ +",
"button": "एक्षकाली ड्रॉ+ मधे निर्यात करा",
"description": "दृष्य तुमच्या एक्षकालीड्रॉ+ चा कार्यस्थल मधे जतन करा."
}
},
"modal": {
"loadFromFile": {
"title": "फ़ाइल मधुन लोड करा",
"button": "फ़ाइल मधुन लोड करा",
"description": "फ़ाइल मधुन लोड केल्या वर ते <bold>तुमचा सध्याचा कामा ठिकाणि एईल </bold><br></br> तुम्हीं तुमचं चित्र एकाधं खाली दिलेलं विकल्प निवडुन पहले सुरक्षीत करु शकता."
},
"shareableLink": {
"title": "लिंक पासून लोड करा",
"button": "माझ सध्याचे कार्य बदला",
"description": "बाहरी चित्र लोड केल्या वर ते <bold>तुमचा सध्याचा कामा ठिकाणि एईल </bold><br></br> तुम्हीं तुमचं चित्र एकाधं खाली दिलेलं विकल्प निवडुन पहले सुरक्षीत करु शकता."
}
}
} }
} }
+53 -4
View File
@@ -109,8 +109,12 @@
"createContainerFromText": "", "createContainerFromText": "",
"link": { "link": {
"edit": "", "edit": "",
"editEmbed": "",
"create": "", "create": "",
"label": "" "createEmbed": "",
"label": "",
"labelEmbed": "",
"empty": ""
}, },
"lineEditor": { "lineEditor": {
"edit": "", "edit": "",
@@ -160,13 +164,16 @@
"darkMode": "", "darkMode": "",
"lightMode": "", "lightMode": "",
"zenMode": "", "zenMode": "",
"objectsSnapMode": "",
"exitZenMode": "ဇင်မြင်ကွင်းမှထွက်", "exitZenMode": "ဇင်မြင်ကွင်းမှထွက်",
"cancel": "", "cancel": "",
"clear": "", "clear": "",
"remove": "", "remove": "",
"embed": "",
"publishLibrary": "", "publishLibrary": "",
"submit": "", "submit": "",
"confirm": "" "confirm": "",
"embeddableInteractionButton": ""
}, },
"alerts": { "alerts": {
"clearReset": "ကားချပ်တစ်ခုလုံးရှင်းလင်းပါတော့မည်။ အတည်ပြုပါ။", "clearReset": "ကားချပ်တစ်ခုလုံးရှင်းလင်းပါတော့မည်။ အတည်ပြုပါ။",
@@ -196,6 +203,7 @@
"imageInsertError": "", "imageInsertError": "",
"fileTooBig": "", "fileTooBig": "",
"svgImageInsertError": "", "svgImageInsertError": "",
"failedToFetchImage": "",
"invalidSVGString": "", "invalidSVGString": "",
"cannotResolveCollabServer": "", "cannotResolveCollabServer": "",
"importLibraryError": "", "importLibraryError": "",
@@ -206,6 +214,10 @@
"line2": "", "line2": "",
"line3": "", "line3": "",
"line4": "" "line4": ""
},
"libraryElementTypeError": {
"embeddable": "",
"image": ""
} }
}, },
"toolBar": { "toolBar": {
@@ -224,6 +236,8 @@
"link": "", "link": "",
"eraser": "", "eraser": "",
"frame": "", "frame": "",
"embeddable": "",
"laser": "",
"hand": "", "hand": "",
"extraTools": "" "extraTools": ""
}, },
@@ -237,6 +251,7 @@
"linearElement": "အမှတ်များချမှတ်ရေးဆွဲရန်ကလစ်နှိပ်ပါ၊ မျဉ်းတစ်ကြောင်းတည်းအတွက် တရွတ်ဆွဲပါ။", "linearElement": "အမှတ်များချမှတ်ရေးဆွဲရန်ကလစ်နှိပ်ပါ၊ မျဉ်းတစ်ကြောင်းတည်းအတွက် တရွတ်ဆွဲပါ။",
"freeDraw": "ကလစ်နှိပ်၍ တရွတ်ဆွဲပါ၊ ပြီးလျှင်လွှတ်ပါ။", "freeDraw": "ကလစ်နှိပ်၍ တရွတ်ဆွဲပါ၊ ပြီးလျှင်လွှတ်ပါ။",
"text": "မှတ်ချက်။ ။မည်သည့်ကိရိယာရွေးထားသည်ဖြစ်စေ ကလစ်နှစ်ချက်နှိပ်၍စာသားထည့်နိုင်သည်", "text": "မှတ်ချက်။ ။မည်သည့်ကိရိယာရွေးထားသည်ဖြစ်စေ ကလစ်နှစ်ချက်နှိပ်၍စာသားထည့်နိုင်သည်",
"embeddable": "",
"text_selected": "", "text_selected": "",
"text_editing": "", "text_editing": "",
"linearElementMulti": "နောက်ဆုံးအမှတ်ပေါ်တွင်ကလစ်နှိပ်ခြင်း၊ Escape (သို့) Enter နှိပ်ခြင်းတို့ဖြင့်အဆုံးသတ်နိုင်", "linearElementMulti": "နောက်ဆုံးအမှတ်ပေါ်တွင်ကလစ်နှိပ်ခြင်း၊ Escape (သို့) Enter နှိပ်ခြင်းတို့ဖြင့်အဆုံးသတ်နိုင်",
@@ -252,7 +267,8 @@
"bindTextToElement": "", "bindTextToElement": "",
"deepBoxSelect": "", "deepBoxSelect": "",
"eraserRevert": "", "eraserRevert": "",
"firefox_clipboard_write": "" "firefox_clipboard_write": "",
"disableSnapping": ""
}, },
"canvasError": { "canvasError": {
"cannotShowPreview": "နမူနာမပြသနိုင်ပါ", "cannotShowPreview": "နမူနာမပြသနိုင်ပါ",
@@ -411,7 +427,9 @@
"fileSavedToFilename": "", "fileSavedToFilename": "",
"canvas": "", "canvas": "",
"selection": "", "selection": "",
"pasteAsSingleElement": "" "pasteAsSingleElement": "",
"unableToEmbed": "",
"unrecognizedLinkFormat": ""
}, },
"colors": { "colors": {
"transparent": "", "transparent": "",
@@ -449,5 +467,36 @@
"shades": "", "shades": "",
"hexCode": "", "hexCode": "",
"noShades": "" "noShades": ""
},
"overwriteConfirm": {
"action": {
"exportToImage": {
"title": "",
"button": "",
"description": ""
},
"saveToDisk": {
"title": "",
"button": "",
"description": ""
},
"excalidrawPlus": {
"title": "",
"button": "",
"description": ""
}
},
"modal": {
"loadFromFile": {
"title": "",
"button": "",
"description": ""
},
"shareableLink": {
"title": "",
"button": "",
"description": ""
}
}
} }
} }
+53 -4
View File
@@ -109,8 +109,12 @@
"createContainerFromText": "La tekst flyte i en beholder", "createContainerFromText": "La tekst flyte i en beholder",
"link": { "link": {
"edit": "Rediger lenke", "edit": "Rediger lenke",
"editEmbed": "Rediger lenke og bygg inn",
"create": "Opprett lenke", "create": "Opprett lenke",
"label": "Lenke" "createEmbed": "Opprett lenke og bygg inn",
"label": "Lenke",
"labelEmbed": "Lenk & bygg inn",
"empty": "Ingen lenke er valgt"
}, },
"lineEditor": { "lineEditor": {
"edit": "Rediger linje", "edit": "Rediger linje",
@@ -160,13 +164,16 @@
"darkMode": "Mørk modus", "darkMode": "Mørk modus",
"lightMode": "Lys modus", "lightMode": "Lys modus",
"zenMode": "Zen-modus", "zenMode": "Zen-modus",
"objectsSnapMode": "",
"exitZenMode": "Avslutt zen-modus", "exitZenMode": "Avslutt zen-modus",
"cancel": "Avbryt", "cancel": "Avbryt",
"clear": "Tøm", "clear": "Tøm",
"remove": "Fjern", "remove": "Fjern",
"embed": "Slå av/på innebygging",
"publishLibrary": "Publiser", "publishLibrary": "Publiser",
"submit": "Send inn", "submit": "Send inn",
"confirm": "Bekreft" "confirm": "Bekreft",
"embeddableInteractionButton": "Klikk for å samhandle"
}, },
"alerts": { "alerts": {
"clearReset": "Dette vil tømme lerretet. Er du sikker?", "clearReset": "Dette vil tømme lerretet. Er du sikker?",
@@ -196,6 +203,7 @@
"imageInsertError": "Kunne ikke sette inn bildet. Prøv igjen senere...", "imageInsertError": "Kunne ikke sette inn bildet. Prøv igjen senere...",
"fileTooBig": "Filen er for stor. Maksimal tillatt størrelse er {{maxSize}}.", "fileTooBig": "Filen er for stor. Maksimal tillatt størrelse er {{maxSize}}.",
"svgImageInsertError": "Kunne ikke sette inn SVG-bilde. SVG-koden ser ugyldig ut.", "svgImageInsertError": "Kunne ikke sette inn SVG-bilde. SVG-koden ser ugyldig ut.",
"failedToFetchImage": "",
"invalidSVGString": "Ugyldig SVG.", "invalidSVGString": "Ugyldig SVG.",
"cannotResolveCollabServer": "Kunne ikke koble til samarbeidsserveren. Vennligst oppdater siden og prøv på nytt.", "cannotResolveCollabServer": "Kunne ikke koble til samarbeidsserveren. Vennligst oppdater siden og prøv på nytt.",
"importLibraryError": "Kunne ikke laste bibliotek", "importLibraryError": "Kunne ikke laste bibliotek",
@@ -206,6 +214,10 @@
"line2": "Dette kan resultere i å bryte <bold>tekst-elementene</bold> i tegningene.", "line2": "Dette kan resultere i å bryte <bold>tekst-elementene</bold> i tegningene.",
"line3": "Vi anbefaler på det sterkeste å deaktivere denne innstillingen. Du kan følge <link>disse trinnene</link> om hvordan du gjør det.", "line3": "Vi anbefaler på det sterkeste å deaktivere denne innstillingen. Du kan følge <link>disse trinnene</link> om hvordan du gjør det.",
"line4": "Hvis deaktivering av denne innstillingen ikke fikser visningen av tekstelementer, vennligst åpne en <issueLink>sak</issueLink> på vår GitHub, eller skriv oss på <discordLink>Discord</discordLink>" "line4": "Hvis deaktivering av denne innstillingen ikke fikser visningen av tekstelementer, vennligst åpne en <issueLink>sak</issueLink> på vår GitHub, eller skriv oss på <discordLink>Discord</discordLink>"
},
"libraryElementTypeError": {
"embeddable": "Innebygde elementer kan ikke legges til i biblioteket.",
"image": "Støtte for å legge til bilder i biblioteket kommer snart!"
} }
}, },
"toolBar": { "toolBar": {
@@ -224,6 +236,8 @@
"link": "Legg til / oppdater link for en valgt figur", "link": "Legg til / oppdater link for en valgt figur",
"eraser": "Viskelær", "eraser": "Viskelær",
"frame": "Rammeverktøy", "frame": "Rammeverktøy",
"embeddable": "Nettinnbygging",
"laser": "",
"hand": "Hånd (panoreringsverktøy)", "hand": "Hånd (panoreringsverktøy)",
"extraTools": "Flere verktøy" "extraTools": "Flere verktøy"
}, },
@@ -237,6 +251,7 @@
"linearElement": "Klikk for å starte linje med flere punkter, eller dra for en enkel linje", "linearElement": "Klikk for å starte linje med flere punkter, eller dra for en enkel linje",
"freeDraw": "Klikk og dra, slipp når du er ferdig", "freeDraw": "Klikk og dra, slipp når du er ferdig",
"text": "Tips: du kan også legge til tekst ved å dobbeltklikke hvor som helst med utvalgsverktøyet", "text": "Tips: du kan også legge til tekst ved å dobbeltklikke hvor som helst med utvalgsverktøyet",
"embeddable": "Klikk og dra for å opprette en nettside innebygd",
"text_selected": "Dobbeltklikk eller trykk ENTER for å redigere tekst", "text_selected": "Dobbeltklikk eller trykk ENTER for å redigere tekst",
"text_editing": "Trykk Escape eller Ctrl/Cmd+Enter for å fullføre redigering", "text_editing": "Trykk Escape eller Ctrl/Cmd+Enter for å fullføre redigering",
"linearElementMulti": "Klikk på siste punkt eller trykk Escape eller Enter for å fullføre", "linearElementMulti": "Klikk på siste punkt eller trykk Escape eller Enter for å fullføre",
@@ -252,7 +267,8 @@
"bindTextToElement": "Trykk Enter for å legge til tekst", "bindTextToElement": "Trykk Enter for å legge til tekst",
"deepBoxSelect": "Hold CTRL/CMD for å markere dypt og forhindre flytting", "deepBoxSelect": "Hold CTRL/CMD for å markere dypt og forhindre flytting",
"eraserRevert": "Hold Alt for å reversere elementene merket for sletting", "eraserRevert": "Hold Alt for å reversere elementene merket for sletting",
"firefox_clipboard_write": "Denne funksjonen kan sannsynligvis aktiveres ved å sette \"dom.events.asyncClipboard.clipboardItem\" flagget til \"true\". For å endre nettleserens flagg i Firefox, besøk \"about:config\"-siden." "firefox_clipboard_write": "Denne funksjonen kan sannsynligvis aktiveres ved å sette \"dom.events.asyncClipboard.clipboardItem\" flagget til \"true\". For å endre nettleserens flagg i Firefox, besøk \"about:config\"-siden.",
"disableSnapping": ""
}, },
"canvasError": { "canvasError": {
"cannotShowPreview": "Kan ikke vise forhåndsvisning", "cannotShowPreview": "Kan ikke vise forhåndsvisning",
@@ -411,7 +427,9 @@
"fileSavedToFilename": "Lagret til {filename}", "fileSavedToFilename": "Lagret til {filename}",
"canvas": "lerret", "canvas": "lerret",
"selection": "utvalg", "selection": "utvalg",
"pasteAsSingleElement": "Bruk {{shortcut}} for å lime inn som ett enkelt element,\neller lim inn i en eksisterende tekstbehandler" "pasteAsSingleElement": "Bruk {{shortcut}} for å lime inn som ett enkelt element,\neller lim inn i en eksisterende tekstbehandler",
"unableToEmbed": "Innbygging av denne nettadressen er ikke tillatt. Oppret en sak på GitHub for å be om url-hvitelisting",
"unrecognizedLinkFormat": "Linken du bygget inn samsvarer ikke med det forventede formatet. Prøv å lime inn \"bygg inn\"-strengen fra kildesiden"
}, },
"colors": { "colors": {
"transparent": "Gjennomsiktig", "transparent": "Gjennomsiktig",
@@ -449,5 +467,36 @@
"shades": "Toner", "shades": "Toner",
"hexCode": "Heksadesimal kode", "hexCode": "Heksadesimal kode",
"noShades": "Ingen toner tilgjengelig for denne fargen" "noShades": "Ingen toner tilgjengelig for denne fargen"
},
"overwriteConfirm": {
"action": {
"exportToImage": {
"title": "Eksporter som bilde",
"button": "Eksporter som bilde",
"description": "Eksporter scene-dataene til en fil som du kan importere fra senere."
},
"saveToDisk": {
"title": "Lagre til disk",
"button": "Lagre til disk",
"description": "Eksporter scene-dataene til en fil som du kan importere fra senere."
},
"excalidrawPlus": {
"title": "Excalidraw+",
"button": "Eksporter til Excalidraw+",
"description": "Lagre scenen til ditt Excalidraw+-arbeidsområde."
}
},
"modal": {
"loadFromFile": {
"title": "Last inn fra fil",
"button": "Last inn fra fil",
"description": "Å laste fra en fil vil <bold>erstatte ditt eksisterende innhold</bold>.<br></br>Du kan sikkerhetskopiere tegningen din først ved å bruke en av valgene under."
},
"shareableLink": {
"title": "Last inn fra lenke",
"button": "Erstatt innholdet mitt",
"description": "Lasting av ekstern tegning vil <bold>erstatte ditt eksisterende innhold</bold>.<br></br>Du kan sikkerhetskopiere tegningen din først ved å bruke en av valgene nedenfor."
}
}
} }
} }
+53 -4
View File
@@ -109,8 +109,12 @@
"createContainerFromText": "", "createContainerFromText": "",
"link": { "link": {
"edit": "Wijzig link", "edit": "Wijzig link",
"editEmbed": "Link bewerken & insluiten",
"create": "Maak link", "create": "Maak link",
"label": "Link" "createEmbed": "Link maken en insluiten",
"label": "Link",
"labelEmbed": "Link toevoegen & insluiten",
"empty": "Er is geen link ingesteld"
}, },
"lineEditor": { "lineEditor": {
"edit": "Bewerk regel", "edit": "Bewerk regel",
@@ -160,13 +164,16 @@
"darkMode": "Donkere modus", "darkMode": "Donkere modus",
"lightMode": "Lichte modus", "lightMode": "Lichte modus",
"zenMode": "Zen modus", "zenMode": "Zen modus",
"objectsSnapMode": "",
"exitZenMode": "Verlaat zen modus", "exitZenMode": "Verlaat zen modus",
"cancel": "Annuleren", "cancel": "Annuleren",
"clear": "Wissen", "clear": "Wissen",
"remove": "Verwijderen", "remove": "Verwijderen",
"embed": "Insluiten in-/uitschakelen",
"publishLibrary": "Publiceren", "publishLibrary": "Publiceren",
"submit": "Versturen", "submit": "Versturen",
"confirm": "Bevestigen" "confirm": "Bevestigen",
"embeddableInteractionButton": "Klik voor interactie"
}, },
"alerts": { "alerts": {
"clearReset": "Dit zal het hele canvas verwijderen. Weet je het zeker?", "clearReset": "Dit zal het hele canvas verwijderen. Weet je het zeker?",
@@ -196,6 +203,7 @@
"imageInsertError": "Afbeelding invoegen mislukt. Probeer het later opnieuw...", "imageInsertError": "Afbeelding invoegen mislukt. Probeer het later opnieuw...",
"fileTooBig": "Bestand is te groot. Maximale grootte is {{maxSize}}.", "fileTooBig": "Bestand is te groot. Maximale grootte is {{maxSize}}.",
"svgImageInsertError": "Kon geen SVG-afbeelding invoegen. De SVG-opmaak ziet er niet geldig uit.", "svgImageInsertError": "Kon geen SVG-afbeelding invoegen. De SVG-opmaak ziet er niet geldig uit.",
"failedToFetchImage": "",
"invalidSVGString": "Ongeldige SVG.", "invalidSVGString": "Ongeldige SVG.",
"cannotResolveCollabServer": "Kan geen verbinding maken met de collab server. Herlaad de pagina en probeer het opnieuw.", "cannotResolveCollabServer": "Kan geen verbinding maken met de collab server. Herlaad de pagina en probeer het opnieuw.",
"importLibraryError": "Kon bibliotheek niet laden", "importLibraryError": "Kon bibliotheek niet laden",
@@ -206,6 +214,10 @@
"line2": "", "line2": "",
"line3": "", "line3": "",
"line4": "" "line4": ""
},
"libraryElementTypeError": {
"embeddable": "Ingesloten elementen kunnen niet worden toegevoegd aan de bibliotheek.",
"image": "Ondersteuning voor het toevoegen van afbeeldingen aan de bibliotheek komt binnenkort!"
} }
}, },
"toolBar": { "toolBar": {
@@ -224,6 +236,8 @@
"link": "Link toevoegen / bijwerken voor een geselecteerde vorm", "link": "Link toevoegen / bijwerken voor een geselecteerde vorm",
"eraser": "Gum", "eraser": "Gum",
"frame": "", "frame": "",
"embeddable": "Web insluiten",
"laser": "",
"hand": "", "hand": "",
"extraTools": "" "extraTools": ""
}, },
@@ -237,6 +251,7 @@
"linearElement": "Klik om meerdere punten te starten, sleep voor één lijn", "linearElement": "Klik om meerdere punten te starten, sleep voor één lijn",
"freeDraw": "Klik en sleep, laat los als je klaar bent", "freeDraw": "Klik en sleep, laat los als je klaar bent",
"text": "Tip: je kunt tekst toevoegen door ergens dubbel te klikken met de selectietool", "text": "Tip: je kunt tekst toevoegen door ergens dubbel te klikken met de selectietool",
"embeddable": "Klink-sleep om een website-insluiting te maken",
"text_selected": "Dubbelklik of druk op ENTER om tekst te bewerken", "text_selected": "Dubbelklik of druk op ENTER om tekst te bewerken",
"text_editing": "Druk op Escape of CtrlOrCmd+ENTER om het bewerken te voltooien", "text_editing": "Druk op Escape of CtrlOrCmd+ENTER om het bewerken te voltooien",
"linearElementMulti": "Klik op het laatste punt of druk op Escape of Enter om te stoppen", "linearElementMulti": "Klik op het laatste punt of druk op Escape of Enter om te stoppen",
@@ -252,7 +267,8 @@
"bindTextToElement": "Druk op enter om tekst toe te voegen", "bindTextToElement": "Druk op enter om tekst toe te voegen",
"deepBoxSelect": "", "deepBoxSelect": "",
"eraserRevert": "", "eraserRevert": "",
"firefox_clipboard_write": "" "firefox_clipboard_write": "",
"disableSnapping": ""
}, },
"canvasError": { "canvasError": {
"cannotShowPreview": "Kan voorbeeld niet tonen", "cannotShowPreview": "Kan voorbeeld niet tonen",
@@ -411,7 +427,9 @@
"fileSavedToFilename": "Opgeslagen als {filename}", "fileSavedToFilename": "Opgeslagen als {filename}",
"canvas": "canvas", "canvas": "canvas",
"selection": "selectie", "selection": "selectie",
"pasteAsSingleElement": "Gebruik {{shortcut}} om te plakken als een enkel element,\nof plak in een bestaande teksteditor" "pasteAsSingleElement": "Gebruik {{shortcut}} om te plakken als een enkel element,\nof plak in een bestaande teksteditor",
"unableToEmbed": "Het insluiten van deze url is momenteel niet toegestaan. Zet een probleem op GitHub om de URL op de whitelist te zetten",
"unrecognizedLinkFormat": "De link die u hebt ingesloten komt niet overeen met het verwachte formaat. Probeer de 'embed' string van de bronsite te plakken"
}, },
"colors": { "colors": {
"transparent": "Transparant", "transparent": "Transparant",
@@ -449,5 +467,36 @@
"shades": "", "shades": "",
"hexCode": "", "hexCode": "",
"noShades": "" "noShades": ""
},
"overwriteConfirm": {
"action": {
"exportToImage": {
"title": "",
"button": "",
"description": ""
},
"saveToDisk": {
"title": "",
"button": "",
"description": ""
},
"excalidrawPlus": {
"title": "",
"button": "",
"description": ""
}
},
"modal": {
"loadFromFile": {
"title": "",
"button": "",
"description": ""
},
"shareableLink": {
"title": "",
"button": "",
"description": ""
}
}
} }
} }
+53 -4
View File
@@ -109,8 +109,12 @@
"createContainerFromText": "", "createContainerFromText": "",
"link": { "link": {
"edit": "Rediger lenke", "edit": "Rediger lenke",
"editEmbed": "",
"create": "Lag lenke", "create": "Lag lenke",
"label": "Lenke" "createEmbed": "",
"label": "Lenke",
"labelEmbed": "",
"empty": ""
}, },
"lineEditor": { "lineEditor": {
"edit": "", "edit": "",
@@ -160,13 +164,16 @@
"darkMode": "Mørk modus", "darkMode": "Mørk modus",
"lightMode": "Lys modus", "lightMode": "Lys modus",
"zenMode": "Zen-modus", "zenMode": "Zen-modus",
"objectsSnapMode": "",
"exitZenMode": "Avslutt zen-modus", "exitZenMode": "Avslutt zen-modus",
"cancel": "Avbryt", "cancel": "Avbryt",
"clear": "Tøm", "clear": "Tøm",
"remove": "Fjern", "remove": "Fjern",
"embed": "",
"publishLibrary": "Publiser", "publishLibrary": "Publiser",
"submit": "Send inn", "submit": "Send inn",
"confirm": "Stadfest" "confirm": "Stadfest",
"embeddableInteractionButton": ""
}, },
"alerts": { "alerts": {
"clearReset": "Dette vil tømme lerretet. Er du sikker?", "clearReset": "Dette vil tømme lerretet. Er du sikker?",
@@ -196,6 +203,7 @@
"imageInsertError": "Kunne ikkje sette inn biletet. Prøv igjen seinare...", "imageInsertError": "Kunne ikkje sette inn biletet. Prøv igjen seinare...",
"fileTooBig": "Fila er for stor. Maksimal tillate storleik er {{maxSize}}.", "fileTooBig": "Fila er for stor. Maksimal tillate storleik er {{maxSize}}.",
"svgImageInsertError": "Kunne ikkje sette inn SVG-biletet. SVG-koden ser ugyldig ut.", "svgImageInsertError": "Kunne ikkje sette inn SVG-biletet. SVG-koden ser ugyldig ut.",
"failedToFetchImage": "",
"invalidSVGString": "Ugyldig SVG.", "invalidSVGString": "Ugyldig SVG.",
"cannotResolveCollabServer": "Kunne ikkje kople til samarbeidsserveren. Ver vennleg å oppdatere inn sida og prøv på nytt.", "cannotResolveCollabServer": "Kunne ikkje kople til samarbeidsserveren. Ver vennleg å oppdatere inn sida og prøv på nytt.",
"importLibraryError": "", "importLibraryError": "",
@@ -206,6 +214,10 @@
"line2": "", "line2": "",
"line3": "", "line3": "",
"line4": "" "line4": ""
},
"libraryElementTypeError": {
"embeddable": "",
"image": ""
} }
}, },
"toolBar": { "toolBar": {
@@ -224,6 +236,8 @@
"link": "Legg til/ oppdater lenke til valt figur", "link": "Legg til/ oppdater lenke til valt figur",
"eraser": "Viskelêr", "eraser": "Viskelêr",
"frame": "", "frame": "",
"embeddable": "",
"laser": "",
"hand": "", "hand": "",
"extraTools": "" "extraTools": ""
}, },
@@ -237,6 +251,7 @@
"linearElement": "Klikk for å starte linje med fleire punkt, eller drag for ei enkel linje", "linearElement": "Klikk for å starte linje med fleire punkt, eller drag for ei enkel linje",
"freeDraw": "Klikk og drag, slepp når du er ferdig", "freeDraw": "Klikk og drag, slepp når du er ferdig",
"text": "Tips: du kan òg leggje til tekst ved å dobbeltklikke kor som helst med utvalgsverktyet", "text": "Tips: du kan òg leggje til tekst ved å dobbeltklikke kor som helst med utvalgsverktyet",
"embeddable": "",
"text_selected": "Dobbelklikk eller trykk ENTER for å redigere teksta", "text_selected": "Dobbelklikk eller trykk ENTER for å redigere teksta",
"text_editing": "Trykk Escape eller CtrlOrCmd+ENTER for å fullføre redigeringa", "text_editing": "Trykk Escape eller CtrlOrCmd+ENTER for å fullføre redigeringa",
"linearElementMulti": "Klikk på siste punkt eller trykk Escape eller Enter for å fullføre", "linearElementMulti": "Klikk på siste punkt eller trykk Escape eller Enter for å fullføre",
@@ -252,7 +267,8 @@
"bindTextToElement": "Trykk på enter for å legge til tekst", "bindTextToElement": "Trykk på enter for å legge til tekst",
"deepBoxSelect": "Hald inne Ctrl / Cmd for å velje djupt, og forhindre flytting", "deepBoxSelect": "Hald inne Ctrl / Cmd for å velje djupt, og forhindre flytting",
"eraserRevert": "Hald inne Alt for å reversere markering av element for sletting", "eraserRevert": "Hald inne Alt for å reversere markering av element for sletting",
"firefox_clipboard_write": "" "firefox_clipboard_write": "",
"disableSnapping": ""
}, },
"canvasError": { "canvasError": {
"cannotShowPreview": "Kan ikkje vise førehandsvising", "cannotShowPreview": "Kan ikkje vise førehandsvising",
@@ -411,7 +427,9 @@
"fileSavedToFilename": "Lagra som {filename}", "fileSavedToFilename": "Lagra som {filename}",
"canvas": "lerret", "canvas": "lerret",
"selection": "val", "selection": "val",
"pasteAsSingleElement": "" "pasteAsSingleElement": "",
"unableToEmbed": "",
"unrecognizedLinkFormat": ""
}, },
"colors": { "colors": {
"transparent": "Gjennomsiktig", "transparent": "Gjennomsiktig",
@@ -449,5 +467,36 @@
"shades": "", "shades": "",
"hexCode": "", "hexCode": "",
"noShades": "" "noShades": ""
},
"overwriteConfirm": {
"action": {
"exportToImage": {
"title": "",
"button": "",
"description": ""
},
"saveToDisk": {
"title": "",
"button": "",
"description": ""
},
"excalidrawPlus": {
"title": "",
"button": "",
"description": ""
}
},
"modal": {
"loadFromFile": {
"title": "",
"button": "",
"description": ""
},
"shareableLink": {
"title": "",
"button": "",
"description": ""
}
}
} }
} }
+53 -4
View File
@@ -109,8 +109,12 @@
"createContainerFromText": "", "createContainerFromText": "",
"link": { "link": {
"edit": "Modificar lo ligam", "edit": "Modificar lo ligam",
"editEmbed": "",
"create": "Crear un ligam", "create": "Crear un ligam",
"label": "Ligam" "createEmbed": "",
"label": "Ligam",
"labelEmbed": "",
"empty": ""
}, },
"lineEditor": { "lineEditor": {
"edit": "Modificar la linha", "edit": "Modificar la linha",
@@ -160,13 +164,16 @@
"darkMode": "Mòde escur", "darkMode": "Mòde escur",
"lightMode": "Mòde clar", "lightMode": "Mòde clar",
"zenMode": "Mòde escur", "zenMode": "Mòde escur",
"objectsSnapMode": "",
"exitZenMode": "Sortir del mòde zen", "exitZenMode": "Sortir del mòde zen",
"cancel": "Anullar", "cancel": "Anullar",
"clear": "Escafar", "clear": "Escafar",
"remove": "Tirar", "remove": "Tirar",
"embed": "",
"publishLibrary": "Publicar", "publishLibrary": "Publicar",
"submit": "Enviar", "submit": "Enviar",
"confirm": "Confirmar" "confirm": "Confirmar",
"embeddableInteractionButton": ""
}, },
"alerts": { "alerts": {
"clearReset": "Aquò suprimirà lo canabàs complèt. O volètz vertadièrament?", "clearReset": "Aquò suprimirà lo canabàs complèt. O volètz vertadièrament?",
@@ -196,6 +203,7 @@
"imageInsertError": "Insercion dimatge impossibla. Tornatz ensajar mai tard...", "imageInsertError": "Insercion dimatge impossibla. Tornatz ensajar mai tard...",
"fileTooBig": "Fichièr tròp pesuc. La talha maximala autorizada es {{maxSize}}.", "fileTooBig": "Fichièr tròp pesuc. La talha maximala autorizada es {{maxSize}}.",
"svgImageInsertError": "Insercion dimatge SVG impossibla. Las balisas SVG semblan invalidas.", "svgImageInsertError": "Insercion dimatge SVG impossibla. Las balisas SVG semblan invalidas.",
"failedToFetchImage": "",
"invalidSVGString": "SVG invalid.", "invalidSVGString": "SVG invalid.",
"cannotResolveCollabServer": "Connexion impossibla al servidor collab. Mercés de recargar la pagina e tornar ensajar.", "cannotResolveCollabServer": "Connexion impossibla al servidor collab. Mercés de recargar la pagina e tornar ensajar.",
"importLibraryError": "Impossible de cargar la bibliotèca", "importLibraryError": "Impossible de cargar la bibliotèca",
@@ -206,6 +214,10 @@
"line2": "", "line2": "",
"line3": "", "line3": "",
"line4": "" "line4": ""
},
"libraryElementTypeError": {
"embeddable": "",
"image": ""
} }
}, },
"toolBar": { "toolBar": {
@@ -224,6 +236,8 @@
"link": "Apondre/Actualizar lo ligam per una fòrma seleccionada", "link": "Apondre/Actualizar lo ligam per una fòrma seleccionada",
"eraser": "Goma", "eraser": "Goma",
"frame": "", "frame": "",
"embeddable": "",
"laser": "",
"hand": "Man (aisina de desplaçament de la vista)", "hand": "Man (aisina de desplaçament de la vista)",
"extraTools": "" "extraTools": ""
}, },
@@ -237,6 +251,7 @@
"linearElement": "Clicatz per començar mantun punt, lisatz per una sola linha", "linearElement": "Clicatz per començar mantun punt, lisatz per una sola linha",
"freeDraw": "Clicatz e lisatz, relargatz un còp acabat", "freeDraw": "Clicatz e lisatz, relargatz un còp acabat",
"text": "Astúcia: podètz tanben apondre de tèxt en doble clicant ont que siá amb laisina de seleccion", "text": "Astúcia: podètz tanben apondre de tèxt en doble clicant ont que siá amb laisina de seleccion",
"embeddable": "",
"text_selected": "Clicatz dos còps o quichatz ENTRADA per modificar lo tèxt", "text_selected": "Clicatz dos còps o quichatz ENTRADA per modificar lo tèxt",
"text_editing": "Quichatz ESCAPAR o CtrlOrCmd+ENTRADA per acabar la modificacion", "text_editing": "Quichatz ESCAPAR o CtrlOrCmd+ENTRADA per acabar la modificacion",
"linearElementMulti": "Clicatz sul darrièr punt o quichatz Ecap o Entrada per acabar", "linearElementMulti": "Clicatz sul darrièr punt o quichatz Ecap o Entrada per acabar",
@@ -252,7 +267,8 @@
"bindTextToElement": "Quichatz Entrada per apondre de tèxte", "bindTextToElement": "Quichatz Entrada per apondre de tèxte",
"deepBoxSelect": "Gardar CtrlOCmd per una seleccion gropada e empachar lo desplaçament", "deepBoxSelect": "Gardar CtrlOCmd per una seleccion gropada e empachar lo desplaçament",
"eraserRevert": "Tenètz quichat Alt per anullar los elements marcats per supression", "eraserRevert": "Tenètz quichat Alt per anullar los elements marcats per supression",
"firefox_clipboard_write": "" "firefox_clipboard_write": "",
"disableSnapping": ""
}, },
"canvasError": { "canvasError": {
"cannotShowPreview": "Afichatge impossible de lapercebut", "cannotShowPreview": "Afichatge impossible de lapercebut",
@@ -411,7 +427,9 @@
"fileSavedToFilename": "Enregistrat jos {filename}", "fileSavedToFilename": "Enregistrat jos {filename}",
"canvas": "canabàs", "canvas": "canabàs",
"selection": "seleccion", "selection": "seleccion",
"pasteAsSingleElement": "" "pasteAsSingleElement": "",
"unableToEmbed": "",
"unrecognizedLinkFormat": ""
}, },
"colors": { "colors": {
"transparent": "Transparéncia", "transparent": "Transparéncia",
@@ -449,5 +467,36 @@
"shades": "", "shades": "",
"hexCode": "", "hexCode": "",
"noShades": "" "noShades": ""
},
"overwriteConfirm": {
"action": {
"exportToImage": {
"title": "",
"button": "",
"description": ""
},
"saveToDisk": {
"title": "",
"button": "",
"description": ""
},
"excalidrawPlus": {
"title": "",
"button": "",
"description": ""
}
},
"modal": {
"loadFromFile": {
"title": "",
"button": "",
"description": ""
},
"shareableLink": {
"title": "",
"button": "",
"description": ""
}
}
} }
} }
+53 -4
View File
@@ -109,8 +109,12 @@
"createContainerFromText": "ਪਾਠ ਨੂੰ ਕੰਟੇਨਰ ਵਿੱਚ ਇਕੱਠਾ ਕਰੋ", "createContainerFromText": "ਪਾਠ ਨੂੰ ਕੰਟੇਨਰ ਵਿੱਚ ਇਕੱਠਾ ਕਰੋ",
"link": { "link": {
"edit": "ਕੜੀ ਸੋਧੋ", "edit": "ਕੜੀ ਸੋਧੋ",
"editEmbed": "",
"create": "ਕੜੀ ਬਣਾਓ", "create": "ਕੜੀ ਬਣਾਓ",
"label": "ਕੜੀ" "createEmbed": "",
"label": "ਕੜੀ",
"labelEmbed": "",
"empty": ""
}, },
"lineEditor": { "lineEditor": {
"edit": "ਪੰਕਤੀ ਸੋਧੋ", "edit": "ਪੰਕਤੀ ਸੋਧੋ",
@@ -160,13 +164,16 @@
"darkMode": "ਡਾਰਕ ਮੋਡ", "darkMode": "ਡਾਰਕ ਮੋਡ",
"lightMode": "ਲਾਇਟ ਮੋਡ", "lightMode": "ਲਾਇਟ ਮੋਡ",
"zenMode": "ਜ਼ੈੱਨ ਮੋਡ", "zenMode": "ਜ਼ੈੱਨ ਮੋਡ",
"objectsSnapMode": "",
"exitZenMode": "ਜ਼ੈੱਨ ਮੋਡ 'ਚੋਂ ਬਾਹਰ ਨਿਕਲੋ", "exitZenMode": "ਜ਼ੈੱਨ ਮੋਡ 'ਚੋਂ ਬਾਹਰ ਨਿਕਲੋ",
"cancel": "ਰੱਦ ਕਰੋ", "cancel": "ਰੱਦ ਕਰੋ",
"clear": "ਸਾਫ਼ ਕਰੋ", "clear": "ਸਾਫ਼ ਕਰੋ",
"remove": "ਹਟਾਓ", "remove": "ਹਟਾਓ",
"embed": "",
"publishLibrary": "ਪ੍ਰਕਾਸ਼ਤ ਕਰੋ", "publishLibrary": "ਪ੍ਰਕਾਸ਼ਤ ਕਰੋ",
"submit": "ਜਮ੍ਹਾ ਕਰਵਾਓ", "submit": "ਜਮ੍ਹਾ ਕਰਵਾਓ",
"confirm": "ਪੁਸ਼ਟੀ ਕਰੋ" "confirm": "ਪੁਸ਼ਟੀ ਕਰੋ",
"embeddableInteractionButton": ""
}, },
"alerts": { "alerts": {
"clearReset": "ਇਹ ਸਾਰਾ ਕੈਨਵਸ ਸਾਫ ਕਰ ਦੇਵੇਗਾ। ਕੀ ਤੁਸੀਂ ਪੱਕਾ ਇੰਝ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ?", "clearReset": "ਇਹ ਸਾਰਾ ਕੈਨਵਸ ਸਾਫ ਕਰ ਦੇਵੇਗਾ। ਕੀ ਤੁਸੀਂ ਪੱਕਾ ਇੰਝ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ?",
@@ -196,6 +203,7 @@
"imageInsertError": "ਚਿੱਤਰ ਸ਼ਾਮਲ ਨਹੀਂ ਜਾ ਸਕਿਆ, ਬਾਅਦ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ...", "imageInsertError": "ਚਿੱਤਰ ਸ਼ਾਮਲ ਨਹੀਂ ਜਾ ਸਕਿਆ, ਬਾਅਦ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ...",
"fileTooBig": "ਫਾਈਲ ਬਹੁਤ ਜ਼ਿਆਦਾ ਵੱਡੀ ਹੈ। ਵੱਧ-ਤੋਂ-ਵੱਧ ਪ੍ਰਵਾਨਤ ਅਕਾਰ {{maxSize}} ਹੈ।", "fileTooBig": "ਫਾਈਲ ਬਹੁਤ ਜ਼ਿਆਦਾ ਵੱਡੀ ਹੈ। ਵੱਧ-ਤੋਂ-ਵੱਧ ਪ੍ਰਵਾਨਤ ਅਕਾਰ {{maxSize}} ਹੈ।",
"svgImageInsertError": "SVG ਤਸਵੀਰ ਸ਼ਾਮਲ ਨਹੀਂ ਕਰ ਸਕੇ। SVG ਮਾਰਕ-ਅੱਪ ਨਜਾਇਜ਼ ਲੱਗ ਰਿਹਾ ਹੈ।", "svgImageInsertError": "SVG ਤਸਵੀਰ ਸ਼ਾਮਲ ਨਹੀਂ ਕਰ ਸਕੇ। SVG ਮਾਰਕ-ਅੱਪ ਨਜਾਇਜ਼ ਲੱਗ ਰਿਹਾ ਹੈ।",
"failedToFetchImage": "",
"invalidSVGString": "SVG ਨਜਾਇਜ਼ ਹੈ।", "invalidSVGString": "SVG ਨਜਾਇਜ਼ ਹੈ।",
"cannotResolveCollabServer": "", "cannotResolveCollabServer": "",
"importLibraryError": "ਲਾਇਬ੍ਰੇਰੀ ਲੋਡ ਨਹੀਂ ਕੀਤੀ ਜਾ ਸਕੀ", "importLibraryError": "ਲਾਇਬ੍ਰੇਰੀ ਲੋਡ ਨਹੀਂ ਕੀਤੀ ਜਾ ਸਕੀ",
@@ -206,6 +214,10 @@
"line2": "", "line2": "",
"line3": "", "line3": "",
"line4": "" "line4": ""
},
"libraryElementTypeError": {
"embeddable": "",
"image": ""
} }
}, },
"toolBar": { "toolBar": {
@@ -224,6 +236,8 @@
"link": "", "link": "",
"eraser": "ਰਬੜ", "eraser": "ਰਬੜ",
"frame": "", "frame": "",
"embeddable": "",
"laser": "",
"hand": "", "hand": "",
"extraTools": "" "extraTools": ""
}, },
@@ -237,6 +251,7 @@
"linearElement": "ਇੱਕ ਤੋਂ ਜ਼ਿਆਦਾ ਬਿੰਦੂਆਂ ਲਈ ਕਲਿੱਕ ਕਰਕੇ ਸ਼ੁਰੂਆਤ ਕਰੋ, ਇਕਹਿਰੀ ਲਕੀਰ ਲਈ ਘਸੀਟੋ", "linearElement": "ਇੱਕ ਤੋਂ ਜ਼ਿਆਦਾ ਬਿੰਦੂਆਂ ਲਈ ਕਲਿੱਕ ਕਰਕੇ ਸ਼ੁਰੂਆਤ ਕਰੋ, ਇਕਹਿਰੀ ਲਕੀਰ ਲਈ ਘਸੀਟੋ",
"freeDraw": "ਕਲਿੱਕ ਕਰਕੇ ਘਸੀਟੋ, ਪੂਰਾ ਹੋਣ 'ਤੇ ਛੱਡ ਦਿਉ", "freeDraw": "ਕਲਿੱਕ ਕਰਕੇ ਘਸੀਟੋ, ਪੂਰਾ ਹੋਣ 'ਤੇ ਛੱਡ ਦਿਉ",
"text": "ਨੁਸਖਾ: ਤੁਸੀਂ ਚੋਣਕਾਰ ਸੰਦ ਰਾਹੀਂ ਕਿਤੇ ਵੀ ਡਬਲ-ਕਲਿੱਕ ਕਰਕੇ ਵੀ ਪਾਠ ਜੋੜ ਸਕਦੇ ਹੋ", "text": "ਨੁਸਖਾ: ਤੁਸੀਂ ਚੋਣਕਾਰ ਸੰਦ ਰਾਹੀਂ ਕਿਤੇ ਵੀ ਡਬਲ-ਕਲਿੱਕ ਕਰਕੇ ਵੀ ਪਾਠ ਜੋੜ ਸਕਦੇ ਹੋ",
"embeddable": "",
"text_selected": "ਪਾਠ ਨੂੰ ਸੋਧਣ ਲਈ ਡਬਲ-ਕਲਿੱਕ ਕਰੋ ਜਾਂ ਐਂਟਰ ਦਬਾਓ", "text_selected": "ਪਾਠ ਨੂੰ ਸੋਧਣ ਲਈ ਡਬਲ-ਕਲਿੱਕ ਕਰੋ ਜਾਂ ਐਂਟਰ ਦਬਾਓ",
"text_editing": "ਸੋਧ ਮੁਕੰਮਲ ਕਰਨ ਲਈ ਐਸਕੇਪ (Esc) ਜਾਂ Ctrl-ਜਾਂ-Cmd+ਐਂਟਰ (enter) ਦਬਾਓ", "text_editing": "ਸੋਧ ਮੁਕੰਮਲ ਕਰਨ ਲਈ ਐਸਕੇਪ (Esc) ਜਾਂ Ctrl-ਜਾਂ-Cmd+ਐਂਟਰ (enter) ਦਬਾਓ",
"linearElementMulti": "ਮੁਕੰਮਲ ਕਰਨ ਲਈ ਆਖਰੀ ਬਿੰਦੂ 'ਤੇ ਕਲਿੱਕ ਕਰੋ ਜਾਂ ਇਸਕੇਪ ਜਾਂ ਐਂਟਰ ਦਬਾਓ", "linearElementMulti": "ਮੁਕੰਮਲ ਕਰਨ ਲਈ ਆਖਰੀ ਬਿੰਦੂ 'ਤੇ ਕਲਿੱਕ ਕਰੋ ਜਾਂ ਇਸਕੇਪ ਜਾਂ ਐਂਟਰ ਦਬਾਓ",
@@ -252,7 +267,8 @@
"bindTextToElement": "ਪਾਠ ਜੋੜਨ ਲਈ ਐੰਟਰ ਦਬਾਓ", "bindTextToElement": "ਪਾਠ ਜੋੜਨ ਲਈ ਐੰਟਰ ਦਬਾਓ",
"deepBoxSelect": "", "deepBoxSelect": "",
"eraserRevert": "", "eraserRevert": "",
"firefox_clipboard_write": "" "firefox_clipboard_write": "",
"disableSnapping": ""
}, },
"canvasError": { "canvasError": {
"cannotShowPreview": "ਝਲਕ ਨਹੀਂ ਦਿਖਾ ਸਕਦੇ", "cannotShowPreview": "ਝਲਕ ਨਹੀਂ ਦਿਖਾ ਸਕਦੇ",
@@ -411,7 +427,9 @@
"fileSavedToFilename": "{filename} ਵਿੱਚ ਸਾਂਭੀ", "fileSavedToFilename": "{filename} ਵਿੱਚ ਸਾਂਭੀ",
"canvas": "ਕੈਨਵਸ", "canvas": "ਕੈਨਵਸ",
"selection": "ਚੋਣ", "selection": "ਚੋਣ",
"pasteAsSingleElement": "" "pasteAsSingleElement": "",
"unableToEmbed": "",
"unrecognizedLinkFormat": ""
}, },
"colors": { "colors": {
"transparent": "ਪਾਰਦਰਸ਼ੀ", "transparent": "ਪਾਰਦਰਸ਼ੀ",
@@ -449,5 +467,36 @@
"shades": "ਸ਼ੇਡਾਂ", "shades": "ਸ਼ੇਡਾਂ",
"hexCode": "ਹੈਕਸ ਕੋਡ", "hexCode": "ਹੈਕਸ ਕੋਡ",
"noShades": "ਇਸ ਰੰਗ ਦੀ ਕੋਈ ਸ਼ੇਡ ਉਪਲਬਧ ਨਹੀਂ ਹੈ" "noShades": "ਇਸ ਰੰਗ ਦੀ ਕੋਈ ਸ਼ੇਡ ਉਪਲਬਧ ਨਹੀਂ ਹੈ"
},
"overwriteConfirm": {
"action": {
"exportToImage": {
"title": "",
"button": "",
"description": ""
},
"saveToDisk": {
"title": "",
"button": "",
"description": ""
},
"excalidrawPlus": {
"title": "",
"button": "",
"description": ""
}
},
"modal": {
"loadFromFile": {
"title": "",
"button": "",
"description": ""
},
"shareableLink": {
"title": "",
"button": "",
"description": ""
}
}
} }
} }
+47 -47
View File
@@ -1,56 +1,56 @@
{ {
"ar-SA": 79, "ar-SA": 99,
"az-AZ": 20, "az-AZ": 18,
"bg-BG": 54, "bg-BG": 75,
"bn-BD": 59, "bn-BD": 55,
"ca-ES": 87, "ca-ES": 81,
"cs-CZ": 98, "cs-CZ": 91,
"da-DK": 33, "da-DK": 31,
"de-DE": 100, "de-DE": 100,
"el-GR": 92, "el-GR": 85,
"en": 100, "en": 100,
"es-ES": 88, "es-ES": 96,
"eu-ES": 100, "eu-ES": 99,
"fa-IR": 88, "fa-IR": 87,
"fi-FI": 87, "fi-FI": 81,
"fr-FR": 88, "fr-FR": 98,
"gl-ES": 88, "gl-ES": 90,
"he-IL": 86, "he-IL": 81,
"hi-IN": 77, "hi-IN": 75,
"hu-HU": 76, "hu-HU": 70,
"id-ID": 94, "id-ID": 96,
"it-IT": 98, "it-IT": 99,
"ja-JP": 88, "ja-JP": 95,
"kaa": 18, "kaa": 34,
"kab-KAB": 87, "kab-KAB": 80,
"kk-KZ": 21, "kk-KZ": 20,
"km-KH": 94, "km-KH": 87,
"ko-KR": 100, "ko-KR": 100,
"ku-TR": 100, "ku-TR": 92,
"lt-LT": 55, "lt-LT": 51,
"lv-LV": 88, "lv-LV": 82,
"mr-IN": 95, "mr-IN": 92,
"my-MM": 40, "my-MM": 37,
"nb-NO": 100, "nb-NO": 99,
"nl-NL": 83, "nl-NL": 79,
"nn-NO": 76, "nn-NO": 71,
"oc-FR": 86, "oc-FR": 79,
"pa-IN": 89, "pa-IN": 82,
"pl-PL": 98, "pl-PL": 100,
"pt-BR": 98, "pt-BR": 96,
"pt-PT": 94, "pt-PT": 88,
"ro-RO": 98, "ro-RO": 98,
"ru-RU": 98, "ru-RU": 94,
"si-LK": 9, "si-LK": 8,
"sk-SK": 98, "sk-SK": 99,
"sl-SI": 100, "sl-SI": 100,
"sv-SE": 100, "sv-SE": 100,
"ta-IN": 84, "ta-IN": 85,
"th-TH": 38, "th-TH": 46,
"tr-TR": 86, "tr-TR": 91,
"uk-UA": 96, "uk-UA": 99,
"vi-VN": 56, "vi-VN": 51,
"zh-CN": 100, "zh-CN": 99,
"zh-HK": 25, "zh-HK": 24,
"zh-TW": 100 "zh-TW": 100
} }
+58 -9
View File
@@ -104,13 +104,17 @@
"excalidrawLib": "Biblioteka Excalidraw", "excalidrawLib": "Biblioteka Excalidraw",
"decreaseFontSize": "Zmniejsz rozmiar czcionki", "decreaseFontSize": "Zmniejsz rozmiar czcionki",
"increaseFontSize": "Zwiększ rozmiar czcionki", "increaseFontSize": "Zwiększ rozmiar czcionki",
"unbindText": "Rozłącz tekst", "unbindText": "Odłącz tekst od kontenera",
"bindText": "Połącz tekst z kontenerem", "bindText": "Połącz tekst z kontenerem",
"createContainerFromText": "Zawijaj tekst w kontenerze", "createContainerFromText": "Zawijaj tekst w kontenerze",
"link": { "link": {
"edit": "Edytuj łącze", "edit": "Edytuj łącze",
"editEmbed": "Edytuj i osadź link",
"create": "Utwórz łącze", "create": "Utwórz łącze",
"label": "Łącze" "createEmbed": "Stwórz i osadź link",
"label": "Łącze",
"labelEmbed": "Podlinkuj i osadź",
"empty": "Brakujący link"
}, },
"lineEditor": { "lineEditor": {
"edit": "Edytuj linię", "edit": "Edytuj linię",
@@ -124,8 +128,8 @@
}, },
"statusPublished": "Opublikowano", "statusPublished": "Opublikowano",
"sidebarLock": "Panel boczny zawsze otwarty", "sidebarLock": "Panel boczny zawsze otwarty",
"selectAllElementsInFrame": "", "selectAllElementsInFrame": "Zaznacz wszystkie elementy w ramce",
"removeAllElementsFromFrame": "", "removeAllElementsFromFrame": "Usuń wszystkie elementy z ramki",
"eyeDropper": "Wybierz kolor z płótna" "eyeDropper": "Wybierz kolor z płótna"
}, },
"library": { "library": {
@@ -160,13 +164,16 @@
"darkMode": "Ciemny motyw", "darkMode": "Ciemny motyw",
"lightMode": "Jasny motyw", "lightMode": "Jasny motyw",
"zenMode": "Tryb Zen", "zenMode": "Tryb Zen",
"objectsSnapMode": "Przyciąganie do obiektów",
"exitZenMode": "Wyjdź z trybu Zen", "exitZenMode": "Wyjdź z trybu Zen",
"cancel": "Anuluj", "cancel": "Anuluj",
"clear": "Wyczyść", "clear": "Wyczyść",
"remove": "Usuń", "remove": "Usuń",
"embed": "Przełącz osadzenie",
"publishLibrary": "Opublikuj", "publishLibrary": "Opublikuj",
"submit": "Prześlij", "submit": "Prześlij",
"confirm": "Zatwierdź" "confirm": "Zatwierdź",
"embeddableInteractionButton": "Kliknij, aby wejść w interakcję"
}, },
"alerts": { "alerts": {
"clearReset": "To spowoduje usunięcie wszystkiego z dokumentu. Czy chcesz kontynuować?", "clearReset": "To spowoduje usunięcie wszystkiego z dokumentu. Czy chcesz kontynuować?",
@@ -196,6 +203,7 @@
"imageInsertError": "Nie udało się wstawić obrazu. Spróbuj ponownie później...", "imageInsertError": "Nie udało się wstawić obrazu. Spróbuj ponownie później...",
"fileTooBig": "Plik jest zbyt duży. Maksymalny dozwolony rozmiar to {{maxSize}}.", "fileTooBig": "Plik jest zbyt duży. Maksymalny dozwolony rozmiar to {{maxSize}}.",
"svgImageInsertError": "Nie udało się wstawić obrazu SVG. Znacznik SVG wygląda na nieprawidłowy.", "svgImageInsertError": "Nie udało się wstawić obrazu SVG. Znacznik SVG wygląda na nieprawidłowy.",
"failedToFetchImage": "Nie udało się załadować obrazu.",
"invalidSVGString": "Nieprawidłowy SVG.", "invalidSVGString": "Nieprawidłowy SVG.",
"cannotResolveCollabServer": "Nie można połączyć się z serwerem współpracy w czasie rzeczywistym. Proszę odświeżyć stronę i spróbować ponownie.", "cannotResolveCollabServer": "Nie można połączyć się z serwerem współpracy w czasie rzeczywistym. Proszę odświeżyć stronę i spróbować ponownie.",
"importLibraryError": "Wystąpił błąd w trakcie ładowania biblioteki", "importLibraryError": "Wystąpił błąd w trakcie ładowania biblioteki",
@@ -206,6 +214,10 @@
"line2": "Może to doprowadzić do złamania <bold>elementów tekstu</bold> na rysunkach.", "line2": "Może to doprowadzić do złamania <bold>elementów tekstu</bold> na rysunkach.",
"line3": "Zdecydowanie zalecamy wyłączenie tego ustawienia. Możesz wykonać <link>te kroki</link>, aby to zrobić.", "line3": "Zdecydowanie zalecamy wyłączenie tego ustawienia. Możesz wykonać <link>te kroki</link>, aby to zrobić.",
"line4": "Jeśli wyłączenie tego ustawienia nie naprawia wyświetlania elementów tekstowych, zgłoś <issueLink>problem</issueLink> na naszym GitHubie lub napisz do nas na <discordLink>Discordzie</discordLink>" "line4": "Jeśli wyłączenie tego ustawienia nie naprawia wyświetlania elementów tekstowych, zgłoś <issueLink>problem</issueLink> na naszym GitHubie lub napisz do nas na <discordLink>Discordzie</discordLink>"
},
"libraryElementTypeError": {
"embeddable": "Elementy osadzone nie mogą zostać dodane do biblioteki.",
"image": "Dodawania obrazów do biblioteki nadejdzie wkrótce!"
} }
}, },
"toolBar": { "toolBar": {
@@ -223,9 +235,11 @@
"penMode": "Tryb pióra — zapobiegaj dotknięciom", "penMode": "Tryb pióra — zapobiegaj dotknięciom",
"link": "Dodaj/aktualizuj link dla wybranego kształtu", "link": "Dodaj/aktualizuj link dla wybranego kształtu",
"eraser": "Gumka", "eraser": "Gumka",
"frame": "", "frame": "Ramka",
"embeddable": "Osadzenie z internetu",
"laser": "Wskaźnik laserowy",
"hand": "Ręka (narzędzie do przesuwania)", "hand": "Ręka (narzędzie do przesuwania)",
"extraTools": "" "extraTools": "Więcej narzędzi"
}, },
"headings": { "headings": {
"canvasActions": "Narzędzia", "canvasActions": "Narzędzia",
@@ -237,6 +251,7 @@
"linearElement": "Naciśnij, aby zrobić punkt, przeciągnij, aby narysować linię", "linearElement": "Naciśnij, aby zrobić punkt, przeciągnij, aby narysować linię",
"freeDraw": "Naciśnij i przeciągnij by rysować, puść kiedy skończysz", "freeDraw": "Naciśnij i przeciągnij by rysować, puść kiedy skończysz",
"text": "Wskazówka: możesz również dodać tekst klikając dwukrotnie gdziekolwiek za pomocą narzędzia zaznaczania", "text": "Wskazówka: możesz również dodać tekst klikając dwukrotnie gdziekolwiek za pomocą narzędzia zaznaczania",
"embeddable": "Kliknij i przeciągnij, aby stworzyć osadzenie strony",
"text_selected": "Kliknij dwukrotnie lub naciśnij ENTER, aby edytować tekst", "text_selected": "Kliknij dwukrotnie lub naciśnij ENTER, aby edytować tekst",
"text_editing": "Naciśnij Escape lub Ctrl (Cmd w macOS) + ENTER, aby zakończyć edycję", "text_editing": "Naciśnij Escape lub Ctrl (Cmd w macOS) + ENTER, aby zakończyć edycję",
"linearElementMulti": "Aby zakończyć krzywą, ponownie kliknij w ostatni punkt, bądź naciśnij Esc albo Enter", "linearElementMulti": "Aby zakończyć krzywą, ponownie kliknij w ostatni punkt, bądź naciśnij Esc albo Enter",
@@ -252,7 +267,8 @@
"bindTextToElement": "Wciśnij enter, aby dodać tekst", "bindTextToElement": "Wciśnij enter, aby dodać tekst",
"deepBoxSelect": "Przytrzymaj CtrlOrCmd, aby wybrać w obrębie grupy i uniknąć przeciągania", "deepBoxSelect": "Przytrzymaj CtrlOrCmd, aby wybrać w obrębie grupy i uniknąć przeciągania",
"eraserRevert": "Przytrzymaj Alt, aby przywrócić elementy oznaczone do usunięcia", "eraserRevert": "Przytrzymaj Alt, aby przywrócić elementy oznaczone do usunięcia",
"firefox_clipboard_write": "Ta funkcja może być włączona poprzez ustawienie flagi \"dom.events.asyncClipboard.clipboardItem\" na \"true\". Aby zmienić flagi przeglądarki w Firefox, odwiedź stronę \"about:config\"." "firefox_clipboard_write": "Ta funkcja może być włączona poprzez ustawienie flagi \"dom.events.asyncClipboard.clipboardItem\" na \"true\". Aby zmienić flagi przeglądarki w Firefox, odwiedź stronę \"about:config\".",
"disableSnapping": "Przytrzymaj Ctrl lub Cmd, aby wyłączyć przyciąganie"
}, },
"canvasError": { "canvasError": {
"cannotShowPreview": "Nie można wyświetlić podglądu", "cannotShowPreview": "Nie można wyświetlić podglądu",
@@ -411,7 +427,9 @@
"fileSavedToFilename": "Zapisano jako {filename}", "fileSavedToFilename": "Zapisano jako {filename}",
"canvas": "płótno", "canvas": "płótno",
"selection": "zaznaczenie", "selection": "zaznaczenie",
"pasteAsSingleElement": "Użyj {{shortcut}}, aby wkleić jako pojedynczy element,\nlub wklej do istniejącego edytora tekstu" "pasteAsSingleElement": "Użyj {{shortcut}}, aby wkleić jako pojedynczy element,\nlub wklej do istniejącego edytora tekstu",
"unableToEmbed": "Osadzenie tego linku jest obecnie niedozwolone. Zgłoś propozycję na portalu GitHub, aby dodać go do listy dozwolonych wyjątków",
"unrecognizedLinkFormat": "Osadzony link ma niewłaściwy format. Spróbuj wkleić całą zawartość pola \"embed\" z oryginalnej strony."
}, },
"colors": { "colors": {
"transparent": "Przezroczysty", "transparent": "Przezroczysty",
@@ -449,5 +467,36 @@
"shades": "Odcienie", "shades": "Odcienie",
"hexCode": "Kod HEX", "hexCode": "Kod HEX",
"noShades": "Brak dostępnych odcieni dla tego koloru" "noShades": "Brak dostępnych odcieni dla tego koloru"
},
"overwriteConfirm": {
"action": {
"exportToImage": {
"title": "Eksportuj jako obraz",
"button": "Eksportuj jako obraz",
"description": "Eksportuj zawartość sceny jako obraz z możliwością importowania."
},
"saveToDisk": {
"title": "Zapisz na dysku",
"button": "Zapisz na dysku",
"description": "Eksportuj zawartość sceny jako plik z możliwością importowania."
},
"excalidrawPlus": {
"title": "Excalidraw+",
"button": "Eksportuj do Excalidraw+",
"description": "Zapisz scenę do swojego obszaru roboczego Excalidraw+."
}
},
"modal": {
"loadFromFile": {
"title": "Wczytaj z pliku",
"button": "Wczytaj z pliku",
"description": "Wczytanie z pliku <bold>nadpisze istniejącą zawartość</bold>.<br></br>Możesz najpierw utworzyć kopię zapasową swojego rysunku, używając jednej z poniższych opcji."
},
"shareableLink": {
"title": "Wczytaj z linku",
"button": "Nadpisz moją zawartość",
"description": "Wczytanie zewnętrznego pliku <bold>nadpisze istniejącą zawartość</bold>.<br></br>Możesz najpierw utworzyć kopię zapasową swojego rysunku, używając jednej z poniższych opcji."
}
}
} }
} }
+58 -9
View File
@@ -109,8 +109,12 @@
"createContainerFromText": "Envolver texto em um contêiner", "createContainerFromText": "Envolver texto em um contêiner",
"link": { "link": {
"edit": "Editar link", "edit": "Editar link",
"editEmbed": "",
"create": "Criar link", "create": "Criar link",
"label": "Link" "createEmbed": "",
"label": "Link",
"labelEmbed": "",
"empty": ""
}, },
"lineEditor": { "lineEditor": {
"edit": "Editar linha", "edit": "Editar linha",
@@ -124,9 +128,9 @@
}, },
"statusPublished": "Publicado", "statusPublished": "Publicado",
"sidebarLock": "Manter barra lateral aberta", "sidebarLock": "Manter barra lateral aberta",
"selectAllElementsInFrame": "", "selectAllElementsInFrame": "Selecionar todos os elementos no quadro",
"removeAllElementsFromFrame": "", "removeAllElementsFromFrame": "Remover todos os elementos do quadro",
"eyeDropper": "" "eyeDropper": "Escolher cor da tela"
}, },
"library": { "library": {
"noItems": "Nenhum item adicionado ainda...", "noItems": "Nenhum item adicionado ainda...",
@@ -160,13 +164,16 @@
"darkMode": "Modo escuro", "darkMode": "Modo escuro",
"lightMode": "Modo claro", "lightMode": "Modo claro",
"zenMode": "Modo Zen", "zenMode": "Modo Zen",
"objectsSnapMode": "",
"exitZenMode": "Sair do modo zen", "exitZenMode": "Sair do modo zen",
"cancel": "Cancelar", "cancel": "Cancelar",
"clear": "Limpar", "clear": "Limpar",
"remove": "Remover", "remove": "Remover",
"embed": "",
"publishLibrary": "Publicar", "publishLibrary": "Publicar",
"submit": "Enviar", "submit": "Enviar",
"confirm": "Confirmar" "confirm": "Confirmar",
"embeddableInteractionButton": ""
}, },
"alerts": { "alerts": {
"clearReset": "Isto irá limpar toda a tela. Você tem certeza?", "clearReset": "Isto irá limpar toda a tela. Você tem certeza?",
@@ -196,6 +203,7 @@
"imageInsertError": "Não foi possível inserir imagem. Tente novamente mais tarde...", "imageInsertError": "Não foi possível inserir imagem. Tente novamente mais tarde...",
"fileTooBig": "O arquivo é muito grande. O tamanho máximo permitido é {{maxSize}}.", "fileTooBig": "O arquivo é muito grande. O tamanho máximo permitido é {{maxSize}}.",
"svgImageInsertError": "Não foi possível inserir a imagem SVG. A marcação SVG parece inválida.", "svgImageInsertError": "Não foi possível inserir a imagem SVG. A marcação SVG parece inválida.",
"failedToFetchImage": "",
"invalidSVGString": "SVG Inválido.", "invalidSVGString": "SVG Inválido.",
"cannotResolveCollabServer": "Não foi possível conectar-se ao servidor colaborativo. Por favor, recarregue a página e tente novamente.", "cannotResolveCollabServer": "Não foi possível conectar-se ao servidor colaborativo. Por favor, recarregue a página e tente novamente.",
"importLibraryError": "Não foi possível carregar a biblioteca", "importLibraryError": "Não foi possível carregar a biblioteca",
@@ -206,6 +214,10 @@
"line2": "Isso pode acabar quebrando <bold>Elementos de Texto</bold> em seus desenhos.", "line2": "Isso pode acabar quebrando <bold>Elementos de Texto</bold> em seus desenhos.",
"line3": "Recomendamos fortemente desativar essa configuração. Você pode acessar o <link>passo a passo</link> sobre como fazer isso.", "line3": "Recomendamos fortemente desativar essa configuração. Você pode acessar o <link>passo a passo</link> sobre como fazer isso.",
"line4": "Se desativar essa configuração não corrigir a exibição de elementos de texto, por favor abra uma <issueLink>issue</issueLink> em nosso GitHub, ou mande uma mensagem em nosso <discordLink>Discord</discordLink>" "line4": "Se desativar essa configuração não corrigir a exibição de elementos de texto, por favor abra uma <issueLink>issue</issueLink> em nosso GitHub, ou mande uma mensagem em nosso <discordLink>Discord</discordLink>"
},
"libraryElementTypeError": {
"embeddable": "",
"image": ""
} }
}, },
"toolBar": { "toolBar": {
@@ -223,9 +235,11 @@
"penMode": "Modo caneta — impede o toque", "penMode": "Modo caneta — impede o toque",
"link": "Adicionar/Atualizar link para uma forma selecionada", "link": "Adicionar/Atualizar link para uma forma selecionada",
"eraser": "Borracha", "eraser": "Borracha",
"frame": "", "frame": "Ferramenta de quadro",
"embeddable": "",
"laser": "",
"hand": "Mão (ferramenta de rolagem)", "hand": "Mão (ferramenta de rolagem)",
"extraTools": "" "extraTools": "Mais ferramentas"
}, },
"headings": { "headings": {
"canvasActions": "Ações da tela", "canvasActions": "Ações da tela",
@@ -237,6 +251,7 @@
"linearElement": "Clique para iniciar vários pontos, arraste para uma única linha", "linearElement": "Clique para iniciar vários pontos, arraste para uma única linha",
"freeDraw": "Toque e arraste, solte quando terminar", "freeDraw": "Toque e arraste, solte quando terminar",
"text": "Dica: você também pode adicionar texto clicando duas vezes em qualquer lugar com a ferramenta de seleção", "text": "Dica: você também pode adicionar texto clicando duas vezes em qualquer lugar com a ferramenta de seleção",
"embeddable": "",
"text_selected": "Clique duplo ou tecle ENTER para editar o texto", "text_selected": "Clique duplo ou tecle ENTER para editar o texto",
"text_editing": "Pressione Esc ou Ctrl/Cmd+ENTER para encerrar a edição", "text_editing": "Pressione Esc ou Ctrl/Cmd+ENTER para encerrar a edição",
"linearElementMulti": "Clique no último ponto ou pressione Escape ou Enter para terminar", "linearElementMulti": "Clique no último ponto ou pressione Escape ou Enter para terminar",
@@ -252,7 +267,8 @@
"bindTextToElement": "Pressione Enter para adicionar o texto", "bindTextToElement": "Pressione Enter para adicionar o texto",
"deepBoxSelect": "Segure Ctrl/Cmd para seleção profunda e para evitar arrastar", "deepBoxSelect": "Segure Ctrl/Cmd para seleção profunda e para evitar arrastar",
"eraserRevert": "Segure a tecla Alt para inverter os elementos marcados para exclusão", "eraserRevert": "Segure a tecla Alt para inverter os elementos marcados para exclusão",
"firefox_clipboard_write": "Esse recurso pode ser ativado configurando a opção \"dom.events.asyncClipboard.clipboardItem\" como \"true\". Para alterar os sinalizadores do navegador no Firefox, visite a página \"about:config\"." "firefox_clipboard_write": "Esse recurso pode ser ativado configurando a opção \"dom.events.asyncClipboard.clipboardItem\" como \"true\". Para alterar os sinalizadores do navegador no Firefox, visite a página \"about:config\".",
"disableSnapping": ""
}, },
"canvasError": { "canvasError": {
"cannotShowPreview": "Não é possível mostrar pré-visualização", "cannotShowPreview": "Não é possível mostrar pré-visualização",
@@ -411,7 +427,9 @@
"fileSavedToFilename": "Salvo em {filename}", "fileSavedToFilename": "Salvo em {filename}",
"canvas": "tela", "canvas": "tela",
"selection": "seleção", "selection": "seleção",
"pasteAsSingleElement": "Use {{shortcut}} para colar como um único elemento,\nou cole em um editor de texto já existente" "pasteAsSingleElement": "Use {{shortcut}} para colar como um único elemento,\nou cole em um editor de texto já existente",
"unableToEmbed": "",
"unrecognizedLinkFormat": ""
}, },
"colors": { "colors": {
"transparent": "Transparente", "transparent": "Transparente",
@@ -449,5 +467,36 @@
"shades": "Tons", "shades": "Tons",
"hexCode": "Código hexadecimal", "hexCode": "Código hexadecimal",
"noShades": "Sem tons disponíveis para essa cor" "noShades": "Sem tons disponíveis para essa cor"
},
"overwriteConfirm": {
"action": {
"exportToImage": {
"title": "Exportar como imagem",
"button": "Exportar como imagem",
"description": "Exportar os dados da cena para um arquivo que você poderá importar mais tarde."
},
"saveToDisk": {
"title": "Salvar no computador",
"button": "Salvar no computador",
"description": "Exportar os dados da cena para um arquivo que você poderá importar mais tarde."
},
"excalidrawPlus": {
"title": "Excalidraw+",
"button": "Exportar para Excalidraw+",
"description": "Salvar a cena na sua área de trabalho Excalidraw+."
}
},
"modal": {
"loadFromFile": {
"title": "Carregar de arquivo",
"button": "Carregar de arquivo",
"description": "Carregar de um arquivo irá <bold> substituir o conteúdo existente</bold>.<br></br>Você pode salvar seu desenho primeiro usando uma das opções abaixo."
},
"shareableLink": {
"title": "Carregar de um link",
"button": "Substituir meu conteúdo",
"description": "Carregar um desenho externo irá <bold> substituir seu conteúdo existente</bold>.<br></br>Você pode salvar seu desenho antes utilizando uma das opções abaixo."
}
}
} }
} }
+53 -4
View File
@@ -109,8 +109,12 @@
"createContainerFromText": "Envolver texto num recipiente", "createContainerFromText": "Envolver texto num recipiente",
"link": { "link": {
"edit": "Editar ligação", "edit": "Editar ligação",
"editEmbed": "",
"create": "Criar ligação", "create": "Criar ligação",
"label": "Ligação" "createEmbed": "",
"label": "Ligação",
"labelEmbed": "",
"empty": ""
}, },
"lineEditor": { "lineEditor": {
"edit": "Editar linha", "edit": "Editar linha",
@@ -160,13 +164,16 @@
"darkMode": "Modo escuro", "darkMode": "Modo escuro",
"lightMode": "Modo claro", "lightMode": "Modo claro",
"zenMode": "Modo zen", "zenMode": "Modo zen",
"objectsSnapMode": "",
"exitZenMode": "Sair do modo zen", "exitZenMode": "Sair do modo zen",
"cancel": "Cancelar", "cancel": "Cancelar",
"clear": "Limpar", "clear": "Limpar",
"remove": "Remover", "remove": "Remover",
"embed": "",
"publishLibrary": "Publicar", "publishLibrary": "Publicar",
"submit": "Enviar", "submit": "Enviar",
"confirm": "Confirmar" "confirm": "Confirmar",
"embeddableInteractionButton": ""
}, },
"alerts": { "alerts": {
"clearReset": "Isto irá limpar toda a área de desenho. Tem a certeza?", "clearReset": "Isto irá limpar toda a área de desenho. Tem a certeza?",
@@ -196,6 +203,7 @@
"imageInsertError": "Não foi possível inserir a imagem, tente novamente mais tarde...", "imageInsertError": "Não foi possível inserir a imagem, tente novamente mais tarde...",
"fileTooBig": "O ficheiro é muito grande. O tamanho máximo permitido é {{maxSize}}.", "fileTooBig": "O ficheiro é muito grande. O tamanho máximo permitido é {{maxSize}}.",
"svgImageInsertError": "Não foi possível inserir a imagem SVG. A marcação SVG parece inválida.", "svgImageInsertError": "Não foi possível inserir a imagem SVG. A marcação SVG parece inválida.",
"failedToFetchImage": "",
"invalidSVGString": "SVG inválido.", "invalidSVGString": "SVG inválido.",
"cannotResolveCollabServer": "Não foi possível fazer a ligação ao servidor colaborativo. Por favor, volte a carregar a página e tente novamente.", "cannotResolveCollabServer": "Não foi possível fazer a ligação ao servidor colaborativo. Por favor, volte a carregar a página e tente novamente.",
"importLibraryError": "Não foi possível carregar a biblioteca", "importLibraryError": "Não foi possível carregar a biblioteca",
@@ -206,6 +214,10 @@
"line2": "", "line2": "",
"line3": "", "line3": "",
"line4": "" "line4": ""
},
"libraryElementTypeError": {
"embeddable": "",
"image": ""
} }
}, },
"toolBar": { "toolBar": {
@@ -224,6 +236,8 @@
"link": "Acrescentar/ Adicionar ligação para uma forma seleccionada", "link": "Acrescentar/ Adicionar ligação para uma forma seleccionada",
"eraser": "Borracha", "eraser": "Borracha",
"frame": "", "frame": "",
"embeddable": "",
"laser": "",
"hand": "Mão (ferramenta de movimento da tela)", "hand": "Mão (ferramenta de movimento da tela)",
"extraTools": "" "extraTools": ""
}, },
@@ -237,6 +251,7 @@
"linearElement": "Clique para iniciar vários pontos, arraste para uma única linha", "linearElement": "Clique para iniciar vários pontos, arraste para uma única linha",
"freeDraw": "Clique e arraste, large quando terminar", "freeDraw": "Clique e arraste, large quando terminar",
"text": "Dica: também pode adicionar texto clicando duas vezes em qualquer lugar com a ferramenta de seleção", "text": "Dica: também pode adicionar texto clicando duas vezes em qualquer lugar com a ferramenta de seleção",
"embeddable": "",
"text_selected": "Clique duas vezes ou pressione a tecla Enter para editar o texto", "text_selected": "Clique duas vezes ou pressione a tecla Enter para editar o texto",
"text_editing": "Pressione a tecla Escape ou CtrlOrCmd+ENTER para terminar a edição", "text_editing": "Pressione a tecla Escape ou CtrlOrCmd+ENTER para terminar a edição",
"linearElementMulti": "Clique no último ponto ou pressione Escape ou Enter para terminar", "linearElementMulti": "Clique no último ponto ou pressione Escape ou Enter para terminar",
@@ -252,7 +267,8 @@
"bindTextToElement": "Carregue Enter para acrescentar texto", "bindTextToElement": "Carregue Enter para acrescentar texto",
"deepBoxSelect": "Mantenha a tecla CtrlOrCmd carregada para selecção profunda, impedindo o arrastamento", "deepBoxSelect": "Mantenha a tecla CtrlOrCmd carregada para selecção profunda, impedindo o arrastamento",
"eraserRevert": "Carregue também em Alt para reverter os elementos marcados para serem apagados", "eraserRevert": "Carregue também em Alt para reverter os elementos marcados para serem apagados",
"firefox_clipboard_write": "Esta função pode provavelmente ser ativada definindo a opção \"dom.events.asyncClipboard.clipboardItem\" como \"true\". Para alterar os sinalizadores do navegador no Firefox, visite a página \"about:config\"." "firefox_clipboard_write": "Esta função pode provavelmente ser ativada definindo a opção \"dom.events.asyncClipboard.clipboardItem\" como \"true\". Para alterar os sinalizadores do navegador no Firefox, visite a página \"about:config\".",
"disableSnapping": ""
}, },
"canvasError": { "canvasError": {
"cannotShowPreview": "Não é possível mostrar uma pré-visualização", "cannotShowPreview": "Não é possível mostrar uma pré-visualização",
@@ -411,7 +427,9 @@
"fileSavedToFilename": "Guardado como {filename}", "fileSavedToFilename": "Guardado como {filename}",
"canvas": "área de desenho", "canvas": "área de desenho",
"selection": "seleção", "selection": "seleção",
"pasteAsSingleElement": "Usar {{shortcut}} para colar como um único elemento,\nou colar num editor de texto existente" "pasteAsSingleElement": "Usar {{shortcut}} para colar como um único elemento,\nou colar num editor de texto existente",
"unableToEmbed": "",
"unrecognizedLinkFormat": ""
}, },
"colors": { "colors": {
"transparent": "Transparente", "transparent": "Transparente",
@@ -449,5 +467,36 @@
"shades": "Tons", "shades": "Tons",
"hexCode": "", "hexCode": "",
"noShades": "" "noShades": ""
},
"overwriteConfirm": {
"action": {
"exportToImage": {
"title": "",
"button": "",
"description": ""
},
"saveToDisk": {
"title": "Guardar no disco",
"button": "Guardar no disco",
"description": ""
},
"excalidrawPlus": {
"title": "",
"button": "",
"description": ""
}
},
"modal": {
"loadFromFile": {
"title": "Carregar a partir de ficheiro",
"button": "Carregar a partir de ficheiro",
"description": ""
},
"shareableLink": {
"title": "",
"button": "",
"description": ""
}
}
} }
} }
+53 -4
View File
@@ -109,8 +109,12 @@
"createContainerFromText": "Încadrare text într-un container", "createContainerFromText": "Încadrare text într-un container",
"link": { "link": {
"edit": "Editare URL", "edit": "Editare URL",
"editEmbed": "Editare URL și încorporare",
"create": "Creare URL", "create": "Creare URL",
"label": "URL" "createEmbed": "Creare URL și încorporare",
"label": "URL",
"labelEmbed": "URL și încorporare",
"empty": "Nu este setat niciun URL"
}, },
"lineEditor": { "lineEditor": {
"edit": "Editare linie", "edit": "Editare linie",
@@ -160,13 +164,16 @@
"darkMode": "Mod întunecat", "darkMode": "Mod întunecat",
"lightMode": "Mod luminos", "lightMode": "Mod luminos",
"zenMode": "Mod zen", "zenMode": "Mod zen",
"objectsSnapMode": "Ancorare la obiecte",
"exitZenMode": "Ieșire din modul zen", "exitZenMode": "Ieșire din modul zen",
"cancel": "Anulare", "cancel": "Anulare",
"clear": "Ștergere", "clear": "Ștergere",
"remove": "Eliminare", "remove": "Eliminare",
"embed": "Comutare încorporare",
"publishLibrary": "Publicare", "publishLibrary": "Publicare",
"submit": "Trimitere", "submit": "Trimitere",
"confirm": "Confirmare" "confirm": "Confirmare",
"embeddableInteractionButton": "Clic pentru interacționare"
}, },
"alerts": { "alerts": {
"clearReset": "Această opțiune va șterge întreaga pânză. Confirmi?", "clearReset": "Această opțiune va șterge întreaga pânză. Confirmi?",
@@ -196,6 +203,7 @@
"imageInsertError": "Imaginea nu a putut fi introdusă. Reîncearcă mai târziu...", "imageInsertError": "Imaginea nu a putut fi introdusă. Reîncearcă mai târziu...",
"fileTooBig": "Fișierul este prea mare. Dimensiunea maximă permisă este de {{maxSize}}.", "fileTooBig": "Fișierul este prea mare. Dimensiunea maximă permisă este de {{maxSize}}.",
"svgImageInsertError": "Imaginea SVG nu a putut fi introdus. Marcajul SVG pare invalid.", "svgImageInsertError": "Imaginea SVG nu a putut fi introdus. Marcajul SVG pare invalid.",
"failedToFetchImage": "",
"invalidSVGString": "SVG invalid.", "invalidSVGString": "SVG invalid.",
"cannotResolveCollabServer": "Nu a putut fi realizată conexiunea la serverul de colaborare. Reîncarcă pagina și încearcă din nou.", "cannotResolveCollabServer": "Nu a putut fi realizată conexiunea la serverul de colaborare. Reîncarcă pagina și încearcă din nou.",
"importLibraryError": "Biblioteca nu a putut fi încărcată", "importLibraryError": "Biblioteca nu a putut fi încărcată",
@@ -206,6 +214,10 @@
"line2": "Acest lucru poate duce la întreruperea <bold>elementelor text</bold> din desene.", "line2": "Acest lucru poate duce la întreruperea <bold>elementelor text</bold> din desene.",
"line3": "Îți recomandăm ferm să dezactivezi această setare. Poți urma <link>acești pași</link> pentru a face acest lucru.", "line3": "Îți recomandăm ferm să dezactivezi această setare. Poți urma <link>acești pași</link> pentru a face acest lucru.",
"line4": "Dacă dezactivarea acestei setări nu duce la remedierea afișării elementelor text, deschide un tichet de <issueLink>problemă</issueLink> pe pagina noastră de GitHub sau scrie-ne pe <discordLink>Discord</discordLink>" "line4": "Dacă dezactivarea acestei setări nu duce la remedierea afișării elementelor text, deschide un tichet de <issueLink>problemă</issueLink> pe pagina noastră de GitHub sau scrie-ne pe <discordLink>Discord</discordLink>"
},
"libraryElementTypeError": {
"embeddable": "Elementele încorporabile nu pot fi adăugate la bibliotecă.",
"image": "În curând vor putea fi adăugate imagini în bibliotecă!"
} }
}, },
"toolBar": { "toolBar": {
@@ -224,6 +236,8 @@
"link": "Adăugare/actualizare URL pentru forma selectată", "link": "Adăugare/actualizare URL pentru forma selectată",
"eraser": "Radieră", "eraser": "Radieră",
"frame": "", "frame": "",
"embeddable": "Încorporare web",
"laser": "Indicator laser",
"hand": "Mână (instrument de panoramare)", "hand": "Mână (instrument de panoramare)",
"extraTools": "" "extraTools": ""
}, },
@@ -237,6 +251,7 @@
"linearElement": "Dă clic pentru a crea mai multe puncte, glisează pentru a forma o singură linie", "linearElement": "Dă clic pentru a crea mai multe puncte, glisează pentru a forma o singură linie",
"freeDraw": "Dă clic pe pânză și glisează cursorul, apoi eliberează-l când ai terminat", "freeDraw": "Dă clic pe pânză și glisează cursorul, apoi eliberează-l când ai terminat",
"text": "Sfat: poți adăuga text și dând dublu clic oriunde cu instrumentul de selecție", "text": "Sfat: poți adăuga text și dând dublu clic oriunde cu instrumentul de selecție",
"embeddable": "Dă clic și trage pentru a crea un cod de încorporare de pagină web",
"text_selected": "Dă dublu clic sau apasă tasta Enter pentru a edita textul", "text_selected": "Dă dublu clic sau apasă tasta Enter pentru a edita textul",
"text_editing": "Apasă tasta Escape sau Ctrl sau Cmd + Enter pentru a finaliza editarea", "text_editing": "Apasă tasta Escape sau Ctrl sau Cmd + Enter pentru a finaliza editarea",
"linearElementMulti": "Dă clic pe ultimul punct sau apasă tasta Escape sau tasta Enter pentru a termina", "linearElementMulti": "Dă clic pe ultimul punct sau apasă tasta Escape sau tasta Enter pentru a termina",
@@ -252,7 +267,8 @@
"bindTextToElement": "Apasă tasta Enter pentru a adăuga text", "bindTextToElement": "Apasă tasta Enter pentru a adăuga text",
"deepBoxSelect": "Ține apăsată tasta Ctrl sau Cmd pentru a efectua selectarea de adâncime și pentru a preveni glisarea", "deepBoxSelect": "Ține apăsată tasta Ctrl sau Cmd pentru a efectua selectarea de adâncime și pentru a preveni glisarea",
"eraserRevert": "Ține apăsată tasta Alt pentru a anula elementele marcate pentru ștergere", "eraserRevert": "Ține apăsată tasta Alt pentru a anula elementele marcate pentru ștergere",
"firefox_clipboard_write": "Această caracteristică poate fi probabil activată prin setarea preferinței „dom.events.asyncClipboard.clipboardItem” ca „true”. Pentru a schimba preferințele navigatorului în Firefox, accesează pagina „about:config”." "firefox_clipboard_write": "Această caracteristică poate fi probabil activată prin setarea preferinței „dom.events.asyncClipboard.clipboardItem” ca „true”. Pentru a schimba preferințele navigatorului în Firefox, accesează pagina „about:config”.",
"disableSnapping": "Ține apăsat CtrlOrCmd pentru a dezactiva ancorarea"
}, },
"canvasError": { "canvasError": {
"cannotShowPreview": "Nu se poate afișa previzualizarea", "cannotShowPreview": "Nu se poate afișa previzualizarea",
@@ -411,7 +427,9 @@
"fileSavedToFilename": "Salvat în {filename}", "fileSavedToFilename": "Salvat în {filename}",
"canvas": "pânza", "canvas": "pânza",
"selection": "selecția", "selection": "selecția",
"pasteAsSingleElement": "Folosește {{shortcut}} pentru a insera ca un singur element\nsau insera într-un editor de text existent" "pasteAsSingleElement": "Folosește {{shortcut}} pentru a insera ca un singur element\nsau insera într-un editor de text existent",
"unableToEmbed": "Încorporarea acestui URL nu este permisă momentan. Deschideți un tichet cu probleme pe GitHub pentru a solicita adăugarea acestui URL în lista albă",
"unrecognizedLinkFormat": "URL-ul pe care l-ai încorporat nu coincide cu formatul așteptat. Încearcă să lipești șirul „de încorporat” furnizat de pagina sursă"
}, },
"colors": { "colors": {
"transparent": "Transparent", "transparent": "Transparent",
@@ -449,5 +467,36 @@
"shades": "Nuanțe", "shades": "Nuanțe",
"hexCode": "Cod hexa", "hexCode": "Cod hexa",
"noShades": "Nu este disponibilă nicio nuanță pentru această culoare" "noShades": "Nu este disponibilă nicio nuanță pentru această culoare"
},
"overwriteConfirm": {
"action": {
"exportToImage": {
"title": "Exportare ca imagine",
"button": "Exportare ca imagine",
"description": "Exportă datele scenei ca fișier din care poți importa mai târziu."
},
"saveToDisk": {
"title": "Salvare pe disc",
"button": "Salvare pe disc",
"description": "Exportă datele scenei pe un fișier din care poți importa mai târziu."
},
"excalidrawPlus": {
"title": "Excalidraw+",
"button": "Exportare în Excalidraw+",
"description": "Salvează scena în spațiul de lucru Excalidraw+."
}
},
"modal": {
"loadFromFile": {
"title": "Încărcare din fișier",
"button": "Încărcare din fișier",
"description": "Încărcarea dintr-un fișier va <bold>înlocui conținutul existent</bold>.<br></br>Poți face mai întâi o copie de rezervă a desenului folosind una dintre opțiunile de mai jos."
},
"shareableLink": {
"title": "Încărcare din lnk",
"button": "Înlocuiește conținutul meu",
"description": "Încărcarea unui desen extern va <bold>înlocui conținutul existent</bold>.<br></br>Poți face mai întâi o copie de rezervă a desenului folosind una dintre opțiunile de mai jos."
}
}
} }
} }
+53 -4
View File
@@ -109,8 +109,12 @@
"createContainerFromText": "Поместить текст в контейнер", "createContainerFromText": "Поместить текст в контейнер",
"link": { "link": {
"edit": "Редактировать ссылку", "edit": "Редактировать ссылку",
"editEmbed": "",
"create": "Создать ссылку", "create": "Создать ссылку",
"label": "Ссылка" "createEmbed": "",
"label": "Ссылка",
"labelEmbed": "",
"empty": ""
}, },
"lineEditor": { "lineEditor": {
"edit": "Редактирование строки", "edit": "Редактирование строки",
@@ -160,13 +164,16 @@
"darkMode": "Темная тема", "darkMode": "Темная тема",
"lightMode": "Светлая тема", "lightMode": "Светлая тема",
"zenMode": "Режим Дзен", "zenMode": "Режим Дзен",
"objectsSnapMode": "Привязка к объектам",
"exitZenMode": "Выключить режим концентрации внимания", "exitZenMode": "Выключить режим концентрации внимания",
"cancel": "Отменить", "cancel": "Отменить",
"clear": "Очистить", "clear": "Очистить",
"remove": "Удалить", "remove": "Удалить",
"embed": "",
"publishLibrary": "Опубликовать", "publishLibrary": "Опубликовать",
"submit": "Отправить", "submit": "Отправить",
"confirm": "Подтвердить" "confirm": "Подтвердить",
"embeddableInteractionButton": ""
}, },
"alerts": { "alerts": {
"clearReset": "Это очистит весь холст. Вы уверены?", "clearReset": "Это очистит весь холст. Вы уверены?",
@@ -196,6 +203,7 @@
"imageInsertError": "Не удалось вставить изображение. Попробуйте позже...", "imageInsertError": "Не удалось вставить изображение. Попробуйте позже...",
"fileTooBig": "Очень большой файл. Максимально разрешенный размер {{maxSize}}.", "fileTooBig": "Очень большой файл. Максимально разрешенный размер {{maxSize}}.",
"svgImageInsertError": "Не удалось вставить изображение SVG. Разметка SVG выглядит недействительной.", "svgImageInsertError": "Не удалось вставить изображение SVG. Разметка SVG выглядит недействительной.",
"failedToFetchImage": "Не удалось получить изображение.",
"invalidSVGString": "Некорректный SVG.", "invalidSVGString": "Некорректный SVG.",
"cannotResolveCollabServer": "Не удалось подключиться к серверу совместного редактирования. Перезагрузите страницу и повторите попытку.", "cannotResolveCollabServer": "Не удалось подключиться к серверу совместного редактирования. Перезагрузите страницу и повторите попытку.",
"importLibraryError": "Не удалось загрузить библиотеку", "importLibraryError": "Не удалось загрузить библиотеку",
@@ -206,6 +214,10 @@
"line2": "Это может привести к поломке <bold>Текстовых объектов</bold> на рисунке.", "line2": "Это может привести к поломке <bold>Текстовых объектов</bold> на рисунке.",
"line3": "Мы настоятельно рекомендуем отключить эту настройку. Для этого нужно выполнить <link>эти шаги</link>.", "line3": "Мы настоятельно рекомендуем отключить эту настройку. Для этого нужно выполнить <link>эти шаги</link>.",
"line4": "Если отключение этой настройки не исправит отображение текстовых объектов, создайте <issueLink>issue</issueLink> на нашем GitHub или напишите нам в <discordLink>Discord</discordLink>" "line4": "Если отключение этой настройки не исправит отображение текстовых объектов, создайте <issueLink>issue</issueLink> на нашем GitHub или напишите нам в <discordLink>Discord</discordLink>"
},
"libraryElementTypeError": {
"embeddable": "",
"image": ""
} }
}, },
"toolBar": { "toolBar": {
@@ -224,6 +236,8 @@
"link": "Добавить/обновить ссылку для выбранной фигуры", "link": "Добавить/обновить ссылку для выбранной фигуры",
"eraser": "Ластик", "eraser": "Ластик",
"frame": "", "frame": "",
"embeddable": "",
"laser": "Лазерная указка",
"hand": "Рука (перемещение холста)", "hand": "Рука (перемещение холста)",
"extraTools": "" "extraTools": ""
}, },
@@ -237,6 +251,7 @@
"linearElement": "Нажмите, чтобы начать несколько точек, перетащите для одной линии", "linearElement": "Нажмите, чтобы начать несколько точек, перетащите для одной линии",
"freeDraw": "Нажмите и перетаскивайте, отпустите по завершении", "freeDraw": "Нажмите и перетаскивайте, отпустите по завершении",
"text": "Совет: при выбранном инструменте выделения дважды щёлкните в любом месте, чтобы добавить текст", "text": "Совет: при выбранном инструменте выделения дважды щёлкните в любом месте, чтобы добавить текст",
"embeddable": "",
"text_selected": "Дважды щелкните мышью или нажмите ENTER, чтобы редактировать текст", "text_selected": "Дважды щелкните мышью или нажмите ENTER, чтобы редактировать текст",
"text_editing": "Нажмите Escape либо Ctrl или Cmd + ENTER для завершения редактирования", "text_editing": "Нажмите Escape либо Ctrl или Cmd + ENTER для завершения редактирования",
"linearElementMulti": "Кликните на последней точке или нажмите Escape или Enter чтобы закончить", "linearElementMulti": "Кликните на последней точке или нажмите Escape или Enter чтобы закончить",
@@ -252,7 +267,8 @@
"bindTextToElement": "Нажмите Enter для добавления текста", "bindTextToElement": "Нажмите Enter для добавления текста",
"deepBoxSelect": "Удерживайте Ctrl или Cmd для глубокого выделения, чтобы предотвратить перетаскивание", "deepBoxSelect": "Удерживайте Ctrl или Cmd для глубокого выделения, чтобы предотвратить перетаскивание",
"eraserRevert": "Удерживайте Alt, чтобы вернуть элементы, отмеченные для удаления", "eraserRevert": "Удерживайте Alt, чтобы вернуть элементы, отмеченные для удаления",
"firefox_clipboard_write": "Эта функция может быть включена при изменении значения флага \"dom.events.asyncClipboard.clipboardItem\" на \"true\". Чтобы изменить флаги браузера в Firefox, посетите страницу \"about:config\"." "firefox_clipboard_write": "Эта функция может быть включена при изменении значения флага \"dom.events.asyncClipboard.clipboardItem\" на \"true\". Чтобы изменить флаги браузера в Firefox, посетите страницу \"about:config\".",
"disableSnapping": ""
}, },
"canvasError": { "canvasError": {
"cannotShowPreview": "Не удается отобразить предпросмотр", "cannotShowPreview": "Не удается отобразить предпросмотр",
@@ -411,7 +427,9 @@
"fileSavedToFilename": "Сохранено в {filename}", "fileSavedToFilename": "Сохранено в {filename}",
"canvas": "холст", "canvas": "холст",
"selection": "выделение", "selection": "выделение",
"pasteAsSingleElement": "Используйте {{shortcut}}, чтобы вставить один объект,\nили вставьте в существующий текстовый редактор" "pasteAsSingleElement": "Используйте {{shortcut}}, чтобы вставить один объект,\nили вставьте в существующий текстовый редактор",
"unableToEmbed": "",
"unrecognizedLinkFormat": ""
}, },
"colors": { "colors": {
"transparent": "Прозрачный", "transparent": "Прозрачный",
@@ -449,5 +467,36 @@
"shades": "Оттенки", "shades": "Оттенки",
"hexCode": "Шестнадцатеричный код", "hexCode": "Шестнадцатеричный код",
"noShades": "Нет доступных оттенков для этого цвета" "noShades": "Нет доступных оттенков для этого цвета"
},
"overwriteConfirm": {
"action": {
"exportToImage": {
"title": "Экспортировать как изображение",
"button": "Экспортировать как изображение",
"description": ""
},
"saveToDisk": {
"title": "Сохранить на диск",
"button": "Сохранить на диск",
"description": ""
},
"excalidrawPlus": {
"title": "Excalidraw+",
"button": "Экспорт в Excalidraw+",
"description": ""
}
},
"modal": {
"loadFromFile": {
"title": "Загрузить из файла",
"button": "Загрузить из файла",
"description": ""
},
"shareableLink": {
"title": "Загрузить по ссылке",
"button": "",
"description": ""
}
}
} }
} }

Some files were not shown because too many files have changed in this diff Show More